import { IDataModel } from '../Base' ; import { IResponseMessageHandler } from 'src/app/Common/ResponseMessageHandlers' ; import { Observable , Subject , throwError , of , forkJoin , AsyncSubject } from 'rxjs' ; import { IClusterHealthChunk , IHealthStateChunk , IHealthStateChunkList } from '../../HealthChunkRawDataTypes' ; import { ValueResolver } from 'src/app/Utils/ValueResolver' ; import { mergeMap , map , finalize , catchError } from 'rxjs/operators' ; import { CollectionUtils } from 'src/app/Utils/CollectionUtils' ; import { Utils } from 'src/app/Utils/Utils' ; import { DataService } from 'src/app/services/data.service' ; export interface IDataModelCollection < T extends IDataModel < any > > { collection : T [ ] ; length : number ; isInitialized : boolean ; isRefreshing : boolean ; viewPath : string ; find ( uniqueId ) : T ; refresh ( messageHandler ? ) : Observable < any > ; ensureInitialized ( forceRefresh ? , messageHandler ? ) : Observable < any > ; mergeClusterHealthStateChunk ( clusterHealthChunk ) : Observable < any > ; } export class DataModelCollectionBase < T extends IDataModel < any > > implements IDataModelCollection < T > { public isInitialized = false ; public parent : any ; public collection : T [ ] = [ ] ; public lastRefreshWasSuccessful = false ; private clearOnFailureToUpdate = false ; protected valueResolver : ValueResolver = new ValueResolver ( ) ; private appendOnly : boolean ; private hash : Record < string , T > ; private refreshingPromise : Subject < any > ; public get viewPath ( ) : string { return '' ; } public get length ( ) : number { return this . collection . length ; } public get isRefreshing ( ) : boolean { return ! ! this . refreshingPromise ; } protected get indexPropery ( ) : string { return 'uniqueId' ; } public constructor ( public data , parent ? , appendOnly = false ) { this . parent = parent ; this . appendOnly = appendOnly ; } public refresh ( messageHandler ? ) { let success = true ; if ( ! this . refreshingPromise ) { this . refreshingPromise = new AsyncSubject < any > ( ) ; this . clearOnFailureToUpdate = true ; this . retrieveNewCollection ( messageHandler ) . pipe ( mergeMap ( collection => { return this . update ( collection ) ; } ) , catchError ( err => { success = false ; return of ( err ) ; } ) ) . subscribe ( ( ) => { if ( this . clearOnFailureToUpdate && this . lastRefreshWasSuccessful ) { this . collection = [ ] ; } this . lastRefreshWasSuccessful = success ; this . refreshingPromise . next ( success ) ; this . refreshingPromise . complete ( ) ; this . refreshingPromise = null ; } ) ; } return this . refreshingPromise ? this . refreshingPromise . asObservable ( ) : of ( success ) ; } public clear ( ) { this . cancelLoad ( ) ; return of ( this . refreshingPromise ? this . refreshingPromise : true ) . pipe ( map ( ( ) => { this . collection = [ ] ; this . isInitialized = false ; } ) ) ; } protected cancelLoad ( ) { if ( this . refreshingPromise ) { this . refreshingPromise . next ( ) ; this . refreshingPromise . complete ( ) ; } } protected update ( collection ) { this . isInitialized = true ; this . clearOnFailureToUpdate = false ; this . collection = CollectionUtils . updateDataModelCollection ( this . collection , collection , this . appendOnly ) ; this . hash = Utils . keyBy ( this . collection , this . indexPropery ) ; return this . updateInternal ( ) ; } public ensureInitialized ( forceRefresh ? , messageHandler ? ) { if ( ! this . isInitialized || forceRefresh ) { return this . refresh ( messageHandler ) ; } return of ( this . lastRefreshWasSuccessful ) ; } public find ( uniqueId ) { if ( this . hash ) { return this . hash [ uniqueId ] ; } return null ; } public mergeClusterHealthStateChunk ( clusterHealthChunk ) { return of ( true ) ; } protected retrieveNewCollection ( messageHandler ? ) { return throwError ( null ) ; } protected updateInternal ( ) { return of ( true ) ; } protected updateCollectionFromHealthChunkList < P extends IHealthStateChunk > ( healthChunkList , newIdSelector ) { if ( ! CollectionUtils . compareCollectionsByKeys ( this . collection , healthChunkList . Items , item => item [ this . indexPropery ] , newIdSelector ) ) { if ( ! this . isRefreshing ) { return this . refresh ( ) ; } else { return of ( true ) ; } } const updatePromises = [ ] ; CollectionUtils . updateCollection < T , P > ( this . collection , healthChunkList . Items , item => item [ this . indexPropery ] , newIdSelector , null , ( item , newItem ) => { updatePromises . push ( item . mergeHealthStateChunk ( newItem ) ) ; } ) ; return forkJoin ( updatePromises ) ; } protected getDetailsList ( item ) { return null ; } }