From edd29ccec8e9b641ab8ef2054155e5b29bbd06ff Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 11 Dec 2020 22:11:41 +0100 Subject: [PATCH] WIP: MEGAFILTER --- src/app/components/table/table.component.html | 112 ++++++++++++--- src/app/components/table/table.component.scss | 7 +- src/app/components/table/table.component.ts | 131 +++++++++++++----- 3 files changed, 189 insertions(+), 61 deletions(-) diff --git a/src/app/components/table/table.component.html b/src/app/components/table/table.component.html index 0031901..20121d9 100644 --- a/src/app/components/table/table.component.html +++ b/src/app/components/table/table.component.html @@ -30,28 +30,8 @@ > add - - Filter - - - + + + + + + + + @@ -331,6 +393,10 @@ + diff --git a/src/app/components/table/table.component.scss b/src/app/components/table/table.component.scss index 70e85ef..fd8874b 100644 --- a/src/app/components/table/table.component.scss +++ b/src/app/components/table/table.component.scss @@ -56,12 +56,11 @@ } .highlighted-column { - box-shadow:inset 0 0 0 99999px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 0 0 99999px rgba(0, 0, 0, 0.05); } - - .mat-table-sticky { - box-shadow:inset 0 0 0 99999px rgba(0, 0, 0, 0.1); + .mat-table-sticky { + box-shadow: inset 0 0 0 99999px rgba(0, 0, 0, 0.1); } .button-wrapper { diff --git a/src/app/components/table/table.component.ts b/src/app/components/table/table.component.ts index 24e6c37..66ff813 100644 --- a/src/app/components/table/table.component.ts +++ b/src/app/components/table/table.component.ts @@ -68,6 +68,9 @@ export class TableComponent implements AfterViewInit { additionalColumnsBack: string[] = ['buttons']; displayedColumns: string[] = []; + displayedFilterColumns = []; + filters: any = {}; + loadingRowIds: string[] = []; /** data source of the table */ @@ -80,10 +83,9 @@ export class TableComponent implements AfterViewInit { @Input() relockingIntervalDuration = 1000 * 60 * 1; - filter = { includesString: '', onlyUnsaved: false }; - filterStringChanged: Subject = new Subject(); - initialFilter = this.filter; + filterChanged: Subject = new Subject(); + isLoaded = false; @Output() createEvent = new EventEmitter(); @@ -98,12 +100,27 @@ export class TableComponent implements AfterViewInit { private activatedroute: ActivatedRoute, private cdRef: ChangeDetectorRef ) { - this.filter.includesString = - this.activatedroute.snapshot.queryParamMap.get('filter') || ''; + /*this.filter.includesString = + this.activatedroute.snapshot.queryParamMap.get('filter') || '';*/ + //TODO: add filter from url } - ngAfterViewInit(): void { + ngOnInit() { this.addColumnPropertiesFromGQLSchemaToColumnInfo(); + console.log(this.columnInfo); + this.columnInfo.forEach((column) => + this.displayedColumns.push(column.dataPath) + ); + this.displayedFilterColumns = this.displayedColumns.map( + (columnName) => columnName + '.filter' + ); + this.displayedColumns.unshift(...this.additionalColumnsFront); + this.displayedColumns.push(...this.additionalColumnsBack); + + this.resetFilters(); + } + + ngAfterViewInit(): void { this.data.paginator = this.paginator; this.data.sortingDataAccessor = (item, columnName) => { if (typeof item[columnName] === 'string') { @@ -113,10 +130,52 @@ export class TableComponent implements AfterViewInit { }; this.data.sort = this.sort; - this.data.filter = (this.filter as unknown) as string; + this.data.filter = (this.filters as unknown) as string; this.data.filterPredicate = (data, filter: any) => { - const a = !filter.onlyUnsaved || data.newObject || data.isLockedByMe; - const b = + if (data.newObject) { + return true; // always show new objects + } + if (filter.onlyUnsaved && !data.isLockedByMe) { + return false; + } + for (const filterElementName of Object.keys(filter.columnFilters)) { + const filterElement = filter.columnFilters[filterElementName]; + if (filterElement.value) { + if (filterElement.type === 'String' || filterElement.type === 'Id') { + let searchString = filterElement.value.trim(); + let dataElement = data[filterElementName]?.trim(); + if (!filterElement.options.caseSensitive) { + searchString = searchString.toLowerCase(); + dataElement = dataElement.toLowerCase(); + } + if ( + (filterElement.options.exact && dataElement !== searchString) || + !dataElement.includes(searchString) + ) { + return false; + } + } + } + if (filterElement.min != null || filterElement.max != null) { + if ( + filterElement.type === 'Float' || + filterElement.type === 'Int' || + filterElement.type === 'Money' + ) { + let dataElement = data[filterElementName]; + if (dataElement == null) { + return false; + } + if (filterElement.min != null && dataElement < filterElement.min) { + return false; + } + if (filterElement.max != null && dataElement > filterElement.max) { + return false; + } + } + } + } + /*const b = !filter.includesString || Object.keys(data).some( (k) => @@ -125,19 +184,13 @@ export class TableComponent implements AfterViewInit { .toString() .toLowerCase() .includes(filter.includesString.toLowerCase()) - ); - return a && b; + );*/ + return true; }; - this.filterStringChanged - .pipe(debounceTime(400)) - .subscribe(() => this.applyFilter()); - - this.columnInfo.forEach((column) => - this.displayedColumns.push(column.dataPath) - ); - this.displayedColumns.unshift(...this.additionalColumnsFront); - this.displayedColumns.push(...this.additionalColumnsBack); + this.filterChanged.pipe(debounceTime(400)).subscribe(() => { + this.applyFilters(); + }); this.dataService.loadingRowIds.subscribe((rowIds) => { this.loadingRowIds = rowIds; @@ -287,7 +340,6 @@ export class TableComponent implements AfterViewInit { addNewObject() { this.paginator.firstPage(); - this.setFilter({ ...this.filter, includesString: '' }); this.resetSorting(); this.data.data = [ { newObject: true, id: this.getNewId() }, @@ -413,25 +465,36 @@ export class TableComponent implements AfterViewInit { } showOnlyUnsavedElements(value: boolean) { - this.filter.onlyUnsaved = value; - this.filter.includesString = ''; - this.applyFilter(); + if (value) { + this.resetFilters(); + } + this.filters['onlyUnsaved'] = value; + this.applyFilters(); } - newFilterStringValue(): void { - this.filterStringChanged.next(this.filter.includesString); + newFilterValue(): void { + console.log(this.filters); + this.filterChanged.next(this.filters); } - applyFilter(): void { - this.data.filter = ({ - ...this.filter, - includesString: this.filter.includesString.trim().toLowerCase(), - } as unknown) as string; + applyFilters(): void { + this.isLoaded = false; + setTimeout(() => { + this.data.filter = (this.filters as unknown) as string; + this.isLoaded = true; + }); } - setFilter(filterObject) { - this.filter = filterObject; - this.applyFilter(); + resetFilters() { + this.filters = []; + this.filters['columnFilters'] = []; + for (const column of this.columnInfo) { + this.filters.columnFilters[column.dataPath] = { + value: null, + type: column.type, + options: {}, + }; + } } resetSorting() {