From bb52765f5141f367c923655a673a4fb02dbcbda2 Mon Sep 17 00:00:00 2001
From: Ken Sternberg
<133134217+kensternberg-authentik@users.noreply.github.com>
Date: Mon, 20 Nov 2023 10:24:59 -0800
Subject: [PATCH] web: refactor sidebar capabilities for categorical
subsections (#7482)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: rollback dependabot's upgrade of context
The most frustrating part of this is that I RAN THIS, dammit, with the updated
context and the current Wizard, and it finished the End-to-End tests without
complaint.
* Due for amendment
* Revert "Due for amendment"
This reverts commit 829ad5d3f214fa163958593636b28300d010da42.
* web: refactor sidebar capabilities for categorical subsections
The project "Change Admin UI lists to have sublists per type" requires some initial changes to the
UI to facilitate this request. The AdminSidebar is the principle target of this project, and it is
embedded in the AdminInterface. To facilitate editing the AdminSidebar as an independent entity,
AdminInterface has been moved into its own folder and the AdminSidebar extracted as a standalone Web
Component. This removes, oh, about half the code from AdminInterface. A little cleanup with
`classMap` was also committed.
The rollup config was adjusted to find the new AdminInterface location.
The Sidebar uses the global `config: Config` object to check for Enterprise capabilities. Rather
than plumb all the way down through the Interface => AdminInterface -> AdminSidebar, I chose to make
provide an alternative way of reaching the `config` object, as a *context*. Other configuration
objects (Me, UiConfig, Tenant) interfaces will be contextualized as demand warrants.
Demand will warrant. Just not yet. 1
The Sidebar has been refactored only slightly; the renderers are entirely the same as they were
prior to extraction. What has been changed is the source of information: when we retrieve the
current version we story *only* the information, and use type information to ensure that the version
we store is the version we care about. The same is true of `impersonation`; we care only about the
name of the person being impersonated being present, so we don't store anything else.
Fetches have been moved from `firstUpdated` to the constructor. No reason to have the sidebar
render twice if the network returns before the render is scheduled.
Because the path used to identify the user being impersonated has changed, the `str()` references in
the XLIFF files had to be adjusted. **This change is to a variable only and does not require
translation.**
---
1 The code is littered with checks to `me()?`, `uiConfig?`, `config?`, etc. In the
*context* of being logged in as an administrator those should never be in doubt. I intend to make
our interfaces not have any doubt.
* Function to help generate sizing solutions across Javascript and CSS.
* web: refactor sidebar capabilities for categorical subsections
Move open/close logic into the ak-admin-sidebar itself.
This commit removes the responsibility for opening/closing the sidebar from the interface parent
code and places it inside the sidebar entirely. Since the Django invocation passes none of the
properties ak-interface-admin is capable of receiving, this seems like a safe operation.
The sidebar now assumes the responsibility for hooking up the window event listeners for open/close
and resize.
On connection to the DOM, and on resize, the sidebar checks to see if the viewport width meets the
criteria for a behavioral change (slide-overlay vs slide-push), and on slide-push automatically
opens the sidebar on the assumption that there's plenty of room. In order to support more dynamic
styling going forward, I've substituted the 1280px with 80rem, which is the same, but allows for
some better styling if someone with older eyes needs to "zoom in" on the whole thing with a larger
font size.
The hide/show code involves "reaching up" to touch the host's classList. There's a comment
indicating that this is a slightly fragile thing to do, but in a well-known way.
---
web/rollup.config.mjs | 2 +-
web/src/admin/AdminInterface.ts | 296 ------------------
.../admin/AdminInterface/AdminInterface.ts | 160 ++++++++++
web/src/admin/AdminInterface/AdminSidebar.ts | 214 +++++++++++++
web/src/admin/AdminInterface/index.ts | 5 +
web/src/common/styles/authentik.css | 3 +
web/src/elements/AuthentikContexts.ts | 7 +
web/src/elements/Base.ts | 19 +-
web/src/elements/sidebar/SidebarItem.ts | 111 ++++---
web/src/elements/utils/getRootStyle.ts | 5 +
web/xliff/de.xlf | 4 +-
web/xliff/en.xlf | 4 +-
web/xliff/es.xlf | 4 +-
web/xliff/fr.xlf | 4 +-
web/xliff/nl.xlf | 4 +-
web/xliff/pl.xlf | 4 +-
web/xliff/pseudo-LOCALE.xlf | 4 +-
web/xliff/tr.xlf | 4 +-
web/xliff/zh-Hans.xlf | 4 +-
web/xliff/zh-Hant.xlf | 4 +-
web/xliff/zh_CN.xlf | 4 +-
web/xliff/zh_TW.xlf | 4 +-
22 files changed, 511 insertions(+), 359 deletions(-)
delete mode 100644 web/src/admin/AdminInterface.ts
create mode 100644 web/src/admin/AdminInterface/AdminInterface.ts
create mode 100644 web/src/admin/AdminInterface/AdminSidebar.ts
create mode 100644 web/src/admin/AdminInterface/index.ts
create mode 100644 web/src/elements/AuthentikContexts.ts
create mode 100644 web/src/elements/utils/getRootStyle.ts
diff --git a/web/rollup.config.mjs b/web/rollup.config.mjs
index db9caf6ee1..49825a29dd 100644
--- a/web/rollup.config.mjs
+++ b/web/rollup.config.mjs
@@ -148,7 +148,7 @@ export default [
},
// Admin interface
{
- input: "./src/admin/AdminInterface.ts",
+ input: "./src/admin/AdminInterface/AdminInterface.ts",
output: [
{
format: "es",
diff --git a/web/src/admin/AdminInterface.ts b/web/src/admin/AdminInterface.ts
deleted file mode 100644
index e59793706d..0000000000
--- a/web/src/admin/AdminInterface.ts
+++ /dev/null
@@ -1,296 +0,0 @@
-import { ROUTES } from "@goauthentik/admin/Routes";
-import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
-import {
- EVENT_API_DRAWER_TOGGLE,
- EVENT_NOTIFICATION_DRAWER_TOGGLE,
- EVENT_SIDEBAR_TOGGLE,
- VERSION,
-} from "@goauthentik/common/constants";
-import { configureSentry } from "@goauthentik/common/sentry";
-import { me } from "@goauthentik/common/users";
-import { WebsocketClient } from "@goauthentik/common/ws";
-import { Interface } from "@goauthentik/elements/Base";
-import "@goauthentik/elements/ak-locale-context";
-import "@goauthentik/elements/enterprise/EnterpriseStatusBanner";
-import "@goauthentik/elements/messages/MessageContainer";
-import "@goauthentik/elements/messages/MessageContainer";
-import "@goauthentik/elements/notifications/APIDrawer";
-import "@goauthentik/elements/notifications/NotificationDrawer";
-import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
-import { getURLParam, updateURLParams } from "@goauthentik/elements/router/RouteMatch";
-import "@goauthentik/elements/router/RouterOutlet";
-import "@goauthentik/elements/sidebar/Sidebar";
-import "@goauthentik/elements/sidebar/SidebarItem";
-import { spread } from "@open-wc/lit-helpers";
-
-import { msg, str } from "@lit/localize";
-import { CSSResult, TemplateResult, css, html, nothing } from "lit";
-import { customElement, property, state } from "lit/decorators.js";
-import { map } from "lit/directives/map.js";
-
-import PFButton from "@patternfly/patternfly/components/Button/button.css";
-import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
-import PFPage from "@patternfly/patternfly/components/Page/page.css";
-import PFBase from "@patternfly/patternfly/patternfly-base.css";
-
-import {
- AdminApi,
- CapabilitiesEnum,
- CoreApi,
- SessionUser,
- UiThemeEnum,
- Version,
-} from "@goauthentik/api";
-
-@customElement("ak-interface-admin")
-export class AdminInterface extends Interface {
- @property({ type: Boolean })
- sidebarOpen = true;
-
- @property({ type: Boolean })
- notificationDrawerOpen = getURLParam("notificationDrawerOpen", false);
-
- @property({ type: Boolean })
- apiDrawerOpen = getURLParam("apiDrawerOpen", false);
-
- ws: WebsocketClient;
-
- @state()
- version?: Version;
-
- @state()
- user?: SessionUser;
-
- static get styles(): CSSResult[] {
- return [
- PFBase,
- PFPage,
- PFButton,
- PFDrawer,
- css`
- .pf-c-page__main,
- .pf-c-drawer__content,
- .pf-c-page__drawer {
- z-index: auto !important;
- background-color: transparent;
- }
- .display-none {
- display: none;
- }
- .pf-c-page {
- background-color: var(--pf-c-page--BackgroundColor) !important;
- }
- /* Global page background colour */
- :host([theme="dark"]) .pf-c-page {
- --pf-c-page--BackgroundColor: var(--ak-dark-background);
- }
- `,
- ];
- }
-
- constructor() {
- super();
- this.ws = new WebsocketClient();
- this.sidebarOpen = window.innerWidth >= 1280;
- window.addEventListener("resize", () => {
- this.sidebarOpen = window.innerWidth >= 1280;
- });
- window.addEventListener(EVENT_SIDEBAR_TOGGLE, () => {
- this.sidebarOpen = !this.sidebarOpen;
- });
- window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => {
- this.notificationDrawerOpen = !this.notificationDrawerOpen;
- updateURLParams({
- notificationDrawerOpen: this.notificationDrawerOpen,
- });
- });
- window.addEventListener(EVENT_API_DRAWER_TOGGLE, () => {
- this.apiDrawerOpen = !this.apiDrawerOpen;
- updateURLParams({
- apiDrawerOpen: this.apiDrawerOpen,
- });
- });
- }
-
- async firstUpdated(): Promise {
- configureSentry(true);
- this.version = await new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve();
- this.user = await me();
- const canAccessAdmin =
- this.user.user.isSuperuser ||
- // TODO: somehow add `access_admin_interface` to the API schema
- this.user.user.systemPermissions.includes("access_admin_interface");
- if (!canAccessAdmin && this.user.user.pk > 0) {
- window.location.assign("/if/user/");
- }
- }
-
- render(): TemplateResult {
- return html`
-
`;
}
}
diff --git a/web/src/elements/utils/getRootStyle.ts b/web/src/elements/utils/getRootStyle.ts
new file mode 100644
index 0000000000..f91d63e5ff
--- /dev/null
+++ b/web/src/elements/utils/getRootStyle.ts
@@ -0,0 +1,5 @@
+export function getRootStyle(selector: string, element: HTMLElement = document.documentElement) {
+ return getComputedStyle(element, null).getPropertyValue(selector);
+}
+
+export default getRootStyle;
diff --git a/web/xliff/de.xlf b/web/xliff/de.xlf
index 38ac63d461..cacf5580c6 100644
--- a/web/xliff/de.xlf
+++ b/web/xliff/de.xlf
@@ -4989,9 +4989,9 @@ Bindings to groups/users are checked against the user of the event.
Eine neuere Version des Frontends ist verfügbar.
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.Sie geben sich gerade als
- aus. Klicken Sie zum Stoppen.
+ aus. Klicken Sie zum Stoppen.
User interface
diff --git a/web/xliff/en.xlf b/web/xliff/en.xlf
index fd6274b44d..11d8ee1a50 100644
--- a/web/xliff/en.xlf
+++ b/web/xliff/en.xlf
@@ -5248,9 +5248,9 @@ Bindings to groups/users are checked against the user of the event.
A newer version of the frontend is available.
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.You're currently impersonating
- . Click to stop.
+ . Click to stop.
User interface
diff --git a/web/xliff/es.xlf b/web/xliff/es.xlf
index e6f6fc8998..b5708c7aca 100644
--- a/web/xliff/es.xlf
+++ b/web/xliff/es.xlf
@@ -4914,9 +4914,9 @@ Bindings to groups/users are checked against the user of the event.
Está disponible una versión más reciente de la interfaz.
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.Estás suplantando a
- . Haga clic para parar.
+ . Haga clic para parar.
User interface
diff --git a/web/xliff/fr.xlf b/web/xliff/fr.xlf
index 4343e0ab3d..eb5cbb2f1d 100644
--- a/web/xliff/fr.xlf
+++ b/web/xliff/fr.xlf
@@ -6558,9 +6558,9 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.Vous vous faites actuellement passer pour
- . Cliquer pour arrêter.
+ . Cliquer pour arrêter.
diff --git a/web/xliff/nl.xlf b/web/xliff/nl.xlf
index c6ac855432..f2ceeb89c5 100644
--- a/web/xliff/nl.xlf
+++ b/web/xliff/nl.xlf
@@ -6797,8 +6797,8 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
- You're currently impersonating . Click to stop.
- Je doet momenteel alsof je bent. Klik om te stoppen.
+ You're currently impersonating . Click to stop.
+ Je doet momenteel alsof je bent. Klik om te stoppen.
diff --git a/web/xliff/pl.xlf b/web/xliff/pl.xlf
index d50ab62c2b..0c8118ae86 100644
--- a/web/xliff/pl.xlf
+++ b/web/xliff/pl.xlf
@@ -5104,9 +5104,9 @@ Bindings to groups/users are checked against the user of the event.
Dostępna jest nowsza wersja frontendu.
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.Obecnie podszywasz się pod
- . Kliknij, aby zatrzymać.
+ . Kliknij, aby zatrzymać.
User interface
diff --git a/web/xliff/pseudo-LOCALE.xlf b/web/xliff/pseudo-LOCALE.xlf
index bd038e1bee..78b560613e 100644
--- a/web/xliff/pseudo-LOCALE.xlf
+++ b/web/xliff/pseudo-LOCALE.xlf
@@ -6515,8 +6515,8 @@ Bindings to groups/users are checked against the user of the event.
- You're currently impersonating . Click to stop.
- Ŷōũ'ŕē ćũŕŕēńţĺŷ ĩmƥēŕśōńàţĩńĝ . Ćĺĩćķ ţō śţōƥ.
+ You're currently impersonating . Click to stop.
+ Ŷōũ'ŕē ćũŕŕēńţĺŷ ĩmƥēŕśōńàţĩńĝ . Ćĺĩćķ ţō śţōƥ.
diff --git a/web/xliff/tr.xlf b/web/xliff/tr.xlf
index dd82e3e392..f2eb13ba51 100644
--- a/web/xliff/tr.xlf
+++ b/web/xliff/tr.xlf
@@ -4907,9 +4907,9 @@ Bindings to groups/users are checked against the user of the event.
Ön yüzün daha yeni bir sürümü mevcuttur.
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.Şu anda
- kimliğine bürünüyorsunuz. Durdurmak için tıklayın.
+ kimliğine bürünüyorsunuz. Durdurmak için tıklayın.
User interface
diff --git a/web/xliff/zh-Hans.xlf b/web/xliff/zh-Hans.xlf
index aa8d0b5106..f314f44a26 100644
--- a/web/xliff/zh-Hans.xlf
+++ b/web/xliff/zh-Hans.xlf
@@ -6560,9 +6560,9 @@ Bindings to groups/users are checked against the user of the event.
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.您目前正在模拟
- 的身份。点击以停止。
+ 的身份。点击以停止。
diff --git a/web/xliff/zh-Hant.xlf b/web/xliff/zh-Hant.xlf
index b19eae4ca8..e836104f29 100644
--- a/web/xliff/zh-Hant.xlf
+++ b/web/xliff/zh-Hant.xlf
@@ -4951,9 +4951,9 @@ Bindings to groups/users are checked against the user of the event.
有较新版本的前端可用。
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.你目前正在模拟
- 。单击停止。
+ 。单击停止。
User interface
diff --git a/web/xliff/zh_CN.xlf b/web/xliff/zh_CN.xlf
index e11e7e4adc..e661cbaa45 100644
--- a/web/xliff/zh_CN.xlf
+++ b/web/xliff/zh_CN.xlf
@@ -6560,9 +6560,9 @@ Bindings to groups/users are checked against the user of the event.
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.您目前正在模拟
- 的身份。点击以停止。
+ 的身份。点击以停止。
diff --git a/web/xliff/zh_TW.xlf b/web/xliff/zh_TW.xlf
index 2367c4581f..bc39005a9a 100644
--- a/web/xliff/zh_TW.xlf
+++ b/web/xliff/zh_TW.xlf
@@ -4950,9 +4950,9 @@ Bindings to groups/users are checked against the user of the event.
有较新版本的前端可用。
- You're currently impersonating . Click to stop.
+ You're currently impersonating . Click to stop.你目前正在模拟
- 。单击停止。
+ 。单击停止。
User interface