From 5312f3f884dc18a7de45f9961c0c280721616a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr> Date: Mon, 8 Jun 2020 12:11:53 +0200 Subject: [PATCH] [dome] table ordering by columns vs. by fields --- ivette/src/dome/src/renderer/table/arrays.ts | 55 +++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/ivette/src/dome/src/renderer/table/arrays.ts b/ivette/src/dome/src/renderer/table/arrays.ts index 3159d105c02..cade7114870 100644 --- a/ivette/src/dome/src/renderer/table/arrays.ts +++ b/ivette/src/dome/src/renderer/table/arrays.ts @@ -17,6 +17,8 @@ import { // --- Sorting Utilities // -------------------------------------------------------------------------- +export type ByColumns<Row> = { [dataKey: string]: Compare.Order<Row> }; + interface PACK<Key, Row> { index: number | undefined; key: Key; @@ -25,23 +27,26 @@ interface PACK<Key, Row> { type SORT<K, R> = Order<PACK<K, R>>; -function orderBy<K, R>(fields: ByFields<R>, ord: SortingInfo): SORT<K, R> { - const fd = ord.sortBy as keyof R; - const fn = fields[fd] ?? Compare.equal; +function orderBy<K, R>( + columns: ByColumns<R>, + ord: SortingInfo, +): SORT<K, R> { + const dataKey = ord.sortBy; + const byData = columns[dataKey] ?? Compare.equal; const rv = ord.sortDirection === 'DESC'; type D = PACK<K, R>; - const byField = (x: D, y: D) => fn(x.row[fd], y.row[fd]); + const byEntry = (x: D, y: D) => byData(x.row, y.row); const byIndex = (x: D, y: D) => (x.index ?? 0) - (y.index ?? 0); - return Compare.direction(Compare.sequence(byField, byIndex), rv); + return Compare.direction(Compare.sequence(byEntry, byIndex), rv); } function orderByRing<K, R>( natural: undefined | Order<R>, - compare: undefined | ByFields<R>, + columns: undefined | ByColumns<R>, ring: SortingInfo[], ): SORT<K, R> { type D = PACK<K, R>; - const byRing = compare ? ring.map((ord) => orderBy(compare, ord)) : []; + const byRing = columns ? ring.map((ord) => orderBy(columns, ord)) : []; const byData = natural ? ((x: D, y: D) => natural(x.row, y.row)) : undefined; return Compare.sequence(...byRing, byData); } @@ -75,7 +80,7 @@ export class MapModel<Key, Row> private natural?: Order<Row>; // Sortable columns and associated ordering (if any) - private columns?: ByFields<Row>; + private columns?: ByColumns<Row>; // Comparison Ring private ring: SortingInfo[] = []; @@ -140,13 +145,14 @@ export class MapModel<Key, Row> // --- Ordering // -------------------------------------------------------------------------- - /** Sets comparison functions for _all_ columns. - Non-specified columns becomes _non_ sortable. This will be used to refine + /** Sets comparison functions for the specified columns. Previous + comparison for un-specified columns are kept unchanged, if any. + This will be used to refine [[setNaturalOrder]] in response to user column selection with [[setSortBy]] provided you enable by-column sorting from the table view. Finally triggers a reload. */ - setColumnOrder(columns?: ByFields<Row>) { - this.columns = columns; + setColumnOrder(columns?: ByColumns<Row>) { + this.columns = { ...this.columns, ...columns }; this.reload(); } @@ -167,7 +173,30 @@ export class MapModel<Key, Row> */ setOrderingByFields(byfields: ByFields<Row>) { this.natural = Compare.byFields(byfields); - this.columns = byfields; + const columns = this.columns ?? {}; + for (let k of Object.keys(byfields)) { + const dataKey = k as (string & keyof Row); + const fn = byfields[dataKey]; + if (fn) columns[dataKey] = (x: Row, y: Row) => { + const dx = x[dataKey]; + const dy = y[dataKey]; + if (dx === dy) return 0; + if (dx === undefined) return 1; + if (dy === undefined) return -1; + return fn(dx, dy); + }; + } + this.columns = columns; + this.reload(); + } + + /** + Remove the sorting function for the provided column. + */ + deleteColumnOrder(dataKey: string) { + const columns = this.columns; + if (columns) delete columns[dataKey]; + this.ring = this.ring.filter(ord => ord.sortBy !== dataKey); this.reload(); } -- GitLab