From 9fb09d147df160cc88385893d7e61dcb85209e4f Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Fri, 1 Nov 2019 13:52:25 +1100 Subject: [PATCH] DEV: allow positioning of nav items and allow selection Previously we could not place extra nav items in a particular order. This change introduces a new `before` attribute to addNavigationBarItem with this attribute we can place a nav item before "top" or any other place. Additionally this allows navigation items to force active state. In some cases we may want an items that is simply a "filter" on latest using `?query_params` when we do that we can "force" the filter active. A concrete example is the assign plugin that adds a nav item for Unassigned => `/c/cat-slug/l/latest?assigned=nobody&status=open` If we did not force then latest would be selected even though the filter is clicked. --- .../components/navigation-item.js.es6 | 7 ++-- .../discourse/lib/plugin-api.js.es6 | 14 ++++++-- .../discourse/models/nav-item.js.es6 | 32 ++++++++++++++++++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/discourse/components/navigation-item.js.es6 b/app/assets/javascripts/discourse/components/navigation-item.js.es6 index a3403573fdf..6d55112a94c 100644 --- a/app/assets/javascripts/discourse/components/navigation-item.js.es6 +++ b/app/assets/javascripts/discourse/components/navigation-item.js.es6 @@ -15,8 +15,11 @@ export default Component.extend( hidden: false, rerenderTriggers: ["content.count"], - @computed("content.filterMode", "filterMode") - active(contentFilterMode, filterMode) { + @computed("content.filterMode", "filterMode", "content.active") + active(contentFilterMode, filterMode, active) { + if (active !== undefined) { + return active; + } return ( contentFilterMode === filterMode || filterMode.indexOf(contentFilterMode) === 0 diff --git a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 index 246470af8cf..26e6d16ef27 100644 --- a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 +++ b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 @@ -46,7 +46,7 @@ import { queryRegistry } from "discourse/widgets/widget"; import Composer from "discourse/models/composer"; // If you add any methods to the API ensure you bump up this number -const PLUGIN_API_VERSION = "0.8.34"; +const PLUGIN_API_VERSION = "0.8.35"; class PluginApi { constructor(version, container) { @@ -736,7 +736,9 @@ class PluginApi { * displayName: "bugs" * href: "/c/bugs", * customFilter: (category, args, router) => { category && category.name !== 'bug' } - * customHref: (category, args, router) => { if (category && category.name) === 'not-a-bug') "/a-feature"; } + * customHref: (category, args, router) => { if (category && category.name) === 'not-a-bug') "/a-feature"; }, + * before: "top", + * forceActive(category, args, router) => router.currentURL === "/a/b/c/d"; * }) */ addNavigationBarItem(item) { @@ -763,6 +765,14 @@ class PluginApi { }; } + const forceActive = item.forceActive; + if (forceActive) { + const router = this.container.lookup("service:router"); + item.forceActive = function(category, args) { + return forceActive(category, args, router); + }; + } + addNavItem(item); } } diff --git a/app/assets/javascripts/discourse/models/nav-item.js.es6 b/app/assets/javascripts/discourse/models/nav-item.js.es6 index 85379d4bfcc..f03a5fc131b 100644 --- a/app/assets/javascripts/discourse/models/nav-item.js.es6 +++ b/app/assets/javascripts/discourse/models/nav-item.js.es6 @@ -193,12 +193,42 @@ NavItem.reopenClass({ return item.customFilter.call(this, category, args); }); + let forceActive = false; + extraItems.forEach(item => { + const before = item.before; + if (before) { + let i = 0; + for (i = 0; i < items.length; i++) { + if (items[i].name === before) { + break; + } + } + items.splice(i, 0, item); + } else { + items.push(item); + } + if (!item.customHref) return; + item.set("href", item.customHref.call(this, category, args)); + + if (item.forceActive && item.forceActive.call(this, category, args)) { + item.active = true; + forceActive = true; + } else { + item.active = undefined; + } }); - return items.concat(extraItems); + if (forceActive) { + items.forEach(i => { + if (i.active === undefined) { + i.active = false; + } + }); + } + return items; } });