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:
parent
ad7d72cea7
commit
71eb8d2e8e
|
@ -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();
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue