From c82f38eb5e82a51887e3655a9ea3f78df3cc11b1 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Thu, 2 Aug 2018 18:13:53 -0400 Subject: [PATCH] LP#1775466 grid local/client sort support Signed-off-by: Bill Erickson --- .../src/app/share/grid/grid-header.component.ts | 7 ++- .../src/eg2/src/app/share/grid/grid.component.ts | 6 +++ Open-ILS/src/eg2/src/app/share/grid/grid.ts | 58 ++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid-header.component.ts b/Open-ILS/src/eg2/src/app/share/grid/grid-header.component.ts index 584cc76394..0010a45f38 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid-header.component.ts +++ b/Open-ILS/src/eg2/src/app/share/grid/grid-header.component.ts @@ -43,7 +43,12 @@ export class GridHeaderComponent implements OnInit { } this.context.dataSource.sort = [{name: col.name, dir: dir}]; - this.context.reload(); + + if (this.context.useLocalSort) { + this.context.sortLocal(); + } else { + this.context.reload(); + } } // Returns true if the provided column is sorting in the diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts b/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts index e169d03162..3a6d073744 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts +++ b/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts @@ -35,6 +35,11 @@ export class GridComponent implements OnInit, AfterViewInit, OnDestroy { // True if the grid supports sorting of multiple columns at once @Input() multiSortable: boolean; + // If true, grid sort requests only operate on data that + // already exists in the grid data source -- no row fetching. + // The assumption is all data is already available. + @Input() useLocalSort: boolean; + // Storage persist key / per-grid-type unique identifier // The value is prefixed with 'eg.grid.' @Input() persistKey: string; @@ -103,6 +108,7 @@ export class GridComponent implements OnInit, AfterViewInit, OnDestroy { this.context.persistKey = this.persistKey; this.context.isSortable = this.sortable === true; this.context.isMultiSortable = this.multiSortable === true; + this.context.useLocalSort = this.useLocalSort === true; this.context.disableMultiSelect = this.disableMultiSelect === true; this.context.rowFlairIsEnabled = this.rowFlairIsEnabled === true; this.context.rowFlairCallback = this.rowFlairCallback; diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid.ts b/Open-ILS/src/eg2/src/app/share/grid/grid.ts index 9262c28d35..b2af62144d 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid.ts +++ b/Open-ILS/src/eg2/src/app/share/grid/grid.ts @@ -30,6 +30,7 @@ export class GridColumn { isDragTarget: boolean; isSortable: boolean; isMultiSortable: boolean; + comparator: (valueA: any, valueB: any) => number; // True if the column was automatically generated. isAuto: boolean; @@ -406,6 +407,7 @@ export class GridContext { idlClass: string; isSortable: boolean; isMultiSortable: boolean; + useLocalSort: boolean; persistKey: string; disableMultiSelect: boolean; dataSource: GridDataSource; @@ -482,6 +484,17 @@ export class GridContext { }); } + // Sort the existing data source instead of requesting sorted + // data from the client. Reset pager to page 1. As with reload(), + // give the client a chance to setting before redisplaying. + sortLocal() { + setTimeout(() => { + this.pager.reset(); + this.sortLocalData(); + this.dataSource.requestPage(this.pager); + }); + } + // Subscribe or unsubscribe to page-change events from the pager. listenToPager() { if (this.pageChanges) { return; } @@ -495,6 +508,51 @@ export class GridContext { this.pageChanges = null; } + // Sort data in the data source array + sortLocalData() { + + const sortDefs = this.dataSource.sort.map(sort => { + const def = { + name: sort.name, + dir: sort.dir, + col: this.columnSet.getColByName(sort.name) + }; + + if (!def.col.comparator) { + def.col.comparator = (a, b) => { + if (a < b) { return -1; } + if (a > b) { return 1; } + return 0; + }; + } + + return def; + }); + + this.dataSource.data.sort((rowA, rowB) => { + + for (let idx = 0; idx < sortDefs.length; idx++) { + const sortDef = sortDefs[idx]; + + const valueA = this.getRowColumnValue(rowA, sortDef.col); + const valueB = this.getRowColumnValue(rowB, sortDef.col); + + if (valueA === '' && valueB === '') { continue; } + if (valueA === '' && valueB !== '') { return 1; } + if (valueA !== '' && valueB === '') { return -1; } + + const diff = sortDef.col.comparator(valueA, valueB); + if (diff === 0) { continue; } + + console.log(valueA, valueB, diff); + + return sortDef.dir === 'DESC' ? -diff : diff; + } + + return 0; // No differences found. + }); + } + getRowIndex(row: any): any { const col = this.columnSet.indexColumn; if (!col) { -- 2.11.0