mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-09-04 10:14:13 +08:00
Add AppState Facade
- Add facade with cross-app loading flag observable - Update AppComponent to use the facade - Update language facade to set loading when calling api
This commit is contained in:
parent
5d78c4257a
commit
58c1ff4264
4 changed files with 73 additions and 18 deletions
|
@ -1,4 +1,6 @@
|
|||
<app-full-page-spinner *ngIf="loading"></app-full-page-spinner>
|
||||
<ng-container *ngIf="(appState$ | async) as appState">
|
||||
<app-full-page-spinner *ngIf="appState.loading"></app-full-page-spinner>
|
||||
</ng-container>
|
||||
<scrm-navbar-ui></scrm-navbar-ui>
|
||||
<scrm-message-ui></scrm-message-ui>
|
||||
<div #mainOutlet></div>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import {Component, ViewChild, ViewContainerRef, OnInit} from '@angular/core';
|
||||
import {Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router} from '@angular/router';
|
||||
import {AppState, AppStateFacade} from "@base/facades/app-state.facade";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
|
@ -8,9 +10,9 @@ import {Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart
|
|||
export class AppComponent implements OnInit {
|
||||
@ViewChild('mainOutlet', {read: ViewContainerRef, static: true})
|
||||
mainOutlet: ViewContainerRef | undefined;
|
||||
loading = false;
|
||||
appState$: Observable<AppState> = this.appStateFacade.vm$;
|
||||
|
||||
constructor(private router: Router) {
|
||||
constructor(private router: Router, private appStateFacade: AppStateFacade) {
|
||||
router.events.subscribe((routerEvent: Event) => this.checkRouterEvent(routerEvent));
|
||||
}
|
||||
|
||||
|
@ -19,13 +21,13 @@ export class AppComponent implements OnInit {
|
|||
|
||||
private checkRouterEvent(routerEvent: Event) {
|
||||
if (routerEvent instanceof NavigationStart) {
|
||||
this.loading = true;
|
||||
this.appStateFacade.updateLoading(true);
|
||||
}
|
||||
|
||||
if (routerEvent instanceof NavigationEnd ||
|
||||
routerEvent instanceof NavigationCancel ||
|
||||
routerEvent instanceof NavigationError) {
|
||||
this.loading = false;
|
||||
this.appStateFacade.updateLoading(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
46
core/app/src/facades/app-state.facade.ts
Normal file
46
core/app/src/facades/app-state.facade.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {BehaviorSubject, Observable, combineLatest} from 'rxjs';
|
||||
import {map, distinctUntilChanged} from 'rxjs/operators';
|
||||
|
||||
export interface AppState {
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
|
||||
let internalState: AppState = {
|
||||
loading: false
|
||||
};
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AppStateFacade {
|
||||
|
||||
protected store = new BehaviorSubject<AppState>(internalState);
|
||||
protected state$ = this.store.asObservable();
|
||||
|
||||
loading$ = this.state$.pipe(map(state => state.loading), distinctUntilChanged());
|
||||
|
||||
/**
|
||||
* ViewModel that resolves once all the data is ready (or updated)...
|
||||
*/
|
||||
vm$: Observable<AppState> = combineLatest([this.loading$]).pipe(
|
||||
map(([loading]) => ({loading}))
|
||||
);
|
||||
|
||||
constructor() {
|
||||
this.updateState({...internalState, loading: false});
|
||||
}
|
||||
|
||||
public updateLoading(loading: boolean) {
|
||||
this.updateState({...internalState, loading});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state
|
||||
* @param state
|
||||
*/
|
||||
protected updateState(state: AppState) {
|
||||
this.store.next(internalState = state);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
|
||||
import {BehaviorSubject, Observable, combineLatest, of} from 'rxjs';
|
||||
import {map, distinctUntilChanged, switchMap} from 'rxjs/operators';
|
||||
import {map, distinctUntilChanged, switchMap, tap} from 'rxjs/operators';
|
||||
import {RecordGQL} from '@services/api/graphql-api/api.record.get';
|
||||
import {AppStateFacade} from "@base/facades/app-state.facade";
|
||||
|
||||
export interface LanguageStringMap {
|
||||
[key: string]: string;
|
||||
|
@ -49,12 +50,12 @@ export class LanguageFacade {
|
|||
})
|
||||
);
|
||||
|
||||
constructor(private recordGQL: RecordGQL) {
|
||||
constructor(private recordGQL: RecordGQL, private appStateFacade: AppStateFacade) {
|
||||
}
|
||||
|
||||
// ------- Public Methods ------------------------
|
||||
|
||||
public updateLanguage(languageType: string) {
|
||||
public updateLanguage(languageType: string): void {
|
||||
this.updateState({..._state, languageType});
|
||||
}
|
||||
|
||||
|
@ -64,7 +65,7 @@ export class LanguageFacade {
|
|||
|
||||
const appStrings$ = combineLatest([this.languageType$]).pipe(
|
||||
switchMap(([languageType]) => this.fetchAppStrings(languageType))
|
||||
)
|
||||
);
|
||||
|
||||
appStrings$.subscribe(languageStrings => {
|
||||
this.updateState({..._state, languageStrings});
|
||||
|
@ -75,23 +76,27 @@ export class LanguageFacade {
|
|||
|
||||
// ------- Private Methods ------------------------
|
||||
|
||||
/** Update internal state cache and emit from store... */
|
||||
protected updateState(state: LanguageState) {
|
||||
/**
|
||||
* Update internal state cache and emit from store...
|
||||
* @param state
|
||||
*/
|
||||
protected updateState(state: LanguageState): void {
|
||||
this.store.next(_state = state);
|
||||
}
|
||||
|
||||
protected fetchAppStrings(language: string): Observable<{}> {
|
||||
|
||||
this.appStateFacade.updateLoading(true);
|
||||
return this.recordGQL
|
||||
.fetch(this.resourceName, `/api/app-strings/${language}`, this.fieldsMetadata)
|
||||
.pipe(map(({data}) => {
|
||||
let items = {};
|
||||
let items = {};
|
||||
|
||||
if (data.appStrings) {
|
||||
items = data.appStrings.items;
|
||||
}
|
||||
if (data.appStrings) {
|
||||
items = data.appStrings.items;
|
||||
}
|
||||
|
||||
return items;
|
||||
}));
|
||||
return items;
|
||||
}),
|
||||
tap(() => this.appStateFacade.updateLoading(false)));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue