DEV: Support models argument for custom sidebar section link API (#17602)

* DEV: Improve documentation for custom sidebar section interfaces

* DEV: Improvements to sidebar custom section plugin API tests

* DEV: Support models argument for custom sidebar section link API
This commit is contained in:
Alan Guo Xiang Tan 2022-07-22 12:06:21 +08:00 committed by GitHub
parent ad7d72cea7
commit 71eb8d2e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 29 deletions

View File

@ -10,31 +10,36 @@ export default class BaseCustomSidebarSectionLink {
} }
/** /**
* @returns {string} Ember route * @returns {string} The Ember route which the section link should link to.
*/ */
get route() { get route() {
this._notImplemented(); this._notImplemented();
} }
/** /**
* @returns {Object} Model for <LinkTo> component. See https://api.emberjs.com/ember/release/classes/Ember.Templates.components/methods/LinkTo?anchor=LinkTo * @returns {Object} `model` argument for the <LinkTo> component. See https://api.emberjs.com/ember/release/classes/Ember.Templates.components/methods/LinkTo?anchor=LinkTo.
*/ */
get model() {} get model() {}
/** /**
* @returns {boolean} Used to determine when this LinkComponent is active * @returns {Object[]} `models` argument for the <LinkTo> component. See https://api.emberjs.com/ember/release/classes/Ember.Templates.components/methods/LinkTo?anchor=LinkTo.
*/
get models() {}
/**
* @returns {boolean} `current-when` argument for the <LinkTo> component. See See https://api.emberjs.com/ember/release/classes/Ember.Templates.components/methods/LinkTo?anchor=LinkTo.
*/ */
get currentWhen() {} get currentWhen() {}
/** /**
* @returns {string} Title for the link * @returns {string} Title for the section link
*/ */
get title() { get title() {
this._notImplemented(); this._notImplemented();
} }
/** /**
* @returns {string} Text for the link * @returns {string} Text for the section link
*/ */
get text() { get text() {
this._notImplemented(); this._notImplemented();

View File

@ -13,6 +13,11 @@ export default class BaseCustomSidebarSection {
this._notImplemented(); this._notImplemented();
} }
/**
* @returns {string} The Ember route which the section header link should link to.
*/
get route() {}
/** /**
* @returns {string} Title for the header * @returns {string} Title for the header
*/ */
@ -33,7 +38,7 @@ export default class BaseCustomSidebarSection {
get actions() {} get actions() {}
/** /**
* @returns {string} Icon for header options button * @returns {string} Icon for dropdown header options button
*/ */
get actionsIcon() {} get actionsIcon() {}

View File

@ -25,6 +25,7 @@
@linkName={{link.name}} @linkName={{link.name}}
@route={{link.route}} @route={{link.route}}
@model={{link.model}} @model={{link.model}}
@models={{link.models}}
@title={{link.title}} @title={{link.title}}
@prefixColor={{link.prefixColor}} @prefixColor={{link.prefixColor}}
@prefixBadge={{link.prefixBadge}} @prefixBadge={{link.prefixBadge}}

View File

@ -11,7 +11,7 @@ import { withPluginApi } from "discourse/lib/plugin-api";
import { resetSidebarSection } from "discourse/lib/sidebar/custom-sections"; import { resetSidebarSection } from "discourse/lib/sidebar/custom-sections";
import { bind } from "discourse-common/utils/decorators"; import { bind } from "discourse-common/utils/decorators";
acceptance("Sidebar - section API", function (needs) { acceptance("Sidebar - Plugin API", function (needs) {
needs.user({ experimental_sidebar_enabled: true }); needs.user({ experimental_sidebar_enabled: true });
needs.hooks.afterEach(() => { needs.hooks.afterEach(() => {
@ -19,6 +19,7 @@ acceptance("Sidebar - section API", function (needs) {
linkDestroy = undefined; linkDestroy = undefined;
sectionDestroy = undefined; sectionDestroy = undefined;
}); });
let linkDestroy, sectionDestroy; let linkDestroy, sectionDestroy;
test("Multiple header actions and links", async function (assert) { test("Multiple header actions and links", async function (assert) {
@ -29,21 +30,23 @@ acceptance("Sidebar - section API", function (needs) {
get name() { get name() {
return "test-chat-channels"; return "test-chat-channels";
} }
get route() { get route() {
return "discovery.latest"; return "discovery.latest";
} }
get model() {
return false;
}
get title() { get title() {
return "chat channels title"; return "chat channels title";
} }
get text() { get text() {
return "chat channels text"; return "chat channels text";
} }
get actionsIcon() { get actionsIcon() {
return "cog"; return "cog";
} }
get actions() { get actions() {
return [ return [
{ {
@ -58,49 +61,63 @@ acceptance("Sidebar - section API", function (needs) {
}, },
]; ];
} }
@bind @bind
willDestroy() { willDestroy() {
sectionDestroy = "section test"; sectionDestroy = "section test";
} }
get links() { get links() {
return [ return [
new (class extends BaseCustomSidebarSectionLink { new (class extends BaseCustomSidebarSectionLink {
get name() { get name() {
"random-channel"; return "random-channel";
} }
get route() { get route() {
return "discovery.latest"; return "topic";
} }
get model() {
return false; get models() {
return ["some-slug", 1];
} }
get title() { get title() {
return "random channel title"; return "random channel title";
} }
get text() { get text() {
return "random channel text"; return "random channel text";
} }
get prefixType() { get prefixType() {
return "icon"; return "icon";
} }
get prefixValue() { get prefixValue() {
return "hashtag"; return "hashtag";
} }
get prefixColor() { get prefixColor() {
return "FF0000"; return "FF0000";
} }
get prefixBadge() { get prefixBadge() {
return "lock"; return "lock";
} }
get suffixType() { get suffixType() {
return "icon"; return "icon";
} }
get suffixValue() { get suffixValue() {
return "circle"; return "circle";
} }
get suffixCSSClass() { get suffixCSSClass() {
return "unread"; return "unread";
} }
@bind @bind
willDestroy() { willDestroy() {
linkDestroy = "link test"; linkDestroy = "link test";
@ -108,61 +125,70 @@ acceptance("Sidebar - section API", function (needs) {
})(), })(),
new (class extends BaseCustomSidebarSectionLink { new (class extends BaseCustomSidebarSectionLink {
get name() { get name() {
"dev-channel"; return "dev-channel";
} }
get route() { get route() {
return "discovery.latest"; return "discovery.latest";
} }
get model() {
return false;
}
get title() { get title() {
return "dev channel title"; return "dev channel title";
} }
get text() { get text() {
return "dev channel text"; return "dev channel text";
} }
get prefixColor() { get prefixColor() {
return "alert"; return "alert";
} }
get prefixType() { get prefixType() {
return "text"; return "text";
} }
get prefixValue() { get prefixValue() {
return "test text"; return "test text";
} }
})(), })(),
new (class extends BaseCustomSidebarSectionLink { new (class extends BaseCustomSidebarSectionLink {
get name() { get name() {
"fun-channel"; return "fun-channel";
} }
get route() { get route() {
return "discovery.latest"; return "discovery.latest";
} }
get model() {
return false;
}
get title() { get title() {
return "fun channel title"; return "fun channel title";
} }
get text() { get text() {
return "fun channel text"; return "fun channel text";
} }
get prefixType() { get prefixType() {
return "image"; return "image";
} }
get prefixValue() { get prefixValue() {
return "/test.png"; return "/test.png";
} }
get hoverType() { get hoverType() {
return "icon"; return "icon";
} }
get hoverValue() { get hoverValue() {
return "times"; return "times";
} }
get hoverAction() { get hoverAction() {
return () => {}; return () => {};
} }
get hoverTitle() { get hoverTitle() {
return "hover button title attribute"; return "hover button title attribute";
} }
@ -175,22 +201,26 @@ acceptance("Sidebar - section API", function (needs) {
}); });
await visit("/"); await visit("/");
assert.strictEqual( assert.strictEqual(
query(".sidebar-section-test-chat-channels .sidebar-section-header a") query(".sidebar-section-test-chat-channels .sidebar-section-header-link")
.title, .title,
"chat channels title", "chat channels title",
"displays header with correct title attribute" "displays header with correct title attribute"
); );
assert.strictEqual( assert.strictEqual(
query( query(
".sidebar-section-test-chat-channels .sidebar-section-header a" ".sidebar-section-test-chat-channels .sidebar-section-header-link"
).textContent.trim(), ).textContent.trim(),
"chat channels text", "chat channels text",
"displays header with correct text" "displays header with correct text"
); );
await click( await click(
".sidebar-section-test-chat-channels .sidebar-section-header-dropdown summary" ".sidebar-section-test-chat-channels .sidebar-section-header-dropdown summary"
); );
assert.strictEqual( assert.strictEqual(
queryAll( queryAll(
".sidebar-section-test-chat-channels .sidebar-section-header-dropdown .select-kit-collection li" ".sidebar-section-test-chat-channels .sidebar-section-header-dropdown .select-kit-collection li"
@ -198,14 +228,17 @@ acceptance("Sidebar - section API", function (needs) {
2, 2,
"displays two actions" "displays two actions"
); );
const actions = queryAll( const actions = queryAll(
".sidebar-section-test-chat-channels .sidebar-section-header-dropdown .select-kit-collection li" ".sidebar-section-test-chat-channels .sidebar-section-header-dropdown .select-kit-collection li"
); );
assert.strictEqual( assert.strictEqual(
actions[0].textContent.trim(), actions[0].textContent.trim(),
"Browse channels", "Browse channels",
"displays first header action with correct text" "displays first header action with correct text"
); );
assert.strictEqual( assert.strictEqual(
actions[1].textContent.trim(), actions[1].textContent.trim(),
"Settings", "Settings",
@ -213,33 +246,44 @@ acceptance("Sidebar - section API", function (needs) {
); );
const links = queryAll( const links = queryAll(
".sidebar-section-test-chat-channels .sidebar-section-content a" ".sidebar-section-test-chat-channels .sidebar-section-link"
); );
assert.strictEqual( assert.strictEqual(
links[0].textContent.trim(), links[0].textContent.trim(),
"random channel text", "random channel text",
"displays first link with correct text" "displays first link with correct text"
); );
assert.strictEqual( assert.strictEqual(
links[0].title, links[0].title,
"random channel title", "random channel title",
"displays first link with correct title attribute" "displays first link with correct title attribute"
); );
assert.ok(
links[0].href.endsWith("/some-slug/1"),
"link has the correct href attribute"
);
assert.strictEqual( assert.strictEqual(
links[0].children.item(0).style.color, links[0].children.item(0).style.color,
"rgb(255, 0, 0)", "rgb(255, 0, 0)",
"has correct prefix color" "has correct prefix color"
); );
assert.strictEqual( assert.strictEqual(
$(links[0].children.item(0).children.item(0)).hasClass("d-icon-hashtag"), $(links[0].children.item(0).children.item(0)).hasClass("d-icon-hashtag"),
true, true,
"displays prefix icon" "displays prefix icon"
); );
assert.strictEqual( assert.strictEqual(
$(links[0].children.item(0).children.item(1)).hasClass("d-icon-lock"), $(links[0].children.item(0).children.item(1)).hasClass("d-icon-lock"),
true, true,
"displays prefix icon badge" "displays prefix icon badge"
); );
assert.strictEqual( assert.strictEqual(
$(links[0].children.item(2).children.item(0)).hasClass("d-icon-circle"), $(links[0].children.item(2).children.item(0)).hasClass("d-icon-circle"),
true, true,
@ -251,16 +295,19 @@ acceptance("Sidebar - section API", function (needs) {
"dev channel text", "dev channel text",
"displays second link with correct text" "displays second link with correct text"
); );
assert.strictEqual( assert.strictEqual(
links[1].title, links[1].title,
"dev channel title", "dev channel title",
"displays second link with correct title attribute" "displays second link with correct title attribute"
); );
assert.strictEqual( assert.strictEqual(
links[1].children.item(0).style.color, links[1].children.item(0).style.color,
"", "",
"has no color style when value is invalid" "has no color style when value is invalid"
); );
assert.strictEqual( assert.strictEqual(
$(links[1].children)[0].textContent.trim(), $(links[1].children)[0].textContent.trim(),
"test text", "test text",
@ -272,27 +319,33 @@ acceptance("Sidebar - section API", function (needs) {
"fun channel text", "fun channel text",
"displays third link with correct text" "displays third link with correct text"
); );
assert.strictEqual( assert.strictEqual(
links[2].title, links[2].title,
"fun channel title", "fun channel title",
"displays third link with correct title attribute" "displays third link with correct title attribute"
); );
assert.strictEqual( assert.strictEqual(
$(links[2].children.item(0).children).attr("src"), $(links[2].children.item(0).children).attr("src"),
"/test.png", "/test.png",
"uses correct prefix image url" "uses correct prefix image url"
); );
assert.strictEqual( assert.strictEqual(
query(".sidebar-section-link-hover button").title, query(".sidebar-section-link-hover button").title,
"hover button title attribute", "hover button title attribute",
"displays hover button with correct title" "displays hover button with correct title"
); );
await click(".header-sidebar-toggle button"); await click(".header-sidebar-toggle button");
assert.strictEqual( assert.strictEqual(
linkDestroy, linkDestroy,
"link test", "link test",
"calls link willDestroy function" "calls link willDestroy function"
); );
assert.strictEqual( assert.strictEqual(
sectionDestroy, sectionDestroy,
"section test", "section test",
@ -307,21 +360,23 @@ acceptance("Sidebar - section API", function (needs) {
get name() { get name() {
return "test-chat-channels"; return "test-chat-channels";
} }
get route() { get route() {
return "discovery.latest"; return "discovery.latest";
} }
get model() {
return false;
}
get title() { get title() {
return "chat channels title"; return "chat channels title";
} }
get text() { get text() {
return "chat channels text"; return "chat channels text";
} }
get actionsIcon() { get actionsIcon() {
return "cog"; return "cog";
} }
get actions() { get actions() {
return [ return [
{ {
@ -331,6 +386,7 @@ acceptance("Sidebar - section API", function (needs) {
}, },
]; ];
} }
get links() { get links() {
return []; return [];
} }
@ -339,17 +395,20 @@ acceptance("Sidebar - section API", function (needs) {
}); });
await visit("/"); await visit("/");
assert.strictEqual( assert.strictEqual(
query( query(
".sidebar-section-test-chat-channels .sidebar-section-header a" ".sidebar-section-test-chat-channels .sidebar-section-header-link"
).textContent.trim(), ).textContent.trim(),
"chat channels text", "chat channels text",
"displays header with correct text" "displays header with correct text"
); );
assert.ok( assert.ok(
exists("button.sidebar-section-header-button"), exists("button.sidebar-section-header-button"),
"displays single header action button" "displays single header action button"
); );
assert.ok( assert.ok(
!exists(".sidebar-section-test-chat-channels .sidebar-section-content a"), !exists(".sidebar-section-test-chat-channels .sidebar-section-content a"),
"displays no links" "displays no links"