@platforma-sdk/ui-vue 1.36.0 → 1.37.0
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/CHANGELOG.md +16 -0
- package/dist/lib.css +1 -1
- package/dist/lib.js +9163 -9045
- package/dist/lib.js.map +1 -1
- package/dist/src/AgGridVue/index.d.ts +1 -0
- package/dist/src/AgGridVue/index.d.ts.map +1 -1
- package/dist/src/AgGridVue/selection.d.ts +30 -0
- package/dist/src/AgGridVue/selection.d.ts.map +1 -0
- package/dist/src/components/PlAgDataTable/PlAgDataTable.vue.d.ts +4 -4
- package/dist/src/components/PlAgDataTable/PlAgDataTable.vue.d.ts.map +1 -1
- package/dist/src/components/PlAgDataTable/PlAgDataTableSheets.vue.d.ts +31 -0
- package/dist/src/components/PlAgDataTable/PlAgDataTableSheets.vue.d.ts.map +1 -0
- package/dist/src/components/PlAgDataTable/PlAgDataTableV2.vue.d.ts +9 -14
- package/dist/src/components/PlAgDataTable/PlAgDataTableV2.vue.d.ts.map +1 -1
- package/dist/src/components/PlAgDataTable/PlAgRowCount.vue.d.ts.map +1 -1
- package/dist/src/components/PlAgDataTable/sources/table-source-v2.d.ts +6 -13
- package/dist/src/components/PlAgDataTable/sources/table-source-v2.d.ts.map +1 -1
- package/dist/src/components/PlAgDataTable/sources/table-source.d.ts.map +1 -1
- package/dist/src/components/PlAgDataTable/sources/table-state-v2.d.ts +8 -0
- package/dist/src/components/PlAgDataTable/sources/table-state-v2.d.ts.map +1 -0
- package/dist/src/components/PlAgDataTable/types.d.ts +33 -9
- package/dist/src/components/PlAgDataTable/types.d.ts.map +1 -1
- package/dist/src/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.d.ts.map +1 -1
- package/dist/src/components/PlAgRowNumHeader.vue.d.ts.map +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/AgGridVue/index.ts +1 -0
- package/src/AgGridVue/selection.ts +82 -0
- package/src/components/PlAgDataTable/PlAgDataTable.vue +35 -27
- package/src/components/PlAgDataTable/PlAgDataTableSheets.vue +125 -0
- package/src/components/PlAgDataTable/PlAgDataTableV2.vue +288 -440
- package/src/components/PlAgDataTable/PlAgRowCount.vue +5 -4
- package/src/components/PlAgDataTable/sources/table-source-v2.ts +33 -57
- package/src/components/PlAgDataTable/sources/table-source.ts +1 -2
- package/src/components/PlAgDataTable/sources/table-state-v2.ts +160 -0
- package/src/components/PlAgDataTable/types.ts +41 -13
- package/src/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue +5 -4
- package/src/components/PlAgRowNumHeader.vue +24 -15
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
isJsonEqual,
|
|
4
|
+
} from '@milaboratories/helpers';
|
|
4
5
|
import type {
|
|
5
6
|
AxisId,
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
PlDataTableGridStateCore,
|
|
8
|
+
PlDataTableStateV2,
|
|
8
9
|
PlSelectionModel,
|
|
9
|
-
PTableColumnSpec,
|
|
10
10
|
PTableColumnSpecJson,
|
|
11
11
|
PTableKey,
|
|
12
|
-
PTableRecordFilter,
|
|
13
|
-
PTableSorting,
|
|
14
12
|
} from '@platforma-sdk/model';
|
|
15
13
|
import {
|
|
16
|
-
|
|
14
|
+
createPlDataTableStateV2,
|
|
17
15
|
getRawPlatformaInstance,
|
|
18
16
|
parseJson,
|
|
19
17
|
} from '@platforma-sdk/model';
|
|
@@ -23,31 +21,31 @@ import type {
|
|
|
23
21
|
ColGroupDef,
|
|
24
22
|
GridApi,
|
|
25
23
|
GridOptions,
|
|
26
|
-
GridReadyEvent,
|
|
27
24
|
GridState,
|
|
28
25
|
ManagedGridOptionKey,
|
|
29
26
|
ManagedGridOptions,
|
|
30
|
-
SortState,
|
|
31
|
-
StateUpdatedEvent,
|
|
32
27
|
} from 'ag-grid-enterprise';
|
|
33
28
|
import {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
|
|
29
|
+
AgGridVue,
|
|
30
|
+
} from 'ag-grid-vue3';
|
|
31
|
+
import {
|
|
32
|
+
computed,
|
|
33
|
+
ref,
|
|
34
|
+
shallowRef,
|
|
35
|
+
toRefs,
|
|
36
|
+
watch,
|
|
37
|
+
} from 'vue';
|
|
38
|
+
import {
|
|
39
|
+
AgGridTheme,
|
|
40
|
+
} from '../../lib';
|
|
46
41
|
import PlAgCsvExporter from '../PlAgCsvExporter/PlAgCsvExporter.vue';
|
|
47
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
PlAgGridColumnManager,
|
|
44
|
+
} from '../PlAgGridColumnManager';
|
|
48
45
|
import PlOverlayLoading from './PlAgOverlayLoading.vue';
|
|
49
46
|
import PlOverlayNoRows from './PlAgOverlayNoRows.vue';
|
|
50
47
|
import PlAgRowCount from './PlAgRowCount.vue';
|
|
48
|
+
import PlAgDataTableSheets from './PlAgDataTableSheets.vue';
|
|
51
49
|
import {
|
|
52
50
|
focusRow,
|
|
53
51
|
makeOnceTracker,
|
|
@@ -57,33 +55,35 @@ import {
|
|
|
57
55
|
autoSizeRowNumberColumn,
|
|
58
56
|
PlAgDataTableRowNumberColId,
|
|
59
57
|
} from './sources/row-number';
|
|
58
|
+
import type {
|
|
59
|
+
PlAgCellButtonAxisParams,
|
|
60
|
+
} from './sources/table-source-v2';
|
|
60
61
|
import {
|
|
61
62
|
makeRowId,
|
|
62
|
-
|
|
63
|
-
updatePFrameGridOptions,
|
|
63
|
+
calculateGridOptions,
|
|
64
64
|
} from './sources/table-source-v2';
|
|
65
65
|
import type {
|
|
66
|
-
PlAgDataTableSettings,
|
|
67
|
-
PlAgDataTableSettingsPTable,
|
|
68
66
|
PlAgDataTableV2Controller,
|
|
69
67
|
PlAgDataTableV2Row,
|
|
70
68
|
PlAgOverlayLoadingParams,
|
|
71
69
|
PlAgOverlayNoRowsParams,
|
|
70
|
+
PlDataTableColumnsInfo,
|
|
71
|
+
PlDataTableSettingsV2,
|
|
72
|
+
PlDataTableSheetsSettings,
|
|
73
|
+
PTableKeyJson,
|
|
72
74
|
} from './types';
|
|
75
|
+
import {
|
|
76
|
+
useTableState,
|
|
77
|
+
} from './sources/table-state-v2';
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
ClipboardModule,
|
|
77
|
-
ServerSideRowModelModule,
|
|
78
|
-
CellSelectionModule,
|
|
79
|
-
]);
|
|
80
|
-
|
|
81
|
-
const tableState = defineModel<PlDataTableState>({
|
|
82
|
-
default: { gridState: {} },
|
|
79
|
+
const tableState = defineModel<PlDataTableStateV2>({
|
|
80
|
+
default: createPlDataTableStateV2(),
|
|
83
81
|
});
|
|
84
82
|
const selection = defineModel<PlSelectionModel>('selection');
|
|
85
83
|
const props = defineProps<{
|
|
86
|
-
settings
|
|
84
|
+
/** Required component settings */
|
|
85
|
+
settings: Readonly<PlDataTableSettingsV2>;
|
|
86
|
+
|
|
87
87
|
/**
|
|
88
88
|
* The showColumnsPanel prop controls the display of a button that activates
|
|
89
89
|
* the columns management panel in the table. To make the button functional
|
|
@@ -91,10 +91,12 @@ const props = defineProps<{
|
|
|
91
91
|
* This component serves as the target for teleporting the button.
|
|
92
92
|
*/
|
|
93
93
|
showColumnsPanel?: boolean;
|
|
94
|
+
|
|
94
95
|
/**
|
|
95
96
|
* Css width of the Column Manager (Panel) modal (default value is `368px`)
|
|
96
97
|
*/
|
|
97
98
|
columnsPanelWidth?: string;
|
|
99
|
+
|
|
98
100
|
/**
|
|
99
101
|
* The showExportButton prop controls the display of a button that allows
|
|
100
102
|
* to export table data in CSV format. To make the button functional
|
|
@@ -102,12 +104,6 @@ const props = defineProps<{
|
|
|
102
104
|
* This component serves as the target for teleporting the button.
|
|
103
105
|
*/
|
|
104
106
|
showExportButton?: boolean;
|
|
105
|
-
/**
|
|
106
|
-
* Force use of client-side row model.
|
|
107
|
-
* Required for reliable work of focusRow.
|
|
108
|
-
* Auto-enabled when selectedRows provided.
|
|
109
|
-
*/
|
|
110
|
-
clientSideModel?: boolean;
|
|
111
107
|
|
|
112
108
|
/**
|
|
113
109
|
* The AxisId property is used to configure and display the PlAgTextAndButtonCell component
|
|
@@ -141,137 +137,27 @@ const props = defineProps<{
|
|
|
141
137
|
const { settings } = toRefs(props);
|
|
142
138
|
const emit = defineEmits<{
|
|
143
139
|
rowDoubleClicked: [key?: PTableKey];
|
|
144
|
-
columnsChanged: [
|
|
140
|
+
columnsChanged: [info: PlDataTableColumnsInfo];
|
|
145
141
|
cellButtonClicked: [key?: PTableKey];
|
|
146
142
|
}>();
|
|
147
143
|
|
|
148
|
-
|
|
149
|
-
if (!tableState.value.pTableParams) tableState.value.pTableParams = {};
|
|
150
|
-
})();
|
|
144
|
+
const { gridState, sheetsState } = useTableState(tableState, settings);
|
|
151
145
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
naAndAbsentAreLeastValues: item.sort === 'asc',
|
|
146
|
+
const sheetsSettings = computed<PlDataTableSheetsSettings>(() => {
|
|
147
|
+
const settingsCopy = { ...settings.value };
|
|
148
|
+
return settingsCopy.sourceId
|
|
149
|
+
? {
|
|
150
|
+
sheets: settingsCopy.sheets ?? [],
|
|
151
|
+
cachedState: [...sheetsState.value],
|
|
152
|
+
}
|
|
153
|
+
: {
|
|
154
|
+
sheets: [],
|
|
155
|
+
cachedState: [],
|
|
163
156
|
};
|
|
164
|
-
}) ?? []
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const gridState = computed<PlDataTableGridStateWithoutSheets>({
|
|
169
|
-
get: () => {
|
|
170
|
-
const state = tableState.value;
|
|
171
|
-
return {
|
|
172
|
-
sourceId: state.gridState.sourceId,
|
|
173
|
-
columnOrder: state.gridState.columnOrder,
|
|
174
|
-
sort: state.gridState.sort,
|
|
175
|
-
columnVisibility: state.gridState.columnVisibility,
|
|
176
|
-
};
|
|
177
|
-
},
|
|
178
|
-
set: (gridState) => {
|
|
179
|
-
// do not apply driver sorting for client side rendering
|
|
180
|
-
const sorting = settings.value?.sourceType !== 'ptable'
|
|
181
|
-
|| gridOptions.value.rowModelType === 'clientSide'
|
|
182
|
-
? undefined
|
|
183
|
-
: makeSorting(gridState.sort);
|
|
184
|
-
|
|
185
|
-
const oldState = tableState.value;
|
|
186
|
-
|
|
187
|
-
const newState = {
|
|
188
|
-
...oldState,
|
|
189
|
-
gridState: { ...oldState.gridState, ...gridState },
|
|
190
|
-
pTableParams: { ...oldState.pTableParams, sorting },
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
// Note: the table constantly emits an unchanged state, so I added this
|
|
194
|
-
if (!isJsonEqual(oldState, newState)) {
|
|
195
|
-
tableState.value = newState;
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const makeSheetId = (axis: AxisId) => canonicalize(getAxisId(axis))!;
|
|
201
|
-
|
|
202
|
-
function makeFilters(
|
|
203
|
-
sheetsState: Record<string, string | number>,
|
|
204
|
-
): PTableRecordFilter[] | undefined {
|
|
205
|
-
if (settings.value?.sourceType !== 'ptable') return undefined;
|
|
206
|
-
return (
|
|
207
|
-
settings.value.sheets?.map((sheet) => ({
|
|
208
|
-
type: 'bySingleColumnV2',
|
|
209
|
-
column: {
|
|
210
|
-
type: 'axis',
|
|
211
|
-
id: sheet.axis,
|
|
212
|
-
},
|
|
213
|
-
predicate: {
|
|
214
|
-
operator: 'Equal',
|
|
215
|
-
reference: sheetsState[makeSheetId(sheet.axis)],
|
|
216
|
-
},
|
|
217
|
-
})) ?? []
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const sheetsState = computed({
|
|
222
|
-
get: () => tableState.value.gridState.sheets ?? {},
|
|
223
|
-
set: (sheetsState) => {
|
|
224
|
-
const filters = makeFilters(sheetsState);
|
|
225
|
-
|
|
226
|
-
const oldState = tableState.value;
|
|
227
|
-
tableState.value = {
|
|
228
|
-
...oldState,
|
|
229
|
-
gridState: { ...oldState.gridState, sheets: sheetsState },
|
|
230
|
-
pTableParams: { ...oldState.pTableParams, filters },
|
|
231
|
-
};
|
|
232
|
-
},
|
|
233
157
|
});
|
|
234
158
|
|
|
235
|
-
const
|
|
236
|
-
settings?: Readonly<PlAgDataTableSettings>,
|
|
237
|
-
): settings is PlAgDataTableSettingsPTable => {
|
|
238
|
-
return settings?.sourceType === 'ptable'
|
|
239
|
-
&& !!settings.sheets
|
|
240
|
-
&& settings.sheets.length > 0;
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
watch(
|
|
244
|
-
() => settings.value,
|
|
245
|
-
(settings, oldSettings) => {
|
|
246
|
-
if (settings?.sourceType !== 'ptable' || !settings.sheets) {
|
|
247
|
-
sheetsState.value = {};
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (
|
|
252
|
-
oldSettings && oldSettings.sourceType === 'ptable'
|
|
253
|
-
&& lodash.isEqual(settings.sheets, oldSettings.sheets)
|
|
254
|
-
) return;
|
|
255
|
-
|
|
256
|
-
const oldSheetsState = sheetsState.value;
|
|
257
|
-
const newSheetsState: Record<string, string | number> = {};
|
|
258
|
-
for (const sheet of settings.sheets) {
|
|
259
|
-
const sheetId = makeSheetId(sheet.axis);
|
|
260
|
-
newSheetsState[sheetId] = oldSheetsState[sheetId]
|
|
261
|
-
?? sheet.defaultValue
|
|
262
|
-
?? sheet.options[0]?.value;
|
|
263
|
-
}
|
|
264
|
-
sheetsState.value = newSheetsState;
|
|
265
|
-
},
|
|
266
|
-
{ immediate: true },
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
const gridApi = shallowRef<GridApi>();
|
|
270
|
-
|
|
271
|
-
const gridApiDef = shallowRef(new Deferred<GridApi>());
|
|
272
|
-
|
|
159
|
+
const gridApi = shallowRef<GridApi<PlAgDataTableV2Row> | null>(null);
|
|
273
160
|
const firstDataRenderedTracker = makeOnceTracker<GridApi<PlAgDataTableV2Row>>();
|
|
274
|
-
|
|
275
161
|
const gridOptions = shallowRef<GridOptions<PlAgDataTableV2Row>>({
|
|
276
162
|
animateRows: false,
|
|
277
163
|
suppressColumnMoveAnimation: true,
|
|
@@ -281,36 +167,17 @@ const gridOptions = shallowRef<GridOptions<PlAgDataTableV2Row>>({
|
|
|
281
167
|
rowSelection: selection.value !== undefined
|
|
282
168
|
? {
|
|
283
169
|
mode: 'multiRow',
|
|
170
|
+
selectAll: 'all',
|
|
171
|
+
groupSelects: 'self',
|
|
284
172
|
checkboxes: false,
|
|
285
173
|
headerCheckbox: false,
|
|
286
174
|
enableClickSelection: false,
|
|
287
175
|
}
|
|
288
176
|
: undefined,
|
|
289
|
-
selectionColumnDef: {
|
|
290
|
-
mainMenuItems: [],
|
|
291
|
-
contextMenuItems: [],
|
|
292
|
-
pinned: 'left',
|
|
293
|
-
lockPinned: true,
|
|
294
|
-
suppressSizeToFit: true,
|
|
295
|
-
suppressAutoSize: true,
|
|
296
|
-
sortable: false,
|
|
297
|
-
resizable: false,
|
|
298
|
-
},
|
|
299
|
-
onRowDataUpdated: (event) => {
|
|
300
|
-
const selectionValue = selection.value;
|
|
301
|
-
if (selectionValue) {
|
|
302
|
-
const nodes = selectionValue
|
|
303
|
-
.selectedKeys
|
|
304
|
-
.map((rowKey) => event.api.getRowNode(makeRowId(rowKey)))
|
|
305
|
-
.filter((node) => !!node);
|
|
306
|
-
event.api.setNodesSelected({ nodes, newValue: true });
|
|
307
|
-
}
|
|
308
|
-
},
|
|
309
177
|
onSelectionChanged: (event) => {
|
|
310
178
|
if (selection.value) {
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
.filter((rowKey) => !!rowKey);
|
|
179
|
+
const state = event.api.getServerSideSelectionState();
|
|
180
|
+
const selectedKeys = state?.toggledNodes?.map((nodeId) => parseJson(nodeId as PTableKeyJson)) ?? [];
|
|
314
181
|
selection.value = { ...selection.value, selectedKeys };
|
|
315
182
|
}
|
|
316
183
|
},
|
|
@@ -326,9 +193,11 @@ const gridOptions = shallowRef<GridOptions<PlAgDataTableV2Row>>({
|
|
|
326
193
|
localeText: {
|
|
327
194
|
loadingError: '...',
|
|
328
195
|
},
|
|
329
|
-
rowModelType: '
|
|
330
|
-
|
|
331
|
-
//
|
|
196
|
+
rowModelType: 'serverSide',
|
|
197
|
+
// cacheBlockSize should be tha same as PlMultiSequenceAlignment limit
|
|
198
|
+
// so that selectAll will add all rows to selection
|
|
199
|
+
cacheBlockSize: 1000,
|
|
200
|
+
maxBlocksInCache: 100,
|
|
332
201
|
blockLoadDebounceMillis: 500,
|
|
333
202
|
serverSideSortAllLevels: true,
|
|
334
203
|
suppressServerSideFullWidthLoadingRow: true,
|
|
@@ -354,101 +223,147 @@ const gridOptions = shallowRef<GridOptions<PlAgDataTableV2Row>>({
|
|
|
354
223
|
{ statusPanel: PlAgRowCount, align: 'left' },
|
|
355
224
|
],
|
|
356
225
|
},
|
|
226
|
+
onGridReady: (event) => {
|
|
227
|
+
const api = event.api;
|
|
228
|
+
trackFirstDataRendered(api, firstDataRenderedTracker);
|
|
229
|
+
autoSizeRowNumberColumn(api);
|
|
230
|
+
const setGridOption = (
|
|
231
|
+
key: ManagedGridOptionKey,
|
|
232
|
+
value: GridOptions[ManagedGridOptionKey],
|
|
233
|
+
) => {
|
|
234
|
+
const options = { ...gridOptions.value };
|
|
235
|
+
options[key] = value;
|
|
236
|
+
gridOptions.value = options;
|
|
237
|
+
api.setGridOption(key, value);
|
|
238
|
+
};
|
|
239
|
+
const updateGridOptions = (options: ManagedGridOptions) => {
|
|
240
|
+
gridOptions.value = {
|
|
241
|
+
...gridOptions.value,
|
|
242
|
+
...options,
|
|
243
|
+
};
|
|
244
|
+
api.updateGridOptions(options);
|
|
245
|
+
};
|
|
246
|
+
gridApi.value = new Proxy(api, {
|
|
247
|
+
get(target, prop, receiver) {
|
|
248
|
+
switch (prop) {
|
|
249
|
+
case 'setGridOption':
|
|
250
|
+
return setGridOption;
|
|
251
|
+
case 'updateGridOptions':
|
|
252
|
+
return updateGridOptions;
|
|
253
|
+
default:
|
|
254
|
+
return Reflect.get(target, prop, receiver);
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
},
|
|
259
|
+
onStateUpdated: (event) => {
|
|
260
|
+
gridOptions.value.initialState = gridState.value = makePartialState(
|
|
261
|
+
event.state,
|
|
262
|
+
);
|
|
263
|
+
event.api.autoSizeColumns(
|
|
264
|
+
event.api.getAllDisplayedColumns().filter(
|
|
265
|
+
(column) => column.getColId() !== PlAgDataTableRowNumberColId,
|
|
266
|
+
),
|
|
267
|
+
);
|
|
268
|
+
},
|
|
269
|
+
onGridPreDestroyed: (event) => {
|
|
270
|
+
gridOptions.value.initialState = gridState.value = makePartialState(
|
|
271
|
+
event.api.getState(),
|
|
272
|
+
);
|
|
273
|
+
gridApi.value = null;
|
|
274
|
+
},
|
|
357
275
|
});
|
|
358
276
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
trackFirstDataRendered(api, firstDataRenderedTracker);
|
|
362
|
-
autoSizeRowNumberColumn(api);
|
|
363
|
-
gridApi.value = new Proxy(api, {
|
|
364
|
-
get(target, prop, receiver) {
|
|
365
|
-
switch (prop) {
|
|
366
|
-
case 'setGridOption':
|
|
367
|
-
return (
|
|
368
|
-
key: ManagedGridOptionKey,
|
|
369
|
-
value: GridOptions[ManagedGridOptionKey],
|
|
370
|
-
) => {
|
|
371
|
-
const options = gridOptions.value;
|
|
372
|
-
options[key] = value;
|
|
373
|
-
gridOptions.value = options;
|
|
374
|
-
api.setGridOption(key, value);
|
|
375
|
-
};
|
|
376
|
-
case 'updateGridOptions':
|
|
377
|
-
return (options: ManagedGridOptions) => {
|
|
378
|
-
gridOptions.value = {
|
|
379
|
-
...gridOptions.value,
|
|
380
|
-
...options,
|
|
381
|
-
};
|
|
382
|
-
api.updateGridOptions(options);
|
|
383
|
-
};
|
|
384
|
-
default:
|
|
385
|
-
return Reflect.get(target, prop, receiver);
|
|
386
|
-
}
|
|
387
|
-
},
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
gridApiDef.value.resolve(gridApi.value);
|
|
391
|
-
};
|
|
392
|
-
|
|
393
|
-
const makePartialState = (state: GridState) => {
|
|
277
|
+
// Restore proper types erased by AgGrid
|
|
278
|
+
function makePartialState(state: GridState): PlDataTableGridStateCore {
|
|
394
279
|
return {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
280
|
+
columnOrder: state.columnOrder as {
|
|
281
|
+
orderedColIds: PTableColumnSpecJson[];
|
|
282
|
+
} | undefined,
|
|
283
|
+
sort: state.sort as {
|
|
284
|
+
sortModel: {
|
|
285
|
+
colId: PTableColumnSpecJson;
|
|
286
|
+
sort: 'asc' | 'desc';
|
|
287
|
+
}[];
|
|
288
|
+
} | undefined,
|
|
398
289
|
columnVisibility: state.columnVisibility as {
|
|
399
290
|
hiddenColIds: PTableColumnSpecJson[];
|
|
400
|
-
}
|
|
291
|
+
} | undefined,
|
|
401
292
|
};
|
|
402
293
|
};
|
|
403
294
|
|
|
404
|
-
|
|
405
|
-
gridOptions.value.initialState = gridState.value = makePartialState(
|
|
406
|
-
event.state,
|
|
407
|
-
);
|
|
408
|
-
event.api.autoSizeColumns(
|
|
409
|
-
event.api.getAllDisplayedColumns().filter(
|
|
410
|
-
(column) => column.getColId() !== PlAgDataTableRowNumberColId,
|
|
411
|
-
),
|
|
412
|
-
);
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
const onGridPreDestroyed = () => {
|
|
416
|
-
gridOptions.value.initialState = gridState.value = makePartialState(
|
|
417
|
-
gridApi.value!.getState(),
|
|
418
|
-
);
|
|
419
|
-
gridApi.value = undefined;
|
|
420
|
-
gridApiDef.value = new Deferred<GridApi>();
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
defineExpose<PlAgDataTableV2Controller>({
|
|
424
|
-
focusRow: (rowKey) => focusRow(makeRowId(rowKey), firstDataRenderedTracker),
|
|
425
|
-
});
|
|
426
|
-
|
|
295
|
+
// Reload AgGrid when new state arrives from server
|
|
427
296
|
const reloadKey = ref(0);
|
|
428
297
|
watch(
|
|
429
298
|
() => [gridApi.value, gridState.value] as const,
|
|
430
|
-
(
|
|
431
|
-
if (
|
|
432
|
-
|
|
433
|
-
const [gridApi, gridState] = state;
|
|
434
|
-
if (!gridApi) return;
|
|
435
|
-
|
|
299
|
+
([gridApi, gridState]) => {
|
|
300
|
+
if (!gridApi || gridApi.isDestroyed()) return;
|
|
436
301
|
const selfState = makePartialState(gridApi.getState());
|
|
437
|
-
if (
|
|
302
|
+
if (!isJsonEqual(gridState, {}) && !isJsonEqual(gridState, selfState)) {
|
|
303
|
+
gridOptions.value.initialState = gridState;
|
|
304
|
+
++reloadKey.value;
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// Make loadingOverlayComponentParams reactive
|
|
310
|
+
let oldOptions: GridOptions | null = null;
|
|
311
|
+
watch(
|
|
312
|
+
() => [gridApi.value, gridOptions.value] as const,
|
|
313
|
+
([gridApi, options]) => {
|
|
314
|
+
// Wait for AgGrid reinitialization, gridApi will eventially become initialized
|
|
315
|
+
if (!gridApi || gridApi.isDestroyed()) return;
|
|
316
|
+
if (options.loading && oldOptions?.loading && !isJsonEqual(
|
|
317
|
+
options.loadingOverlayComponentParams,
|
|
318
|
+
oldOptions?.loadingOverlayComponentParams,
|
|
319
|
+
)) {
|
|
320
|
+
// Hack to reapply loadingOverlayComponentParams
|
|
321
|
+
gridApi.setGridOption('loading', false);
|
|
322
|
+
gridApi.setGridOption('loading', true);
|
|
323
|
+
}
|
|
324
|
+
oldOptions = options;
|
|
325
|
+
},
|
|
326
|
+
{ immediate: true },
|
|
327
|
+
);
|
|
438
328
|
|
|
439
|
-
|
|
440
|
-
|
|
329
|
+
// Make cellRendererSelector reactive
|
|
330
|
+
const cellRendererSelector = computed(() => props.cellRendererSelector ?? null);
|
|
331
|
+
watch(
|
|
332
|
+
() => [gridApi.value, cellRendererSelector.value] as const,
|
|
333
|
+
([gridApi, cellRendererSelector]) => {
|
|
334
|
+
if (!gridApi || gridApi.isDestroyed()) return;
|
|
335
|
+
gridApi.setGridOption('defaultColDef', {
|
|
336
|
+
...gridOptions.value.defaultColDef,
|
|
337
|
+
cellRendererSelector: cellRendererSelector ?? undefined,
|
|
338
|
+
});
|
|
441
339
|
},
|
|
442
340
|
);
|
|
341
|
+
|
|
342
|
+
defineExpose<PlAgDataTableV2Controller>({
|
|
343
|
+
focusRow: (rowKey) => focusRow(makeRowId(rowKey), firstDataRenderedTracker),
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// Propagate columns for filter component
|
|
443
347
|
watch(
|
|
444
348
|
() => gridOptions.value,
|
|
445
349
|
(options, oldOptions) => {
|
|
446
|
-
if (!oldOptions) return;
|
|
447
|
-
if (options.rowModelType != oldOptions.rowModelType) ++reloadKey.value;
|
|
448
350
|
if (
|
|
449
351
|
options.columnDefs
|
|
450
|
-
&& !
|
|
352
|
+
&& !isJsonEqual(options.columnDefs, oldOptions?.columnDefs)
|
|
451
353
|
) {
|
|
354
|
+
const sourceId = settings.value.sourceId;
|
|
355
|
+
if (sourceId === null) {
|
|
356
|
+
if (selection.value) {
|
|
357
|
+
selection.value = {
|
|
358
|
+
axesSpec: [],
|
|
359
|
+
selectedKeys: [],
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
return emit('columnsChanged', {
|
|
363
|
+
sourceId: null,
|
|
364
|
+
columns: [],
|
|
365
|
+
});
|
|
366
|
+
}
|
|
452
367
|
const isColDef = (def: ColDef | ColGroupDef): def is ColDef =>
|
|
453
368
|
!('children' in def);
|
|
454
369
|
const colDefs = options.columnDefs?.filter(isColDef) ?? [];
|
|
@@ -456,228 +371,161 @@ watch(
|
|
|
456
371
|
.map((def) => def.colId)
|
|
457
372
|
.filter((colId) => colId !== undefined)
|
|
458
373
|
.filter((colId) => colId !== PlAgDataTableRowNumberColId)
|
|
459
|
-
.filter((colId) => !isColumnSelectionCol(colId))
|
|
460
374
|
.map((colId) => parseJson(colId as PTableColumnSpecJson))
|
|
461
375
|
?? [];
|
|
462
376
|
const axesSpec = columns
|
|
463
377
|
.filter((column) => column.type === 'axis')
|
|
464
378
|
.map((axis) => axis.spec);
|
|
465
379
|
if (selection.value) {
|
|
466
|
-
selection.value = {
|
|
380
|
+
selection.value = {
|
|
381
|
+
...selection.value,
|
|
382
|
+
axesSpec,
|
|
383
|
+
};
|
|
467
384
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
!lodash.isEqual(
|
|
473
|
-
options.loadingOverlayComponentParams,
|
|
474
|
-
oldOptions.loadingOverlayComponentParams,
|
|
475
|
-
) && options.loading
|
|
476
|
-
) {
|
|
477
|
-
gridApi.value?.setGridOption('loading', false);
|
|
478
|
-
nextTick(() => gridApi.value?.setGridOption('loading', true));
|
|
385
|
+
emit('columnsChanged', {
|
|
386
|
+
sourceId,
|
|
387
|
+
columns,
|
|
388
|
+
});
|
|
479
389
|
}
|
|
480
390
|
},
|
|
481
391
|
{ immediate: true },
|
|
482
392
|
);
|
|
483
393
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
state[sheetId] = newValue;
|
|
488
|
-
sheetsState.value = state;
|
|
489
|
-
return gridApi.value?.updateGridOptions({
|
|
490
|
-
loading: true,
|
|
491
|
-
loadingOverlayComponentParams: {
|
|
492
|
-
...gridOptions.value.loadingOverlayComponentParams,
|
|
493
|
-
notReady: false,
|
|
494
|
-
} satisfies PlAgOverlayLoadingParams,
|
|
495
|
-
});
|
|
496
|
-
};
|
|
497
|
-
|
|
498
|
-
let generation = 0;
|
|
499
|
-
let oldSettings: PlAgDataTableSettings | undefined = undefined;
|
|
394
|
+
// Update AgGrid when settings change
|
|
395
|
+
let oldSettings: PlDataTableSettingsV2 | null = null;
|
|
396
|
+
const generation = ref(0);
|
|
500
397
|
watch(
|
|
501
|
-
() => [settings.value] as const,
|
|
502
|
-
|
|
398
|
+
() => [gridApi.value, settings.value] as const,
|
|
399
|
+
([gridApi, settings]) => {
|
|
400
|
+
// Wait for AgGrid reinitialization, gridApi will eventially become initialized
|
|
401
|
+
if (!gridApi || gridApi.isDestroyed()) return;
|
|
402
|
+
// Verify that this is not a false watch trigger
|
|
403
|
+
if (isJsonEqual(settings, oldSettings)) return;
|
|
404
|
+
++generation.value;
|
|
503
405
|
try {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
if (
|
|
509
|
-
|
|
510
|
-
|
|
406
|
+
// Hide no rows overlay if it is shown, or else loading overlay will not be shown
|
|
407
|
+
gridApi.hideOverlay();
|
|
408
|
+
|
|
409
|
+
// No data source selected -> reset state to default
|
|
410
|
+
if (!settings.sourceId) {
|
|
411
|
+
return gridApi.updateGridOptions({
|
|
412
|
+
loading: true,
|
|
413
|
+
loadingOverlayComponentParams: {
|
|
414
|
+
...gridOptions.value.loadingOverlayComponentParams,
|
|
415
|
+
notReady: true,
|
|
416
|
+
} satisfies PlAgOverlayLoadingParams,
|
|
417
|
+
columnDefs: undefined,
|
|
418
|
+
serverSideDatasource: undefined,
|
|
419
|
+
});
|
|
511
420
|
}
|
|
512
421
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
loadingOverlayComponentParams: {
|
|
527
|
-
...gridOptions.value.loadingOverlayComponentParams,
|
|
528
|
-
notReady: true,
|
|
529
|
-
} satisfies PlAgOverlayLoadingParams,
|
|
530
|
-
columnDefs: [],
|
|
531
|
-
rowData: undefined,
|
|
532
|
-
datasource: undefined,
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
case 'ptable': {
|
|
536
|
-
if (!settings?.model) {
|
|
537
|
-
return gridApi.updateGridOptions({
|
|
538
|
-
loading: true,
|
|
539
|
-
loadingOverlayComponentParams: {
|
|
540
|
-
...gridOptions.value.loadingOverlayComponentParams,
|
|
541
|
-
notReady: false,
|
|
542
|
-
} satisfies PlAgOverlayLoadingParams,
|
|
543
|
-
columnDefs: [],
|
|
544
|
-
rowData: undefined,
|
|
545
|
-
datasource: undefined,
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
gridApi.updateGridOptions({
|
|
550
|
-
loading: true,
|
|
551
|
-
loadingOverlayComponentParams: {
|
|
552
|
-
...gridOptions.value.loadingOverlayComponentParams,
|
|
553
|
-
notReady: false,
|
|
554
|
-
} satisfies PlAgOverlayLoadingParams,
|
|
555
|
-
});
|
|
556
|
-
|
|
557
|
-
const options = await updatePFrameGridOptions(
|
|
558
|
-
getRawPlatformaInstance().pFrameDriver,
|
|
559
|
-
settings.model,
|
|
560
|
-
settings.sheets ?? [],
|
|
561
|
-
!!props.clientSideModel || !!selection.value,
|
|
562
|
-
gridState,
|
|
563
|
-
{
|
|
564
|
-
showCellButtonForAxisId: props.showCellButtonForAxisId,
|
|
565
|
-
cellButtonInvokeRowsOnDoubleClick:
|
|
566
|
-
props.cellButtonInvokeRowsOnDoubleClick,
|
|
567
|
-
trigger: (key?: PTableKey) => emit('cellButtonClicked', key),
|
|
568
|
-
} satisfies PlAgCellButtonAxisParams,
|
|
569
|
-
).catch((err) => {
|
|
570
|
-
if (localGeneration !== generation) return;
|
|
571
|
-
gridApi.updateGridOptions({
|
|
572
|
-
loading: false,
|
|
573
|
-
loadingOverlayComponentParams: {
|
|
574
|
-
...gridOptions.value.loadingOverlayComponentParams,
|
|
575
|
-
notReady: false,
|
|
576
|
-
} satisfies PlAgOverlayLoadingParams,
|
|
577
|
-
});
|
|
578
|
-
throw err;
|
|
579
|
-
});
|
|
580
|
-
if (localGeneration !== generation) return;
|
|
581
|
-
|
|
582
|
-
return gridApi.updateGridOptions({
|
|
583
|
-
loading: false,
|
|
584
|
-
loadingOverlayComponentParams: {
|
|
585
|
-
...gridOptions.value.loadingOverlayComponentParams,
|
|
586
|
-
notReady: false,
|
|
587
|
-
} satisfies PlAgOverlayLoadingParams,
|
|
588
|
-
...options,
|
|
422
|
+
// Data source changed -> show full page loader, clear selection
|
|
423
|
+
if (settings.sourceId !== oldSettings?.sourceId) {
|
|
424
|
+
gridApi.updateGridOptions({
|
|
425
|
+
loading: true,
|
|
426
|
+
loadingOverlayComponentParams: {
|
|
427
|
+
...gridOptions.value.loadingOverlayComponentParams,
|
|
428
|
+
notReady: false,
|
|
429
|
+
} satisfies PlAgOverlayLoadingParams,
|
|
430
|
+
});
|
|
431
|
+
if (selection.value) {
|
|
432
|
+
gridApi.setServerSideSelectionState({
|
|
433
|
+
selectAll: false,
|
|
434
|
+
toggledNodes: [],
|
|
589
435
|
});
|
|
590
436
|
}
|
|
437
|
+
}
|
|
591
438
|
|
|
592
|
-
|
|
593
|
-
|
|
439
|
+
// Model updated -> show skeletons instead of data
|
|
440
|
+
if (!settings.model) {
|
|
441
|
+
const state = gridApi.getServerSideGroupLevelState();
|
|
442
|
+
const rowCount = state.length > 0 ? state[0].rowCount : undefined;
|
|
443
|
+
return gridApi.updateGridOptions({
|
|
444
|
+
serverSideDatasource: {
|
|
445
|
+
getRows: (params) => {
|
|
446
|
+
params.success({ rowData: [], rowCount });
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
});
|
|
594
450
|
}
|
|
451
|
+
|
|
452
|
+
// Model ready -> calculate new state
|
|
453
|
+
const stateGeneration = generation.value;
|
|
454
|
+
calculateGridOptions(
|
|
455
|
+
generation,
|
|
456
|
+
getRawPlatformaInstance().pFrameDriver,
|
|
457
|
+
settings.model,
|
|
458
|
+
settings.sheets ?? [],
|
|
459
|
+
gridState.value.columnVisibility?.hiddenColIds,
|
|
460
|
+
{
|
|
461
|
+
showCellButtonForAxisId: props.showCellButtonForAxisId,
|
|
462
|
+
cellButtonInvokeRowsOnDoubleClick:
|
|
463
|
+
props.cellButtonInvokeRowsOnDoubleClick,
|
|
464
|
+
trigger: (key?: PTableKey) => emit('cellButtonClicked', key),
|
|
465
|
+
} satisfies PlAgCellButtonAxisParams,
|
|
466
|
+
).then((options) => {
|
|
467
|
+
if (gridApi.isDestroyed() || stateGeneration !== generation.value) return;
|
|
468
|
+
return gridApi.updateGridOptions({
|
|
469
|
+
...options,
|
|
470
|
+
});
|
|
471
|
+
}).catch((error: unknown) => {
|
|
472
|
+
if (gridApi.isDestroyed() || stateGeneration !== generation.value) return;
|
|
473
|
+
console.trace(error);
|
|
474
|
+
}).finally(() => {
|
|
475
|
+
if (gridApi.isDestroyed() || stateGeneration !== generation.value) return;
|
|
476
|
+
gridApi.updateGridOptions({
|
|
477
|
+
loading: false,
|
|
478
|
+
});
|
|
479
|
+
});
|
|
595
480
|
} catch (error: unknown) {
|
|
596
|
-
// How should we handle possible errors?
|
|
597
481
|
console.trace(error);
|
|
482
|
+
} finally {
|
|
483
|
+
oldSettings = settings;
|
|
598
484
|
}
|
|
599
485
|
},
|
|
600
|
-
{ immediate: true, deep: true },
|
|
601
|
-
);
|
|
602
|
-
|
|
603
|
-
watch(
|
|
604
|
-
() => props.cellRendererSelector,
|
|
605
|
-
(cellRendererSelector) => {
|
|
606
|
-
if (!gridApi.value) {
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
gridApi.value.setGridOption('defaultColDef', {
|
|
610
|
-
...gridOptions.value.defaultColDef,
|
|
611
|
-
cellRendererSelector,
|
|
612
|
-
});
|
|
613
|
-
},
|
|
614
486
|
);
|
|
615
487
|
</script>
|
|
616
488
|
|
|
617
489
|
<template>
|
|
618
|
-
<div class="
|
|
490
|
+
<div :class="$style.container">
|
|
619
491
|
<PlAgGridColumnManager
|
|
620
492
|
v-if="gridApi && showColumnsPanel"
|
|
621
493
|
:api="gridApi"
|
|
622
494
|
:width="columnsPanelWidth"
|
|
623
495
|
/>
|
|
624
|
-
<PlAgCsvExporter
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
"
|
|
631
|
-
class="ap-ag-data-table-sheets"
|
|
496
|
+
<PlAgCsvExporter
|
|
497
|
+
v-if="gridApi && showExportButton"
|
|
498
|
+
:api="gridApi"
|
|
499
|
+
/>
|
|
500
|
+
<PlAgDataTableSheets
|
|
501
|
+
v-model="sheetsState"
|
|
502
|
+
:settings="sheetsSettings"
|
|
632
503
|
>
|
|
633
|
-
<
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
:model-value="sheetsState[makeSheetId(sheet.axis)]"
|
|
639
|
-
:options="sheet.options"
|
|
640
|
-
:prefix="
|
|
641
|
-
(sheet.axis.annotations?.['pl7.app/label']?.trim()
|
|
642
|
-
?? `Unlabeled axis ${i}`) + ':'
|
|
643
|
-
"
|
|
644
|
-
@update:model-value="
|
|
645
|
-
(newValue) =>
|
|
646
|
-
onSheetChanged(makeSheetId(sheet.axis), newValue)
|
|
647
|
-
"
|
|
648
|
-
/>
|
|
504
|
+
<template #before>
|
|
505
|
+
<slot name="before-sheets" />
|
|
506
|
+
</template>
|
|
507
|
+
<template #after>
|
|
508
|
+
<slot name="after-sheets" />
|
|
649
509
|
</template>
|
|
650
|
-
|
|
651
|
-
</div>
|
|
510
|
+
</PlAgDataTableSheets>
|
|
652
511
|
<AgGridVue
|
|
653
512
|
:key="reloadKey"
|
|
654
513
|
:theme="AgGridTheme"
|
|
655
|
-
class="
|
|
514
|
+
:class="$style.grid"
|
|
656
515
|
:grid-options="gridOptions"
|
|
657
|
-
@grid-ready="onGridReady"
|
|
658
|
-
@state-updated="onStateUpdated"
|
|
659
|
-
@grid-pre-destroyed="onGridPreDestroyed"
|
|
660
516
|
/>
|
|
661
517
|
</div>
|
|
662
518
|
</template>
|
|
663
519
|
|
|
664
|
-
<style lang="css"
|
|
665
|
-
.
|
|
520
|
+
<style lang="css" module>
|
|
521
|
+
.container {
|
|
666
522
|
display: flex;
|
|
667
523
|
flex-direction: column;
|
|
668
524
|
height: 100%;
|
|
669
525
|
gap: 12px;
|
|
670
526
|
}
|
|
671
527
|
|
|
672
|
-
.
|
|
673
|
-
display: flex;
|
|
674
|
-
flex-direction: row;
|
|
675
|
-
gap: 12px;
|
|
676
|
-
flex-wrap: wrap;
|
|
677
|
-
z-index: 3;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
.ap-ag-data-table-grid {
|
|
528
|
+
.grid {
|
|
681
529
|
flex: 1;
|
|
682
530
|
}
|
|
683
531
|
</style>
|