FIX: Show admin plugin route sub-links in sidebar (#24982)

This changes the Plugins link in the admin sidebar to
be a section instead, which then shows all enabled plugin
admin routes (which are custom routes some plugins e.g.
chat define).

This is done via adding some special preloaded data for
all controllers based on AdminController, and also specifically
on Admin::PluginsController, to have the routes loaded without
additional requests on page load.

We just use a cog for all the route icons for now...we don't
have anything better.
This commit is contained in:
Martin Brennan 2023-12-21 11:37:20 +10:00 committed by GitHub
parent 8fce890ead
commit 7fcef5f2f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 87 additions and 18 deletions

View File

@ -1,3 +1,4 @@
import PreloadStore from "discourse/lib/preload-store";
import { ADMIN_NAV_MAP } from "discourse/lib/sidebar/admin-nav-map";
import {
addSidebarPanel,
@ -137,13 +138,6 @@ export function useAdminNavConfig(navMap) {
label: "admin.dashboard.reports_tab",
icon: "chart-pie",
},
{
name: "admin_plugins",
route: "adminPlugins",
label: "admin.plugins.title",
icon: "puzzle-piece",
},
{
name: "admin_badges",
route: "adminBadges",
@ -206,6 +200,17 @@ 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",
});
});
if (this.siteSettings.experimental_form_templates) {
navMap.findBy("name", "customize").links.push({
name: "admin_customize_form_templates",
@ -215,8 +220,6 @@ export default {
});
}
const navConfig = useAdminNavConfig(navMap);
buildAdminSidebar(navConfig, adminSectionLinkClass);
buildAdminSidebar(useAdminNavConfig(navMap), adminSectionLinkClass);
},
};

View File

@ -1,4 +1,17 @@
export const ADMIN_NAV_MAP = [
{
name: "admin_plugins",
route: "adminPlugins.index",
label: "admin.plugins.title",
links: [
{
name: "admin_installed_plugins",
route: "adminPlugins",
label: "admin.plugins.installed",
icon: "puzzle-piece",
},
],
},
{
name: "email",
text: "Email",

View File

@ -7,4 +7,13 @@ class Admin::AdminController < ApplicationController
def index
render body: nil
end
private
def preload_additional_json
store_preloaded(
"enabledPluginAdminRoutes",
MultiJson.dump(Discourse.plugins_sorted_by_name.filter_map(&:admin_route)),
)
end
end

View File

@ -3,9 +3,18 @@
class Admin::PluginsController < Admin::StaffController
def index
render_serialized(
Discourse.visible_plugins.sort_by { |p| p.name.downcase.delete_prefix("discourse-") },
Discourse.plugins_sorted_by_name(enabled_only: false),
AdminPluginSerializer,
root: "plugins",
)
end
private
def preload_additional_json
store_preloaded(
"enabledPluginAdminRoutes",
MultiJson.dump(Discourse.plugins_sorted_by_name.filter_map(&:admin_route)),
)
end
end

View File

@ -446,6 +446,8 @@ class ApplicationController < ActionController::Base
current_user.sync_notification_channel_position
preload_current_user_data
end
preload_additional_json
end
def set_mobile_view
@ -671,6 +673,10 @@ class ApplicationController < ActionController::Base
store_preloaded("fontMap", MultiJson.dump(load_font_map)) if current_user.admin?
end
def preload_additional_json
# noop, should be defined by subcontrollers
end
def custom_html_json
target = view_context.mobile_view? ? :mobile : :desktop

View File

@ -377,6 +377,11 @@ module Discourse
plugins.filter(&:visible?)
end
def self.plugins_sorted_by_name(enabled_only: true)
return visible_plugins.filter(&:enabled?).sort_by(&:name_without_prefix) if enabled_only
visible_plugins.sort_by(&:name_without_prefix)
end
def self.plugin_themes
@plugin_themes ||= plugins.map(&:themes).flatten
end

View File

@ -122,7 +122,7 @@ class Plugin::Instance
@enabled_site_setting ? SiteSetting.get(@enabled_site_setting) : true
end
delegate :name, to: :metadata
delegate :name, :name_without_prefix, to: :metadata
def add_to_serializer(
serializer,

View File

@ -133,6 +133,10 @@ class Plugin::Metadata
end
end
def name_without_prefix
name.downcase.delete_prefix("discourse-")
end
def self.parse(text)
metadata = self.new
text.each_line { |line| break unless metadata.parse_line(line) }

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
describe "Admin Revamp | Sidebar Navigation | Plugin Links", type: :system do
fab!(:admin)
let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new }
before do
chat_system_bootstrap
SiteSetting.enable_admin_sidebar_navigation = true
sign_in(admin)
end
it "shows links to enabled plugin admin routes" do
visit("/admin")
expect(sidebar).to have_section_link("Chat", href: "/admin/plugins/chat")
end
end

View File

@ -20,11 +20,14 @@ describe "Admin Revamp | Sidebar Navigation", type: :system do
expect(sidebar).to have_no_section("admin-nav-section-root")
end
it "does not show the admin sidebar if the setting is disabled" do
SiteSetting.enable_admin_sidebar_navigation = false
visit("/latest")
sidebar.click_link_in_section("community", "admin")
expect(page).to have_current_path("/admin")
expect(sidebar).to have_no_section("admin-nav-section-root")
context "when the setting is disabled" do
before { SiteSetting.enable_admin_sidebar_navigation = false }
it "does not show the admin sidebar" do
visit("/latest")
sidebar.click_link_in_section("community", "admin")
expect(page).to have_current_path("/admin")
expect(sidebar).to have_no_section("admin-nav-section-root")
end
end
end