Browse Source

- add wait services

- remove ngxs from api interceptor and loader-bar component
- remove filter input from loader bar component
pull/6798/head
muhammedaltug 6 years ago
parent
commit
e646718fbe
  1. 10
      npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts
  2. 44
      npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts
  3. 2
      npm/ng-packs/packages/core/src/lib/services/index.ts
  4. 10
      npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts
  5. 41
      npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts
  6. 53
      npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts
  7. 51
      npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts

10
npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts

@ -1,10 +1,9 @@
import { HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc'; import { OAuthService } from 'angular-oauth2-oidc';
import { finalize } from 'rxjs/operators'; import { finalize } from 'rxjs/operators';
import { StartLoader, StopLoader } from '../actions/loader.actions';
import { SessionStateService } from '../services/session-state.service'; import { SessionStateService } from '../services/session-state.service';
import { HttpWaitService } from '../services/http-wait.service';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@ -12,20 +11,19 @@ import { SessionStateService } from '../services/session-state.service';
export class ApiInterceptor implements HttpInterceptor { export class ApiInterceptor implements HttpInterceptor {
constructor( constructor(
private oAuthService: OAuthService, private oAuthService: OAuthService,
private store: Store,
private sessionState: SessionStateService, private sessionState: SessionStateService,
private httpWaitService: HttpWaitService,
) {} ) {}
intercept(request: HttpRequest<any>, next: HttpHandler) { intercept(request: HttpRequest<any>, next: HttpHandler) {
this.store.dispatch(new StartLoader(request)); this.httpWaitService.addRequest(request);
return next return next
.handle( .handle(
request.clone({ request.clone({
setHeaders: this.getAdditionalHeaders(request.headers), setHeaders: this.getAdditionalHeaders(request.headers),
}), }),
) )
.pipe(finalize(() => this.store.dispatch(new StopLoader(request)))); .pipe(finalize(() => this.httpWaitService.deleteRequest(request)));
} }
getAdditionalHeaders(existingHeaders?: HttpHeaders) { getAdditionalHeaders(existingHeaders?: HttpHeaders) {

44
npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts

@ -0,0 +1,44 @@
import { Injectable } from '@angular/core';
import { HttpRequest } from '@angular/common/http';
import { InternalStore } from '../utils/internal-store-utils';
export interface HttpWaitState {
requests: Set<HttpRequest<any>>;
}
@Injectable({
providedIn: 'root',
})
export class HttpWaitService {
protected store = new InternalStore<HttpWaitState>({ requests: new Set() });
getLoading() {
return !!this.store.state.requests.size;
}
getLoading$() {
return this.store.sliceState(({ requests }) => !!requests.size);
}
updateLoading$() {
return this.store.sliceUpdate(({ requests }) => !!requests.size);
}
clearLoading() {
this.store.patch({ requests: new Set() });
}
addRequest(request: HttpRequest<any>) {
const requests = this.store.state.requests;
requests.add(request);
this.store.patch({ requests });
}
deleteRequest(request: HttpRequest<any>) {
const requests = this.store.state.requests;
requests.delete(request);
this.store.patch({ requests });
}
// TODO: Add filter function
}

2
npm/ng-packs/packages/core/src/lib/services/index.ts

@ -4,6 +4,7 @@ export * from './config-state.service';
export * from './content-projection.service'; export * from './content-projection.service';
export * from './dom-insertion.service'; export * from './dom-insertion.service';
export * from './environment.service'; export * from './environment.service';
export * from './http-wait.service';
export * from './lazy-load.service'; export * from './lazy-load.service';
export * from './list.service'; export * from './list.service';
export * from './localization.service'; export * from './localization.service';
@ -13,6 +14,7 @@ export * from './profile-state.service';
export * from './profile.service'; export * from './profile.service';
export * from './replaceable-components.service'; export * from './replaceable-components.service';
export * from './rest.service'; export * from './rest.service';
export * from './router-wait.service';
export * from './routes.service'; export * from './routes.service';
export * from './session-state.service'; export * from './session-state.service';
export * from './subscription.service'; export * from './subscription.service';

10
npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts

@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import { concat, Observable, of, throwError } from 'rxjs'; import { concat, Observable, of, throwError } from 'rxjs';
import { delay, retryWhen, shareReplay, take, tap } from 'rxjs/operators'; import { delay, retryWhen, shareReplay, take, tap } from 'rxjs/operators';
import { LoadingStrategy } from '../strategies'; import { LoadingStrategy } from '../strategies';
import { ResourceWaitService } from './resource-wait.service';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@ -9,9 +10,11 @@ import { LoadingStrategy } from '../strategies';
export class LazyLoadService { export class LazyLoadService {
readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement>(); readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement>();
constructor(private resourceWaitService: ResourceWaitService) {}
load(strategy: LoadingStrategy, retryTimes?: number, retryDelay?: number): Observable<Event> { load(strategy: LoadingStrategy, retryTimes?: number, retryDelay?: number): Observable<Event> {
if (this.loaded.has(strategy.path)) return of(new CustomEvent('load')); if (this.loaded.has(strategy.path)) return of(new CustomEvent('load'));
this.resourceWaitService.addResource(strategy.path);
return strategy.createStream().pipe( return strategy.createStream().pipe(
retryWhen(error$ => retryWhen(error$ =>
concat( concat(
@ -19,7 +22,10 @@ export class LazyLoadService {
throwError(new CustomEvent('error')), throwError(new CustomEvent('error')),
), ),
), ),
tap(() => this.loaded.set(strategy.path, strategy.element)), tap(() => {
this.loaded.set(strategy.path, strategy.element);
this.resourceWaitService.deleteResource(strategy.path);
}),
delay(100), delay(100),
shareReplay({ bufferSize: 1, refCount: true }), shareReplay({ bufferSize: 1, refCount: true }),
); );

41
npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts

@ -0,0 +1,41 @@
import { Injectable } from '@angular/core';
import { InternalStore } from '../utils/internal-store-utils';
export interface ResourceWaitState {
resources: Set<string>;
}
@Injectable({
providedIn: 'root',
})
export class ResourceWaitService {
private store = new InternalStore<ResourceWaitState>({ resources: new Set() });
getLoading() {
return !!this.store.state.resources.size;
}
getLoading$() {
return this.store.sliceState(({ resources }) => !!resources.size);
}
updateLoading$() {
return this.store.sliceUpdate(({ resources }) => !!resources.size);
}
clearLoading() {
this.store.patch({ resources: new Set() });
}
addResource(resource: string) {
const resources = this.store.state.resources;
resources.add(resource);
this.store.patch({ resources });
}
deleteResource(resource: string) {
const resources = this.store.state.resources;
resources.delete(resource);
this.store.patch({ resources });
}
}

53
npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts

@ -0,0 +1,53 @@
import { Injectable } from '@angular/core';
import {
NavigationCancel,
NavigationEnd,
NavigationError,
NavigationStart,
Router,
} from '@angular/router';
import { filter } from 'rxjs/operators';
import { InternalStore } from '../utils/internal-store-utils';
export interface RouterWaitState {
loading: boolean;
}
@Injectable({
providedIn: 'root',
})
export class RouterWaitService {
private store = new InternalStore<RouterWaitState>({ loading: false });
constructor(private router: Router) {
this.router.events
.pipe(
filter(
event =>
event instanceof NavigationStart ||
event instanceof NavigationEnd ||
event instanceof NavigationError ||
event instanceof NavigationCancel,
),
)
.subscribe(event => {
if (event instanceof NavigationStart) this.setLoading(true);
else this.setLoading(false);
});
}
getLoading() {
return this.store.state.loading;
}
getLoading$() {
return this.store.sliceState(({ loading }) => loading);
}
updateLoading$() {
return this.store.sliceUpdate(({ loading }) => loading);
}
setLoading(loading: boolean) {
this.store.patch({ loading });
}
}

51
npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts

@ -1,9 +1,9 @@
import { StartLoader, StopLoader, SubscriptionService } from '@abp/ng.core'; import { SubscriptionService } from '@abp/ng.core';
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; import { Router } from '@angular/router';
import { Actions, ofActionSuccessful } from '@ngxs/store'; import { combineLatest, Subscription, timer } from 'rxjs';
import { Subscription, timer } from 'rxjs'; import { RouterWaitService } from '../../../../../core/src/lib/services/router-wait.service';
import { filter } from 'rxjs/operators'; import { HttpWaitService } from '../../../../../core/src/lib/services/http-wait.service';
@Component({ @Component({
selector: 'abp-loader-bar', selector: 'abp-loader-bar',
@ -51,10 +51,6 @@ export class LoaderBarComponent implements OnDestroy, OnInit {
stopDelay = 800; stopDelay = 800;
@Input()
filter = (action: StartLoader | StopLoader) =>
action.payload.url.indexOf('openid-configuration') < 0;
private readonly clearProgress = () => { private readonly clearProgress = () => {
this.progressLevel = 0; this.progressLevel = 0;
this.cdRef.detectChanges(); this.cdRef.detectChanges();
@ -78,44 +74,27 @@ export class LoaderBarComponent implements OnDestroy, OnInit {
} }
constructor( constructor(
private actions: Actions,
private router: Router, private router: Router,
private cdRef: ChangeDetectorRef, private cdRef: ChangeDetectorRef,
private subscription: SubscriptionService, private subscription: SubscriptionService,
private httpWaitService: HttpWaitService,
private routerWaiterService: RouterWaitService,
) {} ) {}
private subscribeToLoadActions() { ngOnInit() {
this.subscription.addOne( this.subscribeLoading();
this.actions.pipe(ofActionSuccessful(StartLoader, StopLoader), filter(this.filter)),
action => {
if (action instanceof StartLoader) this.startLoading();
else this.stopLoading();
},
);
} }
private subscribeToRouterEvents() { subscribeLoading() {
this.subscription.addOne( this.subscription.addOne(
this.router.events.pipe( combineLatest([this.httpWaitService.getLoading$(), this.routerWaiterService.getLoading$()]),
filter( ([httpLoading, routerLoading]) => {
event => if (httpLoading || routerLoading) this.startLoading();
event instanceof NavigationStart ||
event instanceof NavigationEnd ||
event instanceof NavigationError,
),
),
event => {
if (event instanceof NavigationStart) this.startLoading();
else this.stopLoading(); else this.stopLoading();
}, },
); );
} }
ngOnInit() {
this.subscribeToLoadActions();
this.subscribeToRouterEvents();
}
ngOnDestroy() { ngOnDestroy() {
if (this.interval) this.interval.unsubscribe(); if (this.interval) this.interval.unsubscribe();
} }
@ -124,8 +103,10 @@ export class LoaderBarComponent implements OnDestroy, OnInit {
if (this.isLoading || (this.interval && !this.interval.closed)) return; if (this.isLoading || (this.interval && !this.interval.closed)) return;
this.isLoading = true; this.isLoading = true;
this.progressLevel = 0;
this.interval = timer(0, this.intervalPeriod).subscribe(this.reportProgress); this.interval = timer(0, this.intervalPeriod).subscribe(this.reportProgress);
this.timer.unsubscribe();
this.cdRef.detectChanges();
} }
stopLoading() { stopLoading() {

Loading…
Cancel
Save