mirror of
https://github.com/discourse/discourse.git
synced 2025-06-05 08:54:43 +08:00
DEV: Move admin sidebar out of initializer (#25396)
Having the admin sidebar code in an instance initializer is not ideal because: * It runs during app boot which may not even be necessary based on site settings * It makes it hard for plugins to register additional links in time without resorting to before/after initializer gymnastics This PR moves the admin sidebar into a lib and creates the panel in custom-sections.js, then the sections and links are loaded when the main sidebar component is rendered, which leaves plugins enough time to add additional links in an initializer. --------- Co-authored-by: David Taylor <david@taylorhq.com>
This commit is contained in:
@ -2,13 +2,13 @@ import Component from "@glimmer/component";
|
|||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import { inject as service } from "@ember/service";
|
import { inject as service } from "@ember/service";
|
||||||
|
import { ADMIN_NAV_MAP } from "discourse/lib/sidebar/admin-nav-map";
|
||||||
import {
|
import {
|
||||||
buildAdminSidebar,
|
buildAdminSidebar,
|
||||||
useAdminNavConfig,
|
useAdminNavConfig,
|
||||||
} from "discourse/instance-initializers/admin-sidebar";
|
} from "discourse/lib/sidebar/admin-sidebar";
|
||||||
import { ADMIN_NAV_MAP } from "discourse/lib/sidebar/admin-nav-map";
|
|
||||||
import { resetPanelSections } from "discourse/lib/sidebar/custom-sections";
|
import { resetPanelSections } from "discourse/lib/sidebar/custom-sections";
|
||||||
import { ADMIN_PANEL } from "discourse/services/sidebar-state";
|
import { ADMIN_PANEL } from "discourse/lib/sidebar/panels";
|
||||||
|
|
||||||
// TODO (martin) (2024-02-01) Remove this experimental UI.
|
// TODO (martin) (2024-02-01) Remove this experimental UI.
|
||||||
export default class AdminConfigAreaSidebarExperiment extends Component {
|
export default class AdminConfigAreaSidebarExperiment extends Component {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { inject as service } from "@ember/service";
|
import { inject as service } from "@ember/service";
|
||||||
|
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/lib/sidebar/panels";
|
||||||
import DiscourseURL from "discourse/lib/url";
|
import DiscourseURL from "discourse/lib/url";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/services/sidebar-state";
|
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
export default class AdminRoute extends DiscourseRoute {
|
export default class AdminRoute extends DiscourseRoute {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { inject as service } from "@ember/service";
|
import { inject as service } from "@ember/service";
|
||||||
|
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/lib/sidebar/panels";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/services/sidebar-state";
|
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
export default class AdminRoute extends DiscourseRoute {
|
export default class AdminRoute extends DiscourseRoute {
|
||||||
|
@ -42,7 +42,6 @@ import {
|
|||||||
} from "discourse/helpers/category-link";
|
} from "discourse/helpers/category-link";
|
||||||
import { addUsernameSelectorDecorator } from "discourse/helpers/decorate-username-selector";
|
import { addUsernameSelectorDecorator } from "discourse/helpers/decorate-username-selector";
|
||||||
import { registerCustomAvatarHelper } from "discourse/helpers/user-avatar";
|
import { registerCustomAvatarHelper } from "discourse/helpers/user-avatar";
|
||||||
import { addAdminSidebarSectionLink } from "discourse/instance-initializers/admin-sidebar";
|
|
||||||
import { addBeforeAuthCompleteCallback } from "discourse/instance-initializers/auth-complete";
|
import { addBeforeAuthCompleteCallback } from "discourse/instance-initializers/auth-complete";
|
||||||
import { addPopupMenuOption } from "discourse/lib/composer/custom-popup-menu-options";
|
import { addPopupMenuOption } from "discourse/lib/composer/custom-popup-menu-options";
|
||||||
import { registerDesktopNotificationHandler } from "discourse/lib/desktop-notifications";
|
import { registerDesktopNotificationHandler } from "discourse/lib/desktop-notifications";
|
||||||
@ -67,6 +66,7 @@ import { addTagsHtmlCallback } from "discourse/lib/render-tags";
|
|||||||
import { addFeaturedLinkMetaDecorator } from "discourse/lib/render-topic-featured-link";
|
import { addFeaturedLinkMetaDecorator } from "discourse/lib/render-topic-featured-link";
|
||||||
import { addSearchResultsCallback } from "discourse/lib/search";
|
import { addSearchResultsCallback } from "discourse/lib/search";
|
||||||
import Sharing from "discourse/lib/sharing";
|
import Sharing from "discourse/lib/sharing";
|
||||||
|
import { addAdminSidebarSectionLink } from "discourse/lib/sidebar/admin-sidebar";
|
||||||
import { addSectionLink as addCustomCommunitySectionLink } from "discourse/lib/sidebar/custom-community-section-links";
|
import { addSectionLink as addCustomCommunitySectionLink } from "discourse/lib/sidebar/custom-community-section-links";
|
||||||
import {
|
import {
|
||||||
addSidebarPanel,
|
addSidebarPanel,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
import { isEmpty } from "@ember/utils";
|
||||||
import PreloadStore from "discourse/lib/preload-store";
|
import PreloadStore from "discourse/lib/preload-store";
|
||||||
import { ADMIN_NAV_MAP } from "discourse/lib/sidebar/admin-nav-map";
|
import { ADMIN_NAV_MAP } from "discourse/lib/sidebar/admin-nav-map";
|
||||||
import {
|
import BaseCustomSidebarPanel from "discourse/lib/sidebar/base-custom-sidebar-panel";
|
||||||
addSidebarPanel,
|
import BaseCustomSidebarSection from "discourse/lib/sidebar/base-custom-sidebar-section";
|
||||||
addSidebarSection,
|
import BaseCustomSidebarSectionLink from "discourse/lib/sidebar/base-custom-sidebar-section-link";
|
||||||
} from "discourse/lib/sidebar/custom-sections";
|
import { ADMIN_PANEL } from "discourse/lib/sidebar/panels";
|
||||||
import { ADMIN_PANEL } from "discourse/services/sidebar-state";
|
import { getOwnerWithFallback } from "discourse-common/lib/get-owner";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
let additionalAdminSidebarSectionLinks = {};
|
let additionalAdminSidebarSectionLinks = {};
|
||||||
@ -14,60 +15,52 @@ export function clearAdditionalAdminSidebarSectionLinks() {
|
|||||||
additionalAdminSidebarSectionLinks = {};
|
additionalAdminSidebarSectionLinks = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function defineAdminSectionLink(BaseCustomSidebarSectionLink) {
|
class SidebarAdminSectionLink extends BaseCustomSidebarSectionLink {
|
||||||
const SidebarAdminSectionLink = class extends BaseCustomSidebarSectionLink {
|
constructor({ adminSidebarNavLink }) {
|
||||||
constructor({ adminSidebarNavLink }) {
|
super(...arguments);
|
||||||
super(...arguments);
|
this.adminSidebarNavLink = adminSidebarNavLink;
|
||||||
this.adminSidebarNavLink = adminSidebarNavLink;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
return this.adminSidebarNavLink.name;
|
return this.adminSidebarNavLink.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
get classNames() {
|
get classNames() {
|
||||||
return "admin-sidebar-nav-link";
|
return "admin-sidebar-nav-link";
|
||||||
}
|
}
|
||||||
|
|
||||||
get route() {
|
get route() {
|
||||||
return this.adminSidebarNavLink.route;
|
return this.adminSidebarNavLink.route;
|
||||||
}
|
}
|
||||||
|
|
||||||
get href() {
|
get href() {
|
||||||
return this.adminSidebarNavLink.href;
|
return this.adminSidebarNavLink.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
get models() {
|
get models() {
|
||||||
return this.adminSidebarNavLink.routeModels;
|
return this.adminSidebarNavLink.routeModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
get text() {
|
get text() {
|
||||||
return this.adminSidebarNavLink.label
|
return this.adminSidebarNavLink.label
|
||||||
? I18n.t(this.adminSidebarNavLink.label)
|
? I18n.t(this.adminSidebarNavLink.label)
|
||||||
: this.adminSidebarNavLink.text;
|
: this.adminSidebarNavLink.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
get prefixType() {
|
get prefixType() {
|
||||||
return "icon";
|
return "icon";
|
||||||
}
|
}
|
||||||
|
|
||||||
get prefixValue() {
|
get prefixValue() {
|
||||||
return this.adminSidebarNavLink.icon;
|
return this.adminSidebarNavLink.icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
get title() {
|
get title() {
|
||||||
return this.adminSidebarNavLink.text;
|
return this.adminSidebarNavLink.text;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return SidebarAdminSectionLink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function defineAdminSection(
|
function defineAdminSection(adminNavSectionData) {
|
||||||
adminNavSectionData,
|
|
||||||
BaseCustomSidebarSection,
|
|
||||||
adminSectionLinkClass
|
|
||||||
) {
|
|
||||||
const AdminNavSection = class extends BaseCustomSidebarSection {
|
const AdminNavSection = class extends BaseCustomSidebarSection {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
@ -96,7 +89,7 @@ function defineAdminSection(
|
|||||||
get links() {
|
get links() {
|
||||||
return this.sectionLinks.map(
|
return this.sectionLinks.map(
|
||||||
(sectionLinkData) =>
|
(sectionLinkData) =>
|
||||||
new adminSectionLinkClass({ adminSidebarNavLink: sectionLinkData })
|
new SidebarAdminSectionLink({ adminSidebarNavLink: sectionLinkData })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,27 +156,6 @@ export function useAdminNavConfig(navMap) {
|
|||||||
return navMap;
|
return navMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
let adminSectionLinkClass = null;
|
|
||||||
export function buildAdminSidebar(navConfig) {
|
|
||||||
navConfig.forEach((adminNavSectionData) => {
|
|
||||||
addSidebarSection(
|
|
||||||
(BaseCustomSidebarSection, BaseCustomSidebarSectionLink) => {
|
|
||||||
// We only want to define the link class once even though we have many different sections.
|
|
||||||
adminSectionLinkClass =
|
|
||||||
adminSectionLinkClass ||
|
|
||||||
defineAdminSectionLink(BaseCustomSidebarSectionLink);
|
|
||||||
|
|
||||||
return defineAdminSection(
|
|
||||||
adminNavSectionData,
|
|
||||||
BaseCustomSidebarSection,
|
|
||||||
adminSectionLinkClass
|
|
||||||
);
|
|
||||||
},
|
|
||||||
ADMIN_PANEL
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is used for a plugin API.
|
// This is used for a plugin API.
|
||||||
export function addAdminSidebarSectionLink(sectionName, link) {
|
export function addAdminSidebarSectionLink(sectionName, link) {
|
||||||
if (!additionalAdminSidebarSectionLinks.hasOwnProperty(sectionName)) {
|
if (!additionalAdminSidebarSectionLinks.hasOwnProperty(sectionName)) {
|
||||||
@ -237,41 +209,26 @@ function pluginAdminRouteLinks() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default class AdminSidebarPanel extends BaseCustomSidebarPanel {
|
||||||
name: "admin-sidebar-initializer",
|
key = ADMIN_PANEL;
|
||||||
|
hidden = true;
|
||||||
|
|
||||||
initialize(owner) {
|
get sections() {
|
||||||
this.currentUser = owner.lookup("service:current-user");
|
const siteSettings = getOwnerWithFallback().lookup("service:site-settings");
|
||||||
this.siteSettings = owner.lookup("service:site-settings");
|
if (isEmpty(siteSettings.admin_sidebar_enabled_groups)) {
|
||||||
|
return [];
|
||||||
if (
|
|
||||||
!this.currentUser?.staff ||
|
|
||||||
!this.siteSettings.userInAnyGroups(
|
|
||||||
"admin_sidebar_enabled_groups",
|
|
||||||
this.currentUser
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.adminSidebarExperimentStateManager = owner.lookup(
|
this.adminSidebarExperimentStateManager = getOwnerWithFallback(this).lookup(
|
||||||
"service:admin-sidebar-experiment-state-manager"
|
"service:admin-sidebar-experiment-state-manager"
|
||||||
);
|
);
|
||||||
|
|
||||||
addSidebarPanel(
|
|
||||||
(BaseCustomSidebarPanel) =>
|
|
||||||
class AdminSidebarPanel extends BaseCustomSidebarPanel {
|
|
||||||
key = ADMIN_PANEL;
|
|
||||||
hidden = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const savedConfig = this.adminSidebarExperimentStateManager.navConfig;
|
const savedConfig = this.adminSidebarExperimentStateManager.navConfig;
|
||||||
const navMap = savedConfig || ADMIN_NAV_MAP;
|
const navMap = savedConfig || ADMIN_NAV_MAP;
|
||||||
|
|
||||||
navMap.findBy("name", "plugins").links.push(...pluginAdminRouteLinks());
|
navMap.findBy("name", "plugins").links.push(...pluginAdminRouteLinks());
|
||||||
|
|
||||||
if (this.siteSettings.experimental_form_templates) {
|
if (siteSettings.experimental_form_templates) {
|
||||||
navMap.findBy("name", "customize").links.push({
|
navMap.findBy("name", "customize").links.push({
|
||||||
name: "admin_customize_form_templates",
|
name: "admin_customize_form_templates",
|
||||||
route: "adminCustomizeFormTemplates",
|
route: "adminCustomizeFormTemplates",
|
||||||
@ -280,6 +237,10 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
buildAdminSidebar(useAdminNavConfig(navMap), adminSectionLinkClass);
|
const navConfig = useAdminNavConfig(navMap);
|
||||||
},
|
|
||||||
};
|
return navConfig.map((adminNavSectionData) => {
|
||||||
|
return defineAdminSection(adminNavSectionData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
import BaseCustomSidebarPanel from "discourse/lib/sidebar/base-custom-sidebar-panel";
|
import BaseCustomSidebarPanel from "discourse/lib/sidebar/base-custom-sidebar-panel";
|
||||||
import BaseCustomSidebarSection from "discourse/lib/sidebar/base-custom-sidebar-section";
|
import BaseCustomSidebarSection from "discourse/lib/sidebar/base-custom-sidebar-section";
|
||||||
import BaseCustomSidebarSectionLink from "discourse/lib/sidebar/base-custom-sidebar-section-link";
|
import BaseCustomSidebarSectionLink from "discourse/lib/sidebar/base-custom-sidebar-section-link";
|
||||||
|
import { MAIN_PANEL } from "discourse/lib/sidebar/panels";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
import AdminSidebarPanel from "./admin-sidebar";
|
||||||
|
|
||||||
class MainSidebarPanel {
|
class MainSidebarPanel {
|
||||||
sections = [];
|
sections = [];
|
||||||
@ -23,9 +25,9 @@ class MainSidebarPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export let customPanels = [new MainSidebarPanel()];
|
export let customPanels;
|
||||||
|
export let currentPanelKey;
|
||||||
export let currentPanelKey = "main";
|
resetSidebarPanels();
|
||||||
|
|
||||||
export function addSidebarPanel(func) {
|
export function addSidebarPanel(func) {
|
||||||
const panelClass = func.call(this, BaseCustomSidebarPanel);
|
const panelClass = func.call(this, BaseCustomSidebarPanel);
|
||||||
@ -60,6 +62,6 @@ export function resetPanelSections(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function resetSidebarPanels() {
|
export function resetSidebarPanels() {
|
||||||
customPanels = [new MainSidebarPanel()];
|
customPanels = [new MainSidebarPanel(), new AdminSidebarPanel()];
|
||||||
currentPanelKey = "main";
|
currentPanelKey = MAIN_PANEL;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
export const COMBINED_MODE = "combined";
|
||||||
|
export const SEPARATED_MODE = "separated";
|
||||||
|
export const MAIN_PANEL = "main";
|
||||||
|
export const ADMIN_PANEL = "admin";
|
@ -5,11 +5,11 @@ import {
|
|||||||
currentPanelKey,
|
currentPanelKey,
|
||||||
customPanels as panels,
|
customPanels as panels,
|
||||||
} from "discourse/lib/sidebar/custom-sections";
|
} from "discourse/lib/sidebar/custom-sections";
|
||||||
|
import {
|
||||||
const COMBINED_MODE = "combined";
|
COMBINED_MODE,
|
||||||
const SEPARATED_MODE = "separated";
|
MAIN_PANEL,
|
||||||
export const MAIN_PANEL = "main";
|
SEPARATED_MODE,
|
||||||
export const ADMIN_PANEL = "admin";
|
} from "discourse/lib/sidebar/panels";
|
||||||
|
|
||||||
@disableImplicitInjections
|
@disableImplicitInjections
|
||||||
export default class SidebarState extends Service {
|
export default class SidebarState extends Service {
|
||||||
|
@ -28,7 +28,6 @@ import { resetUserMenuProfileTabItems } from "discourse/components/user-menu/pro
|
|||||||
import { resetCustomPostMessageCallbacks } from "discourse/controllers/topic";
|
import { resetCustomPostMessageCallbacks } from "discourse/controllers/topic";
|
||||||
import { clearHTMLCache } from "discourse/helpers/custom-html";
|
import { clearHTMLCache } from "discourse/helpers/custom-html";
|
||||||
import { resetUsernameDecorators } from "discourse/helpers/decorate-username-selector";
|
import { resetUsernameDecorators } from "discourse/helpers/decorate-username-selector";
|
||||||
import { clearAdditionalAdminSidebarSectionLinks } from "discourse/instance-initializers/admin-sidebar";
|
|
||||||
import { resetBeforeAuthCompleteCallbacks } from "discourse/instance-initializers/auth-complete";
|
import { resetBeforeAuthCompleteCallbacks } from "discourse/instance-initializers/auth-complete";
|
||||||
import { clearPopupMenuOptions } from "discourse/lib/composer/custom-popup-menu-options";
|
import { clearPopupMenuOptions } from "discourse/lib/composer/custom-popup-menu-options";
|
||||||
import { clearDesktopNotificationHandlers } from "discourse/lib/desktop-notifications";
|
import { clearDesktopNotificationHandlers } from "discourse/lib/desktop-notifications";
|
||||||
@ -50,6 +49,7 @@ import PreloadStore from "discourse/lib/preload-store";
|
|||||||
import { clearTopicFooterButtons } from "discourse/lib/register-topic-footer-button";
|
import { clearTopicFooterButtons } from "discourse/lib/register-topic-footer-button";
|
||||||
import { clearTopicFooterDropdowns } from "discourse/lib/register-topic-footer-dropdown";
|
import { clearTopicFooterDropdowns } from "discourse/lib/register-topic-footer-dropdown";
|
||||||
import { clearTagsHtmlCallbacks } from "discourse/lib/render-tags";
|
import { clearTagsHtmlCallbacks } from "discourse/lib/render-tags";
|
||||||
|
import { clearAdditionalAdminSidebarSectionLinks } from "discourse/lib/sidebar/admin-sidebar";
|
||||||
import { resetDefaultSectionLinks as resetTopicsSectionLinks } from "discourse/lib/sidebar/custom-community-section-links";
|
import { resetDefaultSectionLinks as resetTopicsSectionLinks } from "discourse/lib/sidebar/custom-community-section-links";
|
||||||
import { resetSidebarPanels } from "discourse/lib/sidebar/custom-sections";
|
import { resetSidebarPanels } from "discourse/lib/sidebar/custom-sections";
|
||||||
import {
|
import {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/services/sidebar-state";
|
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/lib/sidebar/panels";
|
||||||
import { getUserChatSeparateSidebarMode } from "discourse/plugins/chat/discourse/lib/get-user-chat-separate-sidebar-mode";
|
import { getUserChatSeparateSidebarMode } from "discourse/plugins/chat/discourse/lib/get-user-chat-separate-sidebar-mode";
|
||||||
|
|
||||||
export const CHAT_PANEL = "chat";
|
export const CHAT_PANEL = "chat";
|
||||||
|
@ -2,9 +2,9 @@ import { tracked } from "@glimmer/tracking";
|
|||||||
import Service, { inject as service } from "@ember/service";
|
import Service, { inject as service } from "@ember/service";
|
||||||
import KeyValueStore from "discourse/lib/key-value-store";
|
import KeyValueStore from "discourse/lib/key-value-store";
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
|
import { MAIN_PANEL } from "discourse/lib/sidebar/panels";
|
||||||
import { defaultHomepage } from "discourse/lib/utilities";
|
import { defaultHomepage } from "discourse/lib/utilities";
|
||||||
import Site from "discourse/models/site";
|
import Site from "discourse/models/site";
|
||||||
import { MAIN_PANEL } from "discourse/services/sidebar-state";
|
|
||||||
import getURL from "discourse-common/lib/get-url";
|
import getURL from "discourse-common/lib/get-url";
|
||||||
import { getUserChatSeparateSidebarMode } from "discourse/plugins/chat/discourse/lib/get-user-chat-separate-sidebar-mode";
|
import { getUserChatSeparateSidebarMode } from "discourse/plugins/chat/discourse/lib/get-user-chat-separate-sidebar-mode";
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user