Compare commits
	
		
			42 Commits
		
	
	
		
			version/20
			...
			web/legibi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8f995aab62 | |||
| 2846e49657 | |||
| 0e60e755d4 | |||
| 6cf2433e2b | |||
| e1d565d40e | |||
| ee37e9235b | |||
| 8248163958 | |||
| 9acebec1f6 | |||
| 2a96900dc7 | |||
| ca42506fa0 | |||
| 34de6bfd3a | |||
| 2d94b16411 | |||
| 98503f6009 | |||
| ac4ba5d9e2 | |||
| f19ed14bf8 | |||
| 085debf170 | |||
| cacdf64408 | |||
| 23665d173f | |||
| 272fdc516b | |||
| b08dcc2289 | |||
| c84be1d961 | |||
| 875fc5c735 | |||
| 66cefcc918 | |||
| 5d4c38032f | |||
| 7123b2c57b | |||
| fc00bdee63 | |||
| a056703da0 | |||
| 3f9502072d | |||
| 2d254d6a7e | |||
| a7e3dca917 | |||
| 5d8408287f | |||
| 30beca9118 | |||
| 8946b81dbd | |||
| db96e1a901 | |||
| 8b4e0361c4 | |||
| 22cb5b7379 | |||
| 2d0117d096 | |||
| 035bda4eac | |||
| 50906214e5 | |||
| e505f274b6 | |||
| fe52f44dca | |||
| 3146e5a50f | 
@ -3,7 +3,6 @@ import "@goauthentik/admin/applications/ApplicationCheckAccessForm";
 | 
				
			|||||||
import "@goauthentik/admin/applications/ApplicationForm";
 | 
					import "@goauthentik/admin/applications/ApplicationForm";
 | 
				
			||||||
import "@goauthentik/admin/policies/BoundPoliciesList";
 | 
					import "@goauthentik/admin/policies/BoundPoliciesList";
 | 
				
			||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
					import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
				
			||||||
import { PFSize } from "@goauthentik/common/enums.js";
 | 
					 | 
				
			||||||
import "@goauthentik/components/ak-app-icon";
 | 
					import "@goauthentik/components/ak-app-icon";
 | 
				
			||||||
import "@goauthentik/components/events/ObjectChangelog";
 | 
					import "@goauthentik/components/events/ObjectChangelog";
 | 
				
			||||||
import { AKElement } from "@goauthentik/elements/Base";
 | 
					import { AKElement } from "@goauthentik/elements/Base";
 | 
				
			||||||
@ -13,10 +12,8 @@ import "@goauthentik/elements/Tabs";
 | 
				
			|||||||
import "@goauthentik/elements/buttons/SpinnerButton";
 | 
					import "@goauthentik/elements/buttons/SpinnerButton";
 | 
				
			||||||
import "@goauthentik/elements/rbac/ObjectPermissionsPage";
 | 
					import "@goauthentik/elements/rbac/ObjectPermissionsPage";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { msg } from "@lit/localize";
 | 
					import { PropertyValues } from "lit";
 | 
				
			||||||
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
 | 
					 | 
				
			||||||
import { customElement, property, state } from "lit/decorators.js";
 | 
					import { customElement, property, state } from "lit/decorators.js";
 | 
				
			||||||
import { ifDefined } from "lit/directives/if-defined.js";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import PFBanner from "@patternfly/patternfly/components/Banner/banner.css";
 | 
					import PFBanner from "@patternfly/patternfly/components/Banner/banner.css";
 | 
				
			||||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
 | 
					import PFButton from "@patternfly/patternfly/components/Button/button.css";
 | 
				
			||||||
@ -35,18 +32,14 @@ import {
 | 
				
			|||||||
    RbacPermissionsAssignedByUsersListModelEnum,
 | 
					    RbacPermissionsAssignedByUsersListModelEnum,
 | 
				
			||||||
} from "@goauthentik/api";
 | 
					} from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    ApplicationViewPageLoadingRenderer,
 | 
				
			||||||
 | 
					    ApplicationViewPageRenderer,
 | 
				
			||||||
 | 
					} from "./ApplicationViewPageRenderers.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@customElement("ak-application-view")
 | 
					@customElement("ak-application-view")
 | 
				
			||||||
export class ApplicationViewPage extends AKElement {
 | 
					export class ApplicationViewPage extends AKElement {
 | 
				
