Skip to content

Commit

Permalink
FIX: Admin sidebar fixes and custom link registration (discourse#25200)
Browse files Browse the repository at this point in the history
This commit adds some more links to the admin sidebar and
removes some to give it more parity with the old nav structure.

This also adds the `addAdminSidebarSectionLink` plugin API to
replace the admin-menu plugin outlet, which is used by plugins
like docker-manager to add links to the old admin nav.
  • Loading branch information
martin-brennan authored Jan 12, 2024
1 parent 52511a3 commit de88fc2
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,16 @@ export default class AdminConfigAreaSidebarExperiment extends Component {
return;
}

// Using the private `_routerMicrolib` is not ideal, but Ember doesn't provide
// any other way for us to easily check for route validity.
try {
this.router._router._routerMicrolib.recognizer.handlersFor(
link.route
);
this.validRouteNames.add(link.route);
} catch {
} catch (err) {
// eslint-disable-next-line no-console
console.debug("[AdminSidebarExperiment]", err);
invalidRoutes.push(link.route);
}
});
Expand Down
1 change: 0 additions & 1 deletion app/assets/javascripts/admin/addon/templates/admin.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
{{/if}}
<NavItem @route="adminPlugins" @label="admin.plugins.title" />
{{/if}}
{{! TODO: What do we do with this?? How many plugins are using? }}
<PluginOutlet @name="admin-menu" />
</ul>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import {
import { ADMIN_PANEL } from "discourse/services/sidebar-state";
import I18n from "discourse-i18n";

let additionalAdminSidebarSectionLinks = {};

// For testing.
export function clearAdditionalAdminSidebarSectionLinks() {
additionalAdminSidebarSectionLinks = {};
}

function defineAdminSectionLink(BaseCustomSidebarSectionLink) {
const SidebarAdminSectionLink = class extends BaseCustomSidebarSectionLink {
constructor({ adminSidebarNavLink }) {
Expand Down Expand Up @@ -132,12 +139,6 @@ export function useAdminNavConfig(navMap) {
label: "admin.users.title",
icon: "users",
},
{
name: "admin_reports",
route: "adminReports",
label: "admin.dashboard.reports_tab",
icon: "chart-pie",
},
{
name: "admin_badges",
route: "adminBadges",
Expand All @@ -148,7 +149,18 @@ export function useAdminNavConfig(navMap) {
},
];

return adminNavSections.concat(navMap);
navMap = adminNavSections.concat(navMap);

for (const [sectionName, additionalLinks] of Object.entries(
additionalAdminSidebarSectionLinks
)) {
const section = navMap.findBy("name", sectionName);
if (section && additionalLinks.length) {
section.links.push(...additionalLinks);
}
}

return navMap;
}

let adminSectionLinkClass = null;
Expand All @@ -172,16 +184,68 @@ export function buildAdminSidebar(navConfig) {
});
}

// This is used for a plugin API.
export function addAdminSidebarSectionLink(sectionName, link) {
if (!additionalAdminSidebarSectionLinks.hasOwnProperty(sectionName)) {
additionalAdminSidebarSectionLinks[sectionName] = [];
}

// make the name extra-unique
link.name = `admin_additional_${sectionName}_${link.name}`;

if (!link.href && !link.route) {
// eslint-disable-next-line no-console
console.debug(
"[AdminSidebar]",
`Custom link ${sectionName}_${link.name} must have either href or route`
);
return;
}

if (!link.label && !link.text) {
// eslint-disable-next-line no-console
console.debug(
"[AdminSidebar]",
`Custom link ${sectionName}_${link.name} must have either label (which is an I18n key) or text`
);
return;
}

// label must be valid, don't want broken [XYZ translation missing]
if (link.label && typeof I18n.lookup(link.label) !== "string") {
// eslint-disable-next-line no-console
console.debug(
"[AdminSidebar]",
`Custom link ${sectionName}_${link.name} must have a valid I18n label, got ${link.label}`
);
return;
}

additionalAdminSidebarSectionLinks[sectionName].push(link);
}

function pluginAdminRouteLinks() {
return (PreloadStore.get("enabledPluginAdminRoutes") || []).map(
(pluginAdminRoute) => {
return {
name: `admin_plugin_${pluginAdminRoute.location}`,
route: `adminPlugins.${pluginAdminRoute.location}`,
label: pluginAdminRoute.label,
icon: "cog",
};
}
);
}

export default {
name: "admin-sidebar-initializer",

initialize(owner) {
this.currentUser = owner.lookup("service:current-user");
this.siteSettings = owner.lookup("service:site-settings");

if (!this.currentUser?.staff) {
return;
}

if (
!this.currentUser?.staff ||
!this.siteSettings.userInAnyGroups(
"admin_sidebar_enabled_groups",
this.currentUser
Expand All @@ -205,16 +269,7 @@ export default {
const savedConfig = this.adminSidebarExperimentStateManager.navConfig;
const navMap = savedConfig || ADMIN_NAV_MAP;

const enabledPluginAdminRoutes =
PreloadStore.get("enabledPluginAdminRoutes") || [];
enabledPluginAdminRoutes.forEach((pluginAdminRoute) => {
navMap.findBy("name", "admin_plugins").links.push({
name: `admin_plugin_${pluginAdminRoute.location}`,
route: `adminPlugins.${pluginAdminRoute.location}`,
label: pluginAdminRoute.label,
icon: "cog",
});
});
navMap.findBy("name", "plugins").links.push(...pluginAdminRouteLinks());

if (this.siteSettings.experimental_form_templates) {
navMap.findBy("name", "customize").links.push({
Expand Down
32 changes: 31 additions & 1 deletion app/assets/javascripts/discourse/app/lib/plugin-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
} from "discourse/helpers/category-link";
import { addUsernameSelectorDecorator } from "discourse/helpers/decorate-username-selector";
import { registerCustomAvatarHelper } from "discourse/helpers/user-avatar";
import { addAdminSidebarSectionLink } from "discourse/instance-initializers/admin-sidebar";
import { addBeforeAuthCompleteCallback } from "discourse/instance-initializers/auth-complete";
import { addPopupMenuOption } from "discourse/lib/composer/custom-popup-menu-options";
import { registerDesktopNotificationHandler } from "discourse/lib/desktop-notifications";
Expand Down Expand Up @@ -145,7 +146,7 @@ import { modifySelectKit } from "select-kit/mixins/plugin-api";
// docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version
// using the format described at https://keepachangelog.com/en/1.0.0/.

export const PLUGIN_API_VERSION = "1.23.0";
export const PLUGIN_API_VERSION = "1.24.0";

// This helper prevents us from applying the same `modifyClass` over and over in test mode.
function canModify(klass, type, resolverName, changes) {
Expand Down Expand Up @@ -2298,6 +2299,35 @@ class PluginApi {
addSidebarPanel(func);
}

/**
* EXPERIMENTAL. Do not use.
* Support for adding links to specific admin sidebar sections.
*
* This is intended to replace the admin-menu plugin outlet from
* the old admin horizontal nav.
*
* ```
* api.addAdminSidebarSectionLink("root", {
* name: "unique_link_name",
* label: "admin.some.i18n.label.key",
* route: "(optional) emberRouteId",
* href: "(optional) can be used instead of the route",
* }
* ```
* @param {String} sectionName - The name of the admin sidebar section to add the link to.
* @param {Object} link - A link object representing a section link for the sidebar.
* @param {string} link.name - The name of the link. Needs to be dasherized and lowercase.
* @param {string} link.title - The title attribute for the link.
* @param {string} link.text - The text to display for the link.
* @param {string} [link.route] - The Ember route name to generate the href attribute for the link.
* @param {string} [link.href] - The href attribute for the link.
* @param {string} [link.icon] - The FontAwesome icon to display for the link.
*/
addAdminSidebarSectionLink(sectionName, link) {
addAdminSidebarSectionLink(sectionName, link);
}

/**
* EXPERIMENTAL. Do not use.
* Support for setting a Sidebar panel.
Expand Down
24 changes: 22 additions & 2 deletions app/assets/javascripts/discourse/app/lib/sidebar/admin-nav-map.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import getURL from "discourse-common/lib/get-url";

export const ADMIN_NAV_MAP = [
{
name: "admin_plugins",
name: "plugins",
route: "adminPlugins.index",
label: "admin.plugins.title",
links: [
Expand All @@ -14,7 +16,7 @@ export const ADMIN_NAV_MAP = [
},
{
name: "email",
text: "Email",
text: "Emails",
links: [
{
name: "admin_email",
Expand Down Expand Up @@ -52,6 +54,18 @@ export const ADMIN_NAV_MAP = [
label: "admin.email.rejected",
icon: "ban",
},
{
name: "admin_email_preview_summary",
route: "adminEmail.previewDigest",
label: "admin.email.preview_digest",
icon: "notification.private_message",
},
{
name: "admin_email_advanced_test",
route: "adminEmail.advancedTest",
label: "admin.email.advanced_test.title",
icon: "wrench",
},
],
},
{
Expand Down Expand Up @@ -88,6 +102,12 @@ export const ADMIN_NAV_MAP = [
label: "admin.logs.search_logs.title",
icon: "search",
},
{
name: "admin_logs_error_logs",
href: getURL("/logs"),
label: "admin.logs.logster.title",
icon: "external-link-alt",
},
],
},
{
Expand Down
Loading

0 comments on commit de88fc2

Please sign in to comment.