@ackplus/react-tanstack-data-table 1.1.12 → 1.1.15
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/README.md +143 -11
- package/dist/lib/components/droupdown/menu-dropdown.d.ts.map +1 -1
- package/dist/lib/components/droupdown/menu-dropdown.js +8 -1
- package/dist/lib/components/filters/filter-value-input.js +2 -2
- package/dist/lib/components/pagination/data-table-pagination.d.ts.map +1 -1
- package/dist/lib/components/pagination/data-table-pagination.js +10 -1
- package/dist/lib/components/toolbar/table-export-control.d.ts.map +1 -1
- package/dist/lib/components/toolbar/table-export-control.js +46 -12
- package/dist/lib/contexts/data-table-context.d.ts +7 -10
- package/dist/lib/contexts/data-table-context.d.ts.map +1 -1
- package/dist/lib/contexts/data-table-context.js +5 -1
- package/dist/lib/data-table.d.ts.map +1 -1
- package/dist/lib/data-table.js +517 -237
- package/dist/lib/features/column-filter.feature.js +38 -21
- package/dist/lib/features/selection.feature.d.ts.map +1 -1
- package/dist/lib/features/selection.feature.js +11 -3
- package/dist/lib/types/column.types.d.ts +19 -0
- package/dist/lib/types/column.types.d.ts.map +1 -1
- package/dist/lib/types/data-table-api.d.ts +24 -18
- package/dist/lib/types/data-table-api.d.ts.map +1 -1
- package/dist/lib/types/data-table.types.d.ts +37 -10
- package/dist/lib/types/data-table.types.d.ts.map +1 -1
- package/dist/lib/types/export.types.d.ts +57 -13
- package/dist/lib/types/export.types.d.ts.map +1 -1
- package/dist/lib/types/slots.types.d.ts +3 -1
- package/dist/lib/types/slots.types.d.ts.map +1 -1
- package/dist/lib/types/table.types.d.ts +1 -3
- package/dist/lib/types/table.types.d.ts.map +1 -1
- package/dist/lib/utils/debounced-fetch.utils.d.ts +8 -4
- package/dist/lib/utils/debounced-fetch.utils.d.ts.map +1 -1
- package/dist/lib/utils/debounced-fetch.utils.js +63 -14
- package/dist/lib/utils/export-utils.d.ts +14 -4
- package/dist/lib/utils/export-utils.d.ts.map +1 -1
- package/dist/lib/utils/export-utils.js +362 -66
- package/package.json +4 -2
- package/src/lib/components/droupdown/menu-dropdown.tsx +9 -3
- package/src/lib/components/filters/filter-value-input.tsx +2 -2
- package/src/lib/components/pagination/data-table-pagination.tsx +14 -2
- package/src/lib/components/toolbar/table-export-control.tsx +65 -9
- package/src/lib/contexts/data-table-context.tsx +16 -2
- package/src/lib/data-table.tsx +647 -231
- package/src/lib/features/column-filter.feature.ts +40 -19
- package/src/lib/features/selection.feature.ts +11 -5
- package/src/lib/types/column.types.ts +20 -1
- package/src/lib/types/data-table-api.ts +33 -15
- package/src/lib/types/data-table.types.ts +59 -3
- package/src/lib/types/export.types.ts +79 -10
- package/src/lib/types/slots.types.ts +3 -1
- package/src/lib/types/table.types.ts +1 -3
- package/src/lib/utils/debounced-fetch.utils.ts +90 -18
- package/src/lib/utils/export-utils.ts +496 -69
package/dist/lib/data-table.js
CHANGED
|
@@ -89,7 +89,10 @@ const DEFAULT_INITIAL_STATE = {
|
|
|
89
89
|
*/
|
|
90
90
|
exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, columns, data = [], totalRow = 0, idKey = 'id', extraFilter = null, footerFilter = null,
|
|
91
91
|
// Data management mode (MUI DataGrid style)
|
|
92
|
-
dataMode = 'client', initialLoadData = true, onFetchData,
|
|
92
|
+
dataMode = 'client', initialLoadData = true, onFetchData, // callback to fetch data from the server need to with response { data: T[], total: number }
|
|
93
|
+
onFetchStateChange, // callback to fetch data from the server no need to resonce , this for filter data
|
|
94
|
+
onDataChange, // callback to change data
|
|
95
|
+
onDataStateChange, // callback to change data state
|
|
93
96
|
// Selection props
|
|
94
97
|
enableRowSelection = false, enableMultiRowSelection = true, selectMode = 'page', isRowSelectable, onSelectionChange,
|
|
95
98
|
// Row click props
|
|
@@ -111,7 +114,9 @@ enablePagination = false, paginationMode = 'client',
|
|
|
111
114
|
// Filtering props
|
|
112
115
|
enableGlobalFilter = true, enableColumnFilter = false, filterMode = 'client',
|
|
113
116
|
// Sorting props
|
|
114
|
-
enableSorting = true, sortingMode = 'client', onSortingChange,
|
|
117
|
+
enableSorting = true, sortingMode = 'client', onSortingChange,
|
|
118
|
+
//export props
|
|
119
|
+
exportFilename = 'export', exportConcurrency = 'cancelAndRestart', exportChunkSize = 1000, exportStrictTotalCheck = false, exportSanitizeCSV = true, onExportProgress, onExportComplete, onExportError, onServerExport, onExportCancel, onExportStateChange,
|
|
115
120
|
// Styling props
|
|
116
121
|
enableHover = true, enableStripes = false, tableProps = {}, fitToScreen = true, tableSize: initialTableSize = 'medium',
|
|
117
122
|
// Sticky header/footer props
|
|
@@ -184,14 +189,24 @@ logging, }, ref) {
|
|
|
184
189
|
const [serverData, setServerData] = (0, react_1.useState)(null);
|
|
185
190
|
const [serverTotal, setServerTotal] = (0, react_1.useState)(0);
|
|
186
191
|
const [exportController, setExportController] = (0, react_1.useState)(null);
|
|
192
|
+
const [exportProgress, setExportProgress] = (0, react_1.useState)({});
|
|
193
|
+
const [exportPhase, setExportPhase] = (0, react_1.useState)(null);
|
|
194
|
+
const [queuedExportCount, setQueuedExportCount] = (0, react_1.useState)(0);
|
|
187
195
|
// -------------------------------
|
|
188
196
|
// Ref hooks (grouped together)
|
|
189
197
|
// -------------------------------
|
|
190
198
|
const tableContainerRef = (0, react_1.useRef)(null);
|
|
191
199
|
const internalApiRef = (0, react_1.useRef)(null);
|
|
200
|
+
const exportControllerRef = (0, react_1.useRef)(null);
|
|
201
|
+
const exportQueueRef = (0, react_1.useRef)(Promise.resolve());
|
|
202
|
+
const isExternallyControlledData = (0, react_1.useMemo)(() => !onFetchData && (!!onDataChange || !!onFetchStateChange), [onFetchData, onDataChange, onFetchStateChange]);
|
|
192
203
|
const { debouncedFetch, isLoading: fetchLoading } = (0, debounced_fetch_utils_1.useDebouncedFetch)(onFetchData);
|
|
193
|
-
const tableData = (0, react_1.useMemo)(() =>
|
|
194
|
-
|
|
204
|
+
const tableData = (0, react_1.useMemo)(() => {
|
|
205
|
+
if (isExternallyControlledData)
|
|
206
|
+
return data;
|
|
207
|
+
return serverData !== null ? serverData : data;
|
|
208
|
+
}, [isExternallyControlledData, serverData, data]);
|
|
209
|
+
const tableTotalRow = (0, react_1.useMemo)(() => (isExternallyControlledData ? (totalRow || data.length) : (serverData !== null ? serverTotal : totalRow || data.length)), [isExternallyControlledData, serverData, serverTotal, totalRow, data]);
|
|
195
210
|
const tableLoading = (0, react_1.useMemo)(() => onFetchData ? (loading || fetchLoading) : loading, [onFetchData, loading, fetchLoading]);
|
|
196
211
|
const enhancedColumns = (0, react_1.useMemo)(() => {
|
|
197
212
|
let columnsMap = [...columns];
|
|
@@ -239,13 +254,7 @@ logging, }, ref) {
|
|
|
239
254
|
// Callback hooks (grouped together)
|
|
240
255
|
// -------------------------------
|
|
241
256
|
const fetchData = (0, react_1.useCallback)(async (overrides = {}, options) => {
|
|
242
|
-
var _a, _b, _c;
|
|
243
|
-
if (!onFetchData) {
|
|
244
|
-
if (logger.isLevelEnabled('debug')) {
|
|
245
|
-
logger.debug('onFetchData not provided, skipping fetch', { overrides, columnFilter, sorting, pagination });
|
|
246
|
-
}
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
257
|
+
var _a, _b, _c, _d, _e;
|
|
249
258
|
const filters = {
|
|
250
259
|
globalFilter,
|
|
251
260
|
pagination,
|
|
@@ -253,20 +262,35 @@ logging, }, ref) {
|
|
|
253
262
|
sorting,
|
|
254
263
|
...overrides,
|
|
255
264
|
};
|
|
256
|
-
|
|
265
|
+
if (onFetchStateChange) {
|
|
266
|
+
onFetchStateChange(filters, options === null || options === void 0 ? void 0 : options.meta);
|
|
267
|
+
}
|
|
268
|
+
if (!onFetchData) {
|
|
269
|
+
if (logger.isLevelEnabled('debug')) {
|
|
270
|
+
logger.debug('onFetchData not provided, skipping fetch', { overrides, columnFilter, sorting, pagination });
|
|
271
|
+
}
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
257
274
|
if (logger.isLevelEnabled('info')) {
|
|
258
|
-
logger.info('Requesting data', {
|
|
275
|
+
logger.info('Requesting data', {
|
|
276
|
+
filters,
|
|
277
|
+
reason: (_a = options === null || options === void 0 ? void 0 : options.meta) === null || _a === void 0 ? void 0 : _a.reason,
|
|
278
|
+
force: (_b = options === null || options === void 0 ? void 0 : options.meta) === null || _b === void 0 ? void 0 : _b.force,
|
|
279
|
+
});
|
|
259
280
|
}
|
|
260
281
|
try {
|
|
261
|
-
const delay = (
|
|
262
|
-
const result = await debouncedFetch(filters,
|
|
282
|
+
const delay = (_c = options === null || options === void 0 ? void 0 : options.delay) !== null && _c !== void 0 ? _c : 300; // respects 0
|
|
283
|
+
const result = await debouncedFetch(filters, {
|
|
284
|
+
debounceDelay: delay,
|
|
285
|
+
meta: options === null || options === void 0 ? void 0 : options.meta,
|
|
286
|
+
});
|
|
263
287
|
if (logger.isLevelEnabled('info')) {
|
|
264
288
|
logger.info('Fetch resolved', {
|
|
265
|
-
rows: (
|
|
289
|
+
rows: (_e = (_d = result === null || result === void 0 ? void 0 : result.data) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0,
|
|
266
290
|
total: result === null || result === void 0 ? void 0 : result.total,
|
|
267
291
|
});
|
|
268
292
|
}
|
|
269
|
-
if (
|
|
293
|
+
if (result && Array.isArray(result.data) && result.total !== undefined) {
|
|
270
294
|
setServerData(result.data);
|
|
271
295
|
setServerTotal(result.total);
|
|
272
296
|
}
|
|
@@ -287,7 +311,23 @@ logging, }, ref) {
|
|
|
287
311
|
sorting,
|
|
288
312
|
debouncedFetch,
|
|
289
313
|
logger,
|
|
314
|
+
onFetchStateChange,
|
|
290
315
|
]);
|
|
316
|
+
const normalizeRefreshOptions = (0, react_1.useCallback)((options, fallbackReason = 'refresh') => {
|
|
317
|
+
var _a, _b, _c;
|
|
318
|
+
if (typeof options === 'boolean') {
|
|
319
|
+
return {
|
|
320
|
+
resetPagination: options,
|
|
321
|
+
force: false,
|
|
322
|
+
reason: fallbackReason,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
resetPagination: (_a = options === null || options === void 0 ? void 0 : options.resetPagination) !== null && _a !== void 0 ? _a : false,
|
|
327
|
+
force: (_b = options === null || options === void 0 ? void 0 : options.force) !== null && _b !== void 0 ? _b : false,
|
|
328
|
+
reason: (_c = options === null || options === void 0 ? void 0 : options.reason) !== null && _c !== void 0 ? _c : fallbackReason,
|
|
329
|
+
};
|
|
330
|
+
}, []);
|
|
291
331
|
const handleSelectionStateChange = (0, react_1.useCallback)((updaterOrValue) => {
|
|
292
332
|
setSelectionState((prevState) => {
|
|
293
333
|
const next = typeof updaterOrValue === 'function' ? updaterOrValue(prevState) : updaterOrValue;
|
|
@@ -526,11 +566,20 @@ logging, }, ref) {
|
|
|
526
566
|
// Effects (after callbacks)
|
|
527
567
|
// -------------------------------
|
|
528
568
|
(0, react_1.useEffect)(() => {
|
|
529
|
-
if (
|
|
569
|
+
if (!isExternallyControlledData || serverData === null)
|
|
570
|
+
return;
|
|
571
|
+
setServerData(null);
|
|
572
|
+
setServerTotal(0);
|
|
573
|
+
}, [isExternallyControlledData, serverData]);
|
|
574
|
+
(0, react_1.useEffect)(() => {
|
|
575
|
+
if (initialLoadData && (onFetchData || onFetchStateChange)) {
|
|
530
576
|
if (logger.isLevelEnabled('info')) {
|
|
531
577
|
logger.info('Initial data load triggered', { initialLoadData });
|
|
532
578
|
}
|
|
533
|
-
fetchData({}
|
|
579
|
+
fetchData({}, {
|
|
580
|
+
delay: 0,
|
|
581
|
+
meta: { reason: 'initial' },
|
|
582
|
+
});
|
|
534
583
|
}
|
|
535
584
|
else if (logger.isLevelEnabled('debug')) {
|
|
536
585
|
logger.debug('Skipping initial data load', {
|
|
@@ -559,12 +608,13 @@ logging, }, ref) {
|
|
|
559
608
|
if (!onDataStateChange)
|
|
560
609
|
return;
|
|
561
610
|
const live = table.getState();
|
|
611
|
+
const liveColumnFilter = live.columnFilter;
|
|
562
612
|
// only keep what you persist/store
|
|
563
613
|
const payload = {
|
|
564
614
|
sorting: live.sorting,
|
|
565
615
|
pagination: live.pagination,
|
|
566
616
|
globalFilter: live.globalFilter,
|
|
567
|
-
columnFilter:
|
|
617
|
+
columnFilter: liveColumnFilter,
|
|
568
618
|
columnVisibility: live.columnVisibility,
|
|
569
619
|
columnSizing: live.columnSizing,
|
|
570
620
|
columnOrder: live.columnOrder,
|
|
@@ -593,7 +643,7 @@ logging, }, ref) {
|
|
|
593
643
|
var _a;
|
|
594
644
|
const resetSorting = initialStateConfig.sorting || [];
|
|
595
645
|
const resetGlobalFilter = (_a = initialStateConfig.globalFilter) !== null && _a !== void 0 ? _a : '';
|
|
596
|
-
const resetColumnFilter = initialStateConfig.columnFilter
|
|
646
|
+
const resetColumnFilter = initialStateConfig.columnFilter;
|
|
597
647
|
const resetPagination = enablePagination
|
|
598
648
|
? (initialStateConfig.pagination || { pageIndex: 0, pageSize: 10 })
|
|
599
649
|
: undefined;
|
|
@@ -604,14 +654,66 @@ logging, }, ref) {
|
|
|
604
654
|
...(resetPagination ? { pagination: resetPagination } : {}),
|
|
605
655
|
};
|
|
606
656
|
}, [initialStateConfig, enablePagination]);
|
|
657
|
+
const applyDataMutation = (0, react_1.useCallback)((action, updater, details = {}) => {
|
|
658
|
+
const previousData = [...tableData];
|
|
659
|
+
const nextData = updater(previousData);
|
|
660
|
+
if (nextData === previousData)
|
|
661
|
+
return nextData;
|
|
662
|
+
const nextTotal = Math.max(0, tableTotalRow + (nextData.length - previousData.length));
|
|
663
|
+
if (!isExternallyControlledData) {
|
|
664
|
+
setServerData(nextData);
|
|
665
|
+
setServerTotal(nextTotal);
|
|
666
|
+
}
|
|
667
|
+
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(nextData, {
|
|
668
|
+
action,
|
|
669
|
+
previousData,
|
|
670
|
+
nextData,
|
|
671
|
+
totalRow: nextTotal,
|
|
672
|
+
...details,
|
|
673
|
+
});
|
|
674
|
+
if (logger.isLevelEnabled('debug')) {
|
|
675
|
+
logger.debug('Applied data mutation', {
|
|
676
|
+
action,
|
|
677
|
+
previousCount: previousData.length,
|
|
678
|
+
nextCount: nextData.length,
|
|
679
|
+
totalRow: nextTotal,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
return nextData;
|
|
683
|
+
}, [isExternallyControlledData, logger, onDataChange, tableData, tableTotalRow]);
|
|
684
|
+
const triggerRefresh = (0, react_1.useCallback)(async (options, fallbackReason = 'refresh') => {
|
|
685
|
+
const normalizedOptions = normalizeRefreshOptions(options, fallbackReason);
|
|
686
|
+
const nextPagination = enablePagination
|
|
687
|
+
? {
|
|
688
|
+
pageIndex: normalizedOptions.resetPagination ? 0 : pagination.pageIndex,
|
|
689
|
+
pageSize: pagination.pageSize,
|
|
690
|
+
}
|
|
691
|
+
: undefined;
|
|
692
|
+
const shouldUpdatePagination = !!nextPagination
|
|
693
|
+
&& (nextPagination.pageIndex !== pagination.pageIndex || nextPagination.pageSize !== pagination.pageSize);
|
|
694
|
+
if (nextPagination && shouldUpdatePagination) {
|
|
695
|
+
setPagination(nextPagination);
|
|
696
|
+
onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(nextPagination);
|
|
697
|
+
}
|
|
698
|
+
await fetchData(nextPagination ? { pagination: nextPagination } : {}, {
|
|
699
|
+
delay: 0,
|
|
700
|
+
meta: {
|
|
701
|
+
reason: normalizedOptions.reason,
|
|
702
|
+
force: normalizedOptions.force,
|
|
703
|
+
},
|
|
704
|
+
});
|
|
705
|
+
return;
|
|
706
|
+
}, [normalizeRefreshOptions, enablePagination, pagination, onPaginationChange, fetchData]);
|
|
607
707
|
const resetAllAndReload = (0, react_1.useCallback)(() => {
|
|
608
708
|
var _a;
|
|
609
709
|
const resetState = getResetState();
|
|
610
710
|
setSorting(resetState.sorting || []);
|
|
611
711
|
setGlobalFilter((_a = resetState.globalFilter) !== null && _a !== void 0 ? _a : '');
|
|
612
712
|
setColumnFilter(resetState.columnFilter);
|
|
613
|
-
if (resetState.pagination)
|
|
713
|
+
if (resetState.pagination) {
|
|
614
714
|
setPagination(resetState.pagination);
|
|
715
|
+
onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(resetState.pagination);
|
|
716
|
+
}
|
|
615
717
|
setSelectionState(initialSelectionState);
|
|
616
718
|
setExpanded({});
|
|
617
719
|
// layout state
|
|
@@ -619,9 +721,97 @@ logging, }, ref) {
|
|
|
619
721
|
setColumnSizing(initialStateConfig.columnSizing || {});
|
|
620
722
|
setColumnOrder(initialStateConfig.columnOrder || []);
|
|
621
723
|
setColumnPinning(initialStateConfig.columnPinning || { left: [], right: [] });
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
724
|
+
const resetOptions = normalizeRefreshOptions({
|
|
725
|
+
resetPagination: true,
|
|
726
|
+
force: true,
|
|
727
|
+
reason: 'reset',
|
|
728
|
+
}, 'reset');
|
|
729
|
+
void fetchData(resetState, {
|
|
730
|
+
delay: 0,
|
|
731
|
+
meta: {
|
|
732
|
+
reason: resetOptions.reason,
|
|
733
|
+
force: resetOptions.force,
|
|
734
|
+
},
|
|
735
|
+
});
|
|
736
|
+
}, [getResetState, initialSelectionState, initialStateConfig, onPaginationChange, normalizeRefreshOptions, fetchData]);
|
|
737
|
+
const setExportControllerSafely = (0, react_1.useCallback)((value) => {
|
|
738
|
+
setExportController((current) => {
|
|
739
|
+
const next = typeof value === 'function' ? value(current) : value;
|
|
740
|
+
exportControllerRef.current = next;
|
|
741
|
+
return next;
|
|
742
|
+
});
|
|
743
|
+
}, []);
|
|
744
|
+
const handleExportProgressInternal = (0, react_1.useCallback)((progress) => {
|
|
745
|
+
setExportProgress(progress || {});
|
|
746
|
+
onExportProgress === null || onExportProgress === void 0 ? void 0 : onExportProgress(progress);
|
|
747
|
+
}, [onExportProgress]);
|
|
748
|
+
const handleExportStateChangeInternal = (0, react_1.useCallback)((state) => {
|
|
749
|
+
setExportPhase(state.phase);
|
|
750
|
+
if (state.processedRows !== undefined
|
|
751
|
+
|| state.totalRows !== undefined
|
|
752
|
+
|| state.percentage !== undefined) {
|
|
753
|
+
setExportProgress({
|
|
754
|
+
processedRows: state.processedRows,
|
|
755
|
+
totalRows: state.totalRows,
|
|
756
|
+
percentage: state.percentage,
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
onExportStateChange === null || onExportStateChange === void 0 ? void 0 : onExportStateChange(state);
|
|
760
|
+
}, [onExportStateChange]);
|
|
761
|
+
const runExportWithPolicy = (0, react_1.useCallback)(async (options) => {
|
|
762
|
+
const { format, filename, mode, execute } = options;
|
|
763
|
+
const startExecution = async () => {
|
|
764
|
+
const controller = new AbortController();
|
|
765
|
+
setExportProgress({});
|
|
766
|
+
setExportControllerSafely(controller);
|
|
767
|
+
try {
|
|
768
|
+
await execute(controller);
|
|
769
|
+
}
|
|
770
|
+
finally {
|
|
771
|
+
setExportControllerSafely((current) => (current === controller ? null : current));
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
if (exportConcurrency === 'queue') {
|
|
775
|
+
setQueuedExportCount((prev) => prev + 1);
|
|
776
|
+
const runQueued = async () => {
|
|
777
|
+
setQueuedExportCount((prev) => Math.max(0, prev - 1));
|
|
778
|
+
await startExecution();
|
|
779
|
+
};
|
|
780
|
+
const queuedPromise = exportQueueRef.current
|
|
781
|
+
.catch(() => undefined)
|
|
782
|
+
.then(runQueued);
|
|
783
|
+
exportQueueRef.current = queuedPromise;
|
|
784
|
+
return queuedPromise;
|
|
785
|
+
}
|
|
786
|
+
const activeController = exportControllerRef.current;
|
|
787
|
+
if (activeController) {
|
|
788
|
+
if (exportConcurrency === 'ignoreIfRunning') {
|
|
789
|
+
handleExportStateChangeInternal({
|
|
790
|
+
phase: 'error',
|
|
791
|
+
mode,
|
|
792
|
+
format,
|
|
793
|
+
filename,
|
|
794
|
+
message: 'An export is already running',
|
|
795
|
+
code: 'EXPORT_IN_PROGRESS',
|
|
796
|
+
endedAt: Date.now(),
|
|
797
|
+
});
|
|
798
|
+
onExportError === null || onExportError === void 0 ? void 0 : onExportError({
|
|
799
|
+
message: 'An export is already running',
|
|
800
|
+
code: 'EXPORT_IN_PROGRESS',
|
|
801
|
+
});
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
if (exportConcurrency === 'cancelAndRestart') {
|
|
805
|
+
activeController.abort();
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
await startExecution();
|
|
809
|
+
}, [
|
|
810
|
+
exportConcurrency,
|
|
811
|
+
handleExportStateChangeInternal,
|
|
812
|
+
onExportError,
|
|
813
|
+
setExportControllerSafely,
|
|
814
|
+
]);
|
|
625
815
|
const dataTableApi = (0, react_1.useMemo)(() => {
|
|
626
816
|
// helpers (avoid repeating boilerplate)
|
|
627
817
|
const buildInitialOrder = () => enhancedColumns.map((col, index) => {
|
|
@@ -654,6 +844,12 @@ logging, }, ref) {
|
|
|
654
844
|
const applyGlobalFilter = (next) => {
|
|
655
845
|
handleGlobalFilterChange(next);
|
|
656
846
|
};
|
|
847
|
+
const getRowIndexById = (rowsToSearch, rowId) => rowsToSearch.findIndex((row, index) => String((0, utils_1.generateRowId)(row, index, idKey)) === rowId);
|
|
848
|
+
const clampInsertIndex = (rowsToMutate, insertIndex) => {
|
|
849
|
+
if (insertIndex === undefined)
|
|
850
|
+
return rowsToMutate.length;
|
|
851
|
+
return Math.max(0, Math.min(insertIndex, rowsToMutate.length));
|
|
852
|
+
};
|
|
657
853
|
return {
|
|
658
854
|
table: {
|
|
659
855
|
getTable: () => table,
|
|
@@ -935,129 +1131,135 @@ logging, }, ref) {
|
|
|
935
1131
|
// Data Management (kept same, but ensure state changes go through handlers)
|
|
936
1132
|
// -------------------------------
|
|
937
1133
|
data: {
|
|
938
|
-
refresh: (
|
|
939
|
-
|
|
940
|
-
const allState = table.getState();
|
|
941
|
-
const current = allState.pagination;
|
|
942
|
-
const nextPagination = {
|
|
943
|
-
pageIndex: resetPagination ? 0 : (_a = current === null || current === void 0 ? void 0 : current.pageIndex) !== null && _a !== void 0 ? _a : 0,
|
|
944
|
-
pageSize: (_d = (_b = current === null || current === void 0 ? void 0 : current.pageSize) !== null && _b !== void 0 ? _b : (_c = initialStateConfig.pagination) === null || _c === void 0 ? void 0 : _c.pageSize) !== null && _d !== void 0 ? _d : 10,
|
|
945
|
-
};
|
|
946
|
-
// must go through handler so server fetch triggers
|
|
947
|
-
applyPagination(nextPagination);
|
|
948
|
-
// emit persisted state (your emitTableState effect will also do it)
|
|
949
|
-
onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange({ ...allState, pagination: nextPagination });
|
|
950
|
-
fetchData === null || fetchData === void 0 ? void 0 : fetchData({ pagination: nextPagination });
|
|
951
|
-
if (logger.isLevelEnabled("debug")) {
|
|
952
|
-
logger.debug("Refreshing data", { nextPagination, allState });
|
|
953
|
-
}
|
|
1134
|
+
refresh: (options) => {
|
|
1135
|
+
void triggerRefresh(options, 'refresh');
|
|
954
1136
|
},
|
|
955
|
-
reload: () => {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
}
|
|
1137
|
+
reload: (options = {}) => {
|
|
1138
|
+
var _a, _b;
|
|
1139
|
+
void triggerRefresh({
|
|
1140
|
+
...options,
|
|
1141
|
+
resetPagination: (_a = options.resetPagination) !== null && _a !== void 0 ? _a : false,
|
|
1142
|
+
reason: (_b = options.reason) !== null && _b !== void 0 ? _b : 'reload',
|
|
1143
|
+
}, 'reload');
|
|
1144
|
+
},
|
|
1145
|
+
resetAll: () => resetAllAndReload(),
|
|
1146
|
+
getAllData: () => [...tableData],
|
|
1147
|
+
getRowData: (rowId) => {
|
|
1148
|
+
const rowIndex = getRowIndexById(tableData, rowId);
|
|
1149
|
+
return rowIndex === -1 ? undefined : tableData[rowIndex];
|
|
962
1150
|
},
|
|
963
|
-
|
|
964
|
-
getAllData: () => { var _a; return ((_a = table.getRowModel().rows) === null || _a === void 0 ? void 0 : _a.map((row) => row.original)) || []; },
|
|
965
|
-
getRowData: (rowId) => { var _a, _b; return (_b = (_a = table.getRowModel().rows) === null || _a === void 0 ? void 0 : _a.find((row) => String(row.original[idKey]) === rowId)) === null || _b === void 0 ? void 0 : _b.original; },
|
|
966
|
-
getRowByIndex: (index) => { var _a, _b; return (_b = (_a = table.getRowModel().rows) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b.original; },
|
|
1151
|
+
getRowByIndex: (index) => tableData[index],
|
|
967
1152
|
updateRow: (rowId, updates) => {
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1153
|
+
applyDataMutation('updateRow', (rowsToMutate) => {
|
|
1154
|
+
const rowIndex = getRowIndexById(rowsToMutate, rowId);
|
|
1155
|
+
if (rowIndex === -1)
|
|
1156
|
+
return rowsToMutate;
|
|
1157
|
+
const nextData = [...rowsToMutate];
|
|
1158
|
+
nextData[rowIndex] = { ...nextData[rowIndex], ...updates };
|
|
1159
|
+
return nextData;
|
|
1160
|
+
}, { rowId });
|
|
973
1161
|
},
|
|
974
1162
|
updateRowByIndex: (index, updates) => {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
}
|
|
1163
|
+
applyDataMutation('updateRowByIndex', (rowsToMutate) => {
|
|
1164
|
+
if (!rowsToMutate[index])
|
|
1165
|
+
return rowsToMutate;
|
|
1166
|
+
const nextData = [...rowsToMutate];
|
|
1167
|
+
nextData[index] = { ...nextData[index], ...updates };
|
|
1168
|
+
return nextData;
|
|
1169
|
+
}, { index });
|
|
983
1170
|
},
|
|
984
1171
|
insertRow: (newRow, index) => {
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
newData.push(newRow);
|
|
991
|
-
setServerData(newData || []);
|
|
992
|
-
if (logger.isLevelEnabled("debug"))
|
|
993
|
-
logger.debug("Inserting row", newRow);
|
|
1172
|
+
applyDataMutation('insertRow', (rowsToMutate) => {
|
|
1173
|
+
const nextData = [...rowsToMutate];
|
|
1174
|
+
nextData.splice(clampInsertIndex(nextData, index), 0, newRow);
|
|
1175
|
+
return nextData;
|
|
1176
|
+
}, { index });
|
|
994
1177
|
},
|
|
995
1178
|
deleteRow: (rowId) => {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1179
|
+
applyDataMutation('deleteRow', (rowsToMutate) => {
|
|
1180
|
+
const rowIndex = getRowIndexById(rowsToMutate, rowId);
|
|
1181
|
+
if (rowIndex === -1)
|
|
1182
|
+
return rowsToMutate;
|
|
1183
|
+
const nextData = [...rowsToMutate];
|
|
1184
|
+
nextData.splice(rowIndex, 1);
|
|
1185
|
+
return nextData;
|
|
1186
|
+
}, { rowId });
|
|
1000
1187
|
},
|
|
1001
1188
|
deleteRowByIndex: (index) => {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1189
|
+
applyDataMutation('deleteRowByIndex', (rowsToMutate) => {
|
|
1190
|
+
if (index < 0 || index >= rowsToMutate.length)
|
|
1191
|
+
return rowsToMutate;
|
|
1192
|
+
const nextData = [...rowsToMutate];
|
|
1193
|
+
nextData.splice(index, 1);
|
|
1194
|
+
return nextData;
|
|
1195
|
+
}, { index });
|
|
1007
1196
|
},
|
|
1008
1197
|
deleteSelectedRows: () => {
|
|
1009
|
-
var _a, _b;
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1198
|
+
var _a, _b, _c;
|
|
1199
|
+
const currentSelection = ((_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table)) || selectionState;
|
|
1200
|
+
const selectedIds = new Set((currentSelection.ids || []).map((id) => String(id)));
|
|
1201
|
+
const loadedRowIds = tableData.map((row, index) => String((0, utils_1.generateRowId)(row, index, idKey)));
|
|
1202
|
+
const deletableRowIds = currentSelection.type === 'exclude'
|
|
1203
|
+
? loadedRowIds.filter((rowId) => !selectedIds.has(rowId))
|
|
1204
|
+
: loadedRowIds.filter((rowId) => selectedIds.has(rowId));
|
|
1205
|
+
if (deletableRowIds.length === 0)
|
|
1012
1206
|
return;
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
.
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1207
|
+
if (currentSelection.type === 'exclude'
|
|
1208
|
+
&& table.getRowCount() > loadedRowIds.length
|
|
1209
|
+
&& logger.isLevelEnabled('info')) {
|
|
1210
|
+
logger.info('deleteSelectedRows in exclude mode removed currently loaded rows only', {
|
|
1211
|
+
removedRows: deletableRowIds.length,
|
|
1212
|
+
totalSelected: (_b = table.getSelectedCount) === null || _b === void 0 ? void 0 : _b.call(table),
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
const deletableRowIdSet = new Set(deletableRowIds);
|
|
1216
|
+
applyDataMutation('deleteSelectedRows', (rowsToMutate) => rowsToMutate.filter((row, index) => !deletableRowIdSet.has(String((0, utils_1.generateRowId)(row, index, idKey)))), { rowIds: deletableRowIds });
|
|
1217
|
+
(_c = table.deselectAll) === null || _c === void 0 ? void 0 : _c.call(table);
|
|
1218
|
+
},
|
|
1219
|
+
replaceAllData: (newData) => {
|
|
1220
|
+
applyDataMutation('replaceAllData', () => [...newData]);
|
|
1021
1221
|
},
|
|
1022
|
-
replaceAllData: (newData) => setServerData === null || setServerData === void 0 ? void 0 : setServerData(newData),
|
|
1023
1222
|
updateMultipleRows: (updates) => {
|
|
1024
|
-
const updateMap = new Map(updates.map((
|
|
1025
|
-
|
|
1026
|
-
const
|
|
1027
|
-
const updateData = updateMap.get(
|
|
1028
|
-
return updateData ? { ...row
|
|
1029
|
-
});
|
|
1030
|
-
setServerData(newData || []);
|
|
1223
|
+
const updateMap = new Map(updates.map((update) => [update.rowId, update.data]));
|
|
1224
|
+
applyDataMutation('updateMultipleRows', (rowsToMutate) => rowsToMutate.map((row, index) => {
|
|
1225
|
+
const currentRowId = String((0, utils_1.generateRowId)(row, index, idKey));
|
|
1226
|
+
const updateData = updateMap.get(currentRowId);
|
|
1227
|
+
return updateData ? { ...row, ...updateData } : row;
|
|
1228
|
+
}));
|
|
1031
1229
|
},
|
|
1032
1230
|
insertMultipleRows: (newRows, startIndex) => {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
setServerData === null || setServerData === void 0 ? void 0 : setServerData(newData);
|
|
1231
|
+
applyDataMutation('insertMultipleRows', (rowsToMutate) => {
|
|
1232
|
+
const nextData = [...rowsToMutate];
|
|
1233
|
+
nextData.splice(clampInsertIndex(nextData, startIndex), 0, ...newRows);
|
|
1234
|
+
return nextData;
|
|
1235
|
+
}, { index: startIndex });
|
|
1039
1236
|
},
|
|
1040
1237
|
deleteMultipleRows: (rowIds) => {
|
|
1041
1238
|
const idsToDelete = new Set(rowIds);
|
|
1042
|
-
|
|
1043
|
-
.filter((row) => !idsToDelete.has(String(row.original[idKey])))
|
|
1044
|
-
.map((row) => row.original);
|
|
1045
|
-
setServerData(newData);
|
|
1239
|
+
applyDataMutation('deleteMultipleRows', (rowsToMutate) => rowsToMutate.filter((row, index) => !idsToDelete.has(String((0, utils_1.generateRowId)(row, index, idKey)))), { rowIds });
|
|
1046
1240
|
},
|
|
1047
1241
|
updateField: (rowId, fieldName, value) => {
|
|
1048
|
-
|
|
1049
|
-
|
|
1242
|
+
applyDataMutation('updateField', (rowsToMutate) => {
|
|
1243
|
+
const rowIndex = getRowIndexById(rowsToMutate, rowId);
|
|
1244
|
+
if (rowIndex === -1)
|
|
1245
|
+
return rowsToMutate;
|
|
1246
|
+
const nextData = [...rowsToMutate];
|
|
1247
|
+
nextData[rowIndex] = { ...nextData[rowIndex], [fieldName]: value };
|
|
1248
|
+
return nextData;
|
|
1249
|
+
}, { rowId });
|
|
1050
1250
|
},
|
|
1051
1251
|
updateFieldByIndex: (index, fieldName, value) => {
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1252
|
+
applyDataMutation('updateFieldByIndex', (rowsToMutate) => {
|
|
1253
|
+
if (!rowsToMutate[index])
|
|
1254
|
+
return rowsToMutate;
|
|
1255
|
+
const nextData = [...rowsToMutate];
|
|
1256
|
+
nextData[index] = { ...nextData[index], [fieldName]: value };
|
|
1257
|
+
return nextData;
|
|
1258
|
+
}, { index });
|
|
1057
1259
|
},
|
|
1058
|
-
findRows: (predicate) =>
|
|
1059
|
-
findRowIndex: (predicate) =>
|
|
1060
|
-
getDataCount: () =>
|
|
1260
|
+
findRows: (predicate) => tableData.filter(predicate),
|
|
1261
|
+
findRowIndex: (predicate) => tableData.findIndex(predicate),
|
|
1262
|
+
getDataCount: () => tableData.length,
|
|
1061
1263
|
getFilteredDataCount: () => table.getFilteredRowModel().rows.length,
|
|
1062
1264
|
},
|
|
1063
1265
|
// -------------------------------
|
|
@@ -1072,7 +1274,7 @@ logging, }, ref) {
|
|
|
1072
1274
|
applySorting(initialStateConfig.sorting || []);
|
|
1073
1275
|
applyGlobalFilter((_a = initialStateConfig.globalFilter) !== null && _a !== void 0 ? _a : "");
|
|
1074
1276
|
},
|
|
1075
|
-
resetAll: () => resetAllAndReload(
|
|
1277
|
+
resetAll: () => resetAllAndReload(),
|
|
1076
1278
|
saveLayout: () => ({
|
|
1077
1279
|
columnVisibility: table.getState().columnVisibility,
|
|
1078
1280
|
columnSizing: table.getState().columnSizing,
|
|
@@ -1117,141 +1319,212 @@ logging, }, ref) {
|
|
|
1117
1319
|
// -------------------------------
|
|
1118
1320
|
export: {
|
|
1119
1321
|
exportCSV: async (options = {}) => {
|
|
1120
|
-
|
|
1121
|
-
const
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1322
|
+
const { filename = exportFilename, chunkSize = exportChunkSize, strictTotalCheck = exportStrictTotalCheck, sanitizeCSV = exportSanitizeCSV, } = options;
|
|
1323
|
+
const mode = dataMode === "server" && !!onServerExport ? 'server' : 'client';
|
|
1324
|
+
await runExportWithPolicy({
|
|
1325
|
+
format: 'csv',
|
|
1326
|
+
filename,
|
|
1327
|
+
mode,
|
|
1328
|
+
execute: async (controller) => {
|
|
1329
|
+
var _a;
|
|
1330
|
+
const toStateChange = (state) => {
|
|
1331
|
+
const isFinalPhase = state.phase === 'completed' || state.phase === 'cancelled' || state.phase === 'error';
|
|
1332
|
+
handleExportStateChangeInternal({
|
|
1333
|
+
phase: state.phase,
|
|
1334
|
+
mode,
|
|
1335
|
+
format: 'csv',
|
|
1336
|
+
filename,
|
|
1337
|
+
processedRows: state.processedRows,
|
|
1338
|
+
totalRows: state.totalRows,
|
|
1339
|
+
percentage: state.percentage,
|
|
1340
|
+
message: state.message,
|
|
1341
|
+
code: state.code,
|
|
1342
|
+
startedAt: state.phase === 'starting' ? Date.now() : undefined,
|
|
1343
|
+
endedAt: isFinalPhase ? Date.now() : undefined,
|
|
1344
|
+
queueLength: queuedExportCount,
|
|
1345
|
+
});
|
|
1346
|
+
if (state.phase === 'cancelled') {
|
|
1347
|
+
onExportCancel === null || onExportCancel === void 0 ? void 0 : onExportCancel();
|
|
1348
|
+
}
|
|
1131
1349
|
};
|
|
1132
|
-
if (
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1350
|
+
if (mode === 'server' && onServerExport) {
|
|
1351
|
+
const currentFilters = {
|
|
1352
|
+
globalFilter: table.getState().globalFilter,
|
|
1353
|
+
columnFilter: table.getState().columnFilter,
|
|
1354
|
+
sorting: table.getState().sorting,
|
|
1355
|
+
pagination: table.getState().pagination,
|
|
1356
|
+
};
|
|
1357
|
+
if (logger.isLevelEnabled("debug"))
|
|
1358
|
+
logger.debug("Server export CSV", { currentFilters });
|
|
1359
|
+
await (0, utils_1.exportServerData)(table, {
|
|
1360
|
+
format: "csv",
|
|
1361
|
+
filename,
|
|
1362
|
+
fetchData: (filters, selection, signal) => onServerExport(filters, selection, signal),
|
|
1363
|
+
currentFilters,
|
|
1364
|
+
selection: (_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table),
|
|
1365
|
+
onProgress: handleExportProgressInternal,
|
|
1366
|
+
onComplete: onExportComplete,
|
|
1367
|
+
onError: onExportError,
|
|
1368
|
+
onStateChange: toStateChange,
|
|
1369
|
+
signal: controller.signal,
|
|
1370
|
+
chunkSize,
|
|
1371
|
+
strictTotalCheck,
|
|
1372
|
+
sanitizeCSV,
|
|
1373
|
+
});
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1146
1376
|
await (0, utils_1.exportClientData)(table, {
|
|
1147
1377
|
format: "csv",
|
|
1148
1378
|
filename,
|
|
1149
|
-
onProgress:
|
|
1379
|
+
onProgress: handleExportProgressInternal,
|
|
1150
1380
|
onComplete: onExportComplete,
|
|
1151
1381
|
onError: onExportError,
|
|
1382
|
+
onStateChange: toStateChange,
|
|
1383
|
+
signal: controller.signal,
|
|
1384
|
+
sanitizeCSV,
|
|
1152
1385
|
});
|
|
1153
1386
|
if (logger.isLevelEnabled("debug"))
|
|
1154
1387
|
logger.debug("Client export CSV", filename);
|
|
1155
1388
|
}
|
|
1156
|
-
}
|
|
1157
|
-
catch (error) {
|
|
1158
|
-
onExportError === null || onExportError === void 0 ? void 0 : onExportError({ message: error.message || "Export failed", code: "EXPORT_ERROR" });
|
|
1159
|
-
}
|
|
1160
|
-
finally {
|
|
1161
|
-
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
|
|
1162
|
-
}
|
|
1389
|
+
});
|
|
1163
1390
|
},
|
|
1164
1391
|
exportExcel: async (options = {}) => {
|
|
1165
|
-
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1392
|
+
const { filename = exportFilename, chunkSize = exportChunkSize, strictTotalCheck = exportStrictTotalCheck, sanitizeCSV = exportSanitizeCSV, } = options;
|
|
1393
|
+
const mode = dataMode === "server" && !!onServerExport ? 'server' : 'client';
|
|
1394
|
+
await runExportWithPolicy({
|
|
1395
|
+
format: 'excel',
|
|
1396
|
+
filename,
|
|
1397
|
+
mode,
|
|
1398
|
+
execute: async (controller) => {
|
|
1399
|
+
var _a;
|
|
1400
|
+
const toStateChange = (state) => {
|
|
1401
|
+
const isFinalPhase = state.phase === 'completed' || state.phase === 'cancelled' || state.phase === 'error';
|
|
1402
|
+
handleExportStateChangeInternal({
|
|
1403
|
+
phase: state.phase,
|
|
1404
|
+
mode,
|
|
1405
|
+
format: 'excel',
|
|
1406
|
+
filename,
|
|
1407
|
+
processedRows: state.processedRows,
|
|
1408
|
+
totalRows: state.totalRows,
|
|
1409
|
+
percentage: state.percentage,
|
|
1410
|
+
message: state.message,
|
|
1411
|
+
code: state.code,
|
|
1412
|
+
startedAt: state.phase === 'starting' ? Date.now() : undefined,
|
|
1413
|
+
endedAt: isFinalPhase ? Date.now() : undefined,
|
|
1414
|
+
queueLength: queuedExportCount,
|
|
1415
|
+
});
|
|
1416
|
+
if (state.phase === 'cancelled') {
|
|
1417
|
+
onExportCancel === null || onExportCancel === void 0 ? void 0 : onExportCancel();
|
|
1418
|
+
}
|
|
1176
1419
|
};
|
|
1177
|
-
if (
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1420
|
+
if (mode === 'server' && onServerExport) {
|
|
1421
|
+
const currentFilters = {
|
|
1422
|
+
globalFilter: table.getState().globalFilter,
|
|
1423
|
+
columnFilter: table.getState().columnFilter,
|
|
1424
|
+
sorting: table.getState().sorting,
|
|
1425
|
+
pagination: table.getState().pagination,
|
|
1426
|
+
};
|
|
1427
|
+
if (logger.isLevelEnabled("debug"))
|
|
1428
|
+
logger.debug("Server export Excel", { currentFilters });
|
|
1429
|
+
await (0, utils_1.exportServerData)(table, {
|
|
1430
|
+
format: "excel",
|
|
1431
|
+
filename,
|
|
1432
|
+
fetchData: (filters, selection, signal) => onServerExport(filters, selection, signal),
|
|
1433
|
+
currentFilters,
|
|
1434
|
+
selection: (_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table),
|
|
1435
|
+
onProgress: handleExportProgressInternal,
|
|
1436
|
+
onComplete: onExportComplete,
|
|
1437
|
+
onError: onExportError,
|
|
1438
|
+
onStateChange: toStateChange,
|
|
1439
|
+
signal: controller.signal,
|
|
1440
|
+
chunkSize,
|
|
1441
|
+
strictTotalCheck,
|
|
1442
|
+
sanitizeCSV,
|
|
1443
|
+
});
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1191
1446
|
await (0, utils_1.exportClientData)(table, {
|
|
1192
1447
|
format: "excel",
|
|
1193
1448
|
filename,
|
|
1194
|
-
onProgress:
|
|
1449
|
+
onProgress: handleExportProgressInternal,
|
|
1195
1450
|
onComplete: onExportComplete,
|
|
1196
1451
|
onError: onExportError,
|
|
1452
|
+
onStateChange: toStateChange,
|
|
1453
|
+
signal: controller.signal,
|
|
1454
|
+
sanitizeCSV,
|
|
1197
1455
|
});
|
|
1198
1456
|
if (logger.isLevelEnabled("debug"))
|
|
1199
1457
|
logger.debug("Client export Excel", filename);
|
|
1200
1458
|
}
|
|
1201
|
-
}
|
|
1202
|
-
catch (error) {
|
|
1203
|
-
onExportError === null || onExportError === void 0 ? void 0 : onExportError({ message: error.message || "Export failed", code: "EXPORT_ERROR" });
|
|
1204
|
-
if (logger.isLevelEnabled("debug"))
|
|
1205
|
-
logger.debug("Server export Excel failed", error);
|
|
1206
|
-
}
|
|
1207
|
-
finally {
|
|
1208
|
-
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
|
|
1209
|
-
}
|
|
1459
|
+
});
|
|
1210
1460
|
},
|
|
1211
1461
|
exportServerData: async (options) => {
|
|
1212
|
-
|
|
1213
|
-
const { format, filename = exportFilename, fetchData: fetchFn = onServerExport } = options;
|
|
1462
|
+
const { format, filename = exportFilename, fetchData: fetchFn = onServerExport, chunkSize = exportChunkSize, strictTotalCheck = exportStrictTotalCheck, sanitizeCSV = exportSanitizeCSV, } = options;
|
|
1214
1463
|
if (!fetchFn) {
|
|
1215
1464
|
onExportError === null || onExportError === void 0 ? void 0 : onExportError({ message: "No server export function provided", code: "NO_SERVER_EXPORT" });
|
|
1216
1465
|
if (logger.isLevelEnabled("debug"))
|
|
1217
1466
|
logger.debug("Server export data failed", "No server export function provided");
|
|
1218
1467
|
return;
|
|
1219
1468
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1469
|
+
await runExportWithPolicy({
|
|
1470
|
+
format,
|
|
1471
|
+
filename,
|
|
1472
|
+
mode: 'server',
|
|
1473
|
+
execute: async (controller) => {
|
|
1474
|
+
var _a;
|
|
1475
|
+
const currentFilters = {
|
|
1476
|
+
globalFilter: table.getState().globalFilter,
|
|
1477
|
+
columnFilter: table.getState().columnFilter,
|
|
1478
|
+
sorting: table.getState().sorting,
|
|
1479
|
+
pagination: table.getState().pagination,
|
|
1480
|
+
};
|
|
1481
|
+
if (logger.isLevelEnabled("debug"))
|
|
1482
|
+
logger.debug("Server export data", { currentFilters });
|
|
1483
|
+
await (0, utils_1.exportServerData)(table, {
|
|
1484
|
+
format,
|
|
1485
|
+
filename,
|
|
1486
|
+
fetchData: (filters, selection, signal) => fetchFn(filters, selection, signal),
|
|
1487
|
+
currentFilters,
|
|
1488
|
+
selection: (_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table),
|
|
1489
|
+
onProgress: handleExportProgressInternal,
|
|
1490
|
+
onComplete: onExportComplete,
|
|
1491
|
+
onError: onExportError,
|
|
1492
|
+
onStateChange: (state) => {
|
|
1493
|
+
const isFinalPhase = state.phase === 'completed' || state.phase === 'cancelled' || state.phase === 'error';
|
|
1494
|
+
handleExportStateChangeInternal({
|
|
1495
|
+
phase: state.phase,
|
|
1496
|
+
mode: 'server',
|
|
1497
|
+
format,
|
|
1498
|
+
filename,
|
|
1499
|
+
processedRows: state.processedRows,
|
|
1500
|
+
totalRows: state.totalRows,
|
|
1501
|
+
percentage: state.percentage,
|
|
1502
|
+
message: state.message,
|
|
1503
|
+
code: state.code,
|
|
1504
|
+
startedAt: state.phase === 'starting' ? Date.now() : undefined,
|
|
1505
|
+
endedAt: isFinalPhase ? Date.now() : undefined,
|
|
1506
|
+
queueLength: queuedExportCount,
|
|
1507
|
+
});
|
|
1508
|
+
if (state.phase === 'cancelled') {
|
|
1509
|
+
onExportCancel === null || onExportCancel === void 0 ? void 0 : onExportCancel();
|
|
1510
|
+
}
|
|
1511
|
+
},
|
|
1512
|
+
signal: controller.signal,
|
|
1513
|
+
chunkSize,
|
|
1514
|
+
strictTotalCheck,
|
|
1515
|
+
sanitizeCSV,
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1250
1519
|
},
|
|
1251
1520
|
isExporting: () => isExporting || false,
|
|
1252
1521
|
cancelExport: () => {
|
|
1253
|
-
|
|
1254
|
-
|
|
1522
|
+
const activeController = exportControllerRef.current;
|
|
1523
|
+
if (!activeController) {
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
activeController.abort();
|
|
1527
|
+
setExportControllerSafely((current) => (current === activeController ? null : current));
|
|
1255
1528
|
if (logger.isLevelEnabled("debug"))
|
|
1256
1529
|
logger.debug("Export cancelled");
|
|
1257
1530
|
},
|
|
@@ -1272,17 +1545,26 @@ logging, }, ref) {
|
|
|
1272
1545
|
initialStateConfig,
|
|
1273
1546
|
enablePagination,
|
|
1274
1547
|
idKey,
|
|
1275
|
-
|
|
1276
|
-
|
|
1548
|
+
triggerRefresh,
|
|
1549
|
+
applyDataMutation,
|
|
1550
|
+
tableData,
|
|
1551
|
+
selectionState,
|
|
1277
1552
|
// export
|
|
1278
1553
|
exportFilename,
|
|
1279
|
-
|
|
1554
|
+
exportChunkSize,
|
|
1555
|
+
exportStrictTotalCheck,
|
|
1556
|
+
exportSanitizeCSV,
|
|
1280
1557
|
onExportComplete,
|
|
1281
1558
|
onExportError,
|
|
1559
|
+
onExportCancel,
|
|
1282
1560
|
onServerExport,
|
|
1283
|
-
|
|
1561
|
+
queuedExportCount,
|
|
1284
1562
|
isExporting,
|
|
1285
1563
|
dataMode,
|
|
1564
|
+
handleExportProgressInternal,
|
|
1565
|
+
handleExportStateChangeInternal,
|
|
1566
|
+
runExportWithPolicy,
|
|
1567
|
+
setExportControllerSafely,
|
|
1286
1568
|
logger,
|
|
1287
1569
|
resetAllAndReload,
|
|
1288
1570
|
]);
|
|
@@ -1343,14 +1625,12 @@ logging, }, ref) {
|
|
|
1343
1625
|
// Export cancel callback
|
|
1344
1626
|
// -------------------------------
|
|
1345
1627
|
const handleCancelExport = (0, react_1.useCallback)(() => {
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
onExportCancel();
|
|
1351
|
-
}
|
|
1628
|
+
const activeController = exportControllerRef.current;
|
|
1629
|
+
if (activeController) {
|
|
1630
|
+
activeController.abort();
|
|
1631
|
+
setExportControllerSafely((current) => (current === activeController ? null : current));
|
|
1352
1632
|
}
|
|
1353
|
-
}, [
|
|
1633
|
+
}, [setExportControllerSafely]);
|
|
1354
1634
|
// -------------------------------
|
|
1355
1635
|
// Slot components
|
|
1356
1636
|
// -------------------------------
|
|
@@ -1367,7 +1647,7 @@ logging, }, ref) {
|
|
|
1367
1647
|
// -------------------------------
|
|
1368
1648
|
return ((0, jsx_runtime_1.jsx)(data_table_context_1.DataTableProvider, { table: table, apiRef: internalApiRef, dataMode: dataMode, tableSize: tableSize, onTableSizeChange: (size) => {
|
|
1369
1649
|
setTableSize(size);
|
|
1370
|
-
}, columnFilter: columnFilter, onChangeColumnFilter: handleColumnFilterStateChange, slots: slots, slotProps: slotProps, isExporting: isExporting, exportController: exportController, onCancelExport: handleCancelExport, exportFilename: exportFilename, onExportProgress: onExportProgress, onExportComplete: onExportComplete, onExportError: onExportError, onServerExport: onServerExport, children: (0, jsx_runtime_1.jsxs)(RootComponent, { ...rootSlotProps, children: [(enableGlobalFilter || extraFilter) ? ((0, jsx_runtime_1.jsx)(ToolbarComponent, { extraFilter: extraFilter, enableGlobalFilter: enableGlobalFilter, enableColumnVisibility: enableColumnVisibility, enableColumnFilter: enableColumnFilter, enableExport: enableExport, enableReset: enableReset, enableTableSizeControl: enableTableSizeControl, enableColumnPinning: enableColumnPinning, enableRefresh: enableRefresh, ...toolbarSlotProps, refreshButtonProps: {
|
|
1650
|
+
}, columnFilter: columnFilter, onChangeColumnFilter: handleColumnFilterStateChange, slots: slots, slotProps: slotProps, isExporting: isExporting, exportController: exportController, exportPhase: exportPhase, exportProgress: exportProgress, onCancelExport: handleCancelExport, exportFilename: exportFilename, onExportProgress: onExportProgress, onExportComplete: onExportComplete, onExportError: onExportError, onServerExport: onServerExport, children: (0, jsx_runtime_1.jsxs)(RootComponent, { ...rootSlotProps, children: [(enableGlobalFilter || extraFilter) ? ((0, jsx_runtime_1.jsx)(ToolbarComponent, { extraFilter: extraFilter, enableGlobalFilter: enableGlobalFilter, enableColumnVisibility: enableColumnVisibility, enableColumnFilter: enableColumnFilter, enableExport: enableExport, enableReset: enableReset, enableTableSizeControl: enableTableSizeControl, enableColumnPinning: enableColumnPinning, enableRefresh: enableRefresh, ...toolbarSlotProps, refreshButtonProps: {
|
|
1371
1651
|
loading: tableLoading, // disable while fetching
|
|
1372
1652
|
showSpinnerWhileLoading: false,
|
|
1373
1653
|
onRefresh: () => { var _a, _b, _c; return (_c = (_b = (_a = internalApiRef.current) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.refresh) === null || _c === void 0 ? void 0 : _c.call(_b, true); },
|