diff --git a/client/src/app/shared/components/list-view-table/list-view-table.component.ts b/client/src/app/shared/components/list-view-table/list-view-table.component.ts index ce95c5038..427bfc381 100644 --- a/client/src/app/shared/components/list-view-table/list-view-table.component.ts +++ b/client/src/app/shared/components/list-view-table/list-view-table.component.ts @@ -11,10 +11,11 @@ import { ViewEncapsulation } from '@angular/core'; -import { columnFactory, createDS, PblDataSource, PblNgridComponent } from '@pebula/ngrid'; +import { columnFactory, createDS, DataSourcePredicate, PblDataSource, PblNgridComponent } from '@pebula/ngrid'; import { PblColumnDefinition, PblColumnFactory, PblNgridColumnSet } from '@pebula/ngrid/lib/table'; import { PblNgridDataMatrixRow } from '@pebula/ngrid/target-events'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; +import { distinctUntilChanged } from 'rxjs/operators'; import { OperatorService, Permission } from 'app/core/core-services/operator.service'; import { StorageService } from 'app/core/core-services/storage.service'; @@ -223,10 +224,15 @@ export class ListViewTableComponent>(); /** - * test data source + * Table data source */ public dataSource: PblDataSource; + /** + * Observable to the raw data + */ + private dataListObservable: Observable; + /** * Minimal column width */ @@ -252,17 +258,16 @@ export class ListViewTableComponent { + this.getListObservable(); + await this.restoreSearchQuery(); + this.createDataSource(); + this.changeRowHeight(); + this.scrollToPreviousPosition(); + this.cd.detectChanges(); + } + + /** + * Stop the change detection + */ + public ngOnDestroy(): void { + this.cd.detach(); + for (const sub of this.subs) { + sub.unsubscribe(); + } + this.subs = []; + } + + /** + * Function to create the DataSource + */ + private createDataSource(): void { this.dataSource = createDS() - .onTrigger(() => { - let listObservable: Observable; - if (this.repo && this.viewModelListObservable) { - if (this.filterService && this.sortService) { - // filtering and sorting - this.filterService.initFilters(this.viewModelListObservable); - this.sortService.initSorting(this.filterService.outputObservable); - listObservable = this.sortService.outputObservable; - } else if (this.filterService) { - // only filter service - this.filterService.initFilters(this.viewModelListObservable); - listObservable = this.filterService.outputObservable; - } else if (this.sortService) { - // only sorting - this.sortService.initSorting(this.viewModelListObservable); - listObservable = this.sortService.outputObservable; - } else { - // none of both - listObservable = this.viewModelListObservable; - } - } - - return listObservable ? listObservable : []; - }) + .onTrigger(() => (this.dataListObservable ? this.dataListObservable : [])) .create(); - const filterPredicate = (item: V): boolean => { - if (!this.inputValue) { - return true; - } - - if (this.inputValue) { - // filter by ID - const trimmedInput = this.inputValue.trim().toLowerCase(); - const idString = '' + item.id; - const foundId = - idString - .trim() - .toLowerCase() - .indexOf(trimmedInput) !== -1; - if (foundId) { - return true; - } - - // custom filter predicates - if (this.filterProps && this.filterProps.length) { - for (const prop of this.filterProps) { - if (item[prop]) { - let propertyAsString = ''; - // If the property is a function, call it. - if (typeof item[prop] === 'function') { - propertyAsString = '' + item[prop](); - } else if (item[prop].constructor === Array) { - propertyAsString = item[prop].join(''); - } else { - propertyAsString = '' + item[prop]; - } - - if (!!propertyAsString) { - const foundProp = - propertyAsString - .trim() - .toLowerCase() - .indexOf(trimmedInput) !== -1; - - if (foundProp) { - return true; - } - } - } - } - } - } - }; - - this.dataSource.setFilter(filterPredicate); - // inform listening components about changes in the data source this.dataSource.onSourceChanged.subscribe(() => { this.dataSourceChange.next(this.dataSource); @@ -490,21 +442,51 @@ export class ListViewTableComponent { + this.dataSource.refresh(); + }) + ); + } + + // refresh the data source if the sorting changed + if (this.sortService) { + this.subs.push( + this.sortService.outputObservable.subscribe(() => { + this.dataSource.refresh(); + }) + ); } } /** - * Stop the change detection + * Determines and sets the raw data as observable lists according + * to the used search and filter services */ - public ngOnDestroy(): void { - this.cd.detach(); + private getListObservable(): void { + if (this.repo && this.viewModelListObservable) { + if (this.filterService && this.sortService) { + // filtering and sorting + this.filterService.initFilters(this.viewModelListObservable); + this.sortService.initSorting(this.filterService.outputObservable); + this.dataListObservable = this.sortService.outputObservable; + } else if (this.filterService) { + // only filter service + this.filterService.initFilters(this.viewModelListObservable); + this.dataListObservable = this.filterService.outputObservable; + } else if (this.sortService) { + // only sorting + this.sortService.initSorting(this.viewModelListObservable); + this.dataListObservable = this.sortService.outputObservable; + } else { + // none of both + this.dataListObservable = this.viewModelListObservable; + } + } } /** @@ -514,6 +496,58 @@ export class ListViewTableComponent { + if (!this.inputValue) { + return true; + } + + // filter by ID + const trimmedInput = this.inputValue.trim().toLowerCase(); + const idString = '' + item.id; + const foundId = + idString + .trim() + .toLowerCase() + .indexOf(trimmedInput) !== -1; + if (foundId) { + return true; + } + + // custom filter predicates + if (this.filterProps && this.filterProps.length) { + for (const prop of this.filterProps) { + if (item[prop]) { + let propertyAsString = ''; + // If the property is a function, call it. + if (typeof item[prop] === 'function') { + propertyAsString = '' + item[prop](); + } else if (item[prop].constructor === Array) { + propertyAsString = item[prop].join(''); + } else { + propertyAsString = '' + item[prop]; + } + + if (!!propertyAsString) { + const foundProp = + propertyAsString + .trim() + .toLowerCase() + .indexOf(trimmedInput) !== -1; + + if (foundProp) { + return true; + } + } + } + } + } + }; + } + /** * Generic click handler for rows. Allow so (multi) select anywhere * @param event the clicked row @@ -557,11 +591,7 @@ export class ListViewTableComponent { - this.inputValue = await this.store.get(`query_${key}`); + public async restoreSearchQuery(): Promise { + this.inputValue = await this.store.get(`query_${this.listStorageKey}`); } /** @@ -604,10 +634,9 @@ export class ListViewTableComponent { - this.ngrid.viewport.scrollToIndex(index); - }); + public async scrollToPreviousPosition(): Promise { + const scrollIndex = await this.getScrollIndex(this.listStorageKey); + this.ngrid.viewport.scrollToIndex(scrollIndex); } /**