DEV: Add new experimental admin UI route and sidebar (#23952)

This commit adds a new admin UI under the route `/admin-revamp`, which is
only accessible if the user is in a group defined by the new `enable_experimental_admin_ui_groups` site setting. It
also adds a special `admin` sidebar panel that is shown instead of the `main`
forum one when the admin is in this area.

![image](https://github.com/discourse/discourse/assets/920448/fa0f25e1-e178-4d94-aa5f-472fd3efd787)

We also add an "Admin Revamp" sidebar link to the community section, which
will only appear if the user is in the setting group:

![image](https://github.com/discourse/discourse/assets/920448/ec05ca8b-5a54-442b-ba89-6af35695c104)

Within this there are subroutes defined like `/admin-revamp/config/:area`,
these areas could contain any UI imaginable, this is just laying down an
initial idea of the structure and how the sidebar will work. Sidebar links are
currently hardcoded.

Some other changes:

* Changed the `main` and `chat` panels sidebar panel keys to use exported const values for reuse
* Allowed custom sidebar sections to hide their headers with the `hideSectionHeader` option
* Add a `groupSettingArray` setting on `this.siteSettings` in JS, which accepts a group site setting name
  and splits it by `|` then converts the items in the array to integers, similar to the `_map` magic for ruby
  group site settings
* Adds a `hidden` option for sidebar panels which prevents them from showing in separated mode and prevents
  the switch button from being shown

---------

Co-authored-by: Krzysztof Kotlarek <kotlarek.krzysztof@gmail.com>
This commit is contained in:
Martin Brennan
2023-10-19 14:23:41 +10:00
committed by GitHub
parent 47b2667099
commit 9ef3a18ce4
34 changed files with 606 additions and 23 deletions

View File

@@ -0,0 +1,31 @@
import Controller from "@ember/controller";
import { inject as service } from "@ember/service";
import { dasherize } from "@ember/string";
import discourseComputed from "discourse-common/utils/decorators";
export default class AdminRevampController extends Controller {
@service router;
@discourseComputed("router._router.currentPath")
adminContentsClassName(currentPath) {
let cssClasses = currentPath
.split(".")
.filter((segment) => {
return (
segment !== "index" &&
segment !== "loading" &&
segment !== "show" &&
segment !== "admin"
);
})
.map(dasherize)
.join(" ");
// this is done to avoid breaking css customizations
if (cssClasses.includes("dashboard")) {
cssClasses = `${cssClasses} dashboard-next`;
}
return cssClasses;
}
}

View File

@@ -0,0 +1,10 @@
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
export default class AdminRevampConfigAreaRoute extends Route {
@service router;
async model(params) {
return { area: params.area };
}
}

View File

@@ -0,0 +1,6 @@
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
export default class AdminRevampConfigRoute extends Route {
@service router;
}

View File

@@ -0,0 +1,6 @@
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
export default class AdminRevampLobbyRoute extends Route {
@service router;
}

View File

@@ -0,0 +1,40 @@
import { inject as service } from "@ember/service";
import DiscourseURL from "discourse/lib/url";
import DiscourseRoute from "discourse/routes/discourse";
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/services/sidebar-state";
import I18n from "discourse-i18n";
export default class AdminRoute extends DiscourseRoute {
@service siteSettings;
@service currentUser;
@service sidebarState;
titleToken() {
return I18n.t("admin_title");
}
activate() {
if (
!this.currentUser.isInAnyGroups(
this.siteSettings.groupSettingArray(
"enable_experimental_admin_ui_groups"
)
)
) {
return DiscourseURL.redirectTo("/admin");
}
this.sidebarState.setPanel(ADMIN_PANEL);
this.sidebarState.setSeparatedMode();
this.sidebarState.hideSwitchPanelButtons();
this.controllerFor("application").setProperties({
showTop: false,
});
}
deactivate() {
this.controllerFor("application").set("showTop", true);
this.sidebarState.setPanel(MAIN_PANEL);
}
}

View File

@@ -211,4 +211,14 @@ export default function () {
}
);
});
// EXPERIMENTAL: These admin routes are hidden behind an `enable_experimental_admin_ui_groups`
// site setting and are subject to constant change.
this.route("admin-revamp", { resetNamespace: true }, function () {
this.route("lobby", { path: "/" }, function () {});
this.route("config", { path: "config" }, function () {
this.route("area", { path: "/:area" });
});
});
}

View File

@@ -0,0 +1,3 @@
<div class="admin-revamp__config-area">
Config Area ({{@model.area}})
</div>

View File

@@ -0,0 +1,5 @@
<div class="admin-revamp__config">
Config
{{outlet}}
</div>

View File

@@ -0,0 +1 @@
Admin Revamp Lobby

View File

@@ -0,0 +1,12 @@
{{hide-application-footer}}
<AdminWrapper @class="container">
<div class="row">
<div class="full-width">
<div class="boxed white admin-content">
<div class="admin-contents {{this.adminContentsClassName}}">
{{outlet}}
</div>
</div>
</div>
</div>
</AdminWrapper>