mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Automatically generate all admin links for app for new sidebar (#24175)
NOTE: Most of this is experimental and will be removed at a later time, which is why things like translations have not been added. The new /admin-revamp UI uses a sidebar for admin nav. This initial step adds a script to generate a map of all the current admin nav into a format the sidebar to read. Then, people can experiment with different changes to this structure. The structure can then be edited from `/admin-revamp/config/sidebar-experiment`, and it is saved to local storage so people can visually experiment with different ways of showing the admin sidebar links.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
<div
|
||||
class="admin-config-area-sidebar-experiment"
|
||||
{{did-insert this.loadDefaultNavConfig}}
|
||||
>
|
||||
<h4>Sidebar Experiment</h4>
|
||||
<p>Changes you make here will be applied to the admin sidebar and persist
|
||||
between reloads
|
||||
<em>on this device only</em>. Note that in addition to the
|
||||
<code>text</code>
|
||||
and
|
||||
<code>route</code>
|
||||
options, you can also specify a
|
||||
<code>icon</code>
|
||||
or a
|
||||
<code>href</code>, if you want to link to a specific page but don't know the
|
||||
Ember route.</p>
|
||||
|
||||
<DButton
|
||||
@action={{this.resetToDefault}}
|
||||
@translatedLabel="Reset to Default"
|
||||
/>
|
||||
<DButton
|
||||
class="btn-primary"
|
||||
@action={{this.applyConfig}}
|
||||
@translatedLabel="Apply Config"
|
||||
/>
|
||||
|
||||
<div class="admin-config-area-sidebar-experiment__editor">
|
||||
<AceEditor
|
||||
@content={{this.editedNavConfig}}
|
||||
@editorId="admin-config-area-sidebar-experiment"
|
||||
@save={{this.applyNav}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,66 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { action } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import {
|
||||
buildAdminSidebar,
|
||||
useAdminNavConfig,
|
||||
} from "discourse/instance-initializers/admin-sidebar";
|
||||
import { ADMIN_NAV_MAP } from "discourse/lib/sidebar/admin-nav-map";
|
||||
import { resetPanelSections } from "discourse/lib/sidebar/custom-sections";
|
||||
import { ADMIN_PANEL } from "discourse/services/sidebar-state";
|
||||
|
||||
export default class AdminConfigAreaSidebarExperiment extends Component {
|
||||
@service adminSidebarExperimentStateManager;
|
||||
@service toasts;
|
||||
@tracked editedNavConfig;
|
||||
|
||||
get defaultAdminNav() {
|
||||
return JSON.stringify(ADMIN_NAV_MAP, null, 2);
|
||||
}
|
||||
|
||||
@action
|
||||
loadDefaultNavConfig() {
|
||||
const savedConfig = this.adminSidebarExperimentStateManager.navConfig;
|
||||
this.editedNavConfig = savedConfig
|
||||
? JSON.stringify(savedConfig, null, 2)
|
||||
: this.defaultAdminNav;
|
||||
}
|
||||
|
||||
@action
|
||||
resetToDefault() {
|
||||
this.editedNavConfig = this.defaultAdminNav;
|
||||
this.#saveConfig(ADMIN_NAV_MAP);
|
||||
}
|
||||
|
||||
@action
|
||||
applyConfig() {
|
||||
let config = null;
|
||||
try {
|
||||
config = JSON.parse(this.editedNavConfig);
|
||||
} catch {
|
||||
this.toasts.error({
|
||||
duration: 3000,
|
||||
data: {
|
||||
message: "There was an error, make sure the structure is valid JSON.",
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.#saveConfig(config);
|
||||
}
|
||||
|
||||
#saveConfig(config) {
|
||||
this.adminSidebarExperimentStateManager.navConfig = config;
|
||||
resetPanelSections(
|
||||
ADMIN_PANEL,
|
||||
useAdminNavConfig(config),
|
||||
buildAdminSidebar
|
||||
);
|
||||
this.toasts.success({
|
||||
duration: 3000,
|
||||
data: { message: "Sidebar navigation applied successfully!" },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,19 @@
|
||||
import Route from "@ember/routing/route";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { dasherize } from "@ember/string";
|
||||
import AdminConfigAreaSidebarExperiment from "admin/components/admin-config-area-sidebar-experiment";
|
||||
|
||||
const CONFIG_AREA_COMPONENT_MAP = {
|
||||
"sidebar-experiment": AdminConfigAreaSidebarExperiment,
|
||||
};
|
||||
|
||||
export default class AdminRevampConfigAreaRoute extends Route {
|
||||
@service router;
|
||||
|
||||
async model(params) {
|
||||
return { area: params.area };
|
||||
return {
|
||||
area: params.area,
|
||||
configAreaComponent: CONFIG_AREA_COMPONENT_MAP[dasherize(params.area)],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,10 @@ export default class AdminRoute extends DiscourseRoute {
|
||||
});
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
deactivate(transition) {
|
||||
this.controllerFor("application").set("showTop", true);
|
||||
this.sidebarState.setPanel(MAIN_PANEL);
|
||||
if (!transition?.to.name.startsWith("admin")) {
|
||||
this.sidebarState.setPanel(MAIN_PANEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { inject as service } from "@ember/service";
|
||||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import { MAIN_PANEL } from "discourse/services/sidebar-state";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default class AdminRoute extends DiscourseRoute {
|
||||
@service sidebarState;
|
||||
|
||||
titleToken() {
|
||||
return I18n.t("admin_title");
|
||||
}
|
||||
@@ -14,5 +18,6 @@ export default class AdminRoute extends DiscourseRoute {
|
||||
|
||||
deactivate() {
|
||||
this.controllerFor("application").set("showTop", true);
|
||||
this.sidebarState.setPanel(MAIN_PANEL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import Service from "@ember/service";
|
||||
import KeyValueStore from "discourse/lib/key-value-store";
|
||||
|
||||
export default class AdminSidebarExperimentStateManager extends Service {
|
||||
STORE_NAMESPACE = "discourse_admin_sidebar_experiment_";
|
||||
|
||||
store = new KeyValueStore(this.STORE_NAMESPACE);
|
||||
|
||||
get navConfig() {
|
||||
return this.store.getObject("navConfig");
|
||||
}
|
||||
|
||||
set navConfig(value) {
|
||||
this.store.setObject({ key: "navConfig", value });
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
<div class="admin-revamp__config-area">
|
||||
Config Area ({{@model.area}})
|
||||
{{#if @model.configAreaComponent}}
|
||||
<@model.configAreaComponent />
|
||||
{{/if}}
|
||||
</div>
|
||||
@@ -1,5 +1,3 @@
|
||||
<div class="admin-revamp__config">
|
||||
Config
|
||||
|
||||
{{outlet}}
|
||||
</div>
|
||||
Reference in New Issue
Block a user