web: housekeeping, optimizations and small fixes (#12450)
* web/user: fix incorrect font in RAC endpoint popup Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix navbar button colour in light mode Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add about modal Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix sidebar overlapping page header Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix wizard hint alignment Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add loading state to about modal Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add version context Signed-off-by: Jens Langhammer <jens@goauthentik.io> * stub out init functions on loading interface saves 4 HTTP requests on each full page load 🎉 Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix z-index for panels Signed-off-by: Jens Langhammer <jens@goauthentik.io> * remove redundant api request Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
		
							
								
								
									
										117
									
								
								web/src/admin/AdminInterface/AboutModal.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								web/src/admin/AdminInterface/AboutModal.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
				
			||||||
 | 
					import { VERSION } from "@goauthentik/common/constants";
 | 
				
			||||||
 | 
					import { globalAK } from "@goauthentik/common/global";
 | 
				
			||||||
 | 
					import "@goauthentik/elements/EmptyState";
 | 
				
			||||||
 | 
					import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
 | 
				
			||||||
 | 
					import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
 | 
				
			||||||
 | 
					import { ModalButton } from "@goauthentik/elements/buttons/ModalButton";
 | 
				
			||||||
 | 
					import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { msg } from "@lit/localize";
 | 
				
			||||||
 | 
					import { TemplateResult, css, html } from "lit";
 | 
				
			||||||
 | 
					import { customElement } from "lit/decorators.js";
 | 
				
			||||||
 | 
					import { until } from "lit/directives/until.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import PFAbout from "@patternfly/patternfly/components/AboutModalBox/about-modal-box.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { AdminApi, CapabilitiesEnum, LicenseSummaryStatusEnum } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@customElement("ak-about-modal")
 | 
				
			||||||
 | 
					export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton)) {
 | 
				
			||||||
 | 
					    static get styles() {
 | 
				
			||||||
 | 
					        return super.styles.concat(
 | 
				
			||||||
 | 
					            PFAbout,
 | 
				
			||||||
 | 
					            css`
 | 
				
			||||||
 | 
					                .pf-c-about-modal-box__hero {
 | 
				
			||||||
 | 
					                    background-image: url("/static/dist/assets/images/flow_background.jpg");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            `,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async getAboutEntries(): Promise<[string, string | TemplateResult][]> {
 | 
				
			||||||
 | 
					        const status = await new AdminApi(DEFAULT_CONFIG).adminSystemRetrieve();
 | 
				
			||||||
 | 
					        const version = await new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve();
 | 
				
			||||||
 | 
					        let build: string | TemplateResult = msg("Release");
 | 
				
			||||||
 | 
					        if (globalAK().config.capabilities.includes(CapabilitiesEnum.CanDebug)) {
 | 
				
			||||||
 | 
					            build = msg("Development");
 | 
				
			||||||
 | 
					        } else if (version.buildHash !== "") {
 | 
				
			||||||
 | 
					            build = html`<a
 | 
				
			||||||
 | 
					                rel="noopener noreferrer"
 | 
				
			||||||
 | 
					                href="https://github.com/goauthentik/authentik/commit/${version.buildHash}"
 | 
				
			||||||
 | 
					                target="_blank"
 | 
				
			||||||
 | 
					                >${version.buildHash}</a
 | 
				
			||||||
 | 
					            >`;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            [msg("Version"), version.versionCurrent],
 | 
				
			||||||
 | 
					            [msg("UI Version"), VERSION],
 | 
				
			||||||
 | 
					            [msg("Build"), build],
 | 
				
			||||||
 | 
					            [msg("Python version"), status.runtime.pythonVersion],
 | 
				
			||||||
 | 
					            [msg("Platform"), status.runtime.platform],
 | 
				
			||||||
 | 
					            [msg("Kernel"), status.runtime.uname],
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                msg("OpenSSL"),
 | 
				
			||||||
 | 
					                `${status.runtime.opensslVersion} ${status.runtime.opensslFipsEnabled ? "FIPS" : ""}`,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    renderModal() {
 | 
				
			||||||
 | 
					        let product = globalAK().brand.brandingTitle || DefaultBrand.brandingTitle;
 | 
				
			||||||
 | 
					        if (this.licenseSummary.status != LicenseSummaryStatusEnum.Unlicensed) {
 | 
				
			||||||
 | 
					            product += ` ${msg("Enterprise")}`;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return html`<div
 | 
				
			||||||
 | 
					            class="pf-c-backdrop"
 | 
				
			||||||
 | 
					            @click=${(e: PointerEvent) => {
 | 
				
			||||||
 | 
					                e.stopPropagation();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            <div class="pf-l-bullseye">
 | 
				
			||||||
 | 
					                <div class="pf-c-about-modal-box" role="dialog" aria-modal="true">
 | 
				
			||||||
 | 
					                    <div class="pf-c-about-modal-box__brand">
 | 
				
			||||||
 | 
					                        <img
 | 
				
			||||||
 | 
					                            class="pf-c-about-modal-box__brand-image"
 | 
				
			||||||
 | 
					                            src=${this.brand?.brandingFavicon ?? DefaultBrand.brandingFavicon}
 | 
				
			||||||
 | 
					                            alt="authentik Logo"
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="pf-c-about-modal-box__close">
 | 
				
			||||||
 | 
					                        <button
 | 
				
			||||||
 | 
					                            class="pf-c-button pf-m-plain"
 | 
				
			||||||
 | 
					                            type="button"
 | 
				
			||||||
 | 
					                            @click=${() => {
 | 
				
			||||||
 | 
					                                this.open = false;
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            <i class="fas fa-times" aria-hidden="true"></i>
 | 
				
			||||||
 | 
					                        </button>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="pf-c-about-modal-box__header">
 | 
				
			||||||
 | 
					                        <h1 class="pf-c-title pf-m-4xl">${product}</h1>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="pf-c-about-modal-box__hero"></div>
 | 
				
			||||||
 | 
					                    <div class="pf-c-about-modal-box__content">
 | 
				
			||||||
 | 
					                        <div class="pf-c-about-modal-box__body">
 | 
				
			||||||
 | 
					                            <div class="pf-c-content">
 | 
				
			||||||
 | 
					                                ${until(
 | 
				
			||||||
 | 
					                                    this.getAboutEntries().then((entries) => {
 | 
				
			||||||
 | 
					                                        return html`<dl>
 | 
				
			||||||
 | 
					                                            ${entries.map(([label, value]) => {
 | 
				
			||||||
 | 
					                                                return html`<dt>${label}</dt>
 | 
				
			||||||
 | 
					                                                    <dd>${value}</dd>`;
 | 
				
			||||||
 | 
					                                            })}
 | 
				
			||||||
 | 
					                                        </dl>`;
 | 
				
			||||||
 | 
					                                    }),
 | 
				
			||||||
 | 
					                                    html`<ak-empty-state loading></ak-empty-state>`,
 | 
				
			||||||
 | 
					                                )}
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                        <p class="pf-c-about-modal-box__strapline"></p>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
 | 
					import "@goauthentik/admin/AdminInterface/AboutModal";
 | 
				
			||||||
 | 
					import type { AboutModal } from "@goauthentik/admin/AdminInterface/AboutModal";
 | 
				
			||||||
import { ROUTES } from "@goauthentik/admin/Routes";
 | 
					import { ROUTES } from "@goauthentik/admin/Routes";
 | 
				
			||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    EVENT_API_DRAWER_TOGGLE,
 | 
					    EVENT_API_DRAWER_TOGGLE,
 | 
				
			||||||
    EVENT_NOTIFICATION_DRAWER_TOGGLE,
 | 
					    EVENT_NOTIFICATION_DRAWER_TOGGLE,
 | 
				
			||||||
@ -20,7 +21,7 @@ import "@goauthentik/elements/sidebar/Sidebar";
 | 
				
			|||||||
import "@goauthentik/elements/sidebar/SidebarItem";
 | 
					import "@goauthentik/elements/sidebar/SidebarItem";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { CSSResult, TemplateResult, css, html } from "lit";
 | 
					import { CSSResult, TemplateResult, css, html } from "lit";
 | 
				
			||||||
import { customElement, property, state } from "lit/decorators.js";
 | 
					import { customElement, property, query, state } from "lit/decorators.js";
 | 
				
			||||||
import { classMap } from "lit/directives/class-map.js";
 | 
					import { classMap } from "lit/directives/class-map.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
 | 
					import PFButton from "@patternfly/patternfly/components/Button/button.css";
 | 
				
			||||||
@ -28,7 +29,7 @@ import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
 | 
				
			|||||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
 | 
					import PFPage from "@patternfly/patternfly/components/Page/page.css";
 | 
				
			||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
					import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { AdminApi, SessionUser, UiThemeEnum, Version } from "@goauthentik/api";
 | 
					import { SessionUser, UiThemeEnum, Version } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "./AdminSidebar";
 | 
					import "./AdminSidebar";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,6 +49,9 @@ export class AdminInterface extends EnterpriseAwareInterface {
 | 
				
			|||||||
    @state()
 | 
					    @state()
 | 
				
			||||||
    user?: SessionUser;
 | 
					    user?: SessionUser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @query("ak-about-modal")
 | 
				
			||||||
 | 
					    aboutModal?: AboutModal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get styles(): CSSResult[] {
 | 
					    static get styles(): CSSResult[] {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            PFBase,
 | 
					            PFBase,
 | 
				
			||||||
@ -77,6 +81,9 @@ export class AdminInterface extends EnterpriseAwareInterface {
 | 
				
			|||||||
                ak-admin-sidebar {
 | 
					                ak-admin-sidebar {
 | 
				
			||||||
                    grid-area: nav;
 | 
					                    grid-area: nav;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                .pf-c-drawer__panel {
 | 
				
			||||||
 | 
					                    z-index: var(--pf-global--ZIndex--xl);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            `,
 | 
					            `,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -100,7 +107,6 @@ export class AdminInterface extends EnterpriseAwareInterface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    async firstUpdated(): Promise<void> {
 | 
					    async firstUpdated(): Promise<void> {
 | 
				
			||||||
        configureSentry(true);
 | 
					        configureSentry(true);
 | 
				
			||||||
        this.version = await new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve();
 | 
					 | 
				
			||||||
        this.user = await me();
 | 
					        this.user = await me();
 | 
				
			||||||
        const canAccessAdmin =
 | 
					        const canAccessAdmin =
 | 
				
			||||||
            this.user.user.isSuperuser ||
 | 
					            this.user.user.isSuperuser ||
 | 
				
			||||||
@ -159,6 +165,7 @@ export class AdminInterface extends EnterpriseAwareInterface {
 | 
				
			|||||||
                                    : "display-none"}"
 | 
					                                    : "display-none"}"
 | 
				
			||||||
                                ?hidden=${!this.apiDrawerOpen}
 | 
					                                ?hidden=${!this.apiDrawerOpen}
 | 
				
			||||||
                            ></ak-api-drawer>
 | 
					                            ></ak-api-drawer>
 | 
				
			||||||
 | 
					                            <ak-about-modal></ak-about-modal>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div></div
 | 
					                </div></div
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ import {
 | 
				
			|||||||
    CapabilitiesEnum,
 | 
					    CapabilitiesEnum,
 | 
				
			||||||
    WithCapabilitiesConfig,
 | 
					    WithCapabilitiesConfig,
 | 
				
			||||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
 | 
					} from "@goauthentik/elements/Interface/capabilitiesProvider";
 | 
				
			||||||
 | 
					import { WithVersion } from "@goauthentik/elements/Interface/versionProvider";
 | 
				
			||||||
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
 | 
					import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
 | 
				
			||||||
import { getRootStyle } from "@goauthentik/elements/utils/getRootStyle";
 | 
					import { getRootStyle } from "@goauthentik/elements/utils/getRootStyle";
 | 
				
			||||||
import { spread } from "@open-wc/lit-helpers";
 | 
					import { spread } from "@open-wc/lit-helpers";
 | 
				
			||||||
@ -16,25 +17,19 @@ import { TemplateResult, html, nothing } from "lit";
 | 
				
			|||||||
import { customElement, property, state } from "lit/decorators.js";
 | 
					import { customElement, property, state } from "lit/decorators.js";
 | 
				
			||||||
import { map } from "lit/directives/map.js";
 | 
					import { map } from "lit/directives/map.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { AdminApi, CoreApi, UiThemeEnum, Version } from "@goauthentik/api";
 | 
					import { CoreApi, UiThemeEnum } from "@goauthentik/api";
 | 
				
			||||||
import type { SessionUser, UserSelf } from "@goauthentik/api";
 | 
					import type { SessionUser, UserSelf } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@customElement("ak-admin-sidebar")
 | 
					@customElement("ak-admin-sidebar")
 | 
				
			||||||
export class AkAdminSidebar extends WithCapabilitiesConfig(AKElement) {
 | 
					export class AkAdminSidebar extends WithCapabilitiesConfig(WithVersion(AKElement)) {
 | 
				
			||||||
    @property({ type: Boolean, reflect: true })
 | 
					    @property({ type: Boolean, reflect: true })
 | 
				
			||||||
    open = true;
 | 
					    open = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @state()
 | 
					 | 
				
			||||||
    version: Version["versionCurrent"] | null = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @state()
 | 
					    @state()
 | 
				
			||||||
    impersonation: UserSelf["username"] | null = null;
 | 
					    impersonation: UserSelf["username"] | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve().then((version) => {
 | 
					 | 
				
			||||||
            this.version = version.versionCurrent;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        me().then((user: SessionUser) => {
 | 
					        me().then((user: SessionUser) => {
 | 
				
			||||||
            this.impersonation = user.original ? user.user.username : null;
 | 
					            this.impersonation = user.original ? user.user.username : null;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -175,12 +170,10 @@ export class AkAdminSidebar extends WithCapabilitiesConfig(AKElement) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    renderNewVersionMessage() {
 | 
					    renderNewVersionMessage() {
 | 
				
			||||||
        return this.version && this.version !== VERSION
 | 
					        return this.version && this.version.versionCurrent !== VERSION
 | 
				
			||||||
            ? html`
 | 
					            ? html`
 | 
				
			||||||
                  <ak-sidebar-item ?highlight=${true}>
 | 
					                  <ak-sidebar-item ?highlight=${true}>
 | 
				
			||||||
                      <span slot="label"
 | 
					                      <span slot="label">${msg("A newer version of the UI is available.")}</span>
 | 
				
			||||||
                          >${msg("A newer version of the frontend is available.")}</span
 | 
					 | 
				
			||||||
                      >
 | 
					 | 
				
			||||||
                  </ak-sidebar-item>
 | 
					                  </ak-sidebar-item>
 | 
				
			||||||
              `
 | 
					              `
 | 
				
			||||||
            : nothing;
 | 
					            : nothing;
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,6 @@ export class AkApplicationWizardHint extends AKElement implements ShowHintContro
 | 
				
			|||||||
            PFLabel,
 | 
					            PFLabel,
 | 
				
			||||||
            css`
 | 
					            css`
 | 
				
			||||||
                .pf-c-page__main-section {
 | 
					                .pf-c-page__main-section {
 | 
				
			||||||
                    padding-top: 0;
 | 
					 | 
				
			||||||
                    padding-bottom: 0;
 | 
					                    padding-bottom: 0;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                .ak-hint-text {
 | 
					                .ak-hint-text {
 | 
				
			||||||
 | 
				
			|||||||
@ -63,7 +63,7 @@ export class ShowHintController implements ReactiveController {
 | 
				
			|||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        return html`<ak-hint-footer
 | 
					        return html`<ak-hint-footer
 | 
				
			||||||
            ><div style="text-align: right">
 | 
					            ><div style="text-align: right">
 | 
				
			||||||
                <input type="checkbox" @input=${this.hide} />${msg(
 | 
					                <input type="checkbox" @input=${this.hide} /> ${msg(
 | 
				
			||||||
                    "Don't show this message again.",
 | 
					                    "Don't show this message again.",
 | 
				
			||||||
                )}
 | 
					                )}
 | 
				
			||||||
            </div></ak-hint-footer
 | 
					            </div></ak-hint-footer
 | 
				
			||||||
 | 
				
			|||||||
@ -58,6 +58,14 @@ export class NavigationButtons extends AKElement {
 | 
				
			|||||||
                .pf-c-page__header-tools {
 | 
					                .pf-c-page__header-tools {
 | 
				
			||||||
                    display: flex;
 | 
					                    display: flex;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                :host([theme="dark"]) .pf-c-page__header-tools {
 | 
				
			||||||
 | 
					                    color: var(--ak-dark-foreground) !important;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                :host([theme="light"]) .pf-c-page__header-tools-item .fas,
 | 
				
			||||||
 | 
					                :host([theme="light"]) .pf-c-notification-badge__count,
 | 
				
			||||||
 | 
					                :host([theme="light"]) .pf-c-page__header-tools-group .pf-c-button {
 | 
				
			||||||
 | 
					                    color: var(--ak-global--Color--100) !important;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            `,
 | 
					            `,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { createContext } from "@lit/context";
 | 
					import { createContext } from "@lit/context";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { Config, CurrentBrand, LicenseSummary, SessionUser } from "@goauthentik/api";
 | 
					import type { Config, CurrentBrand, LicenseSummary, SessionUser, Version } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const authentikConfigContext = createContext<Config>(Symbol("authentik-config-context"));
 | 
					export const authentikConfigContext = createContext<Config>(Symbol("authentik-config-context"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -12,4 +12,6 @@ export const authentikEnterpriseContext = createContext<LicenseSummary>(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const authentikBrandContext = createContext<CurrentBrand>(Symbol("authentik-brand-context"));
 | 
					export const authentikBrandContext = createContext<CurrentBrand>(Symbol("authentik-brand-context"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const authentikVersionContext = createContext<Version>(Symbol("authentik-version-context"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default authentikConfigContext;
 | 
					export default authentikConfigContext;
 | 
				
			||||||
 | 
				
			|||||||
@ -100,7 +100,7 @@ export class AKElement extends LitElement {
 | 
				
			|||||||
        this._applyTheme(root, await this.getTheme());
 | 
					        this._applyTheme(root, await this.getTheme());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private async _initCustomCSS(root: DocumentOrShadowRoot): Promise<void> {
 | 
					    async _initCustomCSS(root: DocumentOrShadowRoot): Promise<void> {
 | 
				
			||||||
        const sheets = await fetchCustomCSS();
 | 
					        const sheets = await fetchCustomCSS();
 | 
				
			||||||
        sheets.map((css) => {
 | 
					        sheets.map((css) => {
 | 
				
			||||||
            if (css === "") {
 | 
					            if (css === "") {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
 | 
					import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
 | 
				
			||||||
 | 
					import { VersionContextController } from "@goauthentik/elements/Interface/VersionContextController";
 | 
				
			||||||
import { ModalOrchestrationController } from "@goauthentik/elements/controllers/ModalOrchestrationController.js";
 | 
					import { ModalOrchestrationController } from "@goauthentik/elements/controllers/ModalOrchestrationController.js";
 | 
				
			||||||
import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet";
 | 
					import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -6,7 +7,7 @@ import { state } from "lit/decorators.js";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
					import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { Config, CurrentBrand, LicenseSummary } from "@goauthentik/api";
 | 
					import type { Config, CurrentBrand, LicenseSummary, Version } from "@goauthentik/api";
 | 
				
			||||||
import { UiThemeEnum } from "@goauthentik/api";
 | 
					import { UiThemeEnum } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { AKElement, rootInterface } from "../Base";
 | 
					import { AKElement, rootInterface } from "../Base";
 | 
				
			||||||
@ -19,11 +20,13 @@ export type AkInterface = HTMLElement & {
 | 
				
			|||||||
    brand?: CurrentBrand;
 | 
					    brand?: CurrentBrand;
 | 
				
			||||||
    uiConfig?: UIConfig;
 | 
					    uiConfig?: UIConfig;
 | 
				
			||||||
    config?: Config;
 | 
					    config?: Config;
 | 
				
			||||||
 | 
					    version?: Version;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const brandContext = Symbol("brandContext");
 | 
					const brandContext = Symbol("brandContext");
 | 
				
			||||||
const configContext = Symbol("configContext");
 | 
					const configContext = Symbol("configContext");
 | 
				
			||||||
const modalController = Symbol("modalController");
 | 
					const modalController = Symbol("modalController");
 | 
				
			||||||
 | 
					const versionContext = Symbol("versionContext");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Interface extends AKElement implements AkInterface {
 | 
					export class Interface extends AKElement implements AkInterface {
 | 
				
			||||||
    @state()
 | 
					    @state()
 | 
				
			||||||
@ -35,6 +38,8 @@ export class Interface extends AKElement implements AkInterface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    [modalController]!: ModalOrchestrationController;
 | 
					    [modalController]!: ModalOrchestrationController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [versionContext]!: VersionContextController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @state()
 | 
					    @state()
 | 
				
			||||||
    config?: Config;
 | 
					    config?: Config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,10 +49,15 @@ export class Interface extends AKElement implements AkInterface {
 | 
				
			|||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        document.adoptedStyleSheets = [...document.adoptedStyleSheets, ensureCSSStyleSheet(PFBase)];
 | 
					        document.adoptedStyleSheets = [...document.adoptedStyleSheets, ensureCSSStyleSheet(PFBase)];
 | 
				
			||||||
 | 
					        this._initContexts();
 | 
				
			||||||
 | 
					        this.dataset.akInterfaceRoot = "true";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _initContexts() {
 | 
				
			||||||
        this[brandContext] = 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);
 | 
				
			||||||
        this.dataset.akInterfaceRoot = "true";
 | 
					        this[versionContext] = new VersionContextController(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _activateTheme(theme: UiThemeEnum, ...roots: DocumentOrShadowRoot[]): void {
 | 
					    _activateTheme(theme: UiThemeEnum, ...roots: DocumentOrShadowRoot[]): void {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										51
									
								
								web/src/elements/Interface/VersionContextController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								web/src/elements/Interface/VersionContextController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
				
			||||||
 | 
					import { EVENT_REFRESH } from "@goauthentik/common/constants";
 | 
				
			||||||
 | 
					import { authentikVersionContext } from "@goauthentik/elements/AuthentikContexts";
 | 
				
			||||||
 | 
					import type { ReactiveElementHost } from "@goauthentik/elements/types.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ContextProvider } from "@lit/context";
 | 
				
			||||||
 | 
					import type { ReactiveController } from "lit";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type { Version } from "@goauthentik/api";
 | 
				
			||||||
 | 
					import { AdminApi } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type { AkInterface } from "./Interface";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class VersionContextController implements ReactiveController {
 | 
				
			||||||
 | 
					    host!: ReactiveElementHost<AkInterface>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context!: ContextProvider<{ __context__: Version | undefined }>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(host: ReactiveElementHost<AkInterface>) {
 | 
				
			||||||
 | 
					        this.host = host;
 | 
				
			||||||
 | 
					        this.context = new ContextProvider(this.host, {
 | 
				
			||||||
 | 
					            context: authentikVersionContext,
 | 
				
			||||||
 | 
					            initialValue: undefined,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        this.fetch = this.fetch.bind(this);
 | 
				
			||||||
 | 
					        this.fetch();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fetch() {
 | 
				
			||||||
 | 
					        new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve().then((version) => {
 | 
				
			||||||
 | 
					            this.context.setValue(version);
 | 
				
			||||||
 | 
					            this.host.version = version;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hostConnected() {
 | 
				
			||||||
 | 
					        window.addEventListener(EVENT_REFRESH, this.fetch);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hostDisconnected() {
 | 
				
			||||||
 | 
					        window.removeEventListener(EVENT_REFRESH, this.fetch);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hostUpdate() {
 | 
				
			||||||
 | 
					        // If the Interface changes its version information for some reason,
 | 
				
			||||||
 | 
					        // we should notify all users of the context of that change. doesn't
 | 
				
			||||||
 | 
					        if (this.host.version !== this.context.value) {
 | 
				
			||||||
 | 
					            this.context.setValue(this.host.version);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								web/src/elements/Interface/versionProvider.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								web/src/elements/Interface/versionProvider.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import { authentikVersionContext } from "@goauthentik/elements/AuthentikContexts";
 | 
				
			||||||
 | 
					import type { AbstractConstructor } from "@goauthentik/elements/types.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { consume } from "@lit/context";
 | 
				
			||||||
 | 
					import type { LitElement } from "lit";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type { Version } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function WithVersion<T extends AbstractConstructor<LitElement>>(
 | 
				
			||||||
 | 
					    superclass: T,
 | 
				
			||||||
 | 
					    subscribe = true,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    abstract class WithBrandProvider extends superclass {
 | 
				
			||||||
 | 
					        @consume({ context: authentikVersionContext, subscribe })
 | 
				
			||||||
 | 
					        public version!: Version;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return WithBrandProvider;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    EVENT_SIDEBAR_TOGGLE,
 | 
					    EVENT_SIDEBAR_TOGGLE,
 | 
				
			||||||
    EVENT_WS_MESSAGE,
 | 
					    EVENT_WS_MESSAGE,
 | 
				
			||||||
@ -24,7 +23,7 @@ import PFNotificationBadge from "@patternfly/patternfly/components/NotificationB
 | 
				
			|||||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
 | 
					import PFPage from "@patternfly/patternfly/components/Page/page.css";
 | 
				
			||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
					import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { EventsApi, SessionUser } from "@goauthentik/api";
 | 
					import { SessionUser } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@customElement("ak-page-header")
 | 
					@customElement("ak-page-header")
 | 
				
			||||||
export class PageHeader extends WithBrandConfig(AKElement) {
 | 
					export class PageHeader extends WithBrandConfig(AKElement) {
 | 
				
			||||||
@ -34,9 +33,6 @@ export class PageHeader extends WithBrandConfig(AKElement) {
 | 
				
			|||||||
    @property({ type: Boolean })
 | 
					    @property({ type: Boolean })
 | 
				
			||||||
    iconImage = false;
 | 
					    iconImage = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @state()
 | 
					 | 
				
			||||||
    notificationsCount = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @property()
 | 
					    @property()
 | 
				
			||||||
    header = "";
 | 
					    header = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,7 +61,7 @@ export class PageHeader extends WithBrandConfig(AKElement) {
 | 
				
			|||||||
                :host {
 | 
					                :host {
 | 
				
			||||||
                    position: sticky;
 | 
					                    position: sticky;
 | 
				
			||||||
                    top: 0;
 | 
					                    top: 0;
 | 
				
			||||||
                    z-index: 100;
 | 
					                    z-index: var(--pf-global--ZIndex--lg);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                .bar {
 | 
					                .bar {
 | 
				
			||||||
                    border-bottom: var(--pf-global--BorderWidth--sm);
 | 
					                    border-bottom: var(--pf-global--BorderWidth--sm);
 | 
				
			||||||
@ -126,13 +122,6 @@ export class PageHeader extends WithBrandConfig(AKElement) {
 | 
				
			|||||||
        this.me = await me();
 | 
					        this.me = await me();
 | 
				
			||||||
        this.uiConfig = await uiConfig();
 | 
					        this.uiConfig = await uiConfig();
 | 
				
			||||||
        this.uiConfig.navbar.userDisplay = UserDisplay.none;
 | 
					        this.uiConfig.navbar.userDisplay = UserDisplay.none;
 | 
				
			||||||
        const notifications = await new EventsApi(DEFAULT_CONFIG).eventsNotificationsList({
 | 
					 | 
				
			||||||
            seen: false,
 | 
					 | 
				
			||||||
            ordering: "-created",
 | 
					 | 
				
			||||||
            pageSize: 1,
 | 
					 | 
				
			||||||
            user: this.me.user.pk,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        this.notificationsCount = notifications.pagination.count;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setTitle(header?: string) {
 | 
					    setTitle(header?: string) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,25 +1,29 @@
 | 
				
			|||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
					import type { AdminInterface } from "@goauthentik/admin/AdminInterface/AdminInterface";
 | 
				
			||||||
import { globalAK } from "@goauthentik/common/global";
 | 
					import { globalAK } from "@goauthentik/common/global";
 | 
				
			||||||
import { AKElement } from "@goauthentik/elements/Base";
 | 
					import { AKElement, rootInterface } from "@goauthentik/elements/Base";
 | 
				
			||||||
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
 | 
					import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
 | 
				
			||||||
 | 
					import { WithVersion } from "@goauthentik/elements/Interface/versionProvider";
 | 
				
			||||||
 | 
					import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { msg, str } from "@lit/localize";
 | 
					import { msg, str } from "@lit/localize";
 | 
				
			||||||
import { CSSResult, TemplateResult, css, html } from "lit";
 | 
					import { CSSResult, css, html, nothing } from "lit";
 | 
				
			||||||
import { customElement, state } from "lit/decorators.js";
 | 
					import { customElement } from "lit/decorators.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css";
 | 
					import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css";
 | 
				
			||||||
 | 
					import PFButton from "@patternfly/patternfly/components/Button/button.css";
 | 
				
			||||||
import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
 | 
					import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
 | 
				
			||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
					import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { AdminApi, LicenseSummaryStatusEnum, Version } from "@goauthentik/api";
 | 
					import { LicenseSummaryStatusEnum } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@customElement("ak-sidebar-version")
 | 
					@customElement("ak-sidebar-version")
 | 
				
			||||||
export class SidebarVersion extends WithLicenseSummary(AKElement) {
 | 
					export class SidebarVersion extends WithLicenseSummary(WithVersion(AKElement)) {
 | 
				
			||||||
    static get styles(): CSSResult[] {
 | 
					    static get styles(): CSSResult[] {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            PFBase,
 | 
					            PFBase,
 | 
				
			||||||
            PFNav,
 | 
					            PFNav,
 | 
				
			||||||
            PFAvatar,
 | 
					            PFAvatar,
 | 
				
			||||||
 | 
					            PFButton,
 | 
				
			||||||
            css`
 | 
					            css`
 | 
				
			||||||
                :host {
 | 
					                :host {
 | 
				
			||||||
                    display: flex;
 | 
					                    display: flex;
 | 
				
			||||||
@ -37,20 +41,24 @@ export class SidebarVersion extends WithLicenseSummary(AKElement) {
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @state()
 | 
					    render() {
 | 
				
			||||||
    version?: Version;
 | 
					        if (!this.version || !this.licenseSummary) {
 | 
				
			||||||
 | 
					            return nothing;
 | 
				
			||||||
    async firstUpdated() {
 | 
					        }
 | 
				
			||||||
        this.version = await new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve();
 | 
					        let product = globalAK().brand.brandingTitle || DefaultBrand.brandingTitle;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render(): TemplateResult {
 | 
					 | 
				
			||||||
        let product = globalAK().brand.brandingTitle;
 | 
					 | 
				
			||||||
        if (this.licenseSummary.status != LicenseSummaryStatusEnum.Unlicensed) {
 | 
					        if (this.licenseSummary.status != LicenseSummaryStatusEnum.Unlicensed) {
 | 
				
			||||||
            product += ` ${msg("Enterprise")}`;
 | 
					            product += ` ${msg("Enterprise")}`;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return html`<p class="pf-c-title">${product}</p>
 | 
					        return html`<button
 | 
				
			||||||
            <p class="pf-c-title">${msg(str`Version ${this.version?.versionCurrent}`)}</p> `;
 | 
					            class="pf-c-button pf-m-plain"
 | 
				
			||||||
 | 
					            @click=${() => {
 | 
				
			||||||
 | 
					                const int = rootInterface<AdminInterface>();
 | 
				
			||||||
 | 
					                int?.aboutModal?.onClick();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            <p class="pf-c-title">${product}</p>
 | 
				
			||||||
 | 
					            <p class="pf-c-title">${msg(str`Version ${this.version?.versionCurrent || ""}`)}</p>
 | 
				
			||||||
 | 
					        </button>`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,16 @@ export class Loading extends Interface {
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _initContexts(): void {
 | 
				
			||||||
 | 
					        // Stub function to avoid making API requests for things we don't need. The `Interface` base class loads
 | 
				
			||||||
 | 
					        // a bunch of data that is used globally by various things, however this is an interface that is shown
 | 
				
			||||||
 | 
					        // very briefly and we don't need any of that data.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async _initCustomCSS(): Promise<void> {
 | 
				
			||||||
 | 
					        // Stub function to avoid fetching custom CSS.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async getTheme(): Promise<UiThemeEnum> {
 | 
					    async getTheme(): Promise<UiThemeEnum> {
 | 
				
			||||||
        return globalAK()?.brand.uiTheme || UiThemeEnum.Automatic;
 | 
					        return globalAK()?.brand.uiTheme || UiThemeEnum.Automatic;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,12 @@ import "@goauthentik/elements/AppIcon";
 | 
				
			|||||||
import { AKElement, rootInterface } from "@goauthentik/elements/Base";
 | 
					import { AKElement, rootInterface } from "@goauthentik/elements/Base";
 | 
				
			||||||
import "@goauthentik/elements/Expand";
 | 
					import "@goauthentik/elements/Expand";
 | 
				
			||||||
import "@goauthentik/user/LibraryApplication/RACLaunchEndpointModal";
 | 
					import "@goauthentik/user/LibraryApplication/RACLaunchEndpointModal";
 | 
				
			||||||
 | 
					import type { RACLaunchEndpointModal } from "@goauthentik/user/LibraryApplication/RACLaunchEndpointModal";
 | 
				
			||||||
import { UserInterface } from "@goauthentik/user/UserInterface";
 | 
					import { UserInterface } from "@goauthentik/user/UserInterface";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { msg } from "@lit/localize";
 | 
					import { msg } from "@lit/localize";
 | 
				
			||||||
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
 | 
					import { CSSResult, TemplateResult, css, html, nothing } from "lit";
 | 
				
			||||||
import { customElement, property } from "lit/decorators.js";
 | 
					import { customElement, property, query } from "lit/decorators.js";
 | 
				
			||||||
import { classMap } from "lit/directives/class-map.js";
 | 
					import { classMap } from "lit/directives/class-map.js";
 | 
				
			||||||
import { ifDefined } from "lit/directives/if-defined.js";
 | 
					import { ifDefined } from "lit/directives/if-defined.js";
 | 
				
			||||||
import { styleMap } from "lit/directives/style-map.js";
 | 
					import { styleMap } from "lit/directives/style-map.js";
 | 
				
			||||||
@ -31,6 +32,9 @@ export class LibraryApplication extends AKElement {
 | 
				
			|||||||
    @property()
 | 
					    @property()
 | 
				
			||||||
    background = "";
 | 
					    background = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @query("ak-library-rac-endpoint-launch")
 | 
				
			||||||
 | 
					    racEndpointLaunch?: RACLaunchEndpointModal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get styles(): CSSResult[] {
 | 
					    static get styles(): CSSResult[] {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            PFBase,
 | 
					            PFBase,
 | 
				
			||||||
@ -94,14 +98,24 @@ export class LibraryApplication extends AKElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (this.application?.launchUrl === "goauthentik.io://providers/rac/launch") {
 | 
					        if (this.application?.launchUrl === "goauthentik.io://providers/rac/launch") {
 | 
				
			||||||
            return html`<ak-library-rac-endpoint-launch .app=${this.application}>
 | 
					            return html`<ak-library-rac-endpoint-launch .app=${this.application}>
 | 
				
			||||||
                <a slot="trigger"> ${this.application.name} </a>
 | 
					                </ak-library-rac-endpoint-launch>
 | 
				
			||||||
            </ak-library-rac-endpoint-launch>`;
 | 
					                <div class="pf-c-card__title">
 | 
				
			||||||
 | 
					                    <a
 | 
				
			||||||
 | 
					                        @click=${() => {
 | 
				
			||||||
 | 
					                            this.racEndpointLaunch?.onClick();
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                        ${this.application.name}
 | 
				
			||||||
 | 
					                    </a>
 | 
				
			||||||
 | 
					                </div>`;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return html`<a
 | 
					        return html`<div class="pf-c-card__title">
 | 
				
			||||||
            href="${ifDefined(this.application.launchUrl ?? "")}"
 | 
					            <a
 | 
				
			||||||
            target="${ifDefined(this.application.openInNewTab ? "_blank" : undefined)}"
 | 
					                href="${ifDefined(this.application.launchUrl ?? "")}"
 | 
				
			||||||
            >${this.application.name}</a
 | 
					                target="${ifDefined(this.application.openInNewTab ? "_blank" : undefined)}"
 | 
				
			||||||
        >`;
 | 
					                >${this.application.name}</a
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					        </div>`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render(): TemplateResult {
 | 
					    render(): TemplateResult {
 | 
				
			||||||
@ -133,7 +147,7 @@ export class LibraryApplication extends AKElement {
 | 
				
			|||||||
                    ></ak-app-icon>
 | 
					                    ></ak-app-icon>
 | 
				
			||||||
                </a>
 | 
					                </a>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="pf-c-card__title">${this.renderLaunch()}</div>
 | 
					            ${this.renderLaunch()}
 | 
				
			||||||
            <div class="expander"></div>
 | 
					            <div class="expander"></div>
 | 
				
			||||||
            ${expandable ? this.renderExpansion(this.application) : nothing}
 | 
					            ${expandable ? this.renderExpansion(this.application) : nothing}
 | 
				
			||||||
        </div>`;
 | 
					        </div>`;
 | 
				
			||||||
 | 
				
			|||||||
@ -54,12 +54,7 @@ const customStyles = css`
 | 
				
			|||||||
        box-shadow: none !important;
 | 
					        box-shadow: none !important;
 | 
				
			||||||
        color: black !important;
 | 
					        color: black !important;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    :host([theme="dark"]) .pf-c-page__header {
 | 
					    :host([theme="light"]) .pf-c-button.pf-m-secondary {
 | 
				
			||||||
        color: var(--ak-dark-foreground) !important;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    :host([theme="light"]) .pf-c-page__header-tools-item .fas,
 | 
					 | 
				
			||||||
    :host([theme="light"]) .pf-c-notification-badge__count,
 | 
					 | 
				
			||||||
    :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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    .pf-c-page {
 | 
					    .pf-c-page {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user