diff --git a/app/assets/javascripts/discourse/app/components/sidebar/community-section.js b/app/assets/javascripts/discourse/app/components/sidebar/community-section.js index ff6b9626b8e..e704cfe18da 100644 --- a/app/assets/javascripts/discourse/app/components/sidebar/community-section.js +++ b/app/assets/javascripts/discourse/app/components/sidebar/community-section.js @@ -2,7 +2,10 @@ import GlimmerComponent from "discourse/components/glimmer"; import Composer from "discourse/models/composer"; import { getOwner } from "discourse-common/lib/get-owner"; import PermissionType from "discourse/models/permission-type"; -import { customSectionLinks } from "discourse/lib/sidebar/custom-community-section-links"; +import { + customSectionLinks, + secondaryCustomSectionLinks, +} from "discourse/lib/sidebar/custom-community-section-links"; import EverythingSectionLink from "discourse/lib/sidebar/community-section/everything-section-link"; import TrackedSectionLink from "discourse/lib/sidebar/community-section/tracked-section-link"; import MyPostsSectionLink from "discourse/lib/sidebar/community-section/my-posts-section-link"; @@ -36,11 +39,12 @@ export default class SidebarCommunitySection extends GlimmerComponent { } ); - moreSecondarySectionLinks = MORE_SECONDARY_SECTION_LINKS.map( - (sectionLinkClass) => { - return this.#initializeSectionLink(sectionLinkClass); - } - ); + moreSecondarySectionLinks = [ + ...MORE_SECONDARY_SECTION_LINKS, + ...secondaryCustomSectionLinks, + ].map((sectionLinkClass) => { + return this.#initializeSectionLink(sectionLinkClass); + }); #mainSectionLinks = this.currentUser.staff ? [...MAIN_SECTION_LINKS, ...ADMIN_MAIN_SECTION_LINKS] diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index 9c4bd3ccf38..84eb5dbe7fd 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -95,7 +95,7 @@ import { import { CUSTOM_USER_SEARCH_OPTIONS } from "select-kit/components/user-chooser"; import { downloadCalendar } from "discourse/lib/download-calendar"; import { consolePrefix } from "discourse/lib/source-identifier"; -import { addSectionLink } from "discourse/lib/sidebar/custom-community-section-links"; +import { addSectionLink as addCustomCommunitySectionLink } from "discourse/lib/sidebar/custom-community-section-links"; import { addSidebarSection } from "discourse/lib/sidebar/custom-sections"; import DiscourseURL from "discourse/lib/url"; @@ -480,7 +480,15 @@ class PluginApi { * **/ decorateWidget(name, fn) { - if (name === "hamburger-menu:generalLinks") { + this._deprecateDecoratingHamburgerWidgetLinks(name, fn); + decorateWidget(name, fn); + } + + _deprecateDecoratingHamburgerWidgetLinks(name, fn) { + if ( + name === "hamburger-menu:generalLinks" || + name === "hamburger-menu:footerLinks" + ) { const siteSettings = this.container.lookup("site-settings:main"); if (siteSettings.enable_experimental_sidebar_hamburger) { @@ -505,7 +513,7 @@ class PluginApi { args.route = route; } - this.addCommunitySectionLink(args); + this.addCommunitySectionLink(args, name.match(/footerLinks/)); } catch { deprecated( `Usage of \`api.decorateWidget('hamburger-menu:generalLinks')\` is incompatible with the \`enable_experimental_sidebar_hamburger\` site setting. Please use \`api.addCommunitySectionLink\` instead.` @@ -515,8 +523,6 @@ class PluginApi { return; } } - - decorateWidget(name, fn); } /** @@ -1665,9 +1671,9 @@ class PluginApi { /** * EXPERIMENTAL. Do not use. - * Support for adding a navigation link to Sidebar Community section by returning a class which extends from the BaseSectionLink - * class interface. See `lib/sidebar/community-section/base-section-link.js` for documentation on the BaseSectionLink class - * interface. + * Support for adding a navigation link to Sidebar Community section under the "More..." links drawer by returning a + * class which extends from the BaseSectionLink class interface. See `lib/sidebar/community-section/base-section-link.js` + * for documentation on the BaseSectionLink class interface. * * ``` * api.addCommunitySectionLink((baseSectionLink) => { @@ -1716,9 +1722,10 @@ class PluginApi { * @param {string=} arg.href - The href attribute for the link. * @param {string} arg.title - The title attribute for the link. * @param {string} arg.text - The text to display for the link. + * @param {Boolean} [secondary] - Determines whether the section link should be added to the main or secondary section in the "More..." links drawer. */ - addCommunitySectionLink(arg) { - addSectionLink(arg); + addCommunitySectionLink(arg, secondary) { + addCustomCommunitySectionLink(arg, secondary); } /** diff --git a/app/assets/javascripts/discourse/app/lib/sidebar/custom-community-section-links.js b/app/assets/javascripts/discourse/app/lib/sidebar/custom-community-section-links.js index fe09ec2fa6a..301945fb0f5 100644 --- a/app/assets/javascripts/discourse/app/lib/sidebar/custom-community-section-links.js +++ b/app/assets/javascripts/discourse/app/lib/sidebar/custom-community-section-links.js @@ -1,6 +1,8 @@ import BaseSectionLink from "discourse/lib/sidebar/community-section/base-section-link"; export let customSectionLinks = []; +export let secondaryCustomSectionLinks = []; + class RouteInfoHelper { constructor(router, url) { this.routeInfo = router.recognize(url); @@ -39,21 +41,25 @@ class RouteInfoHelper { } /** - * Appends an additional section link under the topics section + * Appends an additional section link to the Community section under the "More..." links drawer. + * * @callback addSectionLinkCallback * @param {BaseSectionLink} baseSectionLink Factory class to inherit from. * @returns {BaseSectionLink} A class that extends BaseSectionLink. * * @param {(addSectionLinkCallback|Object)} args - A callback function or an Object. - * @param {string} arg.name - The name of the link. Needs to be dasherized and lowercase. - * @param {string=} arg.route - The Ember route name to generate the href attribute for the link. - * @param {string=} arg.href - The href attribute for the link. - * @param {string=} arg.title - The title attribute for the link. - * @param {string} arg.text - The text to display for the link. + * @param {string} args.name - The name of the link. Needs to be dasherized and lowercase. + * @param {string=} args.route - The Ember route name to generate the href attribute for the link. + * @param {string=} args.href - The href attribute for the link. + * @param {string=} args.title - The title attribute for the link. + * @param {string} args.text - The text to display for the link. + * @param {Boolean} [secondary] - Determines whether the section link should be added to the main or secondary section in the "More..." links drawer. */ -export function addSectionLink(args) { +export function addSectionLink(args, secondary) { + const links = secondary ? secondaryCustomSectionLinks : customSectionLinks; + if (typeof args === "function") { - customSectionLinks.push(args.call(this, BaseSectionLink)); + links.push(args.call(this, BaseSectionLink)); } else { const klass = class extends BaseSectionLink { constructor() { @@ -97,10 +103,11 @@ export function addSectionLink(args) { } }; - customSectionLinks.push(klass); + links.push(klass); } } export function resetDefaultSectionLinks() { customSectionLinks = []; + secondaryCustomSectionLinks = []; } diff --git a/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js b/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js index 67fd132e2a6..6b094042a73 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js @@ -421,7 +421,45 @@ acceptance("Sidebar - Plugin API", function (needs) { ); }); - test("API bridge for decorating hamburger-menu widget with generalLinks", async function (assert) { + test("API bridge for decorating hamburger-menu widget with footer links", async function (assert) { + withPluginApi("1.3.0", (api) => { + api.decorateWidget("hamburger-menu:footerLinks", () => { + return { + route: "discovery.top", + rawLabel: "my top", + className: "my-custom-top", + }; + }); + }); + + await visit("/"); + + await click( + ".sidebar-section-community .sidebar-more-section-links-details-summary" + ); + + const myCustomTopSectionLink = query( + ".sidebar-section-community .sidebar-more-section-links-details-content-secondary .sidebar-section-link-my-custom-top" + ); + + assert.ok( + myCustomTopSectionLink, + "adds my custom top section link to community section under the secondary section in the More... links drawer" + ); + + assert.ok( + myCustomTopSectionLink.href.endsWith("/top"), + "sets the right href attribute for the my custom top section link" + ); + + assert.strictEqual( + myCustomTopSectionLink.textContent.trim(), + "my top", + "displays the right text for my custom top section link" + ); + }); + + test("API bridge for decorating hamburger-menu widget with general links", async function (assert) { withPluginApi("1.3.0", (api) => { api.decorateWidget("hamburger-menu:generalLinks", () => { return {