UNPKG

@itexpert-dev/base-universal-table

Version:

base universal table for build tables

256 lines (228 loc) 10.7 kB
import {KeyValueStorage} from '@itexpert-dev/key-value-storage' import {Observable, Subject, ReplaySubject} from 'rxjs' import {UniversalTableDataPreprocessors} from './universalTableDataPreprocessors' import {IUniversalTableParsedRequest} from "./common/interfaces/IUniversalTableParsedRequest"; import {ViewContainerRef, Injector, ComponentFactoryResolver, ReflectiveInjector} from "@angular/core"; import {UniversalTableConfigurator} from "./universalTableConfigurator/universalTableConfigurator"; import {IUniversalTableCtrl} from "../../../contracts/IUniversalTableCtrl"; import {IUniversalTableViewScope} from "../../../contracts/IUniversalTableViewScope"; import {IUniversalTableState} from "../../../contracts/IUniversalTableState"; import {IUniversalTableComponents} from "../../../contracts/IUniversalTableDefaultComponents"; import {IUniversalTableCtrlInitParams} from "../../../contracts/IUniversalTableCtrlInitParams"; import {IUniversalTableGetDataResponse} from "../../../contracts/IUniversalTableGetDataResponse"; import {IUniversalTableGetDataRequest} from "../../../contracts/IUniversalTableGetDataRequest"; import {IUniversalTableCellPosition} from "../../../contracts/IUniversalTableCellPosition"; import {IUniversalTableHeaderData} from "../../../contracts/IUniversalTableHeaderData"; class UniversalTableCtrl extends IUniversalTableCtrl{ private headers: Subject<IUniversalTableParsedRequest> = new ReplaySubject<IUniversalTableParsedRequest>(1); private rows: Subject<IUniversalTableParsedRequest> = new ReplaySubject<IUniversalTableParsedRequest>(1); /** * @desc object for ui bind handlers and templates * @type {IUniversalTableViewScope} */ public viewScope:IUniversalTableViewScope = { headers: this.headers.map(next=>this.dataPreprocessors.parseHeaders(next.viewFields, next.metadata)), rows: this.rows.map(next=>this.dataPreprocessors.parseData(next.viewFields, next)), totalResult: 0 }; public currentState: IUniversalTableState; public stateStream: Subject<IUniversalTableState> = new ReplaySubject<IUniversalTableState>(1); /** * @desc ctrl instance components for render UI * @type {IUniversalTableComponents} */ public tableComponents: IUniversalTableComponents = {}; //storage for refs in template for inject components public viewContainerRefs:KeyValueStorage<any> = new KeyValueStorage<any>(); public dataPreprocessors = UniversalTableDataPreprocessors; public config: UniversalTableConfigurator; public initParams: IUniversalTableCtrlInitParams; constructor( initParams: IUniversalTableCtrlInitParams, config: UniversalTableConfigurator ){ super(); this.config = config; this.initParams = initParams; this.currentState = {}; this.stateStream.subscribe( next=>{ Object.assign(this.currentState, next); } ); this.updateCurrentState({isInit: false}); //fix empty components map if(!this.initParams.hasOwnProperty('componentsMap')){ this.initParams.componentsMap = {} } //apply local config by default and init config Object.assign( this.tableComponents, this.config.getDefaultComponents(), this.initParams.componentsMap ); Object.assign( this.currentState, this.config.getDefaultInitTableState(), this.initParams.initState ); } private updateCurrentState(state: IUniversalTableState){ this.stateStream.next(Object.assign({}, this.currentState, state)); } public resolveInit(){ this.updateCurrentState({isInit: true}); }; private getRequireFields(state:IUniversalTableState, request: IUniversalTableGetDataResponse):string[]{ let requireFields: string[]; if (!state.hasOwnProperty('viewFields') || state.viewFields === null){ if (!state.hasOwnProperty('fields') || state.fields === null){ if (this.currentState === null || !this.currentState.hasOwnProperty('fields')){ requireFields = []; Object.keys(request.metadata).map( key=>requireFields.push(key) ) } else{ requireFields = this.currentState.fields } }else{ requireFields = state.fields } } else { requireFields = state.viewFields } return requireFields } public updateState( state: IUniversalTableState = {}, options:{enableStateDiff: boolean} = {enableStateDiff: true} ):Observable<null>{ let newState: IUniversalTableState = {}; if(options.enableStateDiff === true){ let diff: IUniversalTableState = {}; let anyDiff:boolean = false; Object.keys(state).map(key=>{ let val = (state as any)[key]; if((this.currentState as any)[key]!==val){ anyDiff = true; (diff as any)[key] = val } }); if(anyDiff){ return this.setState(Object.assign({}, this.currentState, diff)) }else{ return Observable.empty() } }else{ Object.assign(newState, this.currentState, state); } return this.setState(newState) } private setState(state: IUniversalTableState):Observable<null>{ this.updateCurrentState({isUpdate: true}); let query:IUniversalTableGetDataRequest = { fields: state.fields, filter: state.filter, limit: state.limit, offset: state.offset, sort: state.sort }; return this.initParams //send request to server .getDataMethod(query) //append state to query with actual totalResult .map(next=>{ return Object.assign(next, { state: Object.assign(state, { totalResult: next.totalResult }) }) }) // calculate actual view fields .map(next=>{ let result: IUniversalTableParsedRequest = Object.assign(next, { viewFields: this.getRequireFields(next.state, next) }); return result }) // publish new data to UI binding stream .do((next)=>{ this.headers.next(next); this.rows.next(next); this.updateCurrentState(Object.assign(next.state, {isUpdate: false})); }) .pluck('state') } public printContainer(container: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver, parentInjector: Injector){ let componentKey = this.tableComponents.container; let componentFactory = this.config.componentsStorage.getComponent(componentKey); let injector = ReflectiveInjector.resolveAndCreate( [{ provide: IUniversalTableCtrl, useValue: this }], parentInjector ); let component = componentFactoryResolver.resolveComponentFactory(<any>componentFactory); container.createComponent(component, 0, injector); } public printPaginator(container: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver, parentInjector: Injector){ let componentKey = this.tableComponents.paginator; let componentFactory = this.config.componentsStorage.getComponent(componentKey); let injector = ReflectiveInjector.resolveAndCreate( [{ provide: IUniversalTableCtrl, useValue: this }], parentInjector ); let component = componentFactoryResolver.resolveComponentFactory(<any>componentFactory); container.createComponent(component, 0, injector); } public printCell(container: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver, parentInjector: Injector, cellPosition: IUniversalTableCellPosition){ let componentKey = this.tableComponents.cell; let componentFactory = this.config.componentsStorage.getComponent(componentKey); let injector = ReflectiveInjector.resolveAndCreate( [{ provide: IUniversalTableCtrl, useValue: this },{ provide: IUniversalTableCellPosition, useValue: cellPosition }], parentInjector ); let component = componentFactoryResolver.resolveComponentFactory(<any>componentFactory); container.createComponent(component, 0, injector); } public printGrid(container: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver, parentInjector: Injector){ let componentKey = this.tableComponents.grid; let componentFactory = this.config.componentsStorage.getComponent(componentKey); let injector = ReflectiveInjector.resolveAndCreate( [{ provide: IUniversalTableCtrl, useValue: this }], parentInjector ); let component = componentFactoryResolver.resolveComponentFactory(<any>componentFactory); container.createComponent(component, 0, injector); } public printHeader(container: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver, parentInjector: Injector, headerData: IUniversalTableHeaderData){ let componentKey = this.tableComponents.headers; let componentFactory = this.config.componentsStorage.getComponent(componentKey); let injector = ReflectiveInjector.resolveAndCreate( [{ provide: IUniversalTableCtrl, useValue: this },{ provide: IUniversalTableHeaderData, useValue: headerData }], parentInjector ); let component = componentFactoryResolver.resolveComponentFactory(<any>componentFactory); container.createComponent(component, 0, injector); } } export {UniversalTableCtrl}