@vuu-ui/vuu-utils 0.5.10 → 0.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/cjs/index.js +2 -0
- package/cjs/index.js.map +7 -0
- package/esm/index.js +2 -0
- package/esm/index.js.map +7 -0
- package/package.json +13 -12
- package/types/packages/vuu-utils/src/DataWindow.d.ts +39 -0
- package/types/packages/vuu-utils/src/array-utils.d.ts +3 -0
- package/types/packages/vuu-utils/src/column-utils.d.ts +32 -0
- package/types/packages/vuu-utils/src/data-utils.d.ts +9 -0
- package/types/packages/vuu-utils/src/date-utils.d.ts +1 -0
- package/types/packages/vuu-utils/src/event-emitter.d.ts +19 -0
- package/types/packages/vuu-utils/src/getUniqueId.d.ts +1 -0
- package/{src/index.ts → types/packages/vuu-utils/src/index.d.ts} +0 -0
- package/types/packages/vuu-utils/src/input-utils.d.ts +2 -0
- package/types/packages/vuu-utils/src/invariant.d.ts +1 -0
- package/types/packages/vuu-utils/src/nanoid/index.d.ts +1 -0
- package/types/packages/vuu-utils/src/range-utils.d.ts +21 -0
- package/types/packages/vuu-utils/src/round-decimal.d.ts +1 -0
- package/types/packages/vuu-utils/src/row-utils.d.ts +10 -0
- package/types/packages/vuu-utils/src/sort-utils.d.ts +5 -0
- package/types/packages/vuu-utils/src/text-utils.d.ts +1 -0
- package/types/showcase/src/examples/DataGrid/columnMetaData.d.ts +233 -0
- package/src/DataWindow.ts +0 -111
- package/src/array-utils.ts +0 -37
- package/src/column-utils.ts +0 -224
- package/src/data-utils.ts +0 -60
- package/src/date-utils.ts +0 -4
- package/src/event-emitter.ts +0 -139
- package/src/getUniqueId.ts +0 -1
- package/src/input-utils.ts +0 -50
- package/src/invariant.ts +0 -10
- package/src/nanoid/index.ts +0 -30
- package/src/range-utils.ts +0 -72
- package/src/round-decimal.ts +0 -126
- package/src/row-utils.ts +0 -44
- package/src/sort-utils.ts +0 -71
- package/src/text-utils.ts +0 -9
- package/test/DataWindow.test.ts +0 -108
- package/tsconfig-emit-types.json +0 -10
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface Event {
|
|
2
|
+
}
|
|
3
|
+
export declare type EventListener = (evtName: string, ...args: any[]) => void;
|
|
4
|
+
export declare type EventListenerMap = {
|
|
5
|
+
[eventName: string]: EventListener[] | EventListener;
|
|
6
|
+
};
|
|
7
|
+
export interface IEventEmitter {
|
|
8
|
+
emit: (type: string, ...args: unknown[]) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare class EventEmitter implements IEventEmitter {
|
|
11
|
+
private _events?;
|
|
12
|
+
constructor();
|
|
13
|
+
addListener(type: string, listener: EventListener): void;
|
|
14
|
+
removeListener(type: string, listener: EventListener): void;
|
|
15
|
+
removeAllListeners(type: string): void;
|
|
16
|
+
emit(type: string, ...args: unknown[]): void;
|
|
17
|
+
once(type: string, listener: EventListener): void;
|
|
18
|
+
on(type: string, listener: EventListener): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getUniqueId: () => string;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function invariant(condition: boolean, message: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const uuid: (size?: number) => string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface VuuRange {
|
|
2
|
+
from: number;
|
|
3
|
+
to: number;
|
|
4
|
+
bufferSize?: number;
|
|
5
|
+
reset?: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface FromToRange {
|
|
8
|
+
from: number;
|
|
9
|
+
to: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function getFullRange({ from, to }: VuuRange, bufferSize?: number, rowCount?: number): FromToRange;
|
|
12
|
+
export declare function resetRange({ from, to, bufferSize }: VuuRange): VuuRange;
|
|
13
|
+
export declare class WindowRange {
|
|
14
|
+
from: number;
|
|
15
|
+
to: number;
|
|
16
|
+
constructor(from: number, to: number);
|
|
17
|
+
isWithin(index: number): boolean;
|
|
18
|
+
overlap(from: number, to: number): [number, number];
|
|
19
|
+
copy(): WindowRange;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function roundDecimal(value?: number, align?: string, decimals?: number, zeroPad?: boolean, alignOnDecimals?: boolean): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare type RowIndex = {
|
|
2
|
+
[field: string]: number;
|
|
3
|
+
};
|
|
4
|
+
export declare type Row = {
|
|
5
|
+
[strKey: string]: any;
|
|
6
|
+
} & any[];
|
|
7
|
+
export declare function addRowsToIndex(rows: Row[], index: RowIndex, indexField: string): RowIndex;
|
|
8
|
+
export declare function indexRows(rows: Row[], indexField: string): RowIndex;
|
|
9
|
+
export declare function isEmptyRow(row: Row): boolean;
|
|
10
|
+
export declare function update(rows: Row[], updates: any): Row[];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ColumnDescriptor, KeyedColumnDescriptor } from "@vuu-ui/vuu-datagrid-types";
|
|
2
|
+
import { VuuSort, VuuSortType } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
export declare const applySort: ({ sortDefs }: VuuSort, { name: column }: ColumnDescriptor, extendSort?: boolean, sortType?: VuuSortType) => VuuSort;
|
|
4
|
+
export declare const setSortColumn: ({ sortDefs }: VuuSort, column: KeyedColumnDescriptor, sortType?: "A" | "D") => VuuSort;
|
|
5
|
+
export declare const addSortColumn: ({ sortDefs }: VuuSort, column: KeyedColumnDescriptor, sortType?: "A" | "D") => VuuSort;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const lastWord: (text: string) => string;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
export const pricesColumns: ({
|
|
2
|
+
name: string;
|
|
3
|
+
width: number;
|
|
4
|
+
type?: undefined;
|
|
5
|
+
aggregate?: undefined;
|
|
6
|
+
} | {
|
|
7
|
+
name: string;
|
|
8
|
+
type: {
|
|
9
|
+
name: string;
|
|
10
|
+
renderer: {
|
|
11
|
+
name: string;
|
|
12
|
+
flashStyle: string;
|
|
13
|
+
};
|
|
14
|
+
formatting: {
|
|
15
|
+
decimals: number;
|
|
16
|
+
zeroPad: boolean;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
aggregate: string;
|
|
20
|
+
width?: undefined;
|
|
21
|
+
} | {
|
|
22
|
+
name: string;
|
|
23
|
+
type: {
|
|
24
|
+
name: string;
|
|
25
|
+
renderer?: undefined;
|
|
26
|
+
formatting?: undefined;
|
|
27
|
+
};
|
|
28
|
+
width?: undefined;
|
|
29
|
+
aggregate?: undefined;
|
|
30
|
+
} | {
|
|
31
|
+
name: string;
|
|
32
|
+
width?: undefined;
|
|
33
|
+
type?: undefined;
|
|
34
|
+
aggregate?: undefined;
|
|
35
|
+
})[];
|
|
36
|
+
export const orderColumns: {
|
|
37
|
+
name: string;
|
|
38
|
+
width: number;
|
|
39
|
+
}[];
|
|
40
|
+
export const instrumentPriceColumns: ({
|
|
41
|
+
name: string;
|
|
42
|
+
width: number;
|
|
43
|
+
type?: undefined;
|
|
44
|
+
aggregate?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
name: string;
|
|
47
|
+
width?: undefined;
|
|
48
|
+
type?: undefined;
|
|
49
|
+
aggregate?: undefined;
|
|
50
|
+
} | {
|
|
51
|
+
name: string;
|
|
52
|
+
type: {
|
|
53
|
+
name: string;
|
|
54
|
+
renderer?: undefined;
|
|
55
|
+
formatting?: undefined;
|
|
56
|
+
};
|
|
57
|
+
width?: undefined;
|
|
58
|
+
aggregate?: undefined;
|
|
59
|
+
} | {
|
|
60
|
+
name: string;
|
|
61
|
+
type: {
|
|
62
|
+
name: string;
|
|
63
|
+
renderer: {
|
|
64
|
+
name: string;
|
|
65
|
+
flashStyle: string;
|
|
66
|
+
};
|
|
67
|
+
formatting: {
|
|
68
|
+
decimals: number;
|
|
69
|
+
zeroPad: boolean;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
aggregate: string;
|
|
73
|
+
width?: undefined;
|
|
74
|
+
})[];
|
|
75
|
+
export namespace instrumentSchema {
|
|
76
|
+
const columns: ({
|
|
77
|
+
name: string;
|
|
78
|
+
width: number;
|
|
79
|
+
type?: undefined;
|
|
80
|
+
aggregate?: undefined;
|
|
81
|
+
} | {
|
|
82
|
+
name: string;
|
|
83
|
+
type: {
|
|
84
|
+
name: string;
|
|
85
|
+
renderer: {
|
|
86
|
+
name: string;
|
|
87
|
+
flashStyle: string;
|
|
88
|
+
};
|
|
89
|
+
formatting: {
|
|
90
|
+
decimals: number;
|
|
91
|
+
zeroPad: boolean;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
aggregate: string;
|
|
95
|
+
width?: undefined;
|
|
96
|
+
} | {
|
|
97
|
+
name: string;
|
|
98
|
+
type: string;
|
|
99
|
+
aggregate: string;
|
|
100
|
+
width?: undefined;
|
|
101
|
+
} | {
|
|
102
|
+
name: string;
|
|
103
|
+
width?: undefined;
|
|
104
|
+
type?: undefined;
|
|
105
|
+
aggregate?: undefined;
|
|
106
|
+
})[];
|
|
107
|
+
}
|
|
108
|
+
export namespace instrumentSchemaFixed {
|
|
109
|
+
const columns_1: ({
|
|
110
|
+
name: string;
|
|
111
|
+
width: number;
|
|
112
|
+
locked: boolean;
|
|
113
|
+
type?: undefined;
|
|
114
|
+
aggregate?: undefined;
|
|
115
|
+
} | {
|
|
116
|
+
name: string;
|
|
117
|
+
width: number;
|
|
118
|
+
locked?: undefined;
|
|
119
|
+
type?: undefined;
|
|
120
|
+
aggregate?: undefined;
|
|
121
|
+
} | {
|
|
122
|
+
name: string;
|
|
123
|
+
type: {
|
|
124
|
+
name: string;
|
|
125
|
+
renderer: {
|
|
126
|
+
name: string;
|
|
127
|
+
flashStyle: string;
|
|
128
|
+
};
|
|
129
|
+
formatting: {
|
|
130
|
+
decimals: number;
|
|
131
|
+
zeroPad: boolean;
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
aggregate: string;
|
|
135
|
+
width?: undefined;
|
|
136
|
+
locked?: undefined;
|
|
137
|
+
} | {
|
|
138
|
+
name: string;
|
|
139
|
+
type: string;
|
|
140
|
+
aggregate: string;
|
|
141
|
+
width?: undefined;
|
|
142
|
+
locked?: undefined;
|
|
143
|
+
} | {
|
|
144
|
+
name: string;
|
|
145
|
+
width?: undefined;
|
|
146
|
+
locked?: undefined;
|
|
147
|
+
type?: undefined;
|
|
148
|
+
aggregate?: undefined;
|
|
149
|
+
})[];
|
|
150
|
+
export { columns_1 as columns };
|
|
151
|
+
}
|
|
152
|
+
export namespace instrumentSchemaLabels {
|
|
153
|
+
const columns_2: ({
|
|
154
|
+
name: string;
|
|
155
|
+
width: number;
|
|
156
|
+
label: string;
|
|
157
|
+
type?: undefined;
|
|
158
|
+
aggregate?: undefined;
|
|
159
|
+
} | {
|
|
160
|
+
name: string;
|
|
161
|
+
type: {
|
|
162
|
+
name: string;
|
|
163
|
+
renderer: {
|
|
164
|
+
name: string;
|
|
165
|
+
flashStyle: string;
|
|
166
|
+
};
|
|
167
|
+
formatting: {
|
|
168
|
+
decimals: number;
|
|
169
|
+
zeroPad: boolean;
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
aggregate: string;
|
|
173
|
+
width?: undefined;
|
|
174
|
+
label?: undefined;
|
|
175
|
+
} | {
|
|
176
|
+
name: string;
|
|
177
|
+
label: string;
|
|
178
|
+
type: string;
|
|
179
|
+
aggregate: string;
|
|
180
|
+
width?: undefined;
|
|
181
|
+
} | {
|
|
182
|
+
name: string;
|
|
183
|
+
label: string;
|
|
184
|
+
width?: undefined;
|
|
185
|
+
type?: undefined;
|
|
186
|
+
aggregate?: undefined;
|
|
187
|
+
} | {
|
|
188
|
+
name: string;
|
|
189
|
+
width?: undefined;
|
|
190
|
+
label?: undefined;
|
|
191
|
+
type?: undefined;
|
|
192
|
+
aggregate?: undefined;
|
|
193
|
+
})[];
|
|
194
|
+
export { columns_2 as columns };
|
|
195
|
+
}
|
|
196
|
+
export namespace instrumentSchemaHeaders {
|
|
197
|
+
const columns_3: ({
|
|
198
|
+
name: string;
|
|
199
|
+
width: number;
|
|
200
|
+
heading: string[];
|
|
201
|
+
type?: undefined;
|
|
202
|
+
aggregate?: undefined;
|
|
203
|
+
} | {
|
|
204
|
+
name: string;
|
|
205
|
+
type: {
|
|
206
|
+
name: string;
|
|
207
|
+
renderer: {
|
|
208
|
+
name: string;
|
|
209
|
+
flashStyle: string;
|
|
210
|
+
};
|
|
211
|
+
formatting: {
|
|
212
|
+
decimals: number;
|
|
213
|
+
zeroPad: boolean;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
aggregate: string;
|
|
217
|
+
heading: string[];
|
|
218
|
+
width?: undefined;
|
|
219
|
+
} | {
|
|
220
|
+
name: string;
|
|
221
|
+
type: string;
|
|
222
|
+
aggregate: string;
|
|
223
|
+
heading: string[];
|
|
224
|
+
width?: undefined;
|
|
225
|
+
} | {
|
|
226
|
+
name: string;
|
|
227
|
+
heading: string[];
|
|
228
|
+
width?: undefined;
|
|
229
|
+
type?: undefined;
|
|
230
|
+
aggregate?: undefined;
|
|
231
|
+
})[];
|
|
232
|
+
export { columns_3 as columns };
|
|
233
|
+
}
|
package/src/DataWindow.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { WindowRange } from "./range-utils";
|
|
2
|
-
import { metadataKeys } from "./column-utils";
|
|
3
|
-
|
|
4
|
-
export type DataItem = string | number | boolean;
|
|
5
|
-
export type DataRow = [
|
|
6
|
-
/** index */
|
|
7
|
-
number,
|
|
8
|
-
/** render index */
|
|
9
|
-
number,
|
|
10
|
-
/** isLeaf */
|
|
11
|
-
boolean,
|
|
12
|
-
/** isExpanded */
|
|
13
|
-
boolean,
|
|
14
|
-
/** depth */
|
|
15
|
-
number,
|
|
16
|
-
/** child count */
|
|
17
|
-
number,
|
|
18
|
-
/** key */
|
|
19
|
-
string,
|
|
20
|
-
/** selected */
|
|
21
|
-
number,
|
|
22
|
-
/** data values */
|
|
23
|
-
...DataItem[]
|
|
24
|
-
];
|
|
25
|
-
export type RangeLike = { from: number; to: number };
|
|
26
|
-
|
|
27
|
-
const { KEY } = metadataKeys;
|
|
28
|
-
|
|
29
|
-
const log = (message: string) =>
|
|
30
|
-
console.log(`%c[DataWindow] ${message}`, "color: purple;font-weight: bold;");
|
|
31
|
-
export class DataWindow {
|
|
32
|
-
private range: WindowRange;
|
|
33
|
-
public data: DataRow[];
|
|
34
|
-
public rowCount = 0;
|
|
35
|
-
constructor({ from, to }: RangeLike) {
|
|
36
|
-
log(`constructor ${from} - ${to}`);
|
|
37
|
-
this.range = new WindowRange(from, to);
|
|
38
|
-
//internal data is always 0 based, we add range.from to determine an offset
|
|
39
|
-
this.data = new Array(to - from);
|
|
40
|
-
// window.dataWindow = this.data;
|
|
41
|
-
// log(`constructor initial range ${from} - ${to}`);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
setRowCount = (rowCount: number) => {
|
|
45
|
-
// log(`rowCount => ${rowCount}`);
|
|
46
|
-
if (rowCount < this.data.length) {
|
|
47
|
-
this.data.length = rowCount;
|
|
48
|
-
}
|
|
49
|
-
this.rowCount = rowCount;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// return true if existing row was updated
|
|
53
|
-
add(data: DataRow) {
|
|
54
|
-
const [index] = data;
|
|
55
|
-
if (this.isWithinRange(index)) {
|
|
56
|
-
const internalIndex = index - this.range.from;
|
|
57
|
-
const isUpdate = this.data[internalIndex] !== undefined;
|
|
58
|
-
this.data[internalIndex] = data;
|
|
59
|
-
return isUpdate;
|
|
60
|
-
} else {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
getAtIndex(index: number) {
|
|
66
|
-
return this.range.isWithin(index) &&
|
|
67
|
-
this.data[index - this.range.from] != null
|
|
68
|
-
? this.data[index - this.range.from]
|
|
69
|
-
: undefined;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
getByKey(key: string) {
|
|
73
|
-
return this.data.find((row) => row[KEY] === key);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
isWithinRange(index: number) {
|
|
77
|
-
return this.range.isWithin(index) && index <= this.rowCount;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
setRange(from: number, to: number) {
|
|
81
|
-
log(`setRange ${from} ${to}`);
|
|
82
|
-
if (from !== this.range.from || to !== this.range.to) {
|
|
83
|
-
const [overlapFrom, overlapTo] = this.range.overlap(from, to);
|
|
84
|
-
const newData = new Array(to - from);
|
|
85
|
-
for (let i = overlapFrom; i < overlapTo; i++) {
|
|
86
|
-
const data = this.getAtIndex(i);
|
|
87
|
-
if (data) {
|
|
88
|
-
const index = i - from;
|
|
89
|
-
newData[index] = data;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
this.data = newData;
|
|
93
|
-
this.range.from = from;
|
|
94
|
-
this.range.to = to;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
hasData(from: number, to: number) {
|
|
99
|
-
const offset = this.range.from;
|
|
100
|
-
const start = from - offset;
|
|
101
|
-
const end = Math.min(to - offset - 1, this.rowCount - 1);
|
|
102
|
-
return this.data[start] !== undefined && this.data[end] !== undefined;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
getData(from: number, to: number): any[] {
|
|
106
|
-
const { from: clientFrom, to: clientTo } = this.range;
|
|
107
|
-
const startOffset = Math.max(0, from - clientFrom);
|
|
108
|
-
const endOffset = Math.min(to - clientFrom, this.rowCount ?? to);
|
|
109
|
-
return this.data.slice(startOffset, endOffset);
|
|
110
|
-
}
|
|
111
|
-
}
|
package/src/array-utils.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export type PartitionTest<T> = (value: T, index: number) => boolean;
|
|
2
|
-
|
|
3
|
-
export function partition<T>(
|
|
4
|
-
array: T[],
|
|
5
|
-
test: PartitionTest<T>,
|
|
6
|
-
pass: T[] = [],
|
|
7
|
-
fail: T[] = []
|
|
8
|
-
): [T[], T[]] {
|
|
9
|
-
for (let i = 0, len = array.length; i < len; i++) {
|
|
10
|
-
(test(array[i], i) ? pass : fail).push(array[i]);
|
|
11
|
-
}
|
|
12
|
-
return [pass, fail];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Note order of items can be different between arrays
|
|
16
|
-
// If an identityProperty is not defined, item identity is used
|
|
17
|
-
export function itemsChanged<T = unknown>(
|
|
18
|
-
currentItems: T[],
|
|
19
|
-
newItems: T[],
|
|
20
|
-
identityProperty?: string
|
|
21
|
-
) {
|
|
22
|
-
if (currentItems.length !== newItems.length) {
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
if (identityProperty === undefined) {
|
|
26
|
-
return !currentItems.every((item) => newItems.includes(item));
|
|
27
|
-
} else {
|
|
28
|
-
return currentItems.some(
|
|
29
|
-
(currentItem) =>
|
|
30
|
-
newItems.findIndex(
|
|
31
|
-
(newItem) =>
|
|
32
|
-
(newItem as { [key: string]: unknown })[identityProperty] ===
|
|
33
|
-
(currentItem as { [key: string]: unknown })[identityProperty]
|
|
34
|
-
) === -1
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
}
|
package/src/column-utils.ts
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ColumnDescriptor,
|
|
3
|
-
GroupColumnDescriptor,
|
|
4
|
-
KeyedColumnDescriptor,
|
|
5
|
-
} from "@vuu-ui/vuu-datagrid-types";
|
|
6
|
-
import { VuuGroupBy } from "@vuu-ui/vuu-protocol-types";
|
|
7
|
-
import { instrumentPriceColumns } from "../../../showcase/src/examples/DataGrid/columnMetaData";
|
|
8
|
-
import { Row } from "./row-utils";
|
|
9
|
-
|
|
10
|
-
export interface ColumnMap {
|
|
11
|
-
[columnName: string]: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const SORT_ASC = "asc";
|
|
15
|
-
|
|
16
|
-
export type SortCriteriaItem = string | [string, "asc"]; // TODO where is 'desc'?
|
|
17
|
-
|
|
18
|
-
export function mapSortCriteria(
|
|
19
|
-
sortCriteria: SortCriteriaItem[],
|
|
20
|
-
columnMap: ColumnMap,
|
|
21
|
-
metadataOffset = 0
|
|
22
|
-
): [number, "asc"][] {
|
|
23
|
-
return sortCriteria.map((s) => {
|
|
24
|
-
if (typeof s === "string") {
|
|
25
|
-
return [columnMap[s] + metadataOffset, "asc"];
|
|
26
|
-
} else if (Array.isArray(s)) {
|
|
27
|
-
const [columnName, sortDir] = s;
|
|
28
|
-
return [columnMap[columnName] + metadataOffset, sortDir || SORT_ASC];
|
|
29
|
-
} else {
|
|
30
|
-
throw Error("columnUtils.mapSortCriteria invalid input");
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const isKeyedColumn = (
|
|
36
|
-
column: ColumnDescriptor
|
|
37
|
-
): column is KeyedColumnDescriptor => {
|
|
38
|
-
return typeof (column as KeyedColumnDescriptor).key === "number";
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const isNumericColumn = ({ serverDataType }: ColumnDescriptor) =>
|
|
42
|
-
serverDataType === undefined
|
|
43
|
-
? false
|
|
44
|
-
: serverDataType === "int" ||
|
|
45
|
-
serverDataType === "long" ||
|
|
46
|
-
serverDataType === "double";
|
|
47
|
-
|
|
48
|
-
export const toColumnDescriptor = (name: string): ColumnDescriptor => ({
|
|
49
|
-
name,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const EMPTY_COLUMN_MAP = {} as const;
|
|
53
|
-
|
|
54
|
-
export function buildColumnMap(
|
|
55
|
-
columns?: (KeyedColumnDescriptor | string)[]
|
|
56
|
-
): ColumnMap {
|
|
57
|
-
const start = metadataKeys.count;
|
|
58
|
-
if (columns) {
|
|
59
|
-
return columns.reduce((map, column, i) => {
|
|
60
|
-
if (typeof column === "string") {
|
|
61
|
-
map[column] = start + i;
|
|
62
|
-
} else if (typeof column.key === "number") {
|
|
63
|
-
map[column.name] = column.key;
|
|
64
|
-
} else {
|
|
65
|
-
map[column.name] = start + i;
|
|
66
|
-
}
|
|
67
|
-
return map;
|
|
68
|
-
}, {} as ColumnMap);
|
|
69
|
-
} else {
|
|
70
|
-
return EMPTY_COLUMN_MAP;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function projectUpdates(updates: number[]): number[] {
|
|
75
|
-
const results: number[] = [];
|
|
76
|
-
const metadataOffset = metadataKeys.count - 2;
|
|
77
|
-
for (let i = 0; i < updates.length; i += 3) {
|
|
78
|
-
results[i] = updates[i] + metadataOffset;
|
|
79
|
-
results[i + 1] = updates[i + 1];
|
|
80
|
-
results[i + 2] = updates[i + 2];
|
|
81
|
-
}
|
|
82
|
-
return results;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function projectColumns(
|
|
86
|
-
tableRowColumnMap: ColumnMap,
|
|
87
|
-
columns: ColumnDescriptor[]
|
|
88
|
-
) {
|
|
89
|
-
const columnCount = columns.length;
|
|
90
|
-
const { IDX, RENDER_IDX, DEPTH, COUNT, KEY, SELECTED, count } = metadataKeys;
|
|
91
|
-
return (startIdx: number, offset: number, selectedRows: Row[] = []) =>
|
|
92
|
-
(row: Row, i: number) => {
|
|
93
|
-
// selectedRows are indices of rows within underlying dataset (not sorted or filtered)
|
|
94
|
-
// row is the original row from this set, with original index in IDX pos, which might
|
|
95
|
-
// be overwritten with a different value below if rows are sorted/filtered
|
|
96
|
-
const baseRowIdx: any = row[IDX]; // TODO
|
|
97
|
-
const out = [];
|
|
98
|
-
for (let i = 0; i < columnCount; i++) {
|
|
99
|
-
const colIdx = tableRowColumnMap[columns[i].name];
|
|
100
|
-
out[count + i] = row[colIdx];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
out[IDX] = startIdx + i + offset;
|
|
104
|
-
out[RENDER_IDX] = 0;
|
|
105
|
-
out[DEPTH] = 0;
|
|
106
|
-
out[COUNT] = 0;
|
|
107
|
-
out[KEY] = row[tableRowColumnMap.KEY];
|
|
108
|
-
out[SELECTED] = selectedRows.includes(baseRowIdx) ? 1 : 0;
|
|
109
|
-
return out;
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export const metadataKeys = {
|
|
114
|
-
IDX: 0,
|
|
115
|
-
RENDER_IDX: 1,
|
|
116
|
-
IS_LEAF: 2,
|
|
117
|
-
IS_EXPANDED: 3,
|
|
118
|
-
DEPTH: 4,
|
|
119
|
-
COUNT: 5,
|
|
120
|
-
KEY: 6,
|
|
121
|
-
SELECTED: 7,
|
|
122
|
-
count: 8,
|
|
123
|
-
// TODO following only used in datamodel
|
|
124
|
-
PARENT_IDX: "parent_idx",
|
|
125
|
-
IDX_POINTER: "idx_pointer",
|
|
126
|
-
FILTER_COUNT: "filter_count",
|
|
127
|
-
NEXT_FILTER_IDX: "next_filter_idx",
|
|
128
|
-
} as const;
|
|
129
|
-
|
|
130
|
-
// This method mutates the passed columns array
|
|
131
|
-
const insertColumn = (
|
|
132
|
-
columns: KeyedColumnDescriptor[],
|
|
133
|
-
column: KeyedColumnDescriptor
|
|
134
|
-
) => {
|
|
135
|
-
const { originalIdx } = column;
|
|
136
|
-
if (typeof originalIdx === "number") {
|
|
137
|
-
for (let i = 0; i < columns.length; i++) {
|
|
138
|
-
const { originalIdx: colIdx = -1 } = columns[i];
|
|
139
|
-
if (colIdx > originalIdx) {
|
|
140
|
-
columns.splice(i, 0, column);
|
|
141
|
-
return columns;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
columns.push(column);
|
|
146
|
-
return columns;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
export const flattenColumnGroup = (
|
|
150
|
-
columns: KeyedColumnDescriptor[]
|
|
151
|
-
): KeyedColumnDescriptor[] => {
|
|
152
|
-
if (columns[0]?.isGroup) {
|
|
153
|
-
const [groupColumn, ...nonGroupedColumns] = columns as [
|
|
154
|
-
GroupColumnDescriptor,
|
|
155
|
-
...KeyedColumnDescriptor[]
|
|
156
|
-
];
|
|
157
|
-
groupColumn.columns.forEach((groupColumn) => {
|
|
158
|
-
insertColumn(nonGroupedColumns, groupColumn);
|
|
159
|
-
});
|
|
160
|
-
return nonGroupedColumns;
|
|
161
|
-
} else {
|
|
162
|
-
return columns;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
export function extractGroupColumn(
|
|
167
|
-
columns: KeyedColumnDescriptor[],
|
|
168
|
-
groupBy?: VuuGroupBy
|
|
169
|
-
): [GroupColumnDescriptor | null, KeyedColumnDescriptor[]] {
|
|
170
|
-
if (groupBy && groupBy.length > 0) {
|
|
171
|
-
const flattenedColumns = flattenColumnGroup(columns);
|
|
172
|
-
// Note: groupedColumns will be in column order, not groupBy order
|
|
173
|
-
const [groupedColumns, rest] = flattenedColumns.reduce(
|
|
174
|
-
(result, column, i) => {
|
|
175
|
-
const [g, r] = result;
|
|
176
|
-
if (groupBy.includes(column.name)) {
|
|
177
|
-
g.push({
|
|
178
|
-
...column,
|
|
179
|
-
originalIdx: i,
|
|
180
|
-
});
|
|
181
|
-
} else {
|
|
182
|
-
r.push(column);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return result;
|
|
186
|
-
},
|
|
187
|
-
[[], []] as [KeyedColumnDescriptor[], KeyedColumnDescriptor[]]
|
|
188
|
-
);
|
|
189
|
-
if (groupedColumns.length !== groupBy.length) {
|
|
190
|
-
throw Error(
|
|
191
|
-
`extractGroupColumn: no column definition found for all groupBy cols ${JSON.stringify(
|
|
192
|
-
groupBy
|
|
193
|
-
)} `
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
const groupCount = groupBy.length;
|
|
197
|
-
const groupCols: KeyedColumnDescriptor[] = groupBy.map((name, idx) => {
|
|
198
|
-
// Keep the cols in same order defined on groupBy
|
|
199
|
-
const column = groupedColumns.find(
|
|
200
|
-
(col) => col.name === name
|
|
201
|
-
) as KeyedColumnDescriptor;
|
|
202
|
-
return {
|
|
203
|
-
...column,
|
|
204
|
-
groupLevel: groupCount - idx,
|
|
205
|
-
};
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
const groupCol = {
|
|
209
|
-
key: -1,
|
|
210
|
-
name: "group-col",
|
|
211
|
-
heading: ["group-col"],
|
|
212
|
-
isGroup: true,
|
|
213
|
-
columns: groupCols,
|
|
214
|
-
width: groupCols.map((c) => c.width).reduce((a, b) => a + b) + 100,
|
|
215
|
-
} as GroupColumnDescriptor;
|
|
216
|
-
|
|
217
|
-
return [groupCol, rest];
|
|
218
|
-
}
|
|
219
|
-
return [null, flattenColumnGroup(columns)];
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export const isGroupColumn = (
|
|
223
|
-
column: KeyedColumnDescriptor
|
|
224
|
-
): column is GroupColumnDescriptor => column.isGroup === true;
|