/* * @license * Copyright Akveo. All Rights Reserved. * Licensed under the MIT License. See License.txt in the project root for license information. */ import { Injectable } from '@angular/core'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { NbCollectionViewer } from '../../cdk/collections/collection-viewer'; import { NbDataSource } from '../../cdk/table/data-source'; import { NbSortable, NbSortRequest } from '../tree-grid-sort.component'; import { NbTreeGridDataService } from './tree-grid-data.service'; import { NbTreeGridFilterService } from './tree-grid-filter.service'; import { NbTreeGridSortService } from './tree-grid-sort.service'; import { NbGetters, NB_DEFAULT_ROW_LEVEL, NbTreeGridPresentationNode } from './tree-grid.model'; import { NbToggleOptions, NbTreeGridService } from './tree-grid.service'; export interface NbFilterable { filter(filterRequest: string); } export class NbTreeGridDataSource extends NbDataSource> implements NbSortable, NbFilterable { /** Stream that emits when a new data array is set on the data source. */ private data: BehaviorSubject[]>; /** Stream emitting render data to the table (depends on ordered data changes). */ private readonly renderData = new BehaviorSubject[]>([]); private readonly filterRequest = new BehaviorSubject(''); private readonly sortRequest = new BehaviorSubject(null); constructor(private sortService: NbTreeGridSortService, private filterService: NbTreeGridFilterService, private treeGridService: NbTreeGridService, private treeGridDataService: NbTreeGridDataService) { super(); } setData(data: N[], customGetters?: NbGetters) { let presentationData: NbTreeGridPresentationNode[] = []; if (data) { presentationData = this.treeGridDataService.toPresentationNodes(data, customGetters); } this.data = new BehaviorSubject(presentationData); this.updateChangeSubscription(); } connect( collectionViewer: NbCollectionViewer, ): Observable[] | ReadonlyArray>> { return this.renderData; } disconnect(collectionViewer: NbCollectionViewer) { } expand(row: T) { this.treeGridService.expand(this.data.value, row); this.data.next(this.data.value); } collapse(row: T) { this.treeGridService.collapse(this.data.value, row); this.data.next(this.data.value); } toggle(row: T, options?: NbToggleOptions) { this.treeGridService.toggle(this.data.value, row, options); this.data.next(this.data.value); } toggleByIndex(dataIndex: number, options?: NbToggleOptions) { const node: NbTreeGridPresentationNode = this.renderData.value && this.renderData.value[dataIndex]; if (node) { this.toggle(node.data, options); } } getLevel(rowIndex: number): number { const row = this.renderData.value[rowIndex]; return row ? row.level : NB_DEFAULT_ROW_LEVEL; } sort(sortRequest: NbSortRequest) { this.sortRequest.next(sortRequest); } filter(searchQuery: string) { this.filterRequest.next(searchQuery); } protected updateChangeSubscription() { const dataStream = this.data; const filteredData = combineLatest([dataStream, this.filterRequest]) .pipe( map(([data]) => this.treeGridDataService.copy(data)), map(data => this.filterData(data)), ); const sortedData = combineLatest([filteredData, this.sortRequest]) .pipe( map(([data]) => this.sortData(data)), ); sortedData .pipe( map((data: NbTreeGridPresentationNode[]) => this.treeGridDataService.flattenExpanded(data)), ) .subscribe((data: NbTreeGridPresentationNode[]) => this.renderData.next(data)); } private filterData(data: NbTreeGridPresentationNode[]): NbTreeGridPresentationNode[] { return this.filterService.filter(this.filterRequest.value, data); } private sortData(data: NbTreeGridPresentationNode[]): NbTreeGridPresentationNode[] { return this.sortService.sort(this.sortRequest.value, data); } } @Injectable() export class NbTreeGridDataSourceBuilder { constructor(private filterService: NbTreeGridFilterService, private sortService: NbTreeGridSortService, private treeGridService: NbTreeGridService, private treeGridDataService: NbTreeGridDataService) { } create(data: N[], customGetters?: NbGetters): NbTreeGridDataSource { const dataSource = new NbTreeGridDataSource( this.sortService, this.filterService, this.treeGridService, this.treeGridDataService, ); dataSource.setData(data, customGetters); return dataSource; } }