diff --git a/src/index.ts b/src/index.ts index 1ceca69..8af8287 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,3 +30,5 @@ export * from './lib/tables/table-header/table-header.component'; export * from './lib/misc/status-bar/status-bar.component'; export * from './lib/misc/status-bar/status-bar-config.model'; export * from './lib/inputs/editable-input/editable-input.component'; +export * from './lib/loading/loading.service'; +export * from './lib/loading/full-page-loading-indicator/full-page-loading-indicator.component'; diff --git a/src/lib/common-ui.module.ts b/src/lib/common-ui.module.ts index a0d40b8..6968ea6 100644 --- a/src/lib/common-ui.module.ts +++ b/src/lib/common-ui.module.ts @@ -6,6 +6,7 @@ import { DomSanitizer } from '@angular/platform-browser'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; import { FormsModule } from '@angular/forms'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { IconButtonComponent } from './buttons/icon-button/icon-button.component'; import { ChevronButtonComponent } from './buttons/chevron-button/chevron-button.component'; import { CircleButtonComponent } from './buttons/circle-button/circle-button.component'; @@ -18,16 +19,25 @@ import { TableHeaderComponent } from './tables/table-header/table-header.compone import { SyncWidthDirective } from './tables/sync-width.directive'; import { StatusBarComponent } from './misc/status-bar/status-bar.component'; import { EditableInputComponent } from './inputs/editable-input/editable-input.component'; +import { FullPageLoadingIndicatorComponent } from './loading/full-page-loading-indicator/full-page-loading-indicator.component'; const buttons = [IconButtonComponent, ChevronButtonComponent, CircleButtonComponent]; const inputs = [RoundCheckboxComponent, EditableInputComponent]; -const matModules = [MatIconModule, MatButtonModule, MatTooltipModule]; +const matModules = [MatIconModule, MatButtonModule, MatTooltipModule, MatProgressSpinnerModule]; const modules = [...matModules, FormsModule, TranslateModule]; -const components = [...buttons, ...inputs, TableColumnNameComponent, QuickFiltersComponent, TableHeaderComponent, StatusBarComponent]; +const components = [ + ...buttons, + ...inputs, + TableColumnNameComponent, + QuickFiltersComponent, + TableHeaderComponent, + StatusBarComponent, + FullPageLoadingIndicatorComponent +]; const utils = [SortByPipe, HumanizePipe, SyncWidthDirective]; diff --git a/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.html b/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.html new file mode 100644 index 0000000..46e67a5 --- /dev/null +++ b/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.html @@ -0,0 +1,7 @@ + +
+
+ + +
+
diff --git a/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.scss b/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.scss new file mode 100644 index 0000000..1f73bc9 --- /dev/null +++ b/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.scss @@ -0,0 +1,24 @@ +@import '../../../assets/styles/variables'; + +.full-page-load-section, +.full-page-load-spinner { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +.full-page-load-section { + opacity: 0.7; + background: $white; + z-index: 900; +} + +.full-page-load-spinner { + z-index: 1000; + justify-content: center; + align-items: center; + flex-direction: column; + display: flex; +} diff --git a/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.ts b/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.ts new file mode 100644 index 0000000..c1c9b4e --- /dev/null +++ b/src/lib/loading/full-page-loading-indicator/full-page-loading-indicator.component.ts @@ -0,0 +1,12 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { LoadingService } from '../loading.service'; + +@Component({ + selector: 'iqser-full-page-loading-indicator', + templateUrl: './full-page-loading-indicator.component.html', + styleUrls: ['./full-page-loading-indicator.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FullPageLoadingIndicatorComponent { + constructor(readonly loadingService: LoadingService) {} +} diff --git a/src/lib/loading/loading.service.ts b/src/lib/loading/loading.service.ts new file mode 100644 index 0000000..af0d83f --- /dev/null +++ b/src/lib/loading/loading.service.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; + +const MIN_LOADING_TIME = 300; + +@Injectable({ providedIn: 'root' }) +export class LoadingService { + private readonly _loadingEvent$ = new BehaviorSubject(false); + readonly isLoading$ = this._loadingEvent$.asObservable(); + private _loadingStarted = 0; + + start(): void { + setTimeout(() => { + this._loadingEvent$.next(true); + this._loadingStarted = new Date().getTime(); + }); + } + + stop(): void { + const timeSinceStarted = new Date().getTime() - this._loadingStarted; + const remainingLoadingTime = MIN_LOADING_TIME - timeSinceStarted; + + return remainingLoadingTime > 0 ? this._stopAfter(remainingLoadingTime) : this._stop(); + } + + loadWhile(func: Promise): void { + this.start(); + + func.then( + () => this.stop(), + () => this.stop() + ); + } + + private _stop(): void { + setTimeout(() => this._loadingEvent$.next(false)); + } + + private _stopAfter(timeout: number): void { + setTimeout(() => this._stop(), timeout); + } +}