mirror of
https://github.com/discourse/discourse.git
synced 2025-03-09 14:34:35 +00:00
DEV: Add experimental plugin API to replace tag icon in sidebar (#21675)
Why this change? This change allows plugins or themes to replace the tag icon in the sidebar. The color of the icon can be customised as well. However, do note that this change is marked experimental as we intend to support custom icons for tags in the near term as part of Discourse core. Therefore, the plugin API will become obsolete once that happens and we are marking it experimental to avoid having to deprecate it.
This commit is contained in:
parent
2aa5fc927e
commit
e880ede3d8
@ -12,6 +12,7 @@
|
||||
@currentWhen={{sectionLink.currentWhen}}
|
||||
@prefixType={{sectionLink.prefixType}}
|
||||
@prefixValue={{sectionLink.prefixValue}}
|
||||
@prefixColor={{sectionLink.prefixColor}}
|
||||
@models={{sectionLink.models}}
|
||||
data-tag-name={{sectionLink.tagName}}
|
||||
/>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { isHex } from "discourse/components/sidebar/section-link";
|
||||
|
||||
export default class extends Component {
|
||||
get prefixValue() {
|
||||
@ -11,8 +12,10 @@ export default class extends Component {
|
||||
let hexValues = this.args.prefixValue;
|
||||
|
||||
hexValues = hexValues.reduce((acc, color) => {
|
||||
if (color?.match(/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)) {
|
||||
acc.push(`#${color} 50%`);
|
||||
const hexCode = isHex(color);
|
||||
|
||||
if (hexCode) {
|
||||
acc.push(`#${hexCode} 50%`);
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
@ -1,6 +1,21 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { inject as service } from "@ember/service";
|
||||
|
||||
/**
|
||||
* Checks if a given string is a valid color hex code.
|
||||
*
|
||||
* @param {String|undefined} input Input string to check if it is a valid color hex code. Can be in the form of "FFFFFF" or "#FFFFFF" or "FFF" or "#FFF".
|
||||
* @returns {String|undefined} Returns the matching color hex code without the leading `#` if it is valid, otherwise returns undefined. Example: "FFFFFF" or "FFF".
|
||||
*/
|
||||
export function isHex(input) {
|
||||
const match = input?.match(/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/);
|
||||
|
||||
if (match) {
|
||||
return match[1];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
export default class SectionLink extends Component {
|
||||
@service currentUser;
|
||||
|
||||
@ -53,12 +68,12 @@ export default class SectionLink extends Component {
|
||||
}
|
||||
|
||||
get prefixColor() {
|
||||
const color = this.args.prefixColor;
|
||||
const hexCode = isHex(this.args.prefixColor);
|
||||
|
||||
if (!color || !color.match(/^\w{6}$/)) {
|
||||
return "";
|
||||
if (hexCode) {
|
||||
return `#${hexCode}`;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
return "#" + color;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
@currentWhen={{sectionLink.currentWhen}}
|
||||
@prefixType={{sectionLink.prefixType}}
|
||||
@prefixValue={{sectionLink.prefixValue}}
|
||||
@prefixColor={{sectionLink.prefixColor}}
|
||||
@badgeText={{sectionLink.badgeText}}
|
||||
@models={{sectionLink.models}}
|
||||
@suffixCSSClass={{sectionLink.suffixCSSClass}}
|
||||
|
@ -109,6 +109,7 @@ import {
|
||||
registerCustomCategorySectionLinkPrefix,
|
||||
registerCustomCountable as registerUserCategorySectionLinkCountable,
|
||||
} from "discourse/lib/sidebar/user/categories-section/category-section-link";
|
||||
import { registerCustomTagSectionLinkPrefixIcon } from "discourse/lib/sidebar/user/tags-section/base-tag-section-link";
|
||||
import { REFRESH_COUNTS_APP_EVENT_NAME as REFRESH_USER_SIDEBAR_CATEGORIES_SECTION_COUNTS_APP_EVENT_NAME } from "discourse/components/sidebar/user/categories-section";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { registerNotificationTypeRenderer } from "discourse/lib/notification-types-manager";
|
||||
@ -1965,6 +1966,38 @@ class PluginApi {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. Do not use.
|
||||
* Register a custom prefix for a sidebar tag section link.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* api.registerCustomTagSectionLinkPrefixValue({
|
||||
* tagName: "tag1",
|
||||
* prefixType: "icon",
|
||||
* prefixValue: "wrench",
|
||||
* prefixColor: "#FF0000"
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @params {Object} arg - An object
|
||||
* @params {string} arg.tagName - The name of the tag
|
||||
* @params {string} arg.prefixValue - The name of a FontAwesome 5 icon.
|
||||
* @params {string} arg.prefixColor - The color represented using hexadecimal to use for the prefix. Example: "#FF0000" or "#FFF".
|
||||
*/
|
||||
registerCustomTagSectionLinkPrefixIcon({
|
||||
tagName,
|
||||
prefixValue,
|
||||
prefixColor,
|
||||
}) {
|
||||
registerCustomTagSectionLinkPrefixIcon({
|
||||
tagName,
|
||||
prefixValue,
|
||||
prefixColor,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. Do not use.
|
||||
* Triggers a refresh of the counts for all category section links under the categories section for a logged in user.
|
||||
|
@ -1,6 +1,28 @@
|
||||
let customTagSectionLinkPrefixIcons = {};
|
||||
|
||||
export function registerCustomTagSectionLinkPrefixIcon({
|
||||
tagName,
|
||||
prefixValue,
|
||||
prefixColor,
|
||||
}) {
|
||||
customTagSectionLinkPrefixIcons[tagName] = {
|
||||
prefixValue,
|
||||
prefixColor,
|
||||
};
|
||||
}
|
||||
|
||||
export function resetCustomTagSectionLinkPrefixIcons() {
|
||||
for (let key in customTagSectionLinkPrefixIcons) {
|
||||
if (customTagSectionLinkPrefixIcons.hasOwnProperty(key)) {
|
||||
delete customTagSectionLinkPrefixIcons[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default class BaseTagSectionLink {
|
||||
constructor({ tagName }) {
|
||||
constructor({ tagName, currentUser }) {
|
||||
this.tagName = tagName;
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
get name() {
|
||||
@ -16,6 +38,10 @@ export default class BaseTagSectionLink {
|
||||
}
|
||||
|
||||
get prefixValue() {
|
||||
return "tag";
|
||||
return customTagSectionLinkPrefixIcons[this.tagName]?.prefixValue || "tag";
|
||||
}
|
||||
|
||||
get prefixColor() {
|
||||
return customTagSectionLinkPrefixIcons[this.tagName]?.prefixColor;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,6 @@
|
||||
import BaseTagSectionLink from "discourse/lib/sidebar/user/tags-section/base-tag-section-link";
|
||||
|
||||
export default class PMTagSectionLink extends BaseTagSectionLink {
|
||||
constructor({ currentUser }) {
|
||||
super(...arguments);
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
get models() {
|
||||
return [this.currentUser, this.tagName];
|
||||
}
|
||||
|
@ -12,10 +12,9 @@ export default class TagSectionLink extends BaseTagSectionLink {
|
||||
@tracked hideCount =
|
||||
this.currentUser?.sidebarListDestination !== UNREAD_LIST_DESTINATION;
|
||||
|
||||
constructor({ topicTrackingState, currentUser }) {
|
||||
constructor({ topicTrackingState }) {
|
||||
super(...arguments);
|
||||
this.topicTrackingState = topicTrackingState;
|
||||
this.currentUser = currentUser;
|
||||
this.refreshCounts();
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
resetCustomCategorySectionLinkPrefix,
|
||||
resetCustomCountables,
|
||||
} from "discourse/lib/sidebar/user/categories-section/category-section-link";
|
||||
import { resetCustomTagSectionLinkPrefixIcons } from "discourse/lib/sidebar/user/tags-section/base-tag-section-link";
|
||||
import { UNREAD_LIST_DESTINATION } from "discourse/controllers/preferences/sidebar";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
|
||||
@ -22,6 +23,7 @@ acceptance("Sidebar - Plugin API", function (needs) {
|
||||
needs.user({});
|
||||
|
||||
needs.settings({
|
||||
tagging_enabled: true,
|
||||
navigation_menu: "sidebar",
|
||||
});
|
||||
|
||||
@ -820,4 +822,51 @@ acceptance("Sidebar - Plugin API", function (needs) {
|
||||
resetCustomCategorySectionLinkPrefix();
|
||||
}
|
||||
});
|
||||
|
||||
test("Customizing the prefix icon used in a tag section link for a particular tag", async function (assert) {
|
||||
try {
|
||||
return await withPluginApi(PLUGIN_API_VERSION, async (api) => {
|
||||
updateCurrentUser({
|
||||
display_sidebar_tags: true,
|
||||
sidebar_tags: [
|
||||
{ name: "tag2", pm_only: false },
|
||||
{ name: "tag1", pm_only: false },
|
||||
{ name: "tag3", pm_only: false },
|
||||
],
|
||||
});
|
||||
|
||||
api.registerCustomTagSectionLinkPrefixIcon({
|
||||
tagName: "tag1",
|
||||
prefixValue: "wrench",
|
||||
prefixColor: "#FF0000", // rgb(255, 0, 0)
|
||||
});
|
||||
|
||||
await visit("/");
|
||||
|
||||
assert.ok(
|
||||
exists(
|
||||
`.sidebar-section-link[data-tag-name="tag1"] .prefix-icon.d-icon-wrench`
|
||||
),
|
||||
"wrench icon is displayed for tag1 section link's prefix icon"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
`.sidebar-section-link[data-tag-name="tag1"] .sidebar-section-link-prefix`
|
||||
).style.color,
|
||||
"rgb(255, 0, 0)",
|
||||
"tag1 section link's prefix icon has the right color"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
exists(
|
||||
`.sidebar-section-link[data-tag-name="tag2"] .prefix-icon.d-icon-tag`
|
||||
),
|
||||
"default tag icon is displayed for tag2 section link's prefix icon"
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
resetCustomTagSectionLinkPrefixIcons();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user