web: improve loading indication for modals
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
0f5e0a774a
commit
f9e826d553
|
@ -0,0 +1,28 @@
|
||||||
|
import { css, CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element";
|
||||||
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
import { PFSize } from "./Spinner";
|
||||||
|
|
||||||
|
@customElement("ak-loading-overlay")
|
||||||
|
export class LoadingOverlay extends LitElement {
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
PFBase,
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
background-color: var(--pf-global--BackgroundColor--dark-transparent-100);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): TemplateResult {
|
||||||
|
return html`<ak-spinner size=${PFSize.XLarge}></ak-spinner>`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,7 +66,7 @@ export class ModalButton extends LitElement {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback(): void {
|
firstUpdated(): void {
|
||||||
if (this.handlerBound) return;
|
if (this.handlerBound) return;
|
||||||
window.addEventListener("keyup", this.keyUpHandler);
|
window.addEventListener("keyup", this.keyUpHandler);
|
||||||
this.handlerBound = true;
|
this.handlerBound = true;
|
||||||
|
|
|
@ -4,12 +4,16 @@ import { EVENT_REFRESH } from "../../constants";
|
||||||
import { ModalButton } from "../buttons/ModalButton";
|
import { ModalButton } from "../buttons/ModalButton";
|
||||||
import { Form } from "./Form";
|
import { Form } from "./Form";
|
||||||
import "../buttons/SpinnerButton";
|
import "../buttons/SpinnerButton";
|
||||||
|
import "../LoadingOverlay";
|
||||||
|
|
||||||
@customElement("ak-forms-modal")
|
@customElement("ak-forms-modal")
|
||||||
export class ModalForm extends ModalButton {
|
export class ModalForm extends ModalButton {
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
closeAfterSuccessfulSubmit = true;
|
closeAfterSuccessfulSubmit = true;
|
||||||
|
|
||||||
|
@property({ type: Boolean })
|
||||||
|
loading = false;
|
||||||
|
|
||||||
confirm(): Promise<void> {
|
confirm(): Promise<void> {
|
||||||
const form = this.querySelector<Form<unknown>>("[slot=form]");
|
const form = this.querySelector<Form<unknown>>("[slot=form]");
|
||||||
if (!form) {
|
if (!form) {
|
||||||
|
@ -24,6 +28,7 @@ export class ModalForm extends ModalButton {
|
||||||
this.open = false;
|
this.open = false;
|
||||||
form?.resetForm();
|
form?.resetForm();
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent(EVENT_REFRESH, {
|
new CustomEvent(EVENT_REFRESH, {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
@ -34,7 +39,8 @@ export class ModalForm extends ModalButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderModalInner(): TemplateResult {
|
renderModalInner(): TemplateResult {
|
||||||
return html`<section class="pf-c-page__main-section pf-m-light">
|
return html`${this.loading ? html`<ak-loading-overlay></ak-loading-overlay>` : html``}
|
||||||
|
<section class="pf-c-page__main-section pf-m-light">
|
||||||
<div class="pf-c-content">
|
<div class="pf-c-content">
|
||||||
<h1 class="pf-c-title pf-m-2xl">
|
<h1 class="pf-c-title pf-m-2xl">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
|
@ -47,6 +53,7 @@ export class ModalForm extends ModalButton {
|
||||||
<footer class="pf-c-modal-box__footer">
|
<footer class="pf-c-modal-box__footer">
|
||||||
<ak-spinner-button
|
<ak-spinner-button
|
||||||
.callAction=${() => {
|
.callAction=${() => {
|
||||||
|
this.loading = true;
|
||||||
return this.confirm();
|
return this.confirm();
|
||||||
}}
|
}}
|
||||||
class="pf-m-primary"
|
class="pf-m-primary"
|
||||||
|
|
|
@ -18,6 +18,7 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||||
import AKGlobal from "../authentik.css";
|
import AKGlobal from "../authentik.css";
|
||||||
|
|
||||||
import { unsafeHTML } from "lit-html/directives/unsafe-html";
|
import { unsafeHTML } from "lit-html/directives/unsafe-html";
|
||||||
|
import "../elements/LoadingOverlay";
|
||||||
import "./access_denied/FlowAccessDenied";
|
import "./access_denied/FlowAccessDenied";
|
||||||
import "./stages/authenticator_static/AuthenticatorStaticStage";
|
import "./stages/authenticator_static/AuthenticatorStaticStage";
|
||||||
import "./stages/authenticator_totp/AuthenticatorTOTPStage";
|
import "./stages/authenticator_totp/AuthenticatorTOTPStage";
|
||||||
|
@ -46,7 +47,6 @@ import {
|
||||||
import { DEFAULT_CONFIG, tenant } from "../api/Config";
|
import { DEFAULT_CONFIG, tenant } from "../api/Config";
|
||||||
import { ifDefined } from "lit-html/directives/if-defined";
|
import { ifDefined } from "lit-html/directives/if-defined";
|
||||||
import { until } from "lit-html/directives/until";
|
import { until } from "lit-html/directives/until";
|
||||||
import { PFSize } from "../elements/Spinner";
|
|
||||||
import { TITLE_DEFAULT } from "../constants";
|
import { TITLE_DEFAULT } from "../constants";
|
||||||
import { configureSentry } from "../api/Sentry";
|
import { configureSentry } from "../api/Sentry";
|
||||||
import { WebsocketClient } from "../common/ws";
|
import { WebsocketClient } from "../common/ws";
|
||||||
|
@ -68,16 +68,6 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [PFBase, PFLogin, PFButton, PFTitle, PFList, PFBackgroundImage, AKGlobal].concat(css`
|
return [PFBase, PFLogin, PFButton, PFTitle, PFList, PFBackgroundImage, AKGlobal].concat(css`
|
||||||
.ak-loading {
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
position: absolute;
|
|
||||||
background-color: var(--pf-global--BackgroundColor--dark-transparent-100);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.ak-hidden {
|
.ak-hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -196,12 +186,6 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||||
} as ChallengeTypes;
|
} as ChallengeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLoading(): TemplateResult {
|
|
||||||
return html`<div class="ak-loading">
|
|
||||||
<ak-spinner size=${PFSize.XLarge}></ak-spinner>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderChallenge(): TemplateResult {
|
renderChallenge(): TemplateResult {
|
||||||
if (!this.challenge) {
|
if (!this.challenge) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -309,7 +293,10 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||||
if (!this.challenge) {
|
if (!this.challenge) {
|
||||||
return html`<ak-empty-state ?loading=${true} header=${t`Loading`}> </ak-empty-state>`;
|
return html`<ak-empty-state ?loading=${true} header=${t`Loading`}> </ak-empty-state>`;
|
||||||
}
|
}
|
||||||
return html` ${this.loading ? this.renderLoading() : html``} ${this.renderChallenge()} `;
|
return html`
|
||||||
|
${this.loading ? html`<ak-loading-overlay></ak-loading-overlay>` : html``}
|
||||||
|
${this.renderChallenge()}
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): TemplateResult {
|
render(): TemplateResult {
|
||||||
|
|
Reference in New Issue