			||||||
    @property({ type: String })
 | 
					    static get styles() {
 | 
				
			||||||
    applicationSlug?: string;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @state()
 | 
					 | 
				
			||||||
    application?: Application;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @state()
 | 
					 | 
				
			||||||
    missingOutpost = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static get styles(): CSSResult[] {
 | 
					 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            PFBase,
 | 
					            PFBase,
 | 
				
			||||||
            PFList,
 | 
					            PFList,
 | 
				
			||||||
@ -60,6 +53,15 @@ export class ApplicationViewPage extends AKElement {
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property({ type: String })
 | 
				
			||||||
 | 
					    applicationSlug?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @state()
 | 
				
			||||||
 | 
					    application?: Application;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @state()
 | 
				
			||||||
 | 
					    missingOutpost = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fetchIsMissingOutpost(providersByPk: Array<number>) {
 | 
					    fetchIsMissingOutpost(providersByPk: Array<number>) {
 | 
				
			||||||
        new OutpostsApi(DEFAULT_CONFIG)
 | 
					        new OutpostsApi(DEFAULT_CONFIG)
 | 
				
			||||||
            .outpostsInstancesList({
 | 
					            .outpostsInstancesList({
 | 
				
			||||||
@ -94,231 +96,15 @@ export class ApplicationViewPage extends AKElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render(): TemplateResult {
 | 
					    render() {
 | 
				
			||||||
        return html`<ak-page-header
 | 
					        const renderer = this.application
 | 
				
			||||||
                header=${this.application?.name || msg("Loading")}
 | 
					            ? new ApplicationViewPageRenderer(
 | 
				
			||||||
                description=${ifDefined(this.application?.metaPublisher)}
 | 
					                  this.application,
 | 
				
			||||||
                .iconImage=${true}
 | 
					                  this.missingOutpost,
 | 
				
			||||||
            >
 | 
					                  RbacPermissionsAssignedByUsersListModelEnum.CoreApplication,
 | 
				
			||||||
                <ak-app-icon
 | 
					              )
 | 
				
			||||||
                    size=${PFSize.Medium}
 | 
					            : new ApplicationViewPageLoadingRenderer();
 | 
				
			||||||
                    slot="icon"
 | 
					 | 
				
			||||||
                    .app=${this.application}
 | 
					 | 
				
			||||||
                ></ak-app-icon>
 | 
					 | 
				
			||||||
            </ak-page-header>
 | 
					 | 
				
			||||||
            ${this.renderApp()}`;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    renderApp(): TemplateResult {
 | 
					        return renderer.render();
 | 
				
			||||||
        if (!this.application) {
 | 
					 | 
				
			||||||
            return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
 | 
					 | 
				
			||||||
            </ak-empty-state>`;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return html`<ak-tabs>
 | 
					 | 
				
			||||||
            ${this.missingOutpost
 | 
					 | 
				
			||||||
                ? html`<div slot="header" class="pf-c-banner pf-m-warning">
 | 
					 | 
				
			||||||
                      ${msg("Warning: Application is not used by any Outpost.")}
 | 
					 | 
				
			||||||
                  </div>`
 | 
					 | 
				
			||||||
                : html``}
 | 
					 | 
				
			||||||
            <section
 | 
					 | 
				
			||||||
                slot="page-overview"
 | 
					 | 
				
			||||||
                data-tab-title="${msg("Overview")}"
 | 
					 | 
				
			||||||
                class="pf-c-page__main-section pf-m-no-padding-mobile"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
                <div class="pf-l-grid pf-m-gutter">
 | 
					 | 
				
			||||||
                    <div
 | 
					 | 
				
			||||||
                        class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl"
 | 
					 | 
				
			||||||
                    >
 | 
					 | 
				
			||||||
                        <div class="pf-c-card__title">${msg("Related")}</div>
 | 
					 | 
				
			||||||
                        <div class="pf-c-card__body">
 | 
					 | 
				
			||||||
                            <dl class="pf-c-description-list">
 | 
					 | 
				
			||||||
                                ${this.application.providerObj
 | 
					 | 
				
			||||||
                                    ? html`<div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                                          <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                              <span class="pf-c-description-list__text"
 | 
					 | 
				
			||||||
                                                  >${msg("Provider")}</span
 | 
					 | 
				
			||||||
                                              >
 | 
					 | 
				
			||||||
                                          </dt>
 | 
					 | 
				
			||||||
                                          <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                              <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                                  <a
 | 
					 | 
				
			||||||
                                                      href="#/core/providers/${this.application
 | 
					 | 
				
			||||||
                                                          .providerObj?.pk}"
 | 
					 | 
				
			||||||
                                                  >
 | 
					 | 
				
			||||||
                                                      ${this.application.providerObj?.name}
 | 
					 | 
				
			||||||
                                                      (${this.application.providerObj?.verboseName})
 | 
					 | 
				
			||||||
                                                  </a>
 | 
					 | 
				
			||||||
                                              </div>
 | 
					 | 
				
			||||||
                                          </dd>
 | 
					 | 
				
			||||||
                                      </div>`
 | 
					 | 
				
			||||||
                                    : html``}
 | 
					 | 
				
			||||||
                                ${(this.application.backchannelProvidersObj || []).length > 0
 | 
					 | 
				
			||||||
                                    ? html`<div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                                          <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                              <span class="pf-c-description-list__text"
 | 
					 | 
				
			||||||
                                                  >${msg("Backchannel Providers")}</span
 | 
					 | 
				
			||||||
                                              >
 | 
					 | 
				
			||||||
                                          </dt>
 | 
					 | 
				
			||||||
                                          <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                              <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                                  <ul class="pf-c-list">
 | 
					 | 
				
			||||||
                                                      ${this.application.backchannelProvidersObj.map(
 | 
					 | 
				
			||||||
                                                          (provider) => {
 | 
					 | 
				
			||||||
                                                              return html`
 | 
					 | 
				
			||||||
                                                                  <li>
 | 
					 | 
				
			||||||
                                                                      <a
 | 
					 | 
				
			||||||
                                                                          href="#/core/providers/${provider.pk}"
 | 
					 | 
				
			||||||
                                                                      >
 | 
					 | 
				
			||||||
                                                                          ${provider.name}
 | 
					 | 
				
			||||||
                                                                          (${provider.verboseName})
 | 
					 | 
				
			||||||
                                                                      </a>
 | 
					 | 
				
			||||||
                                                                  </li>
 | 
					 | 
				
			||||||
                                                              `;
 | 
					 | 
				
			||||||
                                                          },
 | 
					 | 
				
			||||||
                                                      )}
 | 
					 | 
				
			||||||
                                                  </ul>
 | 
					 | 
				
			||||||
                                              </div>
 | 
					 | 
				
			||||||
                                          </dd>
 | 
					 | 
				
			||||||
                                      </div>`
 | 
					 | 
				
			||||||
                                    : html``}
 | 
					 | 
				
			||||||
                                <div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                                    <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                        <span class="pf-c-description-list__text"
 | 
					 | 
				
			||||||
                                            >${msg("Policy engine mode")}</span
 | 
					 | 
				
			||||||
                                        >
 | 
					 | 
				
			||||||
                                    </dt>
 | 
					 | 
				
			||||||
                                    <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                        <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                            ${this.application.policyEngineMode?.toUpperCase()}
 | 
					 | 
				
			||||||
                                        </div>
 | 
					 | 
				
			||||||
                                    </dd>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                                <div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                                    <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                        <span class="pf-c-description-list__text"
 | 
					 | 
				
			||||||
                                            >${msg("Edit")}</span
 | 
					 | 
				
			||||||
                                        >
 | 
					 | 
				
			||||||
                                    </dt>
 | 
					 | 
				
			||||||
                                    <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                        <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                            <ak-forms-modal>
 | 
					 | 
				
			||||||
                                                <span slot="submit"> ${msg("Update")} </span>
 | 
					 | 
				
			||||||
                                                <span slot="header">
 | 
					 | 
				
			||||||
                                                    ${msg("Update Application")}
 | 
					 | 
				
			||||||
                                                </span>
 | 
					 | 
				
			||||||
                                                <ak-application-form
 | 
					 | 
				
			||||||
                                                    slot="form"
 | 
					 | 
				
			||||||
                                                    .instancePk=${this.application.slug}
 | 
					 | 
				
			||||||
                                                >
 | 
					 | 
				
			||||||
                                                </ak-application-form>
 | 
					 | 
				
			||||||
                                                <button
 | 
					 | 
				
			||||||
                                                    slot="trigger"
 | 
					 | 
				
			||||||
                                                    class="pf-c-button pf-m-secondary"
 | 
					 | 
				
			||||||
                                                >
 | 
					 | 
				
			||||||
                                                    ${msg("Edit")}
 | 
					 | 
				
			||||||
                                                </button>
 | 
					 | 
				
			||||||
                                            </ak-forms-modal>
 | 
					 | 
				
			||||||
                                        </div>
 | 
					 | 
				
			||||||
                                    </dd>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                                <div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                                    <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                        <span class="pf-c-description-list__text"
 | 
					 | 
				
			||||||
                                            >${msg("Check access")}</span
 | 
					 | 
				
			||||||
                                        >
 | 
					 | 
				
			||||||
                                    </dt>
 | 
					 | 
				
			||||||
                                    <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                        <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                            <ak-forms-modal .closeAfterSuccessfulSubmit=${false}>
 | 
					 | 
				
			||||||
                                                <span slot="submit"> ${msg("Check")} </span>
 | 
					 | 
				
			||||||
                                                <span slot="header">
 | 
					 | 
				
			||||||
                                                    ${msg("Check Application access")}
 | 
					 | 
				
			||||||
                                                </span>
 | 
					 | 
				
			||||||
                                                <ak-application-check-access-form
 | 
					 | 
				
			||||||
                                                    slot="form"
 | 
					 | 
				
			||||||
                                                    .application=${this.application}
 | 
					 | 
				
			||||||
                                                >
 | 
					 | 
				
			||||||
                                                </ak-application-check-access-form>
 | 
					 | 
				
			||||||
                                                <button
 | 
					 | 
				
			||||||
                                                    slot="trigger"
 | 
					 | 
				
			||||||
                                                    class="pf-c-button pf-m-secondary"
 | 
					 | 
				
			||||||
                                                >
 | 
					 | 
				
			||||||
                                                    ${msg("Test")}
 | 
					 | 
				
			||||||
                                                </button>
 | 
					 | 
				
			||||||
                                            </ak-forms-modal>
 | 
					 | 
				
			||||||
                                        </div>
 | 
					 | 
				
			||||||
                                    </dd>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                                ${this.application.launchUrl
 | 
					 | 
				
			||||||
                                    ? html`<div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                                          <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                              <span class="pf-c-description-list__text"
 | 
					 | 
				
			||||||
                                                  >${msg("Launch")}</span
 | 
					 | 
				
			||||||
                                              >
 | 
					 | 
				
			||||||
                                          </dt>
 | 
					 | 
				
			||||||
                                          <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                              <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                                  <a
 | 
					 | 
				
			||||||
                                                      target="_blank"
 | 
					 | 
				
			||||||
                                                      href=${this.application.launchUrl}
 | 
					 | 
				
			||||||
                                                      slot="trigger"
 | 
					 | 
				
			||||||
                                                      class="pf-c-button pf-m-secondary"
 | 
					 | 
				
			||||||
                                                  >
 | 
					 | 
				
			||||||
                                                      ${msg("Launch")}
 | 
					 | 
				
			||||||
                                                  </a>
 | 
					 | 
				
			||||||
                                              </div>
 | 
					 | 
				
			||||||
                                          </dd>
 | 
					 | 
				
			||||||
                                      </div>`
 | 
					 | 
				
			||||||
                                    : html``}
 | 
					 | 
				
			||||||
                            </dl>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div
 | 
					 | 
				
			||||||
                        class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-10-col-on-xl pf-m-10-col-on-2xl"
 | 
					 | 
				
			||||||
                    >
 | 
					 | 
				
			||||||
                        <div class="pf-c-card__title">
 | 
					 | 
				
			||||||
                            ${msg("Logins over the last week (per 8 hours)")}
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div class="pf-c-card__body">
 | 
					 | 
				
			||||||
                            ${this.application &&
 | 
					 | 
				
			||||||
                            html` <ak-charts-application-authorize
 | 
					 | 
				
			||||||
                                applicationSlug=${this.application.slug}
 | 
					 | 
				
			||||||
                            >
 | 
					 | 
				
			||||||
                            </ak-charts-application-authorize>`}
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="pf-c-card pf-l-grid__item pf-m-12-col">
 | 
					 | 
				
			||||||
                        <div class="pf-c-card__title">${msg("Changelog")}</div>
 | 
					 | 
				
			||||||
                        <div class="pf-c-card__body">
 | 
					 | 
				
			||||||
                            <ak-object-changelog
 | 
					 | 
				
			||||||
                                targetModelPk=${this.application.pk || ""}
 | 
					 | 
				
			||||||
                                targetModelApp="authentik_core"
 | 
					 | 
				
			||||||
                                targetModelName="application"
 | 
					 | 
				
			||||||
                            >
 | 
					 | 
				
			||||||
                            </ak-object-changelog>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </section>
 | 
					 | 
				
			||||||
            <section
 | 
					 | 
				
			||||||
                slot="page-policy-bindings"
 | 
					 | 
				
			||||||
                data-tab-title="${msg("Policy / Group / User Bindings")}"
 | 
					 | 
				
			||||||
                class="pf-c-page__main-section pf-m-no-padding-mobile"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
                <div class="pf-c-card">
 | 
					 | 
				
			||||||
                    <div class="pf-c-card__title">
 | 
					 | 
				
			||||||
                        ${msg("These policies control which users can access this application.")}
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <ak-bound-policies-list .target=${this.application.pk}>
 | 
					 | 
				
			||||||
                    </ak-bound-policies-list>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </section>
 | 
					 | 
				
			||||||
            <ak-rbac-object-permission-page
 | 
					 | 
				
			||||||
                slot="page-permissions"
 | 
					 | 
				
			||||||
                data-tab-title="${msg("Permissions")}"
 | 
					 | 
				
			||||||
                model=${RbacPermissionsAssignedByUsersListModelEnum.CoreApplication}
 | 
					 | 
				
			||||||
                objectPk=${this.application.pk}
 | 
					 | 
				
			||||||
            ></ak-rbac-object-permission-page>
 | 
					 | 
				
			||||||
        </ak-tabs>`;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										214
									
								
								web/src/admin/applications/ApplicationViewPageRenderers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								web/src/admin/applications/ApplicationViewPageRenderers.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,214 @@
 | 
				
			|||||||
 | 
					import { PFSize } from "@goauthentik/common/enums.js";
 | 
				
			||||||
 | 
					import { DescriptionPair, renderDescriptionList } from "@goauthentik/components/DescriptionList.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { msg } from "@lit/localize";
 | 
				
			||||||
 | 
					import { html, nothing } from "lit";
 | 
				
			||||||
 | 
					import { ifDefined } from "lit/directives/if-defined.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type { Application, RbacPermissionsAssignedByUsersListModelEnum } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class ApplicationViewPageLoadingRenderer {
 | 
				
			||||||
 | 
					    constructor() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        return html`<ak-page-header header=${msg("Loading")}
 | 
				
			||||||
 | 
					            ><ak-empty-state ?loading="${true}" header=${msg("Loading")}> </ak-empty-state
 | 
				
			||||||
 | 
					        ></ak-page-header>`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class ApplicationViewPageRenderer {
 | 
				
			||||||
 | 
					    constructor(
 | 
				
			||||||
 | 
					        private app: Application,
 | 
				
			||||||
 | 
					        private noOutpost: boolean,
 | 
				
			||||||
 | 
					        private rbacModel: RbacPermissionsAssignedByUsersListModelEnum,
 | 
				
			||||||
 | 
					    ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    missingOutpostMessage() {
 | 
				
			||||||
 | 
					        return this.noOutpost
 | 
				
			||||||
 | 
					            ? html`<div slot="header" class="pf-c-banner pf-m-warning">
 | 
				
			||||||
 | 
					                  ${msg("Warning: Application is not used by any Outpost.")}
 | 
				
			||||||
 | 
					              </div>`
 | 
				
			||||||
 | 
					            : nothing;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    controlCardContents(app: Application): DescriptionPair[] {
 | 
				
			||||||
 | 
					        // prettier-ignore
 | 
				
			||||||
 | 
					        const rows: (DescriptionPair | null)[] = [
 | 
				
			||||||
 | 
					            app.providerObj
 | 
				
			||||||
 | 
					                ? [
 | 
				
			||||||
 | 
					                      msg("Provider"),
 | 
				
			||||||
 | 
					                      html`
 | 
				
			||||||
 | 
					                          <a href="#/core/providers/${app.providerObj?.pk}">
 | 
				
			||||||
 | 
					                              ${app.providerObj?.name} (${app.providerObj?.verboseName})
 | 
				
			||||||
 | 
					                          </a>
 | 
				
			||||||
 | 
					                      `,
 | 
				
			||||||
 | 
					                  ]
 | 
				
			||||||
 | 
					                : null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            (app.backchannelProvidersObj || []).length > 0
 | 
				
			||||||
 | 
					                ? [
 | 
				
			||||||
 | 
					                      msg("Backchannel Providers"),
 | 
				
			||||||
 | 
					                      html`
 | 
				
			||||||
 | 
					                          <ul class="pf-c-list">
 | 
				
			||||||
 | 
					                              ${app.backchannelProvidersObj.map((provider) => {
 | 
				
			||||||
 | 
					                                  return html`
 | 
				
			||||||
 | 
					                                      <li>
 | 
				
			||||||
 | 
					                                          <a href="#/core/providers/${provider.pk}">
 | 
				
			||||||
 | 
					                                              ${provider.name} (${provider.verboseName})
 | 
				
			||||||
 | 
					                                          </a>
 | 
				
			||||||
 | 
					                                      </li>
 | 
				
			||||||
 | 
					                                  `;
 | 
				
			||||||
 | 
					                              })}
 | 
				
			||||||
 | 
					                          </ul>
 | 
				
			||||||
 | 
					                      `,
 | 
				
			||||||
 | 
					                  ]
 | 
				
			||||||
 | 
					                : null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                msg("Policy engine mode"), 
 | 
				
			||||||
 | 
					                app.policyEngineMode?.toUpperCase()
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                msg("Edit"),
 | 
				
			||||||
 | 
					                html`
 | 
				
			||||||
 | 
					                    <ak-forms-modal>
 | 
				
			||||||
 | 
					                        <span slot="submit"> ${msg("Update")} </span>
 | 
				
			||||||
 | 
					                        <span slot="header"> ${msg("Update Application")} </span>
 | 
				
			||||||
 | 
					                        <ak-application-form slot="form" .instancePk=${app.slug}>
 | 
				
			||||||
 | 
					                        </ak-application-form>
 | 
				
			||||||
 | 
					                        <button slot="trigger" class="pf-c-button pf-m-secondary">
 | 
				
			||||||
 | 
					                            ${msg("Edit")}
 | 
				
			||||||
 | 
					                        </button>
 | 
				
			||||||
 | 
					                    </ak-forms-modal>
 | 
				
			||||||
 | 
					                `,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                msg("Check access"),
 | 
				
			||||||
 | 
					                html`
 | 
				
			||||||
 | 
					                    <ak-forms-modal .closeAfterSuccessfulSubmit=${false}>
 | 
				
			||||||
 | 
					                        <span slot="submit"> ${msg("Check")} </span>
 | 
				
			||||||
 | 
					                        <span slot="header"> ${msg("Check Application access")} </span>
 | 
				
			||||||
 | 
					                        <ak-application-check-access-form slot="form" .application=${app}>
 | 
				
			||||||
 | 
					                        </ak-application-check-access-form>
 | 
				
			||||||
 | 
					                        <button slot="trigger" class="pf-c-button pf-m-secondary">
 | 
				
			||||||
 | 
					                            ${msg("Test")}
 | 
				
			||||||
 | 
					                        </button>
 | 
				
			||||||
 | 
					                    </ak-forms-modal>
 | 
				
			||||||
 | 
					                `,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.launchUrl
 | 
				
			||||||
 | 
					                ? [
 | 
				
			||||||
 | 
					                      msg("Launch"),
 | 
				
			||||||
 | 
					                      html`
 | 
				
			||||||
 | 
					                          <a
 | 
				
			||||||
 | 
					                              target="_blank"
 | 
				
			||||||
 | 
					                              href=${app.launchUrl}
 | 
				
			||||||
 | 
					                              slot="trigger"
 | 
				
			||||||
 | 
					                              class="pf-c-button pf-m-secondary"
 | 
				
			||||||
 | 
					                          >
 | 
				
			||||||
 | 
					                              ${msg("Launch")}
 | 
				
			||||||
 | 
					                          </a>
 | 
				
			||||||
 | 
					                      `,
 | 
				
			||||||
 | 
					                  ]
 | 
				
			||||||
 | 
					                : null,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return rows.filter((row) => row !== null) as DescriptionPair[];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    controlCard(app: Application) {
 | 
				
			||||||
 | 
					        return html`
 | 
				
			||||||
 | 
					            <div class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl">
 | 
				
			||||||
 | 
					                <div class="pf-c-card__title">${msg("Related")}</div>
 | 
				
			||||||
 | 
					                <div class="pf-c-card__body">
 | 
				
			||||||
 | 
					                    ${renderDescriptionList(this.controlCardContents(app))}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        `;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    loginsChart(app: Application) {
 | 
				
			||||||
 | 
					        return html`<div
 | 
				
			||||||
 | 
					            class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-10-col-on-xl pf-m-10-col-on-2xl"
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            <div class="pf-c-card__title">${msg("Logins over the last week (per 8 hours)")}</div>
 | 
				
			||||||
 | 
					            <div class="pf-c-card__body">
 | 
				
			||||||
 | 
					                ${app &&
 | 
				
			||||||
 | 
					                html` <ak-charts-application-authorize applicationSlug=${app.slug}>
 | 
				
			||||||
 | 
					                </ak-charts-application-authorize>`}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    changelog(app: Application) {
 | 
				
			||||||
 | 
					        return html`
 | 
				
			||||||
 | 
					            <div class="pf-c-card pf-l-grid__item pf-m-12-col">
 | 
				
			||||||
 | 
					                <div class="pf-c-card__title">${msg("Changelog")}</div>
 | 
				
			||||||
 | 
					                <div class="pf-c-card__body">
 | 
				
			||||||
 | 
					                    <ak-object-changelog
 | 
				
			||||||
 | 
					                        targetModelPk=${app.pk || ""}
 | 
				
			||||||
 | 
					                        targetModelApp="authentik_core"
 | 
				
			||||||
 | 
					                        targetModelName="application"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                    </ak-object-changelog>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        `;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    overview(app: Application) {
 | 
				
			||||||
 | 
					        return html` 
 | 
				
			||||||
 | 
					            <div class="pf-l-grid pf-m-gutter">
 | 
				
			||||||
 | 
					                ${this.controlCard(app)} ${this.loginsChart(app)} ${this.changelog(app)}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </section>`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    policiesList(app: Application) {
 | 
				
			||||||
 | 
					        return html`
 | 
				
			||||||
 | 
					            <div class="pf-c-card">
 | 
				
			||||||
 | 
					                <div class="pf-c-card__title">
 | 
				
			||||||
 | 
					                    ${msg("These policies control which users can access this application.")}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <ak-bound-policies-list .target=${app.pk}> </ak-bound-policies-list>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        `;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        return html` <ak-page-header
 | 
				
			||||||
 | 
					                header=${this.app.name}
 | 
				
			||||||
 | 
					                description=${ifDefined(this.app.metaPublisher)}
 | 
				
			||||||
 | 
					                .iconImage=${true}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					                <ak-app-icon size=${PFSize.Medium} slot="icon" .app=${this.app}></ak-app-icon>
 | 
				
			||||||
 | 
					            </ak-page-header>
 | 
				
			||||||
 | 
					            <ak-tabs>
 | 
				
			||||||
 | 
					                ${this.missingOutpostMessage()}
 | 
				
			||||||
 | 
					                <section
 | 
				
			||||||
 | 
					                    slot="page-overview"
 | 
				
			||||||
 | 
					                    data-tab-title="${msg("Overview")}"
 | 
				
			||||||
 | 
					                    class="pf-c-page__main-section pf-m-no-padding-mobile"
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    ${this.overview(this.app)}
 | 
				
			||||||
 | 
					                </section>
 | 
				
			||||||
 | 
					                <section
 | 
				
			||||||
 | 
					                    slot="page-policy-bindings"
 | 
				
			||||||
 | 
					                    data-tab-title="${msg("Policy / Group / User Bindings")}"
 | 
				
			||||||
 | 
					                    class="pf-c-page__main-section pf-m-no-padding-mobile"
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    ${this.policiesList(this.app)}
 | 
				
			||||||
 | 
					                </section>
 | 
				
			||||||
 | 
					                <ak-rbac-object-permission-page
 | 
				
			||||||
 | 
					                    slot="page-permissions"
 | 
				
			||||||
 | 
					                    data-tab-title="${msg("Permissions")}"
 | 
				
			||||||
 | 
					                    model=${this.rbacModel}
 | 
				
			||||||
 | 
					                    objectPk=${this.app.pk}
 | 
				
			||||||
 | 
					                ></ak-rbac-object-permission-page>
 | 
				
			||||||
 | 
					            </ak-tabs>`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,8 +2,9 @@ import { AKElement } from "@goauthentik/elements/Base";
 | 
				
			|||||||
import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter";
 | 
					import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { msg } from "@lit/localize";
 | 
					import { msg } from "@lit/localize";
 | 
				
			||||||
 | 
					import { PropertyValues } from "@lit/reactive-element/reactive-element";
 | 
				
			||||||
import { TemplateResult, css, html } from "lit";
 | 
					import { TemplateResult, css, html } from "lit";
 | 
				
			||||||
import { customElement, property, queryAll } from "lit/decorators.js";
 | 
					import { customElement, property, queryAll, state } from "lit/decorators.js";
 | 
				
			||||||
import { map } from "lit/directives/map.js";
 | 
					import { map } from "lit/directives/map.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import PFCheck from "@patternfly/patternfly/components/Check/check.css";
 | 
					import PFCheck from "@patternfly/patternfly/components/Check/check.css";
 | 
				
			||||||
@ -112,10 +113,14 @@ export class CheckboxGroup extends AkElementWithCustomEvents {
 | 
				
			|||||||
    @queryAll('input[type="checkbox"]')
 | 
					    @queryAll('input[type="checkbox"]')
 | 
				
			||||||
    checkboxes!: NodeListOf<HTMLInputElement>;
 | 
					    checkboxes!: NodeListOf<HTMLInputElement>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    internals?: ElementInternals;
 | 
					    @state()
 | 
				
			||||||
 | 
					    values: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get json() {
 | 
					    internals?: ElementInternals;
 | 
				
			||||||
        return this.value;
 | 
					    doneFirstUpdate = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    json() {
 | 
				
			||||||
 | 
					        return this.values;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private get formValue() {
 | 
					    private get formValue() {
 | 
				
			||||||
@ -124,7 +129,7 @@ export class CheckboxGroup extends AkElementWithCustomEvents {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        const name = this.name;
 | 
					        const name = this.name;
 | 
				
			||||||
        const entries = new FormData();
 | 
					        const entries = new FormData();
 | 
				
			||||||
        this.value.forEach((v) => entries.append(name, v));
 | 
					        this.values.forEach((v) => entries.append(name, v));
 | 
				
			||||||
        return entries;
 | 
					        return entries;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -136,14 +141,14 @@ export class CheckboxGroup extends AkElementWithCustomEvents {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    onClick(ev: Event) {
 | 
					    onClick(ev: Event) {
 | 
				
			||||||
        ev.stopPropagation();
 | 
					        ev.stopPropagation();
 | 
				
			||||||
        this.value = Array.from(this.checkboxes)
 | 
					        this.values = Array.from(this.checkboxes)
 | 
				
			||||||
            .filter((checkbox) => checkbox.checked)
 | 
					            .filter((checkbox) => checkbox.checked)
 | 
				
			||||||
            .map((checkbox) => checkbox.name);
 | 
					            .map((checkbox) => checkbox.name);
 | 
				
			||||||
        this.dispatchCustomEvent("change", this.value);
 | 
					        this.dispatchCustomEvent("change", this.values);
 | 
				
			||||||
        this.dispatchCustomEvent("input", this.value);
 | 
					        this.dispatchCustomEvent("input", this.values);
 | 
				
			||||||
        if (this.internals) {
 | 
					        if (this.internals) {
 | 
				
			||||||
            this.internals.setValidity({});
 | 
					            this.internals.setValidity({});
 | 
				
			||||||
            if (this.required && this.value.length === 0) {
 | 
					            if (this.required && this.values.length === 0) {
 | 
				
			||||||
                this.internals.setValidity(
 | 
					                this.internals.setValidity(
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        valueMissing: true,
 | 
					                        valueMissing: true,
 | 
				
			||||||
@ -154,6 +159,16 @@ export class CheckboxGroup extends AkElementWithCustomEvents {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            this.internals.setFormValue(this.formValue);
 | 
					            this.internals.setFormValue(this.formValue);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        // Doing a write-back so anyone examining the checkbox.value field will get something
 | 
				
			||||||
 | 
					        // meaningful. Doesn't do anything for anyone, usually, but it's nice to have.
 | 
				
			||||||
 | 
					        this.value = this.values;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    willUpdate(changed: PropertyValues<this>) {
 | 
				
			||||||
 | 
					        if (changed.has("value") && !this.doneFirstUpdate) {
 | 
				
			||||||
 | 
					            this.doneFirstUpdate = true;
 | 
				
			||||||
 | 
					            this.values = this.value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connectedCallback() {
 | 
					    connectedCallback() {
 | 
				
			||||||
@ -183,7 +198,7 @@ export class CheckboxGroup extends AkElementWithCustomEvents {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const renderOne = ([name, label]: CheckboxPr) => {
 | 
					        const renderOne = ([name, label]: CheckboxPr) => {
 | 
				
			||||||
            const selected = this.value.includes(name);
 | 
					            const selected = this.values.includes(name);
 | 
				
			||||||
            const blockFwd = (e: Event) => {
 | 
					            const blockFwd = (e: Event) => {
 | 
				
			||||||
                e.stopImmediatePropagation();
 | 
					                e.stopImmediatePropagation();
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
				
			|||||||
@ -53,6 +53,9 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private isLoading = false;
 | 
					    private isLoading = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private doneFirstUpdate = false;
 | 
				
			||||||
 | 
					    private internalSelected: DualSelectPair[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private pagination?: Pagination;
 | 
					    private pagination?: Pagination;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
@ -69,6 +72,11 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    willUpdate(changedProperties: PropertyValues<this>) {
 | 
					    willUpdate(changedProperties: PropertyValues<this>) {
 | 
				
			||||||
 | 
					        if (changedProperties.has("selected") && !this.doneFirstUpdate) {
 | 
				
			||||||
 | 
					            this.doneFirstUpdate = true;
 | 
				
			||||||
 | 
					            this.internalSelected = this.selected;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (changedProperties.has("searchDelay")) {
 | 
					        if (changedProperties.has("searchDelay")) {
 | 
				
			||||||
            this.doSearch = debounce(
 | 
					            this.doSearch = debounce(
 | 
				
			||||||
                AkDualSelectProvider.prototype.doSearch.bind(this),
 | 
					                AkDualSelectProvider.prototype.doSearch.bind(this),
 | 
				
			||||||
@ -105,7 +113,8 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
 | 
				
			|||||||
        if (!(event instanceof CustomEvent)) {
 | 
					        if (!(event instanceof CustomEvent)) {
 | 
				
			||||||
            throw new Error(`Expecting a CustomEvent for change, received ${event} instead`);
 | 
					            throw new Error(`Expecting a CustomEvent for change, received ${event} instead`);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.selected = event.detail.value;
 | 
					        this.internalSelected = event.detail.value;
 | 
				
			||||||
 | 
					        this.selected = this.internalSelected;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onSearch(event: Event) {
 | 
					    onSearch(event: Event) {
 | 
				
			||||||
@ -124,12 +133,16 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
 | 
				
			|||||||
        return this.dualSelector.value!.selected.map(([k, _]) => k);
 | 
					        return this.dualSelector.value!.selected.map(([k, _]) => k);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    json() {
 | 
				
			||||||
 | 
					        return this.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        return html`<ak-dual-select
 | 
					        return html`<ak-dual-select
 | 
				
			||||||
            ${ref(this.dualSelector)}
 | 
					            ${ref(this.dualSelector)}
 | 
				
			||||||
            .options=${this.options}
 | 
					            .options=${this.options}
 | 
				
			||||||
            .pages=${this.pagination}
 | 
					            .pages=${this.pagination}
 | 
				
			||||||
            .selected=${this.selected}
 | 
					            .selected=${this.internalSelected}
 | 
				
			||||||
            available-label=${this.availableLabel}
 | 
					            available-label=${this.availableLabel}
 | 
				
			||||||
            selected-label=${this.selectedLabel}
 | 
					            selected-label=${this.selectedLabel}
 | 
				
			||||||
        ></ak-dual-select>`;
 | 
					        ></ak-dual-select>`;
 | 
				
			||||||
 | 
				
			|||||||
@ -80,7 +80,7 @@ export function serializeForm<T extends KeyUnknown>(
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ("akControl" in inputElement.dataset) {
 | 
					        if ("akControl" in inputElement.dataset) {
 | 
				
			||||||
            assignValue(element, inputElement.value, json);
 | 
					            assignValue(element, (inputElement as unknown as AkControlElement).json(), json);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user