@1771technologies/lytenyte-pro 1.0.8 → 1.0.10
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/dist/+types.d.ts +1 -1
- package/dist/cell-selection/cell-selection-containers.js +5 -5
- package/dist/cell-selection/cell-selection-driver.js +9 -9
- package/dist/cell-selection/cell-style-row.js +1 -1
- package/dist/cell-selection/split-on-pivot.js +1 -1
- package/dist/cells/cell-editor.js +2 -2
- package/dist/cells/cell-spacer.js +1 -1
- package/dist/cells/cell.js +6 -6
- package/dist/column-manager/branch.js +4 -4
- package/dist/column-manager/column-manager.d.ts +7 -7
- package/dist/column-manager/column-manager.js +8 -8
- package/dist/column-manager/label.js +1 -1
- package/dist/column-manager/leaf.js +4 -4
- package/dist/column-manager/move-handle.js +3 -3
- package/dist/column-manager/panel.js +1 -1
- package/dist/column-manager/root.js +3 -3
- package/dist/column-manager/use-column-manager.js +1 -1
- package/dist/column-manager/visibility-checkbox.js +3 -3
- package/dist/filter-tree/branch.js +3 -3
- package/dist/filter-tree/context.d.ts +2 -2
- package/dist/filter-tree/hooks/use-filter-tree.js +1 -1
- package/dist/filter-tree/inclusion-checkbox.js +1 -1
- package/dist/filter-tree/label.js +1 -1
- package/dist/filter-tree/leaf.js +3 -3
- package/dist/filter-tree/root.js +3 -3
- package/dist/grid-box/grid-box.d.ts +5 -5
- package/dist/grid-box/grid-box.js +6 -6
- package/dist/grid-box/item.js +2 -2
- package/dist/grid-box/panel.js +2 -2
- package/dist/grid-box/root.d.ts +1 -1
- package/dist/grid-box/root.js +3 -3
- package/dist/grid.d.ts +8 -8
- package/dist/grid.js +12 -12
- package/dist/header/header-cell.js +4 -4
- package/dist/header/header-group-cell.js +2 -2
- package/dist/header/header-row.js +1 -1
- package/dist/header/header.js +1 -1
- package/dist/header/resize-handler.js +1 -1
- package/dist/header/use-header-cell-renderer.js +1 -1
- package/dist/icons/index.js +3 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/license.d.ts +1 -0
- package/dist/license.js +10 -13
- package/dist/listbox/item.js +1 -1
- package/dist/listbox/panel.js +1 -1
- package/dist/listbox/root.js +1 -1
- package/dist/root/dialog-driver.js +1 -1
- package/dist/root/popover-driver.js +1 -1
- package/dist/root/root.js +11 -6
- package/dist/row-data-source-client/pivots/create-agg-model.d.ts +2 -2
- package/dist/row-data-source-client/pivots/create-agg-model.js +1 -1
- package/dist/row-data-source-server/async-tree/maybe-apply-set-action-items.js +5 -4
- package/dist/row-data-source-server/range-tree/range-tree.d.ts +1 -1
- package/dist/row-data-source-server/server-data.d.ts +48 -0
- package/dist/row-data-source-server/server-data.js +378 -0
- package/dist/row-data-source-server/use-server-data-source.d.ts +1 -1
- package/dist/row-data-source-server/use-server-data-source.js +181 -524
- package/dist/row-data-source-server/utils/get-node-depth.d.ts +1 -1
- package/dist/row-data-source-server/utils/get-node-path.d.ts +1 -1
- package/dist/rows/row/row.d.ts +1 -1
- package/dist/rows/row/row.js +5 -5
- package/dist/rows/row/use-row-context-value.d.ts +3 -3
- package/dist/rows/row-detail-row.js +1 -1
- package/dist/rows/row-full-width.js +3 -3
- package/dist/rows/rows-container.js +1 -1
- package/dist/rows/rows-sections.js +3 -3
- package/dist/sort-manager/root.d.ts +1 -1
- package/dist/sort-manager/root.js +1 -1
- package/dist/sort-manager/sort-add.js +1 -1
- package/dist/sort-manager/sort-apply.js +2 -2
- package/dist/sort-manager/sort-cancel.js +2 -2
- package/dist/sort-manager/sort-clear.js +1 -1
- package/dist/sort-manager/sort-column-select.js +1 -1
- package/dist/sort-manager/sort-direction-select.js +1 -1
- package/dist/sort-manager/sort-manager.d.ts +11 -11
- package/dist/sort-manager/sort-manager.js +12 -12
- package/dist/sort-manager/sort-remove.js +1 -1
- package/dist/sort-manager/sort-row.d.ts +1 -1
- package/dist/sort-manager/sort-row.js +2 -2
- package/dist/sort-manager/sort-rows.js +1 -1
- package/dist/sort-manager/sort-value-select.js +1 -1
- package/dist/state/api/cell-root.js +2 -2
- package/dist/tree-view/root.js +1 -1
- package/dist/viewport/viewport.js +2 -2
- package/package.json +7 -7
|
@@ -1,404 +1,154 @@
|
|
|
1
|
+
import { effect, makeAtom, signal } from "@1771technologies/lytenyte-shared";
|
|
1
2
|
import { useRef } from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { getNodeDepth } from "./utils/get-node-depth.js";
|
|
4
|
-
import { getRequestId } from "./utils/get-request-id.js";
|
|
5
|
-
import { RangeTree } from "./range-tree/range-tree.js";
|
|
6
|
-
import { getNodePath } from "./utils/get-node-path.js";
|
|
3
|
+
import { ServerData } from "./server-data.js";
|
|
7
4
|
import { equal } from "@1771technologies/lytenyte-js-utils";
|
|
8
|
-
|
|
9
|
-
export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, dataInFilterItemFetcher, cellUpdateHandler, cellUpdateOptimistically = true, blockSize = 200, }) {
|
|
5
|
+
export function makeServerDataSource({ dataFetcher, dataInFilterItemFetcher, dataColumnPivotFetcher, cellUpdateHandler, cellUpdateOptimistically, blockSize = 200, }) {
|
|
10
6
|
let grid = null;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const isLoading
|
|
15
|
-
const
|
|
16
|
-
const error$ = signal(null);
|
|
17
|
-
const loadError = makeAtom(error$);
|
|
18
|
-
const nodesWithError = signal(new Map());
|
|
19
|
-
const initialized = signal(false);
|
|
20
|
-
const model$ = signal({
|
|
21
|
-
sorts: [],
|
|
22
|
-
filters: {},
|
|
23
|
-
filtersIn: {},
|
|
24
|
-
quickSearch: null,
|
|
25
|
-
group: [],
|
|
26
|
-
groupExpansions: {},
|
|
27
|
-
aggregations: {},
|
|
28
|
-
pivotGroupExpansions: {},
|
|
29
|
-
pivotMode: false,
|
|
30
|
-
pivotModel: {
|
|
31
|
-
columns: [],
|
|
32
|
-
filters: {},
|
|
33
|
-
filtersIn: {},
|
|
34
|
-
rows: [],
|
|
35
|
-
sorts: [],
|
|
36
|
-
values: [],
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
const model = makeAtom(model$);
|
|
40
|
-
const pivotGroupExpansions = computed(() => model$().pivotGroupExpansions);
|
|
41
|
-
const rowGroupExpansions = computed(() => model$().groupExpansions);
|
|
42
|
-
const pivotMode = computed(() => model$().pivotMode);
|
|
43
|
-
const topData = signal([]);
|
|
44
|
-
const botData = signal([]);
|
|
45
|
-
const seenRequests = new Set();
|
|
46
|
-
const dataResponseHandler = (res) => {
|
|
47
|
-
const t = tree.get();
|
|
48
|
-
const dataResponses = res.filter((r) => {
|
|
49
|
-
return !("kind" in r && (r.kind === "top" || r.kind === "bottom"));
|
|
50
|
-
});
|
|
51
|
-
dataResponses.sort((l, r) => l.path.length - r.path.length);
|
|
52
|
-
const pinResponses = res.filter((r) => {
|
|
53
|
-
return "kind" in r && (r.kind === "top" || r.kind === "bottom");
|
|
54
|
-
});
|
|
55
|
-
pinResponses.forEach((p) => {
|
|
56
|
-
if (p.kind === "top") {
|
|
57
|
-
topData.set(p.data);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
botData.set(p.data);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
dataResponses.forEach((r) => {
|
|
64
|
-
t.set({
|
|
65
|
-
path: r.path,
|
|
66
|
-
items: r.data.map((c, i) => {
|
|
67
|
-
if (c.kind === "leaf") {
|
|
68
|
-
return {
|
|
69
|
-
kind: "leaf",
|
|
70
|
-
data: c,
|
|
71
|
-
relIndex: r.start + i,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
return {
|
|
76
|
-
kind: "parent",
|
|
77
|
-
data: c,
|
|
78
|
-
path: c.key,
|
|
79
|
-
relIndex: r.start + i,
|
|
80
|
-
size: c.childCount,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}),
|
|
84
|
-
size: r.size,
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
};
|
|
88
|
-
const dataRequestHandler = async (p, force = false, onSuccess, onFailure) => {
|
|
89
|
-
if (!grid)
|
|
90
|
-
return;
|
|
91
|
-
const unseen = p.filter((x) => force || !seenRequests.has(x.id));
|
|
92
|
-
unseen.forEach((x) => seenRequests.add(x.id));
|
|
93
|
-
if (unseen.length === 0) {
|
|
94
|
-
onSuccess?.();
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
nodesWithError.set((prev) => {
|
|
98
|
-
const next = new Map(prev);
|
|
99
|
-
p.forEach((r) => {
|
|
100
|
-
for (let i = r.rowStartIndex; i < r.rowEndIndex; i++) {
|
|
101
|
-
next.delete(i);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
return prev;
|
|
105
|
-
});
|
|
106
|
-
try {
|
|
107
|
-
const res = await dataFetcher({
|
|
108
|
-
grid: grid,
|
|
109
|
-
model: model.get(),
|
|
110
|
-
reqTime: Date.now(),
|
|
111
|
-
requests: p,
|
|
112
|
-
});
|
|
113
|
-
dataResponseHandler(res);
|
|
114
|
-
onSuccess?.();
|
|
115
|
-
}
|
|
116
|
-
catch (e) {
|
|
117
|
-
// Mark them as unseen since the request failed.
|
|
118
|
-
unseen.forEach((x) => seenRequests.delete(x.id));
|
|
119
|
-
onFailure?.(e);
|
|
120
|
-
console.error(e);
|
|
121
|
-
}
|
|
122
|
-
finally {
|
|
123
|
-
snapshot$.set(Date.now());
|
|
124
|
-
grid.state.rowDataStore.rowClearCache();
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
const viewChange = () => {
|
|
128
|
-
if (!grid)
|
|
129
|
-
return;
|
|
130
|
-
const bounds = grid.state.viewBounds.get();
|
|
131
|
-
const f = flat.get();
|
|
132
|
-
const te = bounds.rowTopEnd;
|
|
133
|
-
const seen = new Set();
|
|
134
|
-
const requests = [];
|
|
135
|
-
for (let i = bounds.rowCenterStart - te; i < bounds.rowCenterEnd - te; i++) {
|
|
136
|
-
const ranges = f.rangeTree.findRangesForRowIndex(i);
|
|
137
|
-
ranges.forEach((c) => {
|
|
138
|
-
if (c.parent.kind === "root") {
|
|
139
|
-
const blockIndex = Math.floor(i / blockSize);
|
|
140
|
-
const start = blockIndex * blockSize;
|
|
141
|
-
const end = Math.min(start + blockSize, c.parent.size);
|
|
142
|
-
const reqId = getRequestId([], start, end);
|
|
143
|
-
if (seen.has(reqId))
|
|
144
|
-
return;
|
|
145
|
-
seen.add(reqId);
|
|
146
|
-
const size = start + blockSize > c.parent.size ? c.parent.size - start : blockSize;
|
|
147
|
-
requests.push({
|
|
148
|
-
id: reqId,
|
|
149
|
-
path: [],
|
|
150
|
-
start,
|
|
151
|
-
end,
|
|
152
|
-
rowStartIndex: i,
|
|
153
|
-
rowEndIndex: i + size,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
const blockIndex = Math.floor(c.parent.relIndex / blockSize);
|
|
158
|
-
const start = blockIndex * blockSize;
|
|
159
|
-
const end = Math.min(start + blockSize, c.parent.size);
|
|
160
|
-
const path = getNodePath(c.parent);
|
|
161
|
-
const reqId = getRequestId(path, start, end);
|
|
162
|
-
if (seen.has(reqId))
|
|
163
|
-
return;
|
|
164
|
-
seen.add(reqId);
|
|
165
|
-
const size = start + blockSize > c.parent.size ? c.parent.size - start : blockSize;
|
|
166
|
-
requests.push({
|
|
167
|
-
id: reqId,
|
|
168
|
-
path,
|
|
169
|
-
start,
|
|
170
|
-
end,
|
|
171
|
-
rowStartIndex: i,
|
|
172
|
-
rowEndIndex: i + size,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
dataRequestHandler(requests, false, () => { }, (e) => {
|
|
178
|
-
nodesWithError.set((prev) => {
|
|
179
|
-
const next = new Map(prev);
|
|
180
|
-
requests.forEach((r) => {
|
|
181
|
-
for (let i = r.rowStartIndex; i < r.rowEndIndex; i++) {
|
|
182
|
-
next.set(i, e);
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
return prev;
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
};
|
|
189
|
-
const resetRequest = async () => {
|
|
190
|
-
seenRequests.clear();
|
|
191
|
-
tree.set(makeAsyncTree());
|
|
192
|
-
nodesWithError.set(new Map());
|
|
193
|
-
// Initialize the grid.
|
|
194
|
-
const initialDataRequest = {
|
|
195
|
-
path: [],
|
|
196
|
-
id: getRequestId([], 0, blockSize),
|
|
197
|
-
rowStartIndex: 0,
|
|
198
|
-
rowEndIndex: blockSize,
|
|
199
|
-
start: 0,
|
|
200
|
-
end: blockSize,
|
|
201
|
-
};
|
|
202
|
-
loadError.set(null);
|
|
203
|
-
isLoading.set(true);
|
|
204
|
-
await dataRequestHandler([initialDataRequest], false, () => { }, (e) => {
|
|
205
|
-
loadError.set(e);
|
|
206
|
-
});
|
|
207
|
-
isLoading.set(false);
|
|
208
|
-
};
|
|
209
|
-
const flat$ = computed(() => {
|
|
210
|
-
snapshot$();
|
|
211
|
-
const mode = pivotMode();
|
|
212
|
-
const expansions = mode ? pivotGroupExpansions() : rowGroupExpansions();
|
|
213
|
-
const t = tree$();
|
|
214
|
-
const rowIdToRow = new Map();
|
|
215
|
-
const rowIndexToRow = new Map();
|
|
216
|
-
const rowIdToRowIndex = new Map();
|
|
217
|
-
const ranges = [];
|
|
218
|
-
function processParent(node, start) {
|
|
219
|
-
const rows = [...node.byIndex.values()].sort((l, r) => l.relIndex - r.relIndex);
|
|
220
|
-
// Track the additional rows added by expanded groups
|
|
221
|
-
let offset = 0;
|
|
222
|
-
for (let i = 0; i < rows.length; i++) {
|
|
223
|
-
const row = rows[i];
|
|
224
|
-
const rowIndex = row.relIndex + start + offset;
|
|
225
|
-
rowIndexToRow.set(rowIndex, row);
|
|
226
|
-
rowIdToRowIndex.set(row.data.id, rowIndex);
|
|
227
|
-
rowIdToRow.set(row.data.id, row);
|
|
228
|
-
if (row.kind === "parent" && expansions[row.data.id]) {
|
|
229
|
-
offset += processParent(row, rowIndex + 1);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
ranges.push({ rowStart: start, rowEnd: offset + node.size + start, parent: node });
|
|
233
|
-
return offset + node.size;
|
|
234
|
-
}
|
|
235
|
-
const size = processParent(t, 0);
|
|
236
|
-
const rangeTree = new RangeTree(ranges);
|
|
237
|
-
return {
|
|
238
|
-
size,
|
|
239
|
-
rowIndexToRow,
|
|
240
|
-
rowIdToRow,
|
|
241
|
-
rowIdToRowIndex,
|
|
242
|
-
rangeTree,
|
|
243
|
-
};
|
|
244
|
-
});
|
|
245
|
-
const flat = makeAtom(flat$);
|
|
246
|
-
const topLength = computed(() => topData().length);
|
|
247
|
-
const botLength = computed(() => botData().length);
|
|
248
|
-
const flatLength = computed(() => flat.$().size);
|
|
7
|
+
let flat;
|
|
8
|
+
let source;
|
|
9
|
+
void grid;
|
|
10
|
+
const isLoading = makeAtom(signal(false));
|
|
11
|
+
const loadError = makeAtom(signal(null));
|
|
249
12
|
const cleanup = [];
|
|
250
13
|
const init = (g) => {
|
|
251
14
|
grid = g;
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
pivotGroupExpansions,
|
|
15
|
+
source = new ServerData({
|
|
16
|
+
defaultExpansion: g.state.rowGroupDefaultExpansion.get(),
|
|
17
|
+
blocksize: blockSize,
|
|
18
|
+
expansions: g.state.rowGroupExpansions.get(),
|
|
19
|
+
pivotExpansions: g.state.columnPivotRowGroupExpansions.get(),
|
|
20
|
+
pivotMode: g.state.columnPivotMode.get(),
|
|
21
|
+
onResetLoadBegin: () => {
|
|
22
|
+
isLoading.set(true);
|
|
23
|
+
loadError.set(null);
|
|
24
|
+
},
|
|
25
|
+
onResetLoadEnd: () => isLoading.set(false),
|
|
26
|
+
onResetLoadError: (e) => loadError.set(e),
|
|
27
|
+
onFlatten: (f) => {
|
|
28
|
+
const store = g.state.rowDataStore;
|
|
29
|
+
flat = f;
|
|
30
|
+
store.rowTopCount.set(f.top);
|
|
31
|
+
store.rowCenterCount.set(f.center);
|
|
32
|
+
store.rowBottomCount.set(f.bottom);
|
|
33
|
+
store.rowClearCache();
|
|
34
|
+
},
|
|
273
35
|
});
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
g.state.
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
cleanup.push(effect(() => {
|
|
285
|
-
g.state.rowDataStore.rowTopCount.set(topLength());
|
|
286
|
-
g.state.rowDataStore.rowClearCache();
|
|
287
|
-
}));
|
|
36
|
+
let prevModel = {
|
|
37
|
+
sorts: g.state.sortModel.get(),
|
|
38
|
+
groups: g.state.rowGroupModel.get(),
|
|
39
|
+
filters: g.state.filterModel.get(),
|
|
40
|
+
filtersIn: g.state.filterInModel.get(),
|
|
41
|
+
quickSearch: g.state.quickSearch.get(),
|
|
42
|
+
aggregations: g.state.aggModel.get(),
|
|
43
|
+
pivotMode: g.state.columnPivotMode.get(),
|
|
44
|
+
pivotModel: g.state.columnPivotModel.get(),
|
|
45
|
+
};
|
|
288
46
|
cleanup.push(effect(() => {
|
|
289
|
-
|
|
290
|
-
|
|
47
|
+
const newModel = {
|
|
48
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
49
|
+
sorts: g.state.sortModel.$(),
|
|
50
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
51
|
+
groups: g.state.rowGroupModel.$(),
|
|
52
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
53
|
+
filters: g.state.filterModel.$(),
|
|
54
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
55
|
+
filtersIn: g.state.filterInModel.$(),
|
|
56
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
57
|
+
quickSearch: g.state.quickSearch.$(),
|
|
58
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
59
|
+
aggregations: g.state.aggModel.$(),
|
|
60
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
61
|
+
pivotMode: g.state.columnPivotMode.$(),
|
|
62
|
+
// @ts-expect-error this is fine - just a hidden type
|
|
63
|
+
pivotModel: g.state.columnPivotModel.$(),
|
|
64
|
+
};
|
|
65
|
+
if (equal(newModel, prevModel))
|
|
66
|
+
return;
|
|
67
|
+
source.dataFetcher = (req, expansions, pivotExpansions) => {
|
|
68
|
+
return dataFetcher({
|
|
69
|
+
grid: g,
|
|
70
|
+
model: {
|
|
71
|
+
...newModel,
|
|
72
|
+
groupExpansions: expansions,
|
|
73
|
+
pivotGroupExpansions: pivotExpansions,
|
|
74
|
+
},
|
|
75
|
+
reqTime: Date.now(),
|
|
76
|
+
requests: req,
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
prevModel = newModel;
|
|
291
80
|
}));
|
|
292
|
-
|
|
293
|
-
// Watch the view bound changes.
|
|
294
|
-
g.state.viewBounds.watch(() => {
|
|
295
|
-
viewChange();
|
|
296
|
-
});
|
|
81
|
+
const pivotModel = g.state.columnPivotModel.get();
|
|
297
82
|
let prevPivotColumnModel = pivotModel.columns;
|
|
298
83
|
let prevPivotColumnValues = pivotModel.values;
|
|
299
|
-
const updatePivotColumns = async (
|
|
84
|
+
const updatePivotColumns = async (model, ignoreEqualCheck = false) => {
|
|
300
85
|
if (!ignoreEqualCheck &&
|
|
301
|
-
equal(prevPivotColumnModel,
|
|
302
|
-
equal(prevPivotColumnValues,
|
|
86
|
+
equal(prevPivotColumnModel, model.columns) &&
|
|
87
|
+
equal(prevPivotColumnValues, model.values))
|
|
303
88
|
return;
|
|
304
|
-
const
|
|
305
|
-
grid:
|
|
306
|
-
model:
|
|
89
|
+
const pivotColumns = await dataColumnPivotFetcher?.({
|
|
90
|
+
grid: g,
|
|
91
|
+
model: {
|
|
92
|
+
...prevModel,
|
|
93
|
+
pivotMode: g.state.columnPivotMode.get(),
|
|
94
|
+
pivotModel: model,
|
|
95
|
+
groupExpansions: g.state.rowGroupExpansions.get(),
|
|
96
|
+
pivotGroupExpansions: g.state.columnPivotColumnGroupExpansions.get(),
|
|
97
|
+
},
|
|
307
98
|
reqTime: Date.now(),
|
|
308
99
|
});
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
prevPivotColumnValues = mdl.values;
|
|
100
|
+
g.state.columnPivotColumns.set(pivotColumns ?? []);
|
|
101
|
+
g.state.rowDataStore.rowClearCache();
|
|
102
|
+
prevPivotColumnModel = model.columns;
|
|
103
|
+
prevPivotColumnValues = model.values;
|
|
314
104
|
};
|
|
315
|
-
if (
|
|
105
|
+
if (g.state.columnPivotMode.get())
|
|
316
106
|
updatePivotColumns(pivotModel);
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const rowGroupModel = g.state.rowGroupModel.$();
|
|
321
|
-
// @ts-expect-error this is fine
|
|
322
|
-
const rowGroupExpansions = g.state.rowGroupExpansions.$();
|
|
323
|
-
// @ts-expect-error this is fine
|
|
324
|
-
const aggModel = g.state.aggModel.$();
|
|
325
|
-
// @ts-expect-error this is fine
|
|
326
|
-
const filterModelIn = g.state.filterInModel.$();
|
|
327
|
-
// @ts-expect-error this is fine
|
|
328
|
-
const quickSearch = g.state.quickSearch.$();
|
|
329
|
-
// @ts-expect-error this is fine
|
|
330
|
-
const filterModel = g.state.filterModel.$();
|
|
331
|
-
// @ts-expect-error this is fine
|
|
332
|
-
const sortModel = g.state.sortModel.$();
|
|
333
|
-
// @ts-expect-error this is fine
|
|
334
|
-
const columnPivotExpansions = g.state.columnPivotColumnGroupExpansions.$();
|
|
335
|
-
// @ts-expect-error this is fine
|
|
336
|
-
const model = g.state.columnPivotModel.$();
|
|
337
|
-
// @ts-expect-error this is fine
|
|
338
|
-
const mode = g.state.columnPivotMode.$();
|
|
107
|
+
// Pivot model monitoring
|
|
108
|
+
cleanup.push(grid.state.columnPivotMode.watch(() => {
|
|
109
|
+
const model = g.state.columnPivotModel.get();
|
|
339
110
|
updatePivotColumns(model);
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
111
|
+
}));
|
|
112
|
+
cleanup.push(grid.state.columnPivotModel.watch(() => {
|
|
113
|
+
const model = g.state.columnPivotModel.get();
|
|
114
|
+
updatePivotColumns(model);
|
|
115
|
+
}));
|
|
116
|
+
cleanup.push(g.state.rowGroupDefaultExpansion.watch(() => {
|
|
117
|
+
source.defaultExpansion = g.state.rowGroupDefaultExpansion.get();
|
|
118
|
+
}));
|
|
119
|
+
cleanup.push(g.state.viewBounds.watch(() => {
|
|
120
|
+
const bounds = g.state.viewBounds.get();
|
|
121
|
+
source.rowViewBounds = [bounds.rowCenterStart, bounds.rowCenterEnd];
|
|
122
|
+
}));
|
|
123
|
+
source.dataFetcher = (req, expansions, pivotExpansions) => {
|
|
124
|
+
return dataFetcher({
|
|
125
|
+
grid: g,
|
|
126
|
+
model: {
|
|
127
|
+
...prevModel,
|
|
128
|
+
groupExpansions: expansions,
|
|
129
|
+
pivotGroupExpansions: pivotExpansions,
|
|
130
|
+
},
|
|
131
|
+
reqTime: Date.now(),
|
|
132
|
+
requests: req,
|
|
133
|
+
});
|
|
134
|
+
};
|
|
358
135
|
};
|
|
359
136
|
const rowById = (id) => {
|
|
360
|
-
|
|
361
|
-
const node = f.rowIdToRow.get(id);
|
|
362
|
-
if (!node) {
|
|
363
|
-
{
|
|
364
|
-
const top = peek(topData);
|
|
365
|
-
const node = top.find((c) => c.id === id);
|
|
366
|
-
if (node)
|
|
367
|
-
return { kind: "leaf", data: node.data, id: node.id };
|
|
368
|
-
}
|
|
369
|
-
{
|
|
370
|
-
const bot = peek(topData);
|
|
371
|
-
const node = bot.find((c) => c.id === id);
|
|
372
|
-
if (node)
|
|
373
|
-
return { kind: "leaf", data: node.data, id: node.id };
|
|
374
|
-
}
|
|
375
|
-
return null;
|
|
376
|
-
}
|
|
377
|
-
if (node.kind === "parent") {
|
|
378
|
-
return {
|
|
379
|
-
kind: "branch",
|
|
380
|
-
data: node.data.data,
|
|
381
|
-
id: node.data.id,
|
|
382
|
-
key: node.path,
|
|
383
|
-
depth: getNodeDepth(node),
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
return {
|
|
387
|
-
kind: "leaf",
|
|
388
|
-
data: node.data.data,
|
|
389
|
-
id: node.data.id,
|
|
390
|
-
};
|
|
137
|
+
return flat.rowIdToRow.get(id) ?? null;
|
|
391
138
|
};
|
|
392
139
|
const rowAllChildIds = (rowId) => {
|
|
393
|
-
const f = flat
|
|
140
|
+
const f = flat;
|
|
394
141
|
const row = f.rowIdToRow.get(rowId);
|
|
395
142
|
if (!row || row.kind === "leaf")
|
|
396
143
|
return [];
|
|
397
144
|
const ids = new Set();
|
|
398
|
-
const
|
|
145
|
+
const node = f.rowIdToTreeNode.get(row.id);
|
|
146
|
+
if (!node || node.kind === "leaf")
|
|
147
|
+
return [];
|
|
148
|
+
const stack = [...node.byPath.values()];
|
|
399
149
|
while (stack.length) {
|
|
400
150
|
const item = stack.pop();
|
|
401
|
-
if (item
|
|
151
|
+
if (item?.kind === "leaf") {
|
|
402
152
|
ids.add(item.data.id);
|
|
403
153
|
}
|
|
404
154
|
else {
|
|
@@ -408,124 +158,46 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
408
158
|
}
|
|
409
159
|
return [...ids];
|
|
410
160
|
};
|
|
411
|
-
const rowByIndex = (
|
|
412
|
-
const
|
|
413
|
-
const
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if (ri == null || ri < 0 || ri >= f.size + top.length + bot.length)
|
|
418
|
-
return null;
|
|
419
|
-
// Top node
|
|
420
|
-
if (ri < top.length) {
|
|
421
|
-
const row = top[ri];
|
|
422
|
-
if (!row)
|
|
423
|
-
return null;
|
|
424
|
-
return { kind: "leaf", data: row.data, id: row.id, error };
|
|
425
|
-
}
|
|
426
|
-
if (ri >= f.size + top.length) {
|
|
427
|
-
const i = ri - f.size - top.length;
|
|
428
|
-
const row = bot[i];
|
|
429
|
-
if (!row)
|
|
430
|
-
return null;
|
|
431
|
-
return { kind: "leaf", data: row.data, id: row.id, error };
|
|
432
|
-
}
|
|
433
|
-
const node = f.rowIndexToRow.get(ri - top.length);
|
|
434
|
-
if (!node && error)
|
|
435
|
-
return { kind: "leaf", data: null, id: `error-${ri}`, loading: false, error };
|
|
436
|
-
if (!node)
|
|
437
|
-
return { kind: "leaf", data: null, id: `loading-${ri}`, loading: true, error: null };
|
|
438
|
-
const isLoading = peek(loadingGroups$);
|
|
439
|
-
if (node.kind === "parent") {
|
|
161
|
+
const rowByIndex = (i) => {
|
|
162
|
+
const row = flat.rowIndexToRow.get(i);
|
|
163
|
+
const isLoading = flat.loading.has(i);
|
|
164
|
+
const error = flat.errored.get(i);
|
|
165
|
+
// If we haven't loaded a row yet.
|
|
166
|
+
if (!row)
|
|
440
167
|
return {
|
|
441
|
-
|
|
442
|
-
data:
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
error,
|
|
447
|
-
loading: isLoading.has(node.data.id),
|
|
168
|
+
id: `__loading__placeholder__${i}`,
|
|
169
|
+
data: null,
|
|
170
|
+
kind: "leaf",
|
|
171
|
+
loading: isLoading,
|
|
172
|
+
error: error,
|
|
448
173
|
};
|
|
174
|
+
if (error) {
|
|
175
|
+
return { ...row, error };
|
|
449
176
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
error,
|
|
455
|
-
};
|
|
177
|
+
if (isLoading) {
|
|
178
|
+
return { ...row, loading: isLoading };
|
|
179
|
+
}
|
|
180
|
+
return flat.rowIndexToRow.get(i) ?? null;
|
|
456
181
|
};
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
.
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
return null;
|
|
473
|
-
const row = f.rowIndexToRow.get(rowIndex);
|
|
474
|
-
if (!row || row.kind === "leaf")
|
|
475
|
-
return null;
|
|
476
|
-
const path = getNodePath(row);
|
|
477
|
-
rowIndices.push(rowIndex);
|
|
478
|
-
return {
|
|
479
|
-
id: getRequestId(path, 0, Math.min(blockSize, row.size)),
|
|
480
|
-
start: 0,
|
|
481
|
-
end: Math.min(blockSize, row.size),
|
|
482
|
-
path,
|
|
483
|
-
rowStartIndex: rowIndex + 1,
|
|
484
|
-
rowEndIndex: Math.min(row.size, rowIndex + blockSize + 1),
|
|
485
|
-
};
|
|
486
|
-
})
|
|
487
|
-
.filter((c) => !!c);
|
|
488
|
-
const mode = peek(pivotMode);
|
|
489
|
-
// Remove the errors before requesting.
|
|
490
|
-
const errorRows = peek(nodesWithError);
|
|
491
|
-
if (rowIndices.some((c) => errorRows.has(c))) {
|
|
492
|
-
nodesWithError.set((prev) => {
|
|
493
|
-
const n = new Map(prev);
|
|
494
|
-
rowIndices.forEach((c) => n.delete(c));
|
|
495
|
-
return prev;
|
|
496
|
-
});
|
|
182
|
+
const rowExpand = (expansions) => {
|
|
183
|
+
if (!grid)
|
|
184
|
+
return;
|
|
185
|
+
const mode = grid.state.columnPivotMode.get();
|
|
186
|
+
if (mode) {
|
|
187
|
+
const current = grid.state.columnPivotColumnGroupExpansions.get();
|
|
188
|
+
const next = { ...current, ...expansions };
|
|
189
|
+
source.pivotExpansions = next;
|
|
190
|
+
grid.state.columnPivotRowGroupExpansions.set(next);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
const current = grid.state.rowGroupExpansions.get();
|
|
194
|
+
const next = { ...current, ...expansions };
|
|
195
|
+
source.expansions = next;
|
|
196
|
+
grid.state.rowGroupExpansions.set(next);
|
|
497
197
|
}
|
|
498
|
-
// Mark these groups as loading
|
|
499
|
-
loadingGroups$.set(loadingRows);
|
|
500
|
-
grid?.state.rowDataStore.rowClearCache();
|
|
501
|
-
dataRequestHandler(requests, false, () => {
|
|
502
|
-
if (mode)
|
|
503
|
-
grid?.state.columnPivotColumnGroupExpansions.set((prev) => ({ ...prev, ...p }));
|
|
504
|
-
else
|
|
505
|
-
grid?.state.rowGroupExpansions.set((prev) => ({ ...prev, ...p }));
|
|
506
|
-
const next = new Set(peek(loadingGroups$));
|
|
507
|
-
rowsForThis.forEach((c) => next.delete(c));
|
|
508
|
-
loadingGroups$.set(next);
|
|
509
|
-
setTimeout(() => {
|
|
510
|
-
grid?.state.rowDataStore.rowClearCache();
|
|
511
|
-
});
|
|
512
|
-
}, (error) => {
|
|
513
|
-
nodesWithError.set((prev) => {
|
|
514
|
-
const n = new Map(prev);
|
|
515
|
-
rowIndices.forEach((c) => n.set(c, error));
|
|
516
|
-
return prev;
|
|
517
|
-
});
|
|
518
|
-
const next = new Set(peek(loadingGroups$));
|
|
519
|
-
rowsForThis.forEach((c) => next.delete(c));
|
|
520
|
-
loadingGroups$.set(next);
|
|
521
|
-
setTimeout(() => {
|
|
522
|
-
grid?.state.rowDataStore.rowClearCache();
|
|
523
|
-
});
|
|
524
|
-
});
|
|
525
198
|
};
|
|
526
199
|
const rowToIndex = (rowId) => {
|
|
527
|
-
|
|
528
|
-
return f.rowIdToRowIndex.get(rowId) ?? null;
|
|
200
|
+
return flat.rowIdToRowIndex.get(rowId) ?? null;
|
|
529
201
|
};
|
|
530
202
|
const rowSelect = (params) => {
|
|
531
203
|
if (!grid || params.mode === "none")
|
|
@@ -582,14 +254,17 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
582
254
|
grid.state.rowSelectedIds.set(new Set());
|
|
583
255
|
return;
|
|
584
256
|
}
|
|
585
|
-
const t = flat
|
|
257
|
+
const t = flat;
|
|
586
258
|
grid.state.rowSelectedIds.set(new Set(t.rowIdToRow.keys()));
|
|
587
259
|
};
|
|
588
260
|
const rowSetBotData = () => {
|
|
589
|
-
|
|
261
|
+
console.error("Directly setting bottom data in the server data model is not supported.");
|
|
590
262
|
};
|
|
591
263
|
const rowSetTopData = () => {
|
|
592
|
-
|
|
264
|
+
console.error("Directly setting top data in the server data model is not supported.");
|
|
265
|
+
};
|
|
266
|
+
const rowSetCenterData = () => {
|
|
267
|
+
console.error("Directly setting center data in the server data model is not supported.");
|
|
593
268
|
};
|
|
594
269
|
// CRUD ops
|
|
595
270
|
const rowAdd = () => {
|
|
@@ -599,10 +274,6 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
599
274
|
throw new Error(`Server data source does not support deleting rows directly. Instead push updates via the pushResponses or pushRequests method`);
|
|
600
275
|
};
|
|
601
276
|
const rowUpdate = (updates) => {
|
|
602
|
-
const f = flat.get();
|
|
603
|
-
const top = peek(topData);
|
|
604
|
-
const bot = peek(botData);
|
|
605
|
-
const firstBot = f.size + top.length;
|
|
606
277
|
const idMap = new Map([...updates.entries()]
|
|
607
278
|
.map(([key, data]) => {
|
|
608
279
|
if (typeof key === "string")
|
|
@@ -616,26 +287,10 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
616
287
|
cellUpdateHandler?.(idMap);
|
|
617
288
|
if (!cellUpdateOptimistically)
|
|
618
289
|
return;
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
console.error(`Failed to find the row at index ${rowIndex} which is being updated.`);
|
|
624
|
-
continue;
|
|
625
|
-
}
|
|
626
|
-
if (rowIndex < top.length) {
|
|
627
|
-
top[rowIndex].data = data;
|
|
628
|
-
}
|
|
629
|
-
else if (rowIndex >= firstBot) {
|
|
630
|
-
bot[rowIndex].data = data;
|
|
631
|
-
}
|
|
632
|
-
else {
|
|
633
|
-
const node = f.rowIndexToRow.get(rowIndex - top.length);
|
|
634
|
-
if (node)
|
|
635
|
-
node.data.data = data;
|
|
636
|
-
}
|
|
637
|
-
grid.state.rowDataStore.rowInvalidateIndex(rowIndex);
|
|
638
|
-
}
|
|
290
|
+
idMap.forEach((data, id) => {
|
|
291
|
+
source.updateRow(id, data);
|
|
292
|
+
});
|
|
293
|
+
grid?.state.rowDataStore.rowClearCache();
|
|
639
294
|
};
|
|
640
295
|
const inFilterItems = (c) => {
|
|
641
296
|
if (!dataInFilterItemFetcher || !grid)
|
|
@@ -645,6 +300,16 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
645
300
|
const rowAreAllSelected = () => {
|
|
646
301
|
return false;
|
|
647
302
|
};
|
|
303
|
+
const reset = () => {
|
|
304
|
+
source.reset();
|
|
305
|
+
};
|
|
306
|
+
const pushResponses = (responses) => {
|
|
307
|
+
source.handleResponses(responses);
|
|
308
|
+
};
|
|
309
|
+
const pushRequests = (requests) => {
|
|
310
|
+
source.handleRequests(requests);
|
|
311
|
+
};
|
|
312
|
+
const retry = () => { };
|
|
648
313
|
return {
|
|
649
314
|
init,
|
|
650
315
|
rowAdd,
|
|
@@ -656,9 +321,7 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
656
321
|
rowSelect,
|
|
657
322
|
rowSelectAll,
|
|
658
323
|
rowSetBotData,
|
|
659
|
-
rowSetCenterData
|
|
660
|
-
throw new Error("Server side data source does not support full row updates");
|
|
661
|
-
},
|
|
324
|
+
rowSetCenterData,
|
|
662
325
|
rowSetTopData,
|
|
663
326
|
rowToIndex,
|
|
664
327
|
rowUpdate,
|
|
@@ -666,16 +329,10 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
666
329
|
rowAreAllSelected,
|
|
667
330
|
isLoading,
|
|
668
331
|
loadError,
|
|
669
|
-
pushResponses
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
dataRequestHandler(req, true, onSuccess, onFailure);
|
|
674
|
-
},
|
|
675
|
-
reset: resetRequest,
|
|
676
|
-
retry: () => {
|
|
677
|
-
viewChange();
|
|
678
|
-
},
|
|
332
|
+
pushResponses,
|
|
333
|
+
pushRequests,
|
|
334
|
+
reset,
|
|
335
|
+
retry,
|
|
679
336
|
};
|
|
680
337
|
}
|
|
681
338
|
export function useServerDataSource(p) {
|