web: improve loading indication for modals
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		
							
								
								
									
										28
									
								
								web/src/elements/LoadingOverlay.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								web/src/elements/LoadingOverlay.ts
									
									
									
									
									
										Normal file
									
								
							| @ -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
	
	Block a user
	 Jens Langhammer
					Jens Langhammer