Files
authentik/web/src/elements/Diagram.ts
Teffen Ellis 2c813cbe03 web: Merge branch -- Stale notifications, synchronized context objects, rendering fixes (#19141)
* web: Fix stale notifications.

* Fix overlap of API and notifications drawers.

* Fix issues surrounding duplicate context controller values.

* Clean up drawer events, alignment.

* Export parts. Fix z-index, colors.

* Fix formatting, alignment. repeated renders.

* Fix indent.

* Fix progress bar fade out, positioning, labels.

* Fix clickable area.

* Ignore clickable icons.

* Clean up logging.

* Fix width.

* Move event listeners into decorator.

* Fix double counting of notifications.

* Fix ARIA lables.

* Fix empty state ARIA.

* Fix order of locale updating.

* Fix rebase.

* web: fix notification count update

* Update selector.

* web: Fix CAPTCHA locale.

* Clean up logging.

---------

Co-authored-by: macmoritz <tratarmoritz@gmail.com>
2026-01-05 15:54:50 -05:00

104 lines
2.9 KiB
TypeScript

import "#elements/EmptyState";
import { EVENT_REFRESH } from "#common/constants";
import { DOM_PURIFY_STRICT } from "#common/purify";
import { ThemeChangeEvent } from "#common/theme";
import { AKElement } from "#elements/Base";
import { UiThemeEnum } from "@goauthentik/api";
import mermaid, { MermaidConfig } from "mermaid";
import { css, CSSResult, html, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators.js";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
import { until } from "lit/directives/until.js";
@customElement("ak-diagram")
export class Diagram extends AKElement {
@property({ attribute: false })
diagram?: string;
refreshHandler = (): void => {
if (!this.textContent) return;
this.diagram = this.textContent;
};
handlerBound = false;
static styles: CSSResult[] = [
css`
:host {
display: flex;
justify-content: center;
}
`,
];
config: MermaidConfig;
constructor() {
super();
this.config = {
// The type definition for this says number
// but the example use strings
// and numbers don't work
logLevel: "fatal",
startOnLoad: false,
flowchart: {
curve: "linear",
},
htmlLabels: false,
securityLevel: "strict",
dompurifyConfig: DOM_PURIFY_STRICT,
};
mermaid.initialize(this.config);
}
firstUpdated(): void {
if (this.handlerBound) return;
window.addEventListener(EVENT_REFRESH, this.refreshHandler);
this.addEventListener(ThemeChangeEvent.eventName, ((ev: CustomEvent<UiThemeEnum>) => {
if (ev.detail === UiThemeEnum.Dark) {
this.config.theme = "dark";
} else {
this.config.theme = "default";
}
mermaid.initialize(this.config);
}) as EventListener);
this.handlerBound = true;
this.refreshHandler();
}
disconnectedCallback(): void {
super.disconnectedCallback();
window.removeEventListener(EVENT_REFRESH, this.refreshHandler);
}
render(): TemplateResult {
this.querySelectorAll("*").forEach((el) => {
try {
el.remove();
} catch {
console.debug(`authentik/diagram: failed to remove element ${el}`);
}
});
if (!this.diagram) {
return html`<ak-empty-state loading></ak-empty-state>`;
}
return html`${until(
mermaid.render("graph", this.diagram).then((r) => {
r.bindFunctions?.(this.shadowRoot as unknown as Element);
return unsafeHTML(r.svg);
}),
)}`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-diagram": Diagram;
}
}