@vuu-ui/vuu-data-local 4.1.0 → 4.1.1
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/package.json
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.1.
|
|
2
|
+
"version": "4.1.1",
|
|
3
3
|
"main": "./src/index.js",
|
|
4
4
|
"author": "heswell",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"build:dev": "node ../../scripts/run-build.mjs",
|
|
8
7
|
"build": "node ../../scripts/run-build-rslib.ts",
|
|
9
8
|
"test": "vitest run",
|
|
10
9
|
"type-defs": "node ../../scripts/build-type-defs.mjs"
|
|
11
10
|
},
|
|
12
11
|
"devDependencies": {
|
|
13
|
-
"@vuu-ui/vuu-data-types": "4.1.
|
|
14
|
-
"@vuu-ui/vuu-table-types": "4.1.
|
|
15
|
-
"@vuu-ui/vuu-filter-types": "4.1.
|
|
16
|
-
"@vuu-ui/vuu-protocol-types": "4.1.
|
|
12
|
+
"@vuu-ui/vuu-data-types": "4.1.1",
|
|
13
|
+
"@vuu-ui/vuu-table-types": "4.1.1",
|
|
14
|
+
"@vuu-ui/vuu-filter-types": "4.1.1",
|
|
15
|
+
"@vuu-ui/vuu-protocol-types": "4.1.1"
|
|
17
16
|
},
|
|
18
17
|
"dependencies": {
|
|
19
|
-
"@vuu-ui/vuu-filter-parser": "4.1.
|
|
20
|
-
"@vuu-ui/vuu-utils": "4.1.
|
|
18
|
+
"@vuu-ui/vuu-filter-parser": "4.1.1",
|
|
19
|
+
"@vuu-ui/vuu-utils": "4.1.1"
|
|
21
20
|
},
|
|
22
21
|
"sideEffects": false,
|
|
23
22
|
"files": [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseDataSource, KeySet, NULL_RANGE, getParentRow, isSingleValueFilter, lastPathSegment, metadataKeys,
|
|
1
|
+
import { BaseDataSource, KeySet, NULL_RANGE, getParentRow, isSingleValueFilter, lastPathSegment, metadataKeys, treeToDataSourceRows, uuid } from "@vuu-ui/vuu-utils";
|
|
2
2
|
import { IconProvider } from "./IconProvider.js";
|
|
3
3
|
import { parseFilter } from "@vuu-ui/vuu-filter-parser";
|
|
4
4
|
const treeSchema = (columns)=>({
|
|
@@ -32,6 +32,7 @@ class TreeDataSource extends BaseDataSource {
|
|
|
32
32
|
#size = 0;
|
|
33
33
|
#status = "initialising";
|
|
34
34
|
#filterSet;
|
|
35
|
+
#filterCollapsedRows = new Set();
|
|
35
36
|
rowCount;
|
|
36
37
|
keys = new KeySet(this._range);
|
|
37
38
|
constructor({ data, ...props }){
|
|
@@ -40,7 +41,6 @@ class TreeDataSource extends BaseDataSource {
|
|
|
40
41
|
this.#iconProvider = new IconProvider();
|
|
41
42
|
[this.columnDescriptors, this.#data] = treeToDataSourceRows(data, this.#iconProvider);
|
|
42
43
|
this.expandedRows = getInitiallyExpandedKeys(data);
|
|
43
|
-
console.table(this.#data);
|
|
44
44
|
if (this.columnDescriptors) {
|
|
45
45
|
const columns = this.columnDescriptors.map((c)=>c.name);
|
|
46
46
|
this._configWithVisualLink = {
|
|
@@ -62,7 +62,7 @@ class TreeDataSource extends BaseDataSource {
|
|
|
62
62
|
this.#status = "subscribed";
|
|
63
63
|
this.#selectedRowsCount = selectedKeyValues?.length ?? 0;
|
|
64
64
|
if (selectedKeyValues) this.applySelectedKeyValues(selectedKeyValues, revealSelected);
|
|
65
|
-
|
|
65
|
+
this.computeVisibleRows();
|
|
66
66
|
this.clientCallback?.({
|
|
67
67
|
aggregations: this.#aggregations,
|
|
68
68
|
type: "subscribed",
|
|
@@ -72,7 +72,7 @@ class TreeDataSource extends BaseDataSource {
|
|
|
72
72
|
groupBy: this._configWithVisualLink.groupBy,
|
|
73
73
|
range: this.range,
|
|
74
74
|
sort: this.sort,
|
|
75
|
-
tableSchema:
|
|
75
|
+
tableSchema: this.tableSchema
|
|
76
76
|
});
|
|
77
77
|
this.clientCallback({
|
|
78
78
|
clientViewportId: this.viewport,
|
|
@@ -118,7 +118,32 @@ class TreeDataSource extends BaseDataSource {
|
|
|
118
118
|
};
|
|
119
119
|
if (filter.filter) this.applyFilter(filter);
|
|
120
120
|
else this.#filterSet = void 0;
|
|
121
|
-
|
|
121
|
+
this.refreshVisibleRows();
|
|
122
|
+
}
|
|
123
|
+
filterNodes(predicate) {
|
|
124
|
+
if (predicate) {
|
|
125
|
+
const filterSet = [];
|
|
126
|
+
const { count: nodeDataIndex } = metadataKeys;
|
|
127
|
+
for (const row of this.#data){
|
|
128
|
+
const { [DEPTH]: depth, [KEY]: key, [IDX]: idx } = row;
|
|
129
|
+
const label = row[nodeDataIndex + depth];
|
|
130
|
+
if (predicate({
|
|
131
|
+
depth,
|
|
132
|
+
key,
|
|
133
|
+
label: "string" == typeof label ? label : "",
|
|
134
|
+
nodeData: row[nodeDataIndex]
|
|
135
|
+
})) filterSet.push(idx);
|
|
136
|
+
}
|
|
137
|
+
this.#filterSet = filterSet;
|
|
138
|
+
} else this.#filterSet = void 0;
|
|
139
|
+
this.refreshVisibleRows();
|
|
140
|
+
}
|
|
141
|
+
computeVisibleRows() {
|
|
142
|
+
[this.visibleRows, this.visibleRowIndex] = getVisibleRows(this.#data, this.expandedRows, this.#filterSet, this.#filterCollapsedRows);
|
|
143
|
+
}
|
|
144
|
+
refreshVisibleRows() {
|
|
145
|
+
this.#filterCollapsedRows.clear();
|
|
146
|
+
this.computeVisibleRows();
|
|
122
147
|
const { from, to } = this.range;
|
|
123
148
|
this.clientCallback?.({
|
|
124
149
|
clientViewportId: this.viewport,
|
|
@@ -134,8 +159,9 @@ class TreeDataSource extends BaseDataSource {
|
|
|
134
159
|
const filterSet = [];
|
|
135
160
|
const regex = new RegExp(`${filter.value}`, "i");
|
|
136
161
|
for (const row of this.#data){
|
|
137
|
-
const { [KEY]: key, [IDX]: idx } = row;
|
|
138
|
-
|
|
162
|
+
const { [DEPTH]: depth, [KEY]: key, [IDX]: idx } = row;
|
|
163
|
+
const label = row[metadataKeys.count + depth];
|
|
164
|
+
if (regex.test(lastPathSegment(key, "|")) || "string" == typeof label && regex.test(label)) filterSet.push(idx);
|
|
139
165
|
}
|
|
140
166
|
this.#filterSet = filterSet;
|
|
141
167
|
}
|
|
@@ -198,8 +224,9 @@ class TreeDataSource extends BaseDataSource {
|
|
|
198
224
|
}
|
|
199
225
|
openTreeNode(keyOrIndex) {
|
|
200
226
|
const key = this.getRowKey(keyOrIndex);
|
|
201
|
-
this.
|
|
202
|
-
|
|
227
|
+
if (this.#filterSet) this.#filterCollapsedRows.delete(key);
|
|
228
|
+
else this.expandedRows.add(key);
|
|
229
|
+
this.computeVisibleRows();
|
|
203
230
|
const { from, to } = this._range;
|
|
204
231
|
this.clientCallback?.({
|
|
205
232
|
clientViewportId: this.viewport,
|
|
@@ -211,13 +238,19 @@ class TreeDataSource extends BaseDataSource {
|
|
|
211
238
|
}
|
|
212
239
|
closeTreeNode(keyOrIndex, cascade = false) {
|
|
213
240
|
const key = this.getRowKey(keyOrIndex);
|
|
214
|
-
this.
|
|
215
|
-
|
|
216
|
-
|
|
241
|
+
if (this.#filterSet) this.#filterCollapsedRows.add(key);
|
|
242
|
+
else {
|
|
243
|
+
this.expandedRows.delete(key);
|
|
244
|
+
if (cascade) {
|
|
245
|
+
for (const rowKey of this.expandedRows.keys())if (rowKey.startsWith(key)) this.expandedRows.delete(rowKey);
|
|
246
|
+
}
|
|
217
247
|
}
|
|
218
|
-
|
|
248
|
+
this.computeVisibleRows();
|
|
219
249
|
this.sendRowsToClient();
|
|
220
250
|
}
|
|
251
|
+
get tableSchema() {
|
|
252
|
+
return treeSchema(this.columnDescriptors);
|
|
253
|
+
}
|
|
221
254
|
get status() {
|
|
222
255
|
return this.#status;
|
|
223
256
|
}
|
|
@@ -287,44 +320,45 @@ class TreeDataSource extends BaseDataSource {
|
|
|
287
320
|
}
|
|
288
321
|
}
|
|
289
322
|
const getInitiallyExpandedKeys = (treeSourceNodes, keyBase = "$root", expandedKeys = new Set())=>{
|
|
290
|
-
for (const { childNodes, expanded, label } of treeSourceNodes){
|
|
291
|
-
const key = `${keyBase}|${label}`;
|
|
323
|
+
for (const { childNodes, expanded, keySegment, label } of treeSourceNodes){
|
|
324
|
+
const key = `${keyBase}|${keySegment ?? label}`;
|
|
292
325
|
if (expanded) expandedKeys.add(key);
|
|
293
326
|
if (childNodes) getInitiallyExpandedKeys(childNodes, key, expandedKeys);
|
|
294
327
|
}
|
|
295
328
|
return expandedKeys;
|
|
296
329
|
};
|
|
297
|
-
function getVisibleRows(rows, expandedKeys, filterset) {
|
|
330
|
+
function getVisibleRows(rows, expandedKeys, filterset, filterCollapsedKeys) {
|
|
298
331
|
const visibleRows = [];
|
|
299
332
|
const visibleRowIndex = {};
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const idx
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (missingAncestor(row, previousRow)) {
|
|
308
|
-
let currentRow = row;
|
|
309
|
-
const missingRows = [];
|
|
310
|
-
while(currentRow){
|
|
311
|
-
currentRow = getParentRow(rows, currentRow);
|
|
312
|
-
if (currentRow) missingRows.unshift(currentRow);
|
|
313
|
-
}
|
|
314
|
-
missingRows.forEach((row)=>{
|
|
315
|
-
visibleRows.push(cloneRow(row, index++, true));
|
|
316
|
-
});
|
|
333
|
+
if (filterset) {
|
|
334
|
+
const included = new Set();
|
|
335
|
+
for (const idx of filterset){
|
|
336
|
+
let row = rows[idx];
|
|
337
|
+
while(row && !included.has(row[IDX])){
|
|
338
|
+
included.add(row[IDX]);
|
|
339
|
+
row = getParentRow(rows, row);
|
|
317
340
|
}
|
|
318
|
-
|
|
341
|
+
}
|
|
342
|
+
let collapsedKey;
|
|
343
|
+
for(let i = 0, index = 0; i < rows.length; i++){
|
|
344
|
+
const row = rows[i];
|
|
345
|
+
const { [COUNT]: count, [KEY]: key } = row;
|
|
346
|
+
if (!included.has(row[IDX])) continue;
|
|
347
|
+
if (void 0 !== collapsedKey && key.startsWith(`${collapsedKey}|`)) continue;
|
|
348
|
+
const isCollapsed = filterCollapsedKeys?.has(key) ?? false;
|
|
349
|
+
collapsedKey = isCollapsed ? key : void 0;
|
|
319
350
|
visibleRowIndex[index] = i;
|
|
320
|
-
|
|
321
|
-
const isExpanded = expandedKeys.has(key);
|
|
322
|
-
visibleRows.push(cloneRow(row, index, isExpanded));
|
|
323
|
-
visibleRowIndex[index++] = i;
|
|
324
|
-
const skipNonVisibleRows = !isLeaf && !isExpanded && count > 0;
|
|
325
|
-
if (skipNonVisibleRows) do i += 1;
|
|
326
|
-
while (i < rows.length - 1 && rows[i + 1][DEPTH] > depth)
|
|
351
|
+
visibleRows.push(cloneRow(row, index++, count > 0 && !isCollapsed));
|
|
327
352
|
}
|
|
353
|
+
} else for(let i = 0, index = 0; i < rows.length; i++){
|
|
354
|
+
const row = rows[i];
|
|
355
|
+
const { [COUNT]: count, [DEPTH]: depth, [KEY]: key, [IS_LEAF]: isLeaf } = row;
|
|
356
|
+
const isExpanded = expandedKeys.has(key);
|
|
357
|
+
visibleRows.push(cloneRow(row, index, isExpanded));
|
|
358
|
+
visibleRowIndex[index++] = i;
|
|
359
|
+
const skipNonVisibleRows = !isLeaf && !isExpanded && count > 0;
|
|
360
|
+
if (skipNonVisibleRows) do i += 1;
|
|
361
|
+
while (i < rows.length - 1 && rows[i + 1][DEPTH] > depth)
|
|
328
362
|
}
|
|
329
363
|
return [
|
|
330
364
|
visibleRows,
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import type { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
|
|
2
2
|
import type { LinkDescriptorWithLabel, VuuRange, VuuRpcResponse, VuuRpcRequest, SelectRequest } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
-
import type { DataSourceRow, DataSourceConstructorProps, DataSourceStatus, DataSourceSubscribeCallback, DataSourceSubscribeProps, MenuRpcResponse, DataSourceFilter, DataSourceBase } from "@vuu-ui/vuu-data-types";
|
|
3
|
+
import type { DataSourceRow, DataSourceConstructorProps, DataSourceStatus, DataSourceSubscribeCallback, DataSourceSubscribeProps, MenuRpcResponse, DataSourceFilter, TableSchema, DataSourceBase } from "@vuu-ui/vuu-data-types";
|
|
4
4
|
import { BaseDataSource, TreeSourceNode } from "@vuu-ui/vuu-utils";
|
|
5
|
+
export interface TreeNodeFilterProps {
|
|
6
|
+
depth: number;
|
|
7
|
+
key: string;
|
|
8
|
+
label: string;
|
|
9
|
+
nodeData: unknown;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Tests a single tree node. Nodes that pass are displayed, along with all of
|
|
13
|
+
* their ancestors.
|
|
14
|
+
*/
|
|
15
|
+
export type TreeNodeFilterPredicate = (node: TreeNodeFilterProps) => boolean;
|
|
5
16
|
export interface TreeDataSourceConstructorProps extends Omit<DataSourceConstructorProps, "bufferSize" | "table"> {
|
|
6
17
|
data: TreeSourceNode[];
|
|
7
18
|
}
|
|
@@ -24,6 +35,13 @@ export declare class TreeDataSource extends BaseDataSource implements DataSource
|
|
|
24
35
|
set data(data: TreeSourceNode[]);
|
|
25
36
|
get filter(): DataSourceFilter;
|
|
26
37
|
set filter(filter: DataSourceFilter);
|
|
38
|
+
/**
|
|
39
|
+
* An alternative to a filter expression, filters on any attribute of a
|
|
40
|
+
* tree node, including nodeData. Pass undefined to clear the filter.
|
|
41
|
+
*/
|
|
42
|
+
filterNodes(predicate?: TreeNodeFilterPredicate): void;
|
|
43
|
+
private computeVisibleRows;
|
|
44
|
+
private refreshVisibleRows;
|
|
27
45
|
private applyFilter;
|
|
28
46
|
/**
|
|
29
47
|
* used to apply an initial selection. These may not necessarily be
|
|
@@ -36,6 +54,7 @@ export declare class TreeDataSource extends BaseDataSource implements DataSource
|
|
|
36
54
|
private getRowKey;
|
|
37
55
|
openTreeNode(keyOrIndex: string | number): void;
|
|
38
56
|
closeTreeNode(keyOrIndex: string | number, cascade?: boolean): void;
|
|
57
|
+
get tableSchema(): TableSchema;
|
|
39
58
|
get status(): DataSourceStatus;
|
|
40
59
|
get selectedRowsCount(): number;
|
|
41
60
|
get size(): number;
|