DEV: Add displaySection to sidebar sections (#18479)

This PR renames the old Sidebar::Section displaySection function
to displaySectionContent, and changes the meaning of displaySection
to hide the entire sidebar section including the header. This is
implemented via an arg passed to Sidebar::Section, which will default
to true if it is not passed, and the BaseCustomSidebarSection class
implements a default of `return true` for this function.
This commit is contained in:
Martin Brennan 2022-10-05 13:57:52 +10:00 committed by GitHub
parent 90f1e2df80
commit e3f1e0e9bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 179 additions and 43 deletions

View File

@ -1,42 +1,44 @@
<div class={{concat "sidebar-section-wrapper sidebar-section-" @sectionName}}> {{#if this.displaySection}}
<div class="sidebar-section-header-wrapper sidebar-row"> <div class={{concat "sidebar-section-wrapper sidebar-section-" @sectionName}}>
<Sidebar::SectionHeader @collapsable={{@collapsable}} @toggleSectionDisplay={{this.toggleSectionDisplay}}> <div class="sidebar-section-header-wrapper sidebar-row">
{{#if @collapsable}} <Sidebar::SectionHeader @collapsable={{@collapsable}} @toggleSectionDisplay={{this.toggleSectionDisplay}}>
<span class="sidebar-section-header-caret"> {{#if @collapsable}}
{{d-icon this.headerCaretIcon}} <span class="sidebar-section-header-caret">
{{d-icon this.headerCaretIcon}}
</span>
{{/if}}
<span class="sidebar-section-header-text">
{{@headerLinkText}}
</span> </span>
</Sidebar::SectionHeader>
{{#if this.isSingleHeaderAction}}
{{#each @headerActions as |headerAction|}}
<button
type="button"
class="sidebar-section-header-button"
{{on "click" headerAction.action}}
title={{headerAction.title}}
>
{{d-icon @headerActionsIcon}}
</button>
{{/each}}
{{/if}} {{/if}}
<span class="sidebar-section-header-text"> {{#if this.isMultipleHeaderActions}}
{{@headerLinkText}} <DropdownSelectBox
</span> @options={{hash icon=@headerActionsIcon placementStrategy="absolute"}}
</Sidebar::SectionHeader> @content={{@headerActions}}
@onChange={{action "handleMultipleHeaderActions"}}
@class="sidebar-section-header-dropdown" />
{{/if}}
</div>
{{#if this.isSingleHeaderAction}} {{#if this.displaySectionContent}}
{{#each @headerActions as |headerAction|}} <div class="sidebar-section-content">
<button {{yield}}
type="button" </div>
class="sidebar-section-header-button"
{{on "click" headerAction.action}}
title={{headerAction.title}}
>
{{d-icon @headerActionsIcon}}
</button>
{{/each}}
{{/if}}
{{#if this.isMultipleHeaderActions}}
<DropdownSelectBox
@options={{hash icon=@headerActionsIcon placementStrategy="absolute"}}
@content={{@headerActions}}
@onChange={{action "handleMultipleHeaderActions"}}
@class="sidebar-section-header-dropdown" />
{{/if}} {{/if}}
</div> </div>
{{/if}}
{{#if this.displaySection}}
<div class="sidebar-section-content">
{{yield}}
</div>
{{/if}}
</div>

View File

@ -7,20 +7,20 @@ import { tracked } from "@glimmer/tracking";
export default class SidebarSection extends Component { export default class SidebarSection extends Component {
@service keyValueStore; @service keyValueStore;
@tracked displaySection; @tracked displaySectionContent;
collapsedSidebarSectionKey = `sidebar-section-${this.args.sectionName}-collapsed`; collapsedSidebarSectionKey = `sidebar-section-${this.args.sectionName}-collapsed`;
constructor() { constructor() {
super(...arguments); super(...arguments);
if (this.args.collapsable) { if (this.args.collapsable) {
this.displaySection = this.displaySectionContent =
this.keyValueStore.getItem(this.collapsedSidebarSectionKey) === this.keyValueStore.getItem(this.collapsedSidebarSectionKey) ===
undefined undefined
? true ? true
: false; : false;
} else { } else {
this.displaySection = true; this.displaySectionContent = true;
} }
} }
@ -32,9 +32,9 @@ export default class SidebarSection extends Component {
@action @action
toggleSectionDisplay() { toggleSectionDisplay() {
this.displaySection = !this.displaySection; this.displaySectionContent = !this.displaySectionContent;
if (this.displaySection) { if (this.displaySectionContent) {
this.keyValueStore.remove(this.collapsedSidebarSectionKey); this.keyValueStore.remove(this.collapsedSidebarSectionKey);
} else { } else {
this.keyValueStore.setItem(this.collapsedSidebarSectionKey, true); this.keyValueStore.setItem(this.collapsedSidebarSectionKey, true);
@ -54,7 +54,7 @@ export default class SidebarSection extends Component {
} }
get headerCaretIcon() { get headerCaretIcon() {
return this.displaySection ? "angle-down" : "angle-right"; return this.displaySectionContent ? "angle-down" : "angle-right";
} }
get isSingleHeaderAction() { get isSingleHeaderAction() {
@ -64,4 +64,12 @@ export default class SidebarSection extends Component {
get isMultipleHeaderActions() { get isMultipleHeaderActions() {
return this.args.headerActions?.length > 1; return this.args.headerActions?.length > 1;
} }
get displaySection() {
if (this.args.displaySection === undefined) {
return true;
}
return this.args.displaySection;
}
} }

View File

@ -18,7 +18,8 @@
@headerActionsIcon={{customSection.actionsIcon}} @headerActionsIcon={{customSection.actionsIcon}}
@headerActions={{customSection.actions}} @headerActions={{customSection.actions}}
@willDestroy={{customSection.willDestroy}} @willDestroy={{customSection.willDestroy}}
@collapsable={{@collapsableSections}}> @collapsable={{@collapsableSections}}
@displaySection={{customSection.displaySection}}>
{{#each customSection.links as |link|}} {{#each customSection.links as |link|}}
<Sidebar::SectionLink <Sidebar::SectionLink

View File

@ -35,6 +35,13 @@ export default class BaseCustomSidebarSection {
*/ */
get links() {} get links() {}
/**
* @returns {Boolean} Whether or not to show the entire section including heading.
*/
get displaySection() {
return true;
}
_notImplemented() { _notImplemented() {
throw "not implemented"; throw "not implemented";
} }

View File

@ -564,4 +564,49 @@ acceptance("Sidebar - Plugin API", function (needs) {
"does not display my favourite topic custom section link when current route does not match the link's route" "does not display my favourite topic custom section link when current route does not match the link's route"
); );
}); });
test("Section that is not displayed via displaySection", async function (assert) {
withPluginApi("1.3.0", (api) => {
api.addSidebarSection((BaseCustomSidebarSection) => {
return class extends BaseCustomSidebarSection {
get name() {
return "test-chat-channels";
}
get text() {
return "chat channels text";
}
get actionsIcon() {
return "cog";
}
get actions() {
return [
{
id: "browseChannels",
title: "Browse channels",
action: () => {},
},
];
}
get links() {
return [];
}
get displaySection() {
return false;
}
};
});
});
await visit("/");
assert.notOk(
exists(".sidebar-section-test-chat-channels"),
"does not display the section"
);
});
}); });

View File

@ -0,0 +1,73 @@
import { module, test } from "qunit";
import { hbs } from "ember-cli-htmlbars";
import { click, render } from "@ember/test-helpers";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { exists } from "discourse/tests/helpers/qunit-helpers";
module("Integration | Component | sidebar | section", function (hooks) {
setupRenderingTest(hooks);
test("default displaySection value for section", async function (assert) {
const template = hbs`
<Sidebar::Section
@sectionName="test"
@headerLinkText="test header"
@headerLinkTitle="some title"
@headerActionsIcon="plus"
@headerActions={{this.headerActions}} />`;
this.headerActions = [];
await render(template);
assert.ok(
exists(".sidebar-section-wrapper"),
"section is displayed by default if no display arg is provided"
);
});
test("displaySection is dynamic based on argument", async function (assert) {
const template = hbs`
<Sidebar::Section
@sectionName="test"
@headerLinkText="test header"
@headerLinkTitle="some title"
@headerActionsIcon="plus"
@headerActions={{this.headerActions}}
@displaySection={{this.displaySection}}/>`;
this.displaySection = false;
this.headerActions = [];
await render(template);
assert.notOk(
exists(".sidebar-section-wrapper"),
"section is not displayed"
);
this.set("displaySection", true);
assert.ok(exists(".sidebar-section-wrapper"), "section is displayed");
});
test("can expand and collapse content when section is collapsible", async function (assert) {
const template = hbs`
<Sidebar::Section
@sectionName="test"
@headerLinkText="test header"
@headerLinkTitle="some title"
@headerActionsIcon="plus"
@headerActions={{this.headerActions}}
@collapsable=true />`;
this.headerActions = [];
await render(template);
assert.ok(exists(".sidebar-section-content"), "shows content by default");
await click(".sidebar-section-header-caret");
assert.notOk(
exists(".sidebar-section-content"),
"does not show content after collapsing"
);
});
});