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);
+ }
+}