LP#1775466 grid local/client sort support
authorBill Erickson <berickxx@gmail.com>
Thu, 2 Aug 2018 22:13:53 +0000 (18:13 -0400)
committerBill Erickson <berickxx@gmail.com>
Wed, 5 Sep 2018 14:05:23 +0000 (10:05 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/share/grid/grid-header.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.ts

index 584cc76..0010a45 100644 (file)
@@ -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
index e169d03..3a6d073 100644 (file)
@@ -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;
index 9262c28..b2af621 100644 (file)
@@ -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) {