web/flows: clean up loading, syntax and transitions (#10792)

* remove redundant bindings to ${true}

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* better ui for loading during autosubmit

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* default to loading label when setting ?loading

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove more html``

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* refactor non_field_errors

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove more html``

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* no loading label for overlay

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix py

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Revert "web: bump the wdio group across 2 directories with 5 updates (#10945)"

This reverts commit ea14c57989.

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L.
2024-08-16 14:10:08 +02:00
committed by GitHub
parent 4b21588d8b
commit c3d3646645
36 changed files with 2454 additions and 3829 deletions

View File

@ -11,6 +11,7 @@ import { WebsocketClient } from "@goauthentik/common/ws";
import { Interface } from "@goauthentik/elements/Interface";
import "@goauthentik/elements/LoadingOverlay";
import "@goauthentik/elements/ak-locale-context";
import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
import { themeImage } from "@goauthentik/elements/utils/images";
import "@goauthentik/flow/sources/apple/AppleLoginInit";
import "@goauthentik/flow/sources/plex/PlexLoginInit";
@ -281,8 +282,7 @@ export class FlowExecutor extends Interface implements StageHost {
async renderChallenge(): Promise<TemplateResult> {
if (!this.challenge) {
return html`<ak-empty-state ?loading=${true} header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
switch (this.challenge?.component) {
case "ak-stage-access-denied":
@ -428,28 +428,9 @@ export class FlowExecutor extends Interface implements StageHost {
}
}
renderChallengeWrapper(): TemplateResult {
const logo = html`<div class="pf-c-login__main-header pf-c-brand ak-brand">
<img
src="${themeImage(
first(this.brand?.brandingLogo, globalAK()?.brand.brandingLogo, ""),
)}"
alt="authentik Logo"
/>
</div>`;
if (!this.challenge) {
return html`${logo}<ak-empty-state ?loading=${true} header=${msg("Loading")}>
</ak-empty-state>`;
}
return html`
${this.loading ? html`<ak-loading-overlay></ak-loading-overlay>` : nothing} ${logo}
${until(this.renderChallenge())}
`;
}
async renderInspector(): Promise<TemplateResult> {
async renderInspector() {
if (!this.inspectorOpen) {
return html``;
return nothing;
}
await import("@goauthentik/flow/FlowInspector");
return html`<ak-flow-inspector
@ -489,7 +470,24 @@ export class FlowExecutor extends Interface implements StageHost {
<div class="pf-c-login ${this.getLayout()}">
<div class="${this.getLayoutClass()}">
<div class="pf-c-login__main">
${this.renderChallengeWrapper()}
${this.loading && this.challenge
? html`<ak-loading-overlay></ak-loading-overlay>`
: nothing}
<div
class="pf-c-login__main-header pf-c-brand ak-brand"
>
<img
src="${themeImage(
first(
this.brand?.brandingLogo,
globalAK()?.brand.brandingLogo,
DefaultBrand.brandingLogo,
),
)}"
alt="authentik Logo"
/>
</div>
${until(this.renderChallenge())}
</div>
<footer class="pf-c-login__footer">
<ul class="pf-c-list pf-m-inline">

View File

@ -4,7 +4,7 @@ import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/Expand";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
@ -116,8 +116,7 @@ export class FlowInspector extends AKElement {
}
if (!this.state) {
this.advanceHandler();
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<div class="pf-c-drawer__body pf-m-no-padding">
<div class="pf-c-notification-drawer">
@ -269,7 +268,7 @@ ${JSON.stringify(this.getStage(this.state.currentPlan?.nextPlannedStage?.stageOb
</div>
</div>
</li>`
: html``}
: nothing}
${this.state.currentPlan?.nextPlannedStage &&
!this.state.isCompleted
? html`<li
@ -297,7 +296,7 @@ ${JSON.stringify(this.getStage(this.state.currentPlan?.nextPlannedStage?.stageOb
</div>
</div>
</li>`
: html``}
: nothing}
</ol>
</div>
</div>

View File

@ -30,8 +30,7 @@ export class OAuth2DeviceCode extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>
@ -46,7 +45,7 @@ export class OAuth2DeviceCode extends BaseStage<
<p>${msg("Enter the code shown on your device.")}</p>
<ak-form-element
label="${msg("Code")}"
?required="${true}"
required
class="pf-c-form__group"
.errors=${(this.challenge?.responseErrors || {})["code"]}
>

View File

@ -15,8 +15,7 @@ export class DeviceCodeFinish extends BaseStage<
> {
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<ak-empty-state
icon="fas fa-check"

View File

@ -40,11 +40,11 @@ export class AppleLoginInit extends BaseStage<AppleLoginChallenge, AppleChalleng
this.isModalShown = true;
};
document.head.append(appleAuth);
//Listen for authorization success
// Listen for authorization success
document.addEventListener("AppleIDSignInOnSuccess", () => {
//handle successful response
});
//Listen for authorization failures
// Listen for authorization failures
document.addEventListener("AppleIDSignInOnFailure", (error) => {
console.warn(error);
this.isModalShown = false;
@ -57,7 +57,7 @@ export class AppleLoginInit extends BaseStage<AppleLoginChallenge, AppleChalleng
</header>
<div class="pf-c-login__main-body">
<form class="pf-c-form">
<ak-empty-state ?loading="${true}"> </ak-empty-state>
<ak-empty-state loading></ak-empty-state>
${!this.isModalShown
? html`<button
class="pf-c-button pf-m-primary pf-m-block"

View File

@ -72,10 +72,7 @@ export class PlexLoginInit extends BaseStage<
</header>
<div class="pf-c-login__main-body">
<form class="pf-c-form">
<ak-empty-state
?loading="${true}"
header=${msg("Waiting for authentication...")}
>
<ak-empty-state loading header=${msg("Waiting for authentication...")}>
</ak-empty-state>
<hr class="pf-c-divider" />
<p>${msg("If no Plex popup opens, click the button below.")}</p>

View File

@ -3,7 +3,7 @@ import "@goauthentik/flow/FormStatic";
import { BaseStage } from "@goauthentik/flow/stages/base";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement } from "lit/decorators.js";
import PFForm from "@patternfly/patternfly/components/Form/form.css";
@ -38,8 +38,7 @@ export class FlowErrorStage extends BaseStage<FlowErrorChallenge, FlowChallengeR
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>
@ -57,13 +56,13 @@ export class FlowErrorStage extends BaseStage<FlowErrorChallenge, FlowChallengeR
? html`<div class="pf-c-form__group">
<pre class="ak-exception">${this.challenge.traceback}</pre>
</div>`
: html``}
: nothing}
${this.challenge?.requestId
? html`<div class="pf-c-form__group">
<p>${msg("Request ID")}</p>
<code>${this.challenge.requestId}</code>
</div>`
: html``}
: nothing}
</div>
</ak-empty-state>
</form>

View File

@ -66,7 +66,7 @@ export class RedirectStage extends BaseStage<RedirectChallenge, FlowChallengeRes
>
</ak-empty-state>`;
}
return html`<ak-empty-state ?loading=${true} header=${msg("Loading")}> </ak-empty-state>`;
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`;
}
render(): TemplateResult {

View File

@ -26,8 +26,7 @@ export class AccessDeniedStage extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -65,8 +65,7 @@ export class AuthenticatorDuoStage extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -54,7 +54,7 @@ export class AuthenticatorSMSStage extends BaseStage<
</ak-form-static>
<ak-form-element
label="${msg("Phone number")}"
?required="${true}"
required
class="pf-c-form__group"
.errors=${(this.challenge?.responseErrors || {})["phone_number"]}
>
@ -68,11 +68,7 @@ export class AuthenticatorSMSStage extends BaseStage<
required
/>
</ak-form-element>
${"non_field_errors" in (this.challenge?.responseErrors || {})
? this.renderNonFieldErrors(
this.challenge?.responseErrors?.non_field_errors || [],
)
: html``}
${this.renderNonFieldErrors()}
<div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${msg("Continue")}
@ -109,11 +105,10 @@ export class AuthenticatorSMSStage extends BaseStage<
</ak-form-static>
<ak-form-element
label="${msg("Code")}"
?required="${true}"
required
class="pf-c-form__group"
.errors=${(this.challenge?.responseErrors || {})["code"]}
>
<!-- @ts-ignore -->
<input
type="text"
name="code"
@ -126,11 +121,7 @@ export class AuthenticatorSMSStage extends BaseStage<
required
/>
</ak-form-element>
${"non_field_errors" in (this.challenge?.responseErrors || {})
? this.renderNonFieldErrors(
this.challenge?.responseErrors?.non_field_errors || [],
)
: html``}
${this.renderNonFieldErrors()}
<div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${msg("Continue")}
@ -145,8 +136,7 @@ export class AuthenticatorSMSStage extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
if (this.challenge.phoneNumberRequired) {
return this.renderPhoneNumber();

View File

@ -54,8 +54,7 @@ export class AuthenticatorStaticStage extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -48,8 +48,7 @@ export class AuthenticatorTOTPStage extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>
@ -113,7 +112,7 @@ export class AuthenticatorTOTPStage extends BaseStage<
</p>
<ak-form-element
label="${msg("Code")}"
?required="${true}"
required
class="pf-c-form__group"
.errors=${(this.challenge?.responseErrors || {})["code"]}
>

View File

@ -6,7 +6,7 @@ import { BaseStage, StageHost, SubmitOptions } from "@goauthentik/flow/stages/ba
import { PasswordManagerPrefill } from "@goauthentik/flow/stages/identification/IdentificationStage";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement, state } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
@ -112,7 +112,7 @@ export class AuthenticatorValidateStage
`);
}
renderDevicePickerSingle(deviceChallenge: DeviceChallenge): TemplateResult {
renderDevicePickerSingle(deviceChallenge: DeviceChallenge) {
switch (deviceChallenge.deviceClass) {
case DeviceClassesEnum.Duo:
return html`<i class="fas fa-mobile-alt"></i>
@ -147,7 +147,7 @@ export class AuthenticatorValidateStage
default:
break;
}
return html``;
return nothing;
}
renderDevicePicker(): TemplateResult {
@ -192,9 +192,9 @@ export class AuthenticatorValidateStage
</ul>`;
}
renderDeviceChallenge(): TemplateResult {
renderDeviceChallenge() {
if (!this.selectedDeviceChallenge) {
return html``;
return nothing;
}
switch (this.selectedDeviceChallenge?.deviceClass) {
case DeviceClassesEnum.Static:
@ -224,13 +224,12 @@ export class AuthenticatorValidateStage
>
</ak-stage-authenticator-validate-duo>`;
}
return html``;
return nothing;
}
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
// User only has a single device class, so we don't show a picker
if (this.challenge?.deviceChallenges.length === 1) {

View File

@ -33,8 +33,7 @@ export class AuthenticatorValidateStageWebCode extends BaseDeviceStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<div class="pf-c-login__main-body">
<form
@ -63,7 +62,7 @@ export class AuthenticatorValidateStageWebCode extends BaseDeviceStage<
label="${this.deviceChallenge?.deviceClass === DeviceClassesEnum.Static
? msg("Static token")
: msg("Authentication code")}"
?required="${true}"
required
class="pf-c-form__group"
.errors=${(this.challenge?.responseErrors || {})["code"]}
>

View File

@ -47,8 +47,7 @@ export class AuthenticatorValidateStageWebDuo extends BaseDeviceStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
const errors = this.challenge.responseErrors?.duo || [];
const errorMessage = errors.map((err) => err.string);

View File

@ -2,7 +2,7 @@ import { AuthenticatorValidateStage } from "@goauthentik/flow/stages/authenticat
import { BaseStage, FlowInfoChallenge, PendingUserChallenge } from "@goauthentik/flow/stages/base";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { CSSResult, css, html, nothing } from "lit";
import { property } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
@ -48,9 +48,9 @@ export class BaseDeviceStage<
return this.host?.submit(payload) || Promise.resolve();
}
renderReturnToDevicePicker(): TemplateResult {
renderReturnToDevicePicker() {
if (!this.showBackButton) {
return html``;
return nothing;
}
return html`<button
class="pf-c-button pf-m-secondary pf-m-block"

View File

@ -156,7 +156,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage<
? html`<p class="pf-m-block">
${this.challenge.responseErrors["response"][0].string}
</p>`
: html``}
: nothing}
<div class="pf-c-form__group pf-m-action">
${!this.registerRunning
? html` <button

View File

@ -3,7 +3,7 @@ import { BaseStage } from "@goauthentik/flow/stages/base";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { customElement, query } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFForm from "@patternfly/patternfly/components/Form/form.css";
@ -19,43 +19,38 @@ export class AutosubmitStage extends BaseStage<
AutosubmitChallenge,
AutoSubmitChallengeResponseRequest
> {
@query("form")
private form?: HTMLFormElement;
static get styles(): CSSResult[] {
return [PFBase, PFLogin, PFForm, PFFormControl, PFButton, PFTitle];
}
updated(): void {
this.shadowRoot?.querySelectorAll("form").forEach((form) => {
form.submit();
});
this.form?.submit();
}
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
let title = this.challenge.flowInfo?.title;
if (this.challenge.title && this.challenge.title !== "") {
title = this.challenge.title;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${title}</h1>
</header>
<div class="pf-c-login__main-body">
<form class="pf-c-form" action="${this.challenge.url}" method="POST">
${Object.entries(this.challenge.attrs).map(([key, value]) => {
return html`<input
type="hidden"
name="${key as string}"
value="${value as string}"
/>`;
})}
<ak-empty-state ?loading="${true}"> </ak-empty-state>
</form>
</div>
<footer class="pf-c-login__main-footer">
<ul class="pf-c-login__main-footer-links"></ul>
</footer>`;
if (!title) {
title = msg("Loading");
}
return html`<form class="pf-c-form" action="${this.challenge.url}" method="POST">
${Object.entries(this.challenge.attrs).map(([key, value]) => {
return html`<input
type="hidden"
name="${key as string}"
value="${value as string}"
/>`;
})}
<ak-empty-state loading title=${title}> </ak-empty-state>
</form>`;
}
}

View File

@ -2,7 +2,7 @@ import { AKElement } from "@goauthentik/elements/Base";
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { html, nothing } from "lit";
import { property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
@ -43,8 +43,14 @@ export interface PendingUserChallenge {
pendingUserAvatar?: string;
}
export interface ResponseErrorsChallenge {
responseErrors?: {
[key: string]: Array<ErrorDetail>;
};
}
export class BaseStage<
Tin extends FlowInfoChallenge & PendingUserChallenge,
Tin extends FlowInfoChallenge & PendingUserChallenge & ResponseErrorsChallenge,
Tout,
> extends AKElement {
host!: StageHost;
@ -72,12 +78,17 @@ export class BaseStage<
});
}
renderNonFieldErrors(errors: ErrorDetail[]): TemplateResult {
if (!errors) {
return html``;
renderNonFieldErrors() {
const errors = this.challenge?.responseErrors || {};
if (!("non_field_errors" in errors)) {
return nothing;
}
const nonFieldErrors = errors["non_field_errors"];
if (!nonFieldErrors) {
return nothing;
}
return html`<div class="pf-c-form__alert">
${errors.map((err) => {
${nonFieldErrors.map((err) => {
return html`<div class="pf-c-alert pf-m-inline pf-m-danger">
<div class="pf-c-alert__icon">
<i class="fas fa-exclamation-circle"></i>
@ -88,9 +99,9 @@ export class BaseStage<
</div>`;
}
renderUserInfo(): TemplateResult {
renderUserInfo() {
if (!this.challenge.pendingUser || !this.challenge.pendingUserAvatar) {
return html``;
return nothing;
}
return html`
<ak-form-static

View File

@ -157,16 +157,12 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
if (this.captchaInteractive) {
return html`${this.captchaContainer}`;
}
return html`<ak-empty-state
?loading=${true}
header=${msg("Verifying...")}
></ak-empty-state>`;
return html`<ak-empty-state loading header=${msg("Verifying...")}></ak-empty-state>`;
}
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -3,7 +3,7 @@ import "@goauthentik/flow/FormStatic";
import { BaseStage } from "@goauthentik/flow/stages/base";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { CSSResult, TemplateResult, html, nothing } from "lit";
import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
@ -56,7 +56,7 @@ export class ConsentStage extends BaseStage<ConsentChallenge, ConsentChallengeRe
${this.renderPermissions(this.challenge.permissions)}
</ul>
`
: html``}
: nothing}
</div>
`;
}
@ -76,7 +76,7 @@ export class ConsentStage extends BaseStage<ConsentChallenge, ConsentChallengeRe
${this.renderPermissions(this.challenge.permissions)}
</ul>
`
: html``}
: nothing}
</div>
<div class="pf-c-form__group pf-u-mt-md">
${this.challenge.additionalPermissions.length > 0
@ -88,15 +88,14 @@ export class ConsentStage extends BaseStage<ConsentChallenge, ConsentChallengeRe
${this.renderPermissions(this.challenge.additionalPermissions)}
</ul>
`
: html``}
: nothing}
</div>
`;
}
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -23,8 +23,7 @@ export class DummyStage extends BaseStage<DummyChallenge, DummyChallengeResponse
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -22,8 +22,7 @@ export class EmailStage extends BaseStage<EmailChallenge, EmailChallengeResponse
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -198,9 +198,9 @@ export class IdentificationStage extends BaseStage<
</li>`;
}
renderFooter(): TemplateResult {
renderFooter() {
if (!this.challenge?.enrollUrl && !this.challenge?.recoveryUrl) {
return html``;
return nothing;
}
return html`<div class="pf-c-login__main-footer-band">
${this.challenge.enrollUrl
@ -246,7 +246,7 @@ export class IdentificationStage extends BaseStage<
: nothing}
<ak-form-element
label=${label}
?required="${true}"
required
class="pf-c-form__group"
.errors=${(this.challenge.responseErrors || {})["uid_field"]}
>
@ -273,9 +273,7 @@ export class IdentificationStage extends BaseStage<
></ak-flow-input-password>
`
: nothing}
${"non_field_errors" in (this.challenge?.responseErrors || {})
? this.renderNonFieldErrors(this.challenge?.responseErrors?.non_field_errors || [])
: nothing}
${this.renderNonFieldErrors()}
<div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${this.challenge.primaryAction}
@ -288,8 +286,7 @@ export class IdentificationStage extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -33,8 +33,7 @@ export class PasswordStage extends BaseStage<PasswordChallenge, PasswordChalleng
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>

View File

@ -9,7 +9,7 @@ import "@goauthentik/elements/forms/FormElement";
import { BaseStage } from "@goauthentik/flow/stages/base";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement } from "lit/decorators.js";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
@ -81,7 +81,7 @@ ${prompt.initialValue}</textarea
name="${prompt.fieldKey}"
placeholder="${prompt.placeholder}"
class="pf-c-form-control"
?readonly=${true}
readonly
value="${prompt.initialValue}"
/>`;
case PromptTypeEnum.TextAreaReadOnly:
@ -222,9 +222,9 @@ ${prompt.initialValue}</textarea
}
}
renderPromptHelpText(prompt: StagePrompt): TemplateResult {
renderPromptHelpText(prompt: StagePrompt) {
if (prompt.subText === "") {
return html``;
return nothing;
}
return html`<p class="pf-c-form__helper-text">${unsafeHTML(prompt.subText)}</p>`;
}
@ -253,7 +253,7 @@ ${prompt.initialValue}</textarea
<label class="pf-c-check__label" for="${prompt.fieldKey}">${prompt.label}</label>
${prompt.required
? html`<p class="pf-c-form__helper-text">${msg("Required.")}</p>`
: html``}
: nothing}
<p class="pf-c-form__helper-text">${unsafeHTML(prompt.subText)}</p>
</div>`;
}
@ -280,8 +280,7 @@ ${prompt.initialValue}</textarea
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>
@ -296,12 +295,7 @@ ${prompt.initialValue}</textarea
${this.challenge.fields.map((prompt) => {
return this.renderField(prompt);
})}
${"non_field_errors" in (this.challenge?.responseErrors || {})
? this.renderNonFieldErrors(
this.challenge?.responseErrors?.non_field_errors || [],
)
: html``}
${this.renderContinue()}
${this.renderNonFieldErrors()} ${this.renderContinue()}
</form>
</div>
<footer class="pf-c-login__main-footer">

View File

@ -29,8 +29,7 @@ export class PasswordStage extends BaseStage<
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
return html`<ak-empty-state loading> </ak-empty-state>`;
}
return html`<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>