Compare commits
4 Commits
safari-fol
...
admin-layo
Author | SHA1 | Date | |
---|---|---|---|
7b7ad9b63a | |||
00eff9871f | |||
f4ed74c0c7 | |||
3f81bde962 |
@ -66,13 +66,13 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
|
|||||||
aboutModal?: AboutModal;
|
aboutModal?: AboutModal;
|
||||||
|
|
||||||
@property({ type: Boolean, reflect: true })
|
@property({ type: Boolean, reflect: true })
|
||||||
public sidebarOpen: boolean;
|
public sidebarOpen = true;
|
||||||
|
|
||||||
#toggleSidebar = () => {
|
#toggleSidebar = () => {
|
||||||
this.sidebarOpen = !this.sidebarOpen;
|
this.sidebarOpen = !this.sidebarOpen;
|
||||||
};
|
};
|
||||||
|
|
||||||
#sidebarMatcher: MediaQueryList;
|
sidebarMatcher = window.matchMedia("(min-width: 1200px)");
|
||||||
#sidebarListener = (event: MediaQueryListEvent) => {
|
#sidebarListener = (event: MediaQueryListEvent) => {
|
||||||
this.sidebarOpen = event.matches;
|
this.sidebarOpen = event.matches;
|
||||||
};
|
};
|
||||||
@ -133,9 +133,6 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.ws = new WebsocketClient();
|
this.ws = new WebsocketClient();
|
||||||
|
|
||||||
this.#sidebarMatcher = window.matchMedia("(min-width: 1200px)");
|
|
||||||
this.sidebarOpen = this.#sidebarMatcher.matches;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
@ -157,13 +154,13 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#sidebarMatcher.addEventListener("change", this.#sidebarListener);
|
this.sidebarMatcher.addEventListener("change", this.#sidebarListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public disconnectedCallback(): void {
|
public disconnectedCallback(): void {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
window.removeEventListener(EVENT_SIDEBAR_TOGGLE, this.#toggleSidebar);
|
window.removeEventListener(EVENT_SIDEBAR_TOGGLE, this.#toggleSidebar);
|
||||||
this.#sidebarMatcher.removeEventListener("change", this.#sidebarListener);
|
this.sidebarMatcher.removeEventListener("change", this.#sidebarListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
async firstUpdated(): Promise<void> {
|
async firstUpdated(): Promise<void> {
|
||||||
|
@ -58,9 +58,6 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
PFContent,
|
PFContent,
|
||||||
PFDivider,
|
PFDivider,
|
||||||
css`
|
css`
|
||||||
.pf-l-grid__item {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.pf-l-grid__item.big-graph-container {
|
.pf-l-grid__item.big-graph-container {
|
||||||
height: 35em;
|
height: 35em;
|
||||||
}
|
}
|
||||||
@ -74,6 +71,10 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
line-height: normal;
|
line-height: normal;
|
||||||
font-size: var(--pf-global--icon--FontSize--sm);
|
font-size: var(--pf-global--icon--FontSize--sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart-item {
|
||||||
|
aspect-ratio: 2 / 1;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -104,15 +105,21 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
</ak-page-header>
|
</ak-page-header>
|
||||||
<section class="pf-c-page__main-section">
|
<section class="pf-c-page__main-section">
|
||||||
<div class="pf-l-grid pf-m-gutter">
|
<div class="pf-l-grid pf-m-gutter">
|
||||||
<!-- row 1 -->
|
<div class="pf-l-grid__item pf-m-12-col pf-m-2-row pf-m-9-col-on-xl">
|
||||||
<div
|
<ak-recent-events pageSize="6"></ak-recent-events>
|
||||||
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl pf-l-grid pf-m-gutter"
|
</div>
|
||||||
>
|
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-sm pf-m-3-col-on-xl">
|
||||||
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl">
|
|
||||||
<ak-quick-actions-card .actions=${this.quickActions}>
|
<ak-quick-actions-card .actions=${this.quickActions}>
|
||||||
</ak-quick-actions-card>
|
</ak-quick-actions-card>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl">
|
|
||||||
|
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-sm pf-m-3-col-on-xl">
|
||||||
|
<ak-admin-status-version> </ak-admin-status-version>
|
||||||
|
</div>
|
||||||
|
<div class="pf-l-grid pf-l-grid__item pf-m-12-col pf-m-gutter">
|
||||||
|
${this.renderSecondaryRow()}
|
||||||
|
|
||||||
|
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-md chart-item">
|
||||||
<ak-aggregate-card
|
<ak-aggregate-card
|
||||||
icon="pf-icon pf-icon-zone"
|
icon="pf-icon pf-icon-zone"
|
||||||
header=${msg("Outpost status")}
|
header=${msg("Outpost status")}
|
||||||
@ -121,24 +128,13 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
<ak-admin-status-chart-outpost></ak-admin-status-chart-outpost>
|
<ak-admin-status-chart-outpost></ak-admin-status-chart-outpost>
|
||||||
</ak-aggregate-card>
|
</ak-aggregate-card>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-md chart-item">
|
||||||
class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-4-col-on-2xl"
|
|
||||||
>
|
|
||||||
<ak-aggregate-card icon="fa fa-sync-alt" header=${msg("Sync status")}>
|
<ak-aggregate-card icon="fa fa-sync-alt" header=${msg("Sync status")}>
|
||||||
<ak-admin-status-chart-sync></ak-admin-status-chart-sync>
|
<ak-admin-status-chart-sync></ak-admin-status-chart-sync>
|
||||||
</ak-aggregate-card>
|
</ak-aggregate-card>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-l-grid__item pf-m-12-col">
|
|
||||||
<hr class="pf-c-divider" />
|
|
||||||
</div>
|
|
||||||
${this.renderCards()}
|
|
||||||
</div>
|
|
||||||
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl">
|
|
||||||
<ak-recent-events pageSize="6"></ak-recent-events>
|
|
||||||
</div>
|
|
||||||
<div class="pf-l-grid__item pf-m-12-col">
|
|
||||||
<hr class="pf-c-divider" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- row 3 -->
|
<!-- row 3 -->
|
||||||
<div
|
<div
|
||||||
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-8-col-on-2xl big-graph-container"
|
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-8-col-on-2xl big-graph-container"
|
||||||
@ -166,32 +162,34 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
</section>`;
|
</section>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCards() {
|
renderSecondaryRow() {
|
||||||
const isEnterprise = this.hasEnterpriseLicense;
|
const isEnterprise = this.hasEnterpriseLicense;
|
||||||
|
const colSpan = isEnterprise ? 4 : 6;
|
||||||
|
|
||||||
const classes = {
|
const classes = {
|
||||||
"card-container": true,
|
"card-container": true,
|
||||||
"pf-l-grid__item": true,
|
"pf-l-grid__item": true,
|
||||||
"pf-m-6-col": true,
|
[`pf-m-12-col`]: true,
|
||||||
"pf-m-4-col-on-md": !isEnterprise,
|
[`pf-m-${colSpan}-col-on-md`]: true,
|
||||||
"pf-m-4-col-on-xl": !isEnterprise,
|
|
||||||
"pf-m-3-col-on-md": isEnterprise,
|
|
||||||
"pf-m-3-col-on-xl": isEnterprise,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return html`<div class=${classMap(classes)}>
|
return html`
|
||||||
|
<div class=${classMap(classes)}>
|
||||||
<ak-admin-status-system> </ak-admin-status-system>
|
<ak-admin-status-system> </ak-admin-status-system>
|
||||||
</div>
|
</div>
|
||||||
<div class=${classMap(classes)}>
|
|
||||||
<ak-admin-status-version> </ak-admin-status-version>
|
|
||||||
</div>
|
|
||||||
<div class=${classMap(classes)}>
|
<div class=${classMap(classes)}>
|
||||||
<ak-admin-status-card-workers> </ak-admin-status-card-workers>
|
<ak-admin-status-card-workers> </ak-admin-status-card-workers>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${isEnterprise
|
${isEnterprise
|
||||||
? html` <div class=${classMap(classes)}>
|
? html`
|
||||||
|
<div class=${classMap(classes)}>
|
||||||
<ak-admin-fips-status-system> </ak-admin-fips-status-system>
|
<ak-admin-fips-status-system> </ak-admin-fips-status-system>
|
||||||
</div>`
|
</div>
|
||||||
: nothing} `;
|
`
|
||||||
|
: nothing}
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderActions() {
|
renderActions() {
|
||||||
|
@ -92,9 +92,6 @@ export function normalizeCSSSource(input: StyleSheetInit): CSSResultOrNative {
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a `CSSStyleSheet` from the given input.
|
|
||||||
*/
|
|
||||||
export function createStyleSheetUnsafe(input: StyleSheetInit): CSSStyleSheet {
|
export function createStyleSheetUnsafe(input: StyleSheetInit): CSSStyleSheet {
|
||||||
const result = normalizeCSSSource(input);
|
const result = normalizeCSSSource(input);
|
||||||
if (result instanceof CSSStyleSheet) return result;
|
if (result instanceof CSSStyleSheet) return result;
|
||||||
@ -111,82 +108,41 @@ export function createStyleSheetUnsafe(input: StyleSheetInit): CSSStyleSheet {
|
|||||||
return result.styleSheet;
|
return result.styleSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A symbol to indicate that a stylesheet has been adopted by a style parent.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* Safari considers stylesheet removed from the `adoptedStyleSheets` array
|
|
||||||
* ready for garbage collection. Reuse of the stylesheet will result in tab-crash.
|
|
||||||
*
|
|
||||||
* Always discard the stylesheet after use.
|
|
||||||
*/
|
|
||||||
const StyleSheetAdoptedParent = Symbol("stylesheet-adopted");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A CSS style sheet that has been adopted by a style parent.
|
|
||||||
*/
|
|
||||||
export interface AdoptedStyleSheet extends CSSStyleSheet {
|
|
||||||
[StyleSheetAdoptedParent]: WeakRef<StyleSheetParent>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type-predicate to determine if a given stylesheet has been adopted.
|
|
||||||
*/
|
|
||||||
export function isAdoptedStyleSheet(styleSheet: CSSStyleSheet): styleSheet is AdoptedStyleSheet {
|
|
||||||
if (!(StyleSheetAdoptedParent in styleSheet)) return false;
|
|
||||||
|
|
||||||
return styleSheet[StyleSheetAdoptedParent] instanceof WeakRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append stylesheet(s) to the given roots.
|
* Append stylesheet(s) to the given roots.
|
||||||
*
|
|
||||||
* @see {@linkcode removeStyleSheet} to remove a stylesheet from a given roots.
|
|
||||||
*/
|
*/
|
||||||
export function appendStyleSheet(
|
export function appendStyleSheet(
|
||||||
styleParent: StyleSheetParent,
|
insertions: CSSStyleSheet | Iterable<CSSStyleSheet>,
|
||||||
...insertions: CSSStyleSheet[]
|
...styleParents: StyleSheetParent[]
|
||||||
): void {
|
): void {
|
||||||
insertions = Array.isArray(insertions) ? insertions : [insertions];
|
insertions = Array.isArray(insertions) ? insertions : [insertions];
|
||||||
|
|
||||||
for (const styleSheetInsertion of insertions) {
|
for (const nextStyleSheet of insertions) {
|
||||||
if (isAdoptedStyleSheet(styleSheetInsertion)) {
|
for (const styleParent of styleParents) {
|
||||||
console.warn("Attempted to append adopted stylesheet", {
|
if (styleParent.adoptedStyleSheets.includes(nextStyleSheet)) return;
|
||||||
styleSheetInsertion,
|
|
||||||
currentParent: styleSheetInsertion[StyleSheetAdoptedParent]?.deref(),
|
|
||||||
rules: serializeStyleSheet(styleSheetInsertion),
|
|
||||||
});
|
|
||||||
|
|
||||||
throw new TypeError("Attempted to append a previously adopted stylesheet");
|
styleParent.adoptedStyleSheets = [...styleParent.adoptedStyleSheets, nextStyleSheet];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (styleParent.adoptedStyleSheets.includes(styleSheetInsertion)) return;
|
|
||||||
|
|
||||||
styleParent.adoptedStyleSheets = [...styleParent.adoptedStyleSheets, styleSheetInsertion];
|
|
||||||
|
|
||||||
Object.assign(styleSheetInsertion, {
|
|
||||||
[StyleSheetAdoptedParent]: new WeakRef(styleParent),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a stylesheet from the given roots, matching by referential equality.
|
* Remove a stylesheet from the given roots, matching by referential equality.
|
||||||
*
|
|
||||||
* @see {@linkcode appendStyleSheet} to append a stylesheet to a given roots.
|
|
||||||
*/
|
*/
|
||||||
export function removeStyleSheet(
|
export function removeStyleSheet(
|
||||||
styleParent: StyleSheetParent,
|
currentStyleSheet: CSSStyleSheet,
|
||||||
...removals: CSSStyleSheet[]
|
...styleParents: StyleSheetParent[]
|
||||||
): void {
|
): void {
|
||||||
|
for (const styleParent of styleParents) {
|
||||||
const nextAdoptedStyleSheets = styleParent.adoptedStyleSheets.filter(
|
const nextAdoptedStyleSheets = styleParent.adoptedStyleSheets.filter(
|
||||||
(styleSheet) => !removals.includes(styleSheet),
|
(styleSheet) => styleSheet !== currentStyleSheet,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (nextAdoptedStyleSheets.length === styleParent.adoptedStyleSheets.length) return;
|
if (nextAdoptedStyleSheets.length === styleParent.adoptedStyleSheets.length) return;
|
||||||
|
|
||||||
styleParent.adoptedStyleSheets = nextAdoptedStyleSheets;
|
styleParent.adoptedStyleSheets = nextAdoptedStyleSheets;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a stylesheet to a string.
|
* Serialize a stylesheet to a string.
|
||||||
|
@ -67,6 +67,12 @@ export class NavigationButtons extends AKElement {
|
|||||||
:host([theme="light"]) .pf-c-page__header-tools-group .pf-c-button {
|
:host([theme="light"]) .pf-c-page__header-tools-group .pf-c-button {
|
||||||
color: var(--ak-global--Color--100) !important;
|
color: var(--ak-global--Color--100) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.pf-c-avatar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -95,7 +101,7 @@ export class NavigationButtons extends AKElement {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return html`<div class="pf-c-page__header-tools-item pf-m-hidden pf-m-visible-on-xl">
|
return html`<div class="pf-c-page__header-tools-item pf-m-hidden pf-m-visible-on-lg">
|
||||||
<button class="pf-c-button pf-m-plain" type="button" @click=${onClick}>
|
<button class="pf-c-button pf-m-plain" type="button" @click=${onClick}>
|
||||||
<pf-tooltip position="top" content=${msg("Open API drawer")}>
|
<pf-tooltip position="top" content=${msg("Open API drawer")}>
|
||||||
<i class="fas fa-code" aria-hidden="true"></i>
|
<i class="fas fa-code" aria-hidden="true"></i>
|
||||||
@ -116,7 +122,7 @@ export class NavigationButtons extends AKElement {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return html`<div class="pf-c-page__header-tools-item pf-m-hidden pf-m-visible-on-xl">
|
return html`<div class="pf-c-page__header-tools-item pf-m-hidden pf-m-visible-on-lg">
|
||||||
<button
|
<button
|
||||||
class="pf-c-button pf-m-plain"
|
class="pf-c-button pf-m-plain"
|
||||||
type="button"
|
type="button"
|
||||||
@ -175,7 +181,7 @@ export class NavigationButtons extends AKElement {
|
|||||||
|
|
||||||
renderAvatar() {
|
renderAvatar() {
|
||||||
return html`<img
|
return html`<img
|
||||||
class="pf-c-page__header-tools-item pf-c-avatar pf-m-hidden pf-m-visible-on-xl"
|
class="pf-c-avatar"
|
||||||
src=${ifDefined(this.me?.user.avatar)}
|
src=${ifDefined(this.me?.user.avatar)}
|
||||||
alt="${msg("Avatar image")}"
|
alt="${msg("Avatar image")}"
|
||||||
/>`;
|
/>`;
|
||||||
@ -212,8 +218,8 @@ export class NavigationButtons extends AKElement {
|
|||||||
</div>
|
</div>
|
||||||
${this.renderImpersonation()}
|
${this.renderImpersonation()}
|
||||||
${this.userDisplayName != ""
|
${this.userDisplayName != ""
|
||||||
? html`<div class="pf-c-page__header-tools-group pf-m-hidden">
|
? html`<div class="pf-c-page__header-tools-group">
|
||||||
<div class="pf-c-page__header-tools-item pf-m-visible-on-2xl">
|
<div class="pf-c-page__header-tools-item pf-m-hidden pf-m-visible-on-md">
|
||||||
${this.userDisplayName}
|
${this.userDisplayName}
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
|
@ -7,14 +7,7 @@ import {
|
|||||||
removeStyleSheet,
|
removeStyleSheet,
|
||||||
resolveStyleSheetParent,
|
resolveStyleSheetParent,
|
||||||
} from "@goauthentik/common/stylesheets";
|
} from "@goauthentik/common/stylesheets";
|
||||||
import {
|
import { ResolvedUITheme, createUIThemeEffect, resolveUITheme } from "@goauthentik/common/theme";
|
||||||
CSSColorSchemeValue,
|
|
||||||
ResolvedUITheme,
|
|
||||||
UIThemeListener,
|
|
||||||
createUIThemeEffect,
|
|
||||||
formatColorScheme,
|
|
||||||
resolveUITheme,
|
|
||||||
} from "@goauthentik/common/theme";
|
|
||||||
import { type ThemedElement } from "@goauthentik/common/theme";
|
import { type ThemedElement } from "@goauthentik/common/theme";
|
||||||
|
|
||||||
import { localized } from "@lit/localize";
|
import { localized } from "@lit/localize";
|
||||||
@ -25,15 +18,18 @@ import AKGlobal from "@goauthentik/common/styles/authentik.css";
|
|||||||
import OneDark from "@goauthentik/common/styles/one-dark.css";
|
import OneDark from "@goauthentik/common/styles/one-dark.css";
|
||||||
import ThemeDark from "@goauthentik/common/styles/theme-dark.css";
|
import ThemeDark from "@goauthentik/common/styles/theme-dark.css";
|
||||||
|
|
||||||
import { UiThemeEnum } from "@goauthentik/api";
|
import { CurrentBrand, UiThemeEnum } from "@goauthentik/api";
|
||||||
|
|
||||||
// Re-export the theme helpers
|
// Re-export the theme helpers
|
||||||
export { rootInterface } from "@goauthentik/common/theme";
|
export { rootInterface } from "@goauthentik/common/theme";
|
||||||
|
|
||||||
|
export interface AKElementInit {
|
||||||
|
brand?: Partial<CurrentBrand>;
|
||||||
|
styleParents?: StyleSheetParent[];
|
||||||
|
}
|
||||||
|
|
||||||
@localized()
|
@localized()
|
||||||
export class AKElement extends LitElement implements ThemedElement {
|
export class AKElement extends LitElement implements ThemedElement {
|
||||||
//#region Properties
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The resolved theme of the current element.
|
* The resolved theme of the current element.
|
||||||
*
|
*
|
||||||
@ -49,19 +45,7 @@ export class AKElement extends LitElement implements ThemedElement {
|
|||||||
})
|
})
|
||||||
public activeTheme: ResolvedUITheme;
|
public activeTheme: ResolvedUITheme;
|
||||||
|
|
||||||
//#endregion
|
protected static readonly DarkColorSchemeStyleSheet = createStyleSheetUnsafe(ThemeDark);
|
||||||
|
|
||||||
//#region Private Properties
|
|
||||||
|
|
||||||
readonly #preferredColorScheme: CSSColorSchemeValue;
|
|
||||||
|
|
||||||
#customCSSStyleSheet: CSSStyleSheet | null;
|
|
||||||
#darkThemeStyleSheet: CSSStyleSheet | null = null;
|
|
||||||
#themeAbortController: AbortController | null = null;
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Lifecycle
|
|
||||||
|
|
||||||
protected static finalizeStyles(styles?: CSSResultGroup): CSSResultOrNative[] {
|
protected static finalizeStyles(styles?: CSSResultGroup): CSSResultOrNative[] {
|
||||||
// Ensure all style sheets being passed are really style sheets.
|
// Ensure all style sheets being passed are really style sheets.
|
||||||
@ -79,62 +63,63 @@ export class AKElement extends LitElement implements ThemedElement {
|
|||||||
return [styles, ...baseStyles].map(createStyleSheetUnsafe);
|
return [styles, ...baseStyles].map(createStyleSheetUnsafe);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor(init?: AKElementInit) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
const { brand } = globalAK();
|
const config = globalAK();
|
||||||
|
const { brand = config.brand, styleParents = [] } = init || {};
|
||||||
|
|
||||||
this.#preferredColorScheme = formatColorScheme(brand.uiTheme);
|
|
||||||
this.activeTheme = resolveUITheme(brand?.uiTheme);
|
this.activeTheme = resolveUITheme(brand?.uiTheme);
|
||||||
|
this.#styleParents = styleParents;
|
||||||
|
|
||||||
this.#customCSSStyleSheet = brand?.brandingCustomCss
|
this.#customCSSStyleSheet = brand?.brandingCustomCss
|
||||||
? createStyleSheetUnsafe(brand.brandingCustomCss)
|
? createStyleSheetUnsafe(brand.brandingCustomCss)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#styleParents: StyleSheetParent[] = [];
|
||||||
|
#customCSSStyleSheet: CSSStyleSheet | null;
|
||||||
|
|
||||||
|
#themeAbortController: AbortController | null = null;
|
||||||
|
|
||||||
public disconnectedCallback(): void {
|
public disconnectedCallback(): void {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
this.#themeAbortController?.abort();
|
this.#themeAbortController?.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
#styleRoot?: StyleSheetParent;
|
|
||||||
|
|
||||||
#dispatchTheme: UIThemeListener = (nextUITheme) => {
|
|
||||||
if (!this.#styleRoot) return;
|
|
||||||
|
|
||||||
if (nextUITheme === UiThemeEnum.Dark) {
|
|
||||||
this.#darkThemeStyleSheet ||= createStyleSheetUnsafe(ThemeDark);
|
|
||||||
appendStyleSheet(this.#styleRoot, this.#darkThemeStyleSheet);
|
|
||||||
this.activeTheme = UiThemeEnum.Dark;
|
|
||||||
} else if (this.#darkThemeStyleSheet) {
|
|
||||||
removeStyleSheet(this.#styleRoot, this.#darkThemeStyleSheet);
|
|
||||||
this.#darkThemeStyleSheet = null;
|
|
||||||
this.activeTheme = UiThemeEnum.Light;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected createRenderRoot(): HTMLElement | DocumentFragment {
|
protected createRenderRoot(): HTMLElement | DocumentFragment {
|
||||||
const renderRoot = super.createRenderRoot();
|
const renderRoot = super.createRenderRoot();
|
||||||
this.#styleRoot = resolveStyleSheetParent(renderRoot);
|
|
||||||
|
const styleRoot = resolveStyleSheetParent(renderRoot);
|
||||||
|
const styleParents = Array.from(
|
||||||
|
new Set<StyleSheetParent>([styleRoot, ...this.#styleParents]),
|
||||||
|
);
|
||||||
|
|
||||||
if (this.#customCSSStyleSheet) {
|
if (this.#customCSSStyleSheet) {
|
||||||
console.debug(`authentik/element[${this.tagName.toLowerCase()}]: Adding custom CSS`);
|
console.debug(`authentik/element[${this.tagName.toLowerCase()}]: Adding custom CSS`);
|
||||||
|
|
||||||
appendStyleSheet(this.#styleRoot, this.#customCSSStyleSheet);
|
styleRoot.adoptedStyleSheets = [
|
||||||
|
...styleRoot.adoptedStyleSheets,
|
||||||
|
this.#customCSSStyleSheet,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#themeAbortController = new AbortController();
|
this.#themeAbortController = new AbortController();
|
||||||
|
|
||||||
if (this.#preferredColorScheme === "dark") {
|
createUIThemeEffect(
|
||||||
this.#dispatchTheme(UiThemeEnum.Dark);
|
(currentUITheme) => {
|
||||||
} else if (this.#preferredColorScheme === "auto") {
|
if (currentUITheme === UiThemeEnum.Dark) {
|
||||||
createUIThemeEffect(this.#dispatchTheme, {
|
appendStyleSheet(AKElement.DarkColorSchemeStyleSheet, ...styleParents);
|
||||||
signal: this.#themeAbortController.signal,
|
} else {
|
||||||
});
|
removeStyleSheet(AKElement.DarkColorSchemeStyleSheet, ...styleParents);
|
||||||
}
|
}
|
||||||
|
this.activeTheme = currentUITheme;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
signal: this.#themeAbortController.signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return renderRoot;
|
return renderRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from "@goauthentik/common/stylesheets";
|
} from "@goauthentik/common/stylesheets";
|
||||||
import { ThemedElement } from "@goauthentik/common/theme";
|
import { ThemedElement } from "@goauthentik/common/theme";
|
||||||
import { UIConfig } from "@goauthentik/common/ui/config";
|
import { UIConfig } from "@goauthentik/common/ui/config";
|
||||||
import { AKElement } from "@goauthentik/elements/Base";
|
import { AKElement, AKElementInit } from "@goauthentik/elements/Base";
|
||||||
import { VersionContextController } from "@goauthentik/elements/Interface/VersionContextController";
|
import { VersionContextController } from "@goauthentik/elements/Interface/VersionContextController";
|
||||||
import { ModalOrchestrationController } from "@goauthentik/elements/controllers/ModalOrchestrationController.js";
|
import { ModalOrchestrationController } from "@goauthentik/elements/controllers/ModalOrchestrationController.js";
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ import { BrandContextController } from "./BrandContextController";
|
|||||||
import { ConfigContextController } from "./ConfigContextController";
|
import { ConfigContextController } from "./ConfigContextController";
|
||||||
import { EnterpriseContextController } from "./EnterpriseContextController";
|
import { EnterpriseContextController } from "./EnterpriseContextController";
|
||||||
|
|
||||||
|
const brandContext = Symbol("brandContext");
|
||||||
const configContext = Symbol("configContext");
|
const configContext = Symbol("configContext");
|
||||||
const modalController = Symbol("modalController");
|
const modalController = Symbol("modalController");
|
||||||
const versionContext = Symbol("versionContext");
|
const versionContext = Symbol("versionContext");
|
||||||
@ -26,6 +27,8 @@ const versionContext = Symbol("versionContext");
|
|||||||
export abstract class Interface extends AKElement implements ThemedElement {
|
export abstract class Interface extends AKElement implements ThemedElement {
|
||||||
protected static readonly PFBaseStyleSheet = createStyleSheetUnsafe(PFBase);
|
protected static readonly PFBaseStyleSheet = createStyleSheetUnsafe(PFBase);
|
||||||
|
|
||||||
|
[brandContext]: BrandContextController;
|
||||||
|
|
||||||
[configContext]: ConfigContextController;
|
[configContext]: ConfigContextController;
|
||||||
|
|
||||||
[modalController]: ModalOrchestrationController;
|
[modalController]: ModalOrchestrationController;
|
||||||
@ -36,15 +39,19 @@ export abstract class Interface extends AKElement implements ThemedElement {
|
|||||||
@state()
|
@state()
|
||||||
public brand?: CurrentBrand;
|
public brand?: CurrentBrand;
|
||||||
|
|
||||||
constructor() {
|
constructor({ styleParents = [], ...init }: AKElementInit = {}) {
|
||||||
super();
|
|
||||||
const styleParent = resolveStyleSheetParent(document);
|
const styleParent = resolveStyleSheetParent(document);
|
||||||
|
|
||||||
|
super({
|
||||||
|
...init,
|
||||||
|
styleParents: [styleParent, ...styleParents],
|
||||||
|
});
|
||||||
|
|
||||||
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
|
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
|
||||||
|
|
||||||
appendStyleSheet(styleParent, Interface.PFBaseStyleSheet);
|
appendStyleSheet(Interface.PFBaseStyleSheet, styleParent);
|
||||||
|
|
||||||
this.addController(new BrandContextController(this));
|
this[brandContext] = new BrandContextController(this);
|
||||||
this[configContext] = new ConfigContextController(this);
|
this[configContext] = new ConfigContextController(this);
|
||||||
this[modalController] = new ModalOrchestrationController(this);
|
this[modalController] = new ModalOrchestrationController(this);
|
||||||
}
|
}
|
||||||
@ -70,8 +77,8 @@ export class AuthenticatedInterface extends Interface implements AkAuthenticated
|
|||||||
@state()
|
@state()
|
||||||
public version?: Version;
|
public version?: Version;
|
||||||
|
|
||||||
constructor() {
|
constructor(init?: AKElementInit) {
|
||||||
super();
|
super(init);
|
||||||
|
|
||||||
this[enterpriseContext] = new EnterpriseContextController(this);
|
this[enterpriseContext] = new EnterpriseContextController(this);
|
||||||
this[versionContext] = new VersionContextController(this);
|
this[versionContext] = new VersionContextController(this);
|
||||||
|
@ -89,7 +89,6 @@ export class AKPageNavbar extends WithBrandConfig(AKElement) implements PageNavb
|
|||||||
--ak-brand-background-color: var(
|
--ak-brand-background-color: var(
|
||||||
--pf-c-page__sidebar--m-light--BackgroundColor
|
--pf-c-page__sidebar--m-light--BackgroundColor
|
||||||
);
|
);
|
||||||
--host-navbar-height: var(--ak-c-page-header--height, 7.5rem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([theme="dark"]) {
|
:host([theme="dark"]) {
|
||||||
@ -106,6 +105,7 @@ export class AKPageNavbar extends WithBrandConfig(AKElement) implements PageNavb
|
|||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
min-height: 6rem;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
row-gap: var(--pf-global--spacer--sm);
|
row-gap: var(--pf-global--spacer--sm);
|
||||||
@ -116,10 +116,6 @@ export class AKPageNavbar extends WithBrandConfig(AKElement) implements PageNavb
|
|||||||
"brand toggle primary secondary"
|
"brand toggle primary secondary"
|
||||||
"brand toggle description secondary";
|
"brand toggle description secondary";
|
||||||
|
|
||||||
@media (min-width: 426px) {
|
|
||||||
height: var(--host-navbar-height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
row-gap: var(--pf-global--spacer--xs);
|
row-gap: var(--pf-global--spacer--xs);
|
||||||
|
|
||||||
@ -165,15 +161,7 @@ export class AKPageNavbar extends WithBrandConfig(AKElement) implements PageNavb
|
|||||||
|
|
||||||
&.page-description {
|
&.page-description {
|
||||||
grid-area: description;
|
grid-area: description;
|
||||||
margin-block-end: var(--pf-global--spacer--md);
|
padding-block-end: var(--pf-global--spacer--md);
|
||||||
|
|
||||||
display: box;
|
|
||||||
display: -webkit-box;
|
|
||||||
line-clamp: 2;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
box-orient: vertical;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
@media (max-width: 425px) {
|
@media (max-width: 425px) {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -80,6 +80,7 @@ export class AggregateCard extends AKElement implements IAggregateCard {
|
|||||||
.center-value {
|
.center-value {
|
||||||
font-size: var(--pf-global--icon--FontSize--lg);
|
font-size: var(--pf-global--icon--FontSize--lg);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
place-content: center;
|
||||||
}
|
}
|
||||||
.subtext {
|
.subtext {
|
||||||
margin-top: var(--pf-global--spacer--sm);
|
margin-top: var(--pf-global--spacer--sm);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
appendStyleSheet,
|
appendStyleSheet,
|
||||||
assertAdoptableStyleSheetParent,
|
assertAdoptableStyleSheetParent,
|
||||||
createStyleSheetUnsafe,
|
|
||||||
} from "@goauthentik/common/stylesheets.js";
|
} from "@goauthentik/common/stylesheets.js";
|
||||||
|
|
||||||
import { TemplateResult, render as litRender } from "lit";
|
import { TemplateResult, render as litRender } from "lit";
|
||||||
@ -16,6 +15,6 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
|||||||
export const render = (body: TemplateResult) => {
|
export const render = (body: TemplateResult) => {
|
||||||
assertAdoptableStyleSheetParent(document);
|
assertAdoptableStyleSheetParent(document);
|
||||||
|
|
||||||
appendStyleSheet(document, ...[PFBase, AKGlobal].map(createStyleSheetUnsafe));
|
appendStyleSheet([PFBase, AKGlobal], document);
|
||||||
return litRender(body, document.body);
|
return litRender(body, document.body);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user