diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index a661012ac7..54365ecf64 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -1,5 +1,5 @@ import { CommonModule } from '@angular/common'; -import { HttpClientModule, HttpClientXsrfModule, HTTP_INTERCEPTORS } from '@angular/common/http'; +import { HTTP_INTERCEPTORS, HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'; import { APP_INITIALIZER, Injector, ModuleWithProviders, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; @@ -30,7 +30,7 @@ import { LocaleProvider } from './providers/locale.provider'; import { LocalizationService } from './services/localization.service'; import { ProfileState } from './states/profile.state'; import { oAuthStorage } from './strategies/auth-flow.strategy'; -import { coreOptionsFactory, CORE_OPTIONS } from './tokens/options.token'; +import { CORE_OPTIONS, coreOptionsFactory } from './tokens/options.token'; import { noop } from './utils/common-utils'; import './utils/date-extensions'; import { getInitialData, localeInitializer } from './utils/initial-utils'; diff --git a/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts b/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts index 96427594ae..a74a9bb08d 100644 --- a/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts @@ -1,27 +1,40 @@ import { Injectable } from '@angular/core'; import { HttpRequest } from '@angular/common/http'; import { InternalStore } from '../utils/internal-store-utils'; +import { getPathName } from '../utils/http-utils'; +import { debounceTime, tap } from 'rxjs/operators'; export interface HttpWaitState { requests: Set>; + filteredRequests: Array; + delay: number; +} +export interface HttpRequestInfo { + method: string; + endpoint: string; } - @Injectable({ providedIn: 'root', }) export class HttpWaitService { - protected store = new InternalStore({ requests: new Set() }); + protected store = new InternalStore({ + requests: new Set(), + filteredRequests: [], + delay: 0, + }); getLoading() { - return !!this.store.state.requests.size; + return !!this.applyFilter(this.store.state.requests).length; } getLoading$() { - return this.store.sliceState(({ requests }) => !!requests.size); + return this.store + .sliceState(({ requests }) => !!this.applyFilter(requests).length) + .pipe(this.debounceWhenLoading()); } updateLoading$() { - return this.store.sliceUpdate(({ requests }) => !!requests.size); + return this.store.sliceUpdate(({ requests }) => !!this.applyFilter(requests).length); } clearLoading() { @@ -29,16 +42,55 @@ export class HttpWaitService { } addRequest(request: HttpRequest) { - const requests = this.store.state.requests; + let { requests } = this.store.state; + requests = new Set(requests.values()); requests.add(request); this.store.patch({ requests }); } deleteRequest(request: HttpRequest) { - const requests = this.store.state.requests; + const { requests } = this.store.state; requests.delete(request); this.store.patch({ requests }); } - // TODO: Add filter function + addFilter(request: HttpRequestInfo) { + const filteredRequests = [ + ...this.store.state.filteredRequests.filter(f => !this.isSameRequest(f, request)), + request, + ]; + this.store.patch({ filteredRequests }); + } + + removeFilter(request: HttpRequestInfo) { + const filteredRequests = this.store.state.filteredRequests.filter( + f => !this.isSameRequest(f, request), + ); + this.store.patch({ filteredRequests }); + } + + setDelay(delay: number) { + this.store.patch({ delay }); + } + + private applyFilter(requests: Set>) { + const { filteredRequests } = this.store.state; + return Array.from(requests).filter( + ({ method, url }) => + !filteredRequests.find(filteredRequest => + this.isSameRequest(filteredRequest, { method, endpoint: getPathName(url) }), + ), + ); + } + + private isSameRequest(filteredRequest: HttpRequestInfo, request: HttpRequestInfo) { + const { method, endpoint } = filteredRequest; + return endpoint === request.endpoint && method === request.method; + } + + private debounceWhenLoading() { + return this.store.state.delay && !!this.applyFilter(this.store.state.requests).length + ? debounceTime(this.store.state.delay) + : tap(); + } } diff --git a/npm/ng-packs/packages/core/src/lib/utils/http-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/http-utils.ts new file mode 100644 index 0000000000..50259ec294 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/utils/http-utils.ts @@ -0,0 +1,4 @@ +export function getPathName(url: string): string { + const { pathname } = new URL(url); + return pathname; +} diff --git a/npm/ng-packs/packages/core/src/lib/utils/index.ts b/npm/ng-packs/packages/core/src/lib/utils/index.ts index 2d7ef8eab4..d50fa7712f 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/index.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/index.ts @@ -6,6 +6,7 @@ export * from './factory-utils'; export * from './file-utils'; export * from './form-utils'; export * from './generator-utils'; +export * from './http-utils'; export * from './initial-utils'; export * from './internal-store-utils'; export * from './lazy-load-utils';