diff --git a/src/atlasComponents/splashScreen/splashScreen/splashScreen.component.ts b/src/atlasComponents/splashScreen/splashScreen/splashScreen.component.ts index 585083536b64287853ba3166840b32bb07021007..48d7e6bf038f874c5dc0764a14f0785e8221c447 100644 --- a/src/atlasComponents/splashScreen/splashScreen/splashScreen.component.ts +++ b/src/atlasComponents/splashScreen/splashScreen/splashScreen.component.ts @@ -17,11 +17,10 @@ import { PureContantService } from "src/util"; export class SplashScreen implements AfterViewInit { - public stillLoadingTemplates$: Observable<any[]> + public finishedLoading$: Observable<boolean> public loadedTemplate$: Observable<any[]> public loadedAtlases$: Observable<any[]> - public stillLoadingAtlases$: Observable<any[]> @ViewChild('parentContainer', {read: ElementRef}) private parentContainer: ElementRef @@ -40,34 +39,13 @@ export class SplashScreen implements AfterViewInit { shareReplay(1), ) - this.stillLoadingTemplates$ = combineLatest( - this.constanceService.getTemplateEndpoint$.pipe( - startWith(null) - ), - this.loadedTemplate$.pipe( - startWith([]) - ) - ).pipe( - map(([templateEndpoints, loadedTemplates]) => { - if (templateEndpoints && Array.isArray(templateEndpoints)) { - // TODO this is not exactly correct - return templateEndpoints.slice(loadedTemplates.length) - } else { - return null - } - }) - ) + this.finishedLoading$ = this.pureConstantService.allFetchingReady$ this.loadedAtlases$ = this.store.pipe( select(state => state[viewerStateHelperStoreName]), select(state => state.fetchedAtlases), filter(v => !!v) ) - - this.stillLoadingAtlases$ = this.loadedAtlases$.pipe( - map(arr => this.pureConstantService.totalAtlasesLength - arr.length), - map(num => Array(num >= 0 ? num : 0).fill(null)) - ) } public ngAfterViewInit() { diff --git a/src/atlasComponents/splashScreen/splashScreen/splashScreen.template.html b/src/atlasComponents/splashScreen/splashScreen/splashScreen.template.html index 41922dbfd31ffc03218ae3c13ca87c7af726ce82..1f8105d2759a3c1f79afed5e0c8235950cf77d02 100644 --- a/src/atlasComponents/splashScreen/splashScreen/splashScreen.template.html +++ b/src/atlasComponents/splashScreen/splashScreen/splashScreen.template.html @@ -20,12 +20,13 @@ <mat-card-footer> </mat-card-footer> </mat-card> - <ng-container *ngIf="stillLoadingAtlases$ | async as stillLoadingTemplates"> - <div class="d-flex align-items-center p-4 loadingIndicator" *ngFor="let t of stillLoadingTemplates"> + + <ng-template [ngIf]="!(finishedLoading$ | async)"> + <div class="d-flex align-items-center p-4"> <h1 class="mat-h1"> <spinner-cmp></spinner-cmp> </h1> </div> - </ng-container> + </ng-template> </div> </div> \ No newline at end of file diff --git a/src/state/effects/viewerState.useEffect.ts b/src/state/effects/viewerState.useEffect.ts index a56794c215c671f56b71abbecd05b55f3226d826..a26d43e2b76e9cc8256805f702e3a266041bb650 100644 --- a/src/state/effects/viewerState.useEffect.ts +++ b/src/state/effects/viewerState.useEffect.ts @@ -120,6 +120,10 @@ export class ViewerStateControllerUseEffect implements OnDestroy { @Effect() public onSelectAtlasSelectTmplParc$ = this.actions$.pipe( ofType(viewerStateSelectAtlas.type), + switchMap(action => this.pureService.allFetchingReady$.pipe( + filter(v => !!v), + mapTo(action) + )), withLatestFrom( this.store$.pipe( select(viewerStateFetchedTemplatesSelector), diff --git a/src/util/pureConstant.service.spec.ts b/src/util/pureConstant.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..68302ae81cd99b1d239390d4a2b9aa6b2639f538 --- /dev/null +++ b/src/util/pureConstant.service.spec.ts @@ -0,0 +1,64 @@ +import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing" +import { TestBed } from "@angular/core/testing" +import { MockStore, provideMockStore } from "@ngrx/store/testing" +import { hot } from "jasmine-marbles" +import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service" +import { viewerStateFetchedAtlasesSelector, viewerStateFetchedTemplatesSelector } from "src/services/state/viewerState/selectors" +import { PureContantService } from "./pureConstant.service" + +describe('> pureConstant.service.ts', () => { + describe('> PureContantService', () => { + let httpController: HttpTestingController + beforeEach(() => { + TestBed.configureTestingModule({ + imports:[ + HttpClientTestingModule, + ], + providers: [ + provideMockStore(), + { + provide: AtlasWorkerService, + useValue: { + worker: null + } + } + ] + }) + + const mockStore = TestBed.inject(MockStore) + mockStore.overrideSelector(viewerStateFetchedTemplatesSelector, []) + mockStore.overrideSelector(viewerStateFetchedAtlasesSelector, []) + httpController = TestBed.inject(HttpTestingController) + }) + + afterEach(() => { + httpController.verify() + }) + + it('> can be init', () => { + const service = TestBed.inject(PureContantService) + const exp = httpController.expectOne(`${service.backendUrl}/atlases/`) + exp.flush([]) + expect(service).toBeTruthy() + }) + describe('> allFetchingReady$', () => { + + it('> can be init, and configuration emits allFetchingReady$', () => { + const service = TestBed.inject(PureContantService) + const exp = httpController.expectOne(`${service.backendUrl}/atlases/`) + exp.flush([]) + service.allFetchingReady$.subscribe() + const expT = httpController.expectOne(`${service.backendUrl}templates`) + expT.flush([]) + expect( + service.allFetchingReady$ + ).toBeObservable( + hot('a', { + a: true, + }) + ) + }) + + }) + }) +}) diff --git a/src/util/pureConstant.service.ts b/src/util/pureConstant.service.ts index bc713ff19700ac01da3cda37f0f230daa817b872..d8a4d64b05eaafe1de3f497b1f45ff5776b59545 100644 --- a/src/util/pureConstant.service.ts +++ b/src/util/pureConstant.service.ts @@ -1,13 +1,13 @@ import { Injectable, OnDestroy } from "@angular/core"; -import { Store, createSelector, select } from "@ngrx/store"; -import { Observable, merge, Subscription, of, throwError, forkJoin, fromEvent } from "rxjs"; -import { VIEWER_CONFIG_FEATURE_KEY, IViewerConfigState, viewerConfigSelectorUseMobileUi } from "src/services/state/viewerConfig.store.helper"; -import { shareReplay, tap, scan, catchError, filter, switchMap, map, take } from "rxjs/operators"; +import { Store, select } from "@ngrx/store"; +import { Observable, merge, Subscription, of, throwError, forkJoin, fromEvent, combineLatest, timer } from "rxjs"; +import { viewerConfigSelectorUseMobileUi } from "src/services/state/viewerConfig.store.helper"; +import { shareReplay, tap, scan, catchError, filter, switchMap, map, take, switchMapTo } from "rxjs/operators"; import { HttpClient } from "@angular/common/http"; -import { BACKENDURL } from './constants' -import { viewerStateSetFetchedAtlases } from "src/services/state/viewerState.store.helper"; +import { viewerStateFetchedTemplatesSelector, viewerStateSetFetchedAtlases } from "src/services/state/viewerState.store.helper"; import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service"; import { LoggingService } from "src/logging"; +import { viewerStateFetchedAtlasesSelector } from "src/services/state/viewerState/selectors"; const getUniqueId = () => Math.round(Math.random() * 1e16).toString(16) @@ -23,6 +23,8 @@ export class PureContantService implements OnDestroy{ public totalAtlasesLength: number + public allFetchingReady$: Observable<boolean> + public backendUrl = (BACKEND_URL && `${BACKEND_URL}/`.replace(/\/\/$/, '/')) || `${window.location.origin}${window.location.pathname}` private workerUpdateParcellation$ = fromEvent(this.workerService.worker, 'message').pipe( @@ -112,7 +114,7 @@ export class PureContantService implements OnDestroy{ shareReplay(1) ) - this.fetchedAtlases$ = this.http.get(`${BACKENDURL.replace(/\/$/, '')}/atlases/`, { responseType: 'json' }).pipe( + this.fetchedAtlases$ = this.http.get(`${this.backendUrl.replace(/\/$/, '')}/atlases/`, { responseType: 'json' }).pipe( catchError((err, obs) => of(null)), filter(v => !!v), tap((arr: any[]) => this.totalAtlasesLength = arr.length), @@ -120,7 +122,7 @@ export class PureContantService implements OnDestroy{ ...atlases.map(({ url }) => this.http.get( /^http/.test(url) ? url - : `${BACKENDURL.replace(/\/$/, '')}/${url}`, + : `${this.backendUrl.replace(/\/$/, '')}/${url}`, { responseType: 'json' })) )), scan((acc, curr) => acc.concat(curr).sort((a, b) => (a.order || 1000) - (b.order || 1001)), []), @@ -134,6 +136,25 @@ export class PureContantService implements OnDestroy{ ) ) ) + + this.allFetchingReady$ = combineLatest([ + this.getTemplateEndpoint$.pipe( + map(arr => arr.length), + ), + this.store.pipe( + select(viewerStateFetchedTemplatesSelector), + map(arr => arr.length), + ), + this.store.pipe( + select(viewerStateFetchedAtlasesSelector), + map(arr => arr.length), + ) + ]).pipe( + map(([ expNumTmpl, actNumTmpl, actNumAtlas ]) => { + return expNumTmpl === actNumTmpl && actNumAtlas === this.totalAtlasesLength + }), + shareReplay(1), + ) } private subscriptions: Subscription[] = []