@ackplus/react-tanstack-data-table 1.0.21 → 1.0.23
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 +36 -0
- package/package.json +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/lib/components/pagination/data-table-pagination.js +2 -4
- package/src/lib/components/table/data-table.js +216 -43
- package/src/lib/components/table/data-table.types.d.ts +4 -3
- package/src/lib/examples/advanced-features-example.js +5 -0
- package/src/lib/examples/server-side-fetching-example.js +9 -6
- package/src/lib/hooks/use-data-table-api.d.ts +2 -0
- package/src/lib/hooks/use-data-table-api.js +87 -1
- package/src/lib/utils/debounced-fetch.utils.js +0 -7
- package/src/lib/utils/index.d.ts +1 -0
- package/src/lib/utils/index.js +1 -0
- package/src/lib/utils/logger.d.ts +34 -0
- package/src/lib/utils/logger.js +106 -0
package/README.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
A powerful, feature-rich, and highly customizable React data table component built with Material-UI (MUI) and TanStack Table. Perfect for building modern data-intensive applications with advanced table functionality.
|
|
4
4
|
|
|
5
|
+
## 🚀 Live Demo
|
|
6
|
+
|
|
7
|
+
**[View Live Demo](https://ack-solutions.github.io/react-tanstack-data-table/)**
|
|
8
|
+
|
|
9
|
+
Experience all the features in action with our interactive demo showcasing advanced table functionality, filtering, sorting, pagination, and more.
|
|
10
|
+
|
|
5
11
|
## ✨ Features
|
|
6
12
|
|
|
7
13
|
- 🚀 **High Performance**: Built on TanStack Table for excellent performance with large datasets
|
|
@@ -18,6 +24,7 @@ A powerful, feature-rich, and highly customizable React data table component bui
|
|
|
18
24
|
- 🎛️ **Highly Customizable**: Extensive customization through slots and props
|
|
19
25
|
- 📝 **TypeScript**: Full TypeScript support with comprehensive type definitions
|
|
20
26
|
- 🔌 **Extensible**: Plugin architecture with custom components and hooks
|
|
27
|
+
- 🛠️ **Debug Logging**: Configurable console instrumentation with global or per-table controls
|
|
21
28
|
|
|
22
29
|
## 📦 Installation
|
|
23
30
|
|
|
@@ -1359,6 +1366,34 @@ const handleClick = useCallback(() => {
|
|
|
1359
1366
|
/>
|
|
1360
1367
|
```
|
|
1361
1368
|
|
|
1369
|
+
### Logging & Debugging
|
|
1370
|
+
|
|
1371
|
+
Use the built-in logger to trace pagination, server calls, and state transitions without sprinkling `console.log` statements throughout your app.
|
|
1372
|
+
|
|
1373
|
+
```tsx
|
|
1374
|
+
import { DataTable, configureDataTableLogging } from '@ackplus/react-tanstack-data-table';
|
|
1375
|
+
|
|
1376
|
+
configureDataTableLogging({
|
|
1377
|
+
enabled: true,
|
|
1378
|
+
level: 'debug',
|
|
1379
|
+
includeTimestamp: true,
|
|
1380
|
+
});
|
|
1381
|
+
|
|
1382
|
+
<DataTable
|
|
1383
|
+
columns={columns}
|
|
1384
|
+
data={rows}
|
|
1385
|
+
logging={{
|
|
1386
|
+
enabled: true,
|
|
1387
|
+
level: 'info',
|
|
1388
|
+
prefix: 'OrdersTable',
|
|
1389
|
+
}}
|
|
1390
|
+
/>
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
- Call `configureDataTableLogging` once (for example in your app bootstrap) to set global defaults.
|
|
1394
|
+
- Use the `logging` prop to override settings per table or disable instrumentation for specific instances.
|
|
1395
|
+
- When `logging` is omitted, instances inherit the global configuration.
|
|
1396
|
+
|
|
1362
1397
|
### Troubleshooting
|
|
1363
1398
|
|
|
1364
1399
|
#### Common Issues
|
|
@@ -1422,6 +1457,7 @@ MIT © [ACK Solutions](https://github.com/ack-solutions)
|
|
|
1422
1457
|
|
|
1423
1458
|
## 🆘 Support
|
|
1424
1459
|
|
|
1460
|
+
- 🚀 [Live Demo](https://ack-solutions.github.io/react-tanstack-data-table/) - Interactive examples and playground
|
|
1425
1461
|
- 📖 [Documentation](https://github.com/ack-solutions/react-tanstack-data-table)
|
|
1426
1462
|
- 🐛 [Issue Tracker](https://github.com/ack-solutions/react-tanstack-data-table/issues)
|
|
1427
1463
|
- 💬 [Discussions](https://github.com/ack-solutions/react-tanstack-data-table/discussions)
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type { BulkActionsToolbarProps } from './lib/components/toolbar';
|
|
|
10
10
|
export * from './lib/utils/styling-helpers';
|
|
11
11
|
export * from './lib/utils/column-helpers';
|
|
12
12
|
export * from './lib/utils/table-helpers';
|
|
13
|
+
export * from './lib/utils/logger';
|
|
13
14
|
export * from './lib/hooks';
|
|
14
15
|
export * from './lib/types';
|
|
15
16
|
export type { Column, ColumnDef, Row, Table, Header, Cell, SortingState, ColumnFiltersState, VisibilityState, ColumnOrderState, ColumnPinningState, PaginationState, } from '@tanstack/react-table';
|
package/src/index.js
CHANGED
|
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "DataTableToolbar", { enumerable: true, get: func
|
|
|
20
20
|
tslib_1.__exportStar(require("./lib/utils/styling-helpers"), exports);
|
|
21
21
|
tslib_1.__exportStar(require("./lib/utils/column-helpers"), exports);
|
|
22
22
|
tslib_1.__exportStar(require("./lib/utils/table-helpers"), exports);
|
|
23
|
+
tslib_1.__exportStar(require("./lib/utils/logger"), exports);
|
|
23
24
|
tslib_1.__exportStar(require("./lib/hooks"), exports);
|
|
24
25
|
tslib_1.__exportStar(require("./lib/types"), exports);
|
|
25
26
|
tslib_1.__exportStar(require("./lib/features"), exports);
|
|
@@ -10,8 +10,6 @@ const slot_helpers_1 = require("../../utils/slot-helpers");
|
|
|
10
10
|
exports.DataTablePagination = (0, react_1.memo)((props) => {
|
|
11
11
|
const { footerFilter = null, pagination, totalRow, containerSx, paginationProps, footerSx, slots, slotProps } = props, otherProps = tslib_1.__rest(props, ["footerFilter", "pagination", "totalRow", "containerSx", "paginationProps", "footerSx", "slots", "slotProps"]);
|
|
12
12
|
const { table } = (0, data_table_context_1.useDataTableContext)();
|
|
13
|
-
const paginationSlotProps = (0, slot_helpers_1.extractSlotProps)(slotProps, 'pagination');
|
|
14
|
-
const PaginationSlot = (0, slot_helpers_1.getSlotComponent)(slots, 'pagination', material_1.TablePagination);
|
|
15
13
|
const mergedContainerProps = (0, slot_helpers_1.mergeSlotProps)({
|
|
16
14
|
sx: Object.assign({ display: 'flex', alignItems: 'center', gap: 1, justifyContent: 'space-between', px: 2 }, containerSx),
|
|
17
15
|
});
|
|
@@ -32,6 +30,6 @@ exports.DataTablePagination = (0, react_1.memo)((props) => {
|
|
|
32
30
|
showLastButton: true,
|
|
33
31
|
labelRowsPerPage: 'Rows per page:',
|
|
34
32
|
labelDisplayedRows: ({ from, to, count }) => `${from}–${to} of ${count !== -1 ? count : `more than ${to}`}`,
|
|
35
|
-
},
|
|
36
|
-
return ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({}, mergedContainerProps, { children: [footerFilter && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: footerSx, children: footerFilter })), (0, jsx_runtime_1.jsx)(
|
|
33
|
+
}, Object.assign(Object.assign({}, paginationProps), otherProps));
|
|
34
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({}, mergedContainerProps, { children: [footerFilter && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: footerSx, children: footerFilter })), (0, jsx_runtime_1.jsx)(material_1.TablePagination, Object.assign({}, mergedPaginationProps))] })));
|
|
37
35
|
});
|
|
@@ -10,7 +10,6 @@ const features_1 = require("../../features");
|
|
|
10
10
|
const react_virtual_1 = require("@tanstack/react-virtual");
|
|
11
11
|
const react_1 = require("react");
|
|
12
12
|
const data_table_context_1 = require("../../contexts/data-table-context");
|
|
13
|
-
const use_data_table_api_1 = require("../../hooks/use-data-table-api");
|
|
14
13
|
const utils_1 = require("../../utils");
|
|
15
14
|
const debounced_fetch_utils_1 = require("../../utils/debounced-fetch.utils");
|
|
16
15
|
const slot_helpers_1 = require("../../utils/slot-helpers");
|
|
@@ -40,12 +39,31 @@ const DEFAULT_INITIAL_STATE = {
|
|
|
40
39
|
pendingLogic: 'AND',
|
|
41
40
|
},
|
|
42
41
|
};
|
|
43
|
-
exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, columns, data = [], totalRow = 0, idKey = 'id', extraFilter = null, footerFilter = null, dataMode = 'client', initialLoadData = true, onFetchData, onDataStateChange, enableRowSelection = false, enableMultiRowSelection = true, selectMode = 'page', isRowSelectable, onSelectionChange, enableBulkActions = false, bulkActions, enableColumnResizing = false, columnResizeMode = 'onChange', enableColumnDragging = false, onColumnDragEnd, enableColumnPinning = false, onColumnPinningChange, enableExpanding = false, getRowCanExpand, renderSubComponent, enablePagination = true, paginationMode = 'client', enableGlobalFilter = true, enableColumnFilter = false, filterMode = 'client', enableSorting = true, sortingMode = 'client', onSortingChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, onExportCancel, enableHover = true, enableStripes = false, tableContainerProps = {}, tableProps = {}, fitToScreen = true, tableSize: initialTableSize = 'medium', enableStickyHeaderOrFooter = false, maxHeight = '400px', enableVirtualization = false, estimateRowHeight = 52, enableColumnVisibility = true, enableTableSizeControl = true, enableExport = true, enableReset = true, loading = false, emptyMessage = 'No data available', skeletonRows = 5, onColumnFiltersChange, onPaginationChange, onGlobalFilterChange, slots = {}, slotProps = {}, }, ref) {
|
|
42
|
+
exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, columns, data = [], totalRow = 0, idKey = 'id', extraFilter = null, footerFilter = null, dataMode = 'client', initialLoadData = true, onFetchData, onDataStateChange, enableRowSelection = false, enableMultiRowSelection = true, selectMode = 'page', isRowSelectable, onSelectionChange, enableBulkActions = false, bulkActions, enableColumnResizing = false, columnResizeMode = 'onChange', enableColumnDragging = false, onColumnDragEnd, enableColumnPinning = false, onColumnPinningChange, enableExpanding = false, getRowCanExpand, renderSubComponent, enablePagination = true, paginationMode = 'client', enableGlobalFilter = true, enableColumnFilter = false, filterMode = 'client', enableSorting = true, sortingMode = 'client', onSortingChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, onExportCancel, enableHover = true, enableStripes = false, tableContainerProps = {}, tableProps = {}, fitToScreen = true, tableSize: initialTableSize = 'medium', enableStickyHeaderOrFooter = false, maxHeight = '400px', enableVirtualization = false, estimateRowHeight = 52, enableColumnVisibility = true, enableTableSizeControl = true, enableExport = true, enableReset = true, loading = false, emptyMessage = 'No data available', skeletonRows = 5, onColumnFiltersChange, onPaginationChange, onGlobalFilterChange, slots = {}, slotProps = {}, logging, }, ref) {
|
|
44
43
|
var _a;
|
|
45
44
|
const isServerMode = dataMode === 'server';
|
|
46
45
|
const isServerPagination = paginationMode === 'server' || isServerMode;
|
|
47
46
|
const isServerFiltering = filterMode === 'server' || isServerMode;
|
|
48
47
|
const isServerSorting = sortingMode === 'server' || isServerMode;
|
|
48
|
+
const logger = (0, react_1.useMemo)(() => (0, utils_1.createLogger)('DataTable', logging), [logging]);
|
|
49
|
+
const fetchLogger = (0, react_1.useMemo)(() => logger.child('fetch'), [logger]);
|
|
50
|
+
const paginationLogger = (0, react_1.useMemo)(() => logger.child('pagination'), [logger]);
|
|
51
|
+
const stateLogger = (0, react_1.useMemo)(() => logger.child('state'), [logger]);
|
|
52
|
+
(0, react_1.useEffect)(() => {
|
|
53
|
+
if (logger.isLevelEnabled('info')) {
|
|
54
|
+
logger.info('mounted', {
|
|
55
|
+
dataMode,
|
|
56
|
+
paginationMode,
|
|
57
|
+
filterMode,
|
|
58
|
+
sortingMode,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return () => {
|
|
62
|
+
if (logger.isLevelEnabled('info')) {
|
|
63
|
+
logger.info('unmounted');
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}, [logger, dataMode, paginationMode, filterMode, sortingMode]);
|
|
49
67
|
const initialStateConfig = (0, react_1.useMemo)(() => {
|
|
50
68
|
return Object.assign(Object.assign({}, DEFAULT_INITIAL_STATE), initialState);
|
|
51
69
|
}, [initialState]);
|
|
@@ -124,16 +142,40 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
124
142
|
minWidth: '100%',
|
|
125
143
|
}), [tableWidth]);
|
|
126
144
|
const fetchData = (0, react_1.useCallback)((...args_1) => tslib_1.__awaiter(this, [...args_1], void 0, function* (overrides = {}) {
|
|
127
|
-
|
|
145
|
+
var _a, _b;
|
|
146
|
+
if (!onFetchData) {
|
|
147
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
148
|
+
fetchLogger.debug('onFetchData not provided, skipping fetch', { overrides });
|
|
149
|
+
}
|
|
128
150
|
return;
|
|
151
|
+
}
|
|
129
152
|
const filters = Object.assign({ globalFilter,
|
|
130
153
|
pagination,
|
|
131
154
|
columnFilter,
|
|
132
155
|
sorting }, overrides);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
156
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
157
|
+
fetchLogger.debug('Requesting data', { filters });
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const result = yield debouncedFetch(filters);
|
|
161
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
162
|
+
fetchLogger.debug('Fetch resolved', {
|
|
163
|
+
rows: (_b = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
|
|
164
|
+
total: result === null || result === void 0 ? void 0 : result.total,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if ((result === null || result === void 0 ? void 0 : result.data) && (result === null || result === void 0 ? void 0 : result.total) !== undefined) {
|
|
168
|
+
setServerData(result.data);
|
|
169
|
+
setServerTotal(result.total);
|
|
170
|
+
}
|
|
171
|
+
else if (fetchLogger.isLevelEnabled('warn')) {
|
|
172
|
+
fetchLogger.warn('Fetch handler returned unexpected shape', result);
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
fetchLogger.error('Fetch failed', error);
|
|
178
|
+
throw error;
|
|
137
179
|
}
|
|
138
180
|
}), [
|
|
139
181
|
onFetchData,
|
|
@@ -142,6 +184,7 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
142
184
|
columnFilter,
|
|
143
185
|
sorting,
|
|
144
186
|
debouncedFetch,
|
|
187
|
+
fetchLogger,
|
|
145
188
|
]);
|
|
146
189
|
const handleSelectionStateChange = (0, react_1.useCallback)((updaterOrValue) => {
|
|
147
190
|
setSelectionState((prevState) => {
|
|
@@ -162,15 +205,22 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
162
205
|
}
|
|
163
206
|
}, [onColumnFiltersChange]);
|
|
164
207
|
const tableStateChange = (0, react_1.useCallback)((overrides = {}) => {
|
|
165
|
-
if (onDataStateChange) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
columnOrder,
|
|
171
|
-
columnPinning }, overrides);
|
|
172
|
-
onDataStateChange(currentState);
|
|
208
|
+
if (!onDataStateChange) {
|
|
209
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
210
|
+
stateLogger.debug('No onDataStateChange handler registered; skipping state update notification', { overrides });
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
173
213
|
}
|
|
214
|
+
const currentState = Object.assign({ globalFilter,
|
|
215
|
+
columnFilter,
|
|
216
|
+
sorting,
|
|
217
|
+
pagination,
|
|
218
|
+
columnOrder,
|
|
219
|
+
columnPinning }, overrides);
|
|
220
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
221
|
+
stateLogger.debug('Emitting tableStateChange', currentState);
|
|
222
|
+
}
|
|
223
|
+
onDataStateChange(currentState);
|
|
174
224
|
}, [
|
|
175
225
|
onDataStateChange,
|
|
176
226
|
globalFilter,
|
|
@@ -179,6 +229,7 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
179
229
|
pagination,
|
|
180
230
|
columnOrder,
|
|
181
231
|
columnPinning,
|
|
232
|
+
stateLogger,
|
|
182
233
|
]);
|
|
183
234
|
const handleSortingChange = (0, react_1.useCallback)((updaterOrValue) => {
|
|
184
235
|
let newSorting = typeof updaterOrValue === 'function'
|
|
@@ -187,8 +238,18 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
187
238
|
newSorting = newSorting.filter((sort) => sort.id);
|
|
188
239
|
setSorting(newSorting);
|
|
189
240
|
onSortingChange === null || onSortingChange === void 0 ? void 0 : onSortingChange(newSorting);
|
|
241
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
242
|
+
stateLogger.debug('Sorting change applied', {
|
|
243
|
+
sorting: newSorting,
|
|
244
|
+
serverMode: isServerMode,
|
|
245
|
+
serverSorting: isServerSorting,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
190
248
|
if (isServerMode || isServerSorting) {
|
|
191
249
|
const pagination = resetPageToFirst();
|
|
250
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
251
|
+
stateLogger.debug('Sorting change triggered server fetch', { pagination, sorting: newSorting });
|
|
252
|
+
}
|
|
192
253
|
tableStateChange({ sorting: newSorting, pagination });
|
|
193
254
|
fetchData({
|
|
194
255
|
sorting: newSorting,
|
|
@@ -198,6 +259,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
198
259
|
else if (onDataStateChange) {
|
|
199
260
|
const pagination = resetPageToFirst();
|
|
200
261
|
setTimeout(() => {
|
|
262
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
263
|
+
stateLogger.debug('Sorting change notified client state change', { pagination, sorting: newSorting });
|
|
264
|
+
}
|
|
201
265
|
tableStateChange({ sorting: newSorting, pagination });
|
|
202
266
|
}, 0);
|
|
203
267
|
}
|
|
@@ -209,6 +273,7 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
209
273
|
isServerSorting,
|
|
210
274
|
onDataStateChange,
|
|
211
275
|
tableStateChange,
|
|
276
|
+
stateLogger,
|
|
212
277
|
]);
|
|
213
278
|
const handleColumnOrderChange = (0, react_1.useCallback)((updatedColumnOrder) => {
|
|
214
279
|
const newColumnOrder = typeof updatedColumnOrder === 'function'
|
|
@@ -229,30 +294,67 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
229
294
|
}
|
|
230
295
|
}, [onColumnPinningChange, columnPinning]);
|
|
231
296
|
const handlePaginationChange = (0, react_1.useCallback)((updater) => {
|
|
232
|
-
setPagination(updater);
|
|
233
297
|
const newPagination = typeof updater === 'function' ? updater(pagination) : updater;
|
|
298
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
299
|
+
paginationLogger.debug('Pagination change requested', {
|
|
300
|
+
previous: pagination,
|
|
301
|
+
next: newPagination,
|
|
302
|
+
serverSide: isServerMode || isServerPagination,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
setPagination(newPagination);
|
|
306
|
+
onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(newPagination);
|
|
307
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
308
|
+
paginationLogger.debug('Pagination state updated', newPagination);
|
|
309
|
+
}
|
|
234
310
|
if (isServerMode || isServerPagination) {
|
|
235
311
|
setTimeout(() => {
|
|
312
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
313
|
+
paginationLogger.debug('Notifying server-side pagination change', newPagination);
|
|
314
|
+
}
|
|
236
315
|
tableStateChange({ pagination: newPagination });
|
|
237
316
|
fetchData({ pagination: newPagination });
|
|
238
317
|
}, 0);
|
|
239
318
|
}
|
|
240
319
|
else if (onDataStateChange) {
|
|
241
320
|
setTimeout(() => {
|
|
321
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
322
|
+
paginationLogger.debug('Notifying client-side pagination change', newPagination);
|
|
323
|
+
}
|
|
242
324
|
tableStateChange({ pagination: newPagination });
|
|
243
325
|
}, 0);
|
|
244
326
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
327
|
+
}, [
|
|
328
|
+
pagination,
|
|
329
|
+
isServerMode,
|
|
330
|
+
isServerPagination,
|
|
331
|
+
onDataStateChange,
|
|
332
|
+
fetchData,
|
|
333
|
+
tableStateChange,
|
|
334
|
+
paginationLogger,
|
|
335
|
+
onPaginationChange,
|
|
336
|
+
]);
|
|
248
337
|
const handleGlobalFilterChange = (0, react_1.useCallback)((updaterOrValue) => {
|
|
249
338
|
const newFilter = typeof updaterOrValue === 'function'
|
|
250
339
|
? updaterOrValue(globalFilter)
|
|
251
340
|
: updaterOrValue;
|
|
252
341
|
setGlobalFilter(newFilter);
|
|
342
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
343
|
+
stateLogger.debug('Global filter change applied', {
|
|
344
|
+
value: newFilter,
|
|
345
|
+
serverMode: isServerMode,
|
|
346
|
+
serverFiltering: isServerFiltering,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
253
349
|
if (isServerMode || isServerFiltering) {
|
|
254
350
|
const pagination = resetPageToFirst();
|
|
255
351
|
setTimeout(() => {
|
|
352
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
353
|
+
stateLogger.debug('Global filter change triggering server fetch', {
|
|
354
|
+
pagination,
|
|
355
|
+
value: newFilter,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
256
358
|
tableStateChange({ globalFilter: newFilter, pagination });
|
|
257
359
|
fetchData({ globalFilter: newFilter, pagination });
|
|
258
360
|
}, 0);
|
|
@@ -260,11 +362,17 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
260
362
|
else if (onDataStateChange) {
|
|
261
363
|
const pagination = resetPageToFirst();
|
|
262
364
|
setTimeout(() => {
|
|
365
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
366
|
+
stateLogger.debug('Global filter change notifying client listeners', {
|
|
367
|
+
pagination,
|
|
368
|
+
value: newFilter,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
263
371
|
tableStateChange({ globalFilter: newFilter, pagination });
|
|
264
372
|
}, 0);
|
|
265
373
|
}
|
|
266
374
|
onGlobalFilterChange === null || onGlobalFilterChange === void 0 ? void 0 : onGlobalFilterChange(newFilter);
|
|
267
|
-
}, [globalFilter, isServerMode, isServerFiltering, onDataStateChange, fetchData, tableStateChange]);
|
|
375
|
+
}, [globalFilter, isServerMode, isServerFiltering, onDataStateChange, fetchData, tableStateChange, stateLogger]);
|
|
268
376
|
const onColumnFilterChangeHandler = (0, react_1.useCallback)((updater) => {
|
|
269
377
|
const currentState = columnFilter;
|
|
270
378
|
const newState = typeof updater === 'function'
|
|
@@ -312,6 +420,12 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
312
420
|
enabled: enableVirtualization && !enablePagination && rows.length > 0,
|
|
313
421
|
});
|
|
314
422
|
const resetPageToFirst = () => {
|
|
423
|
+
if (paginationLogger.isLevelEnabled('info')) {
|
|
424
|
+
paginationLogger.info('Resetting to first page due to state change', {
|
|
425
|
+
previousPageIndex: pagination.pageIndex,
|
|
426
|
+
pageSize: pagination.pageSize,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
315
429
|
const newPagination = { pageIndex: 0, pageSize: pagination.pageSize };
|
|
316
430
|
setPagination(newPagination);
|
|
317
431
|
onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(newPagination);
|
|
@@ -355,29 +469,6 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
355
469
|
setColumnOrder(initialOrder);
|
|
356
470
|
}
|
|
357
471
|
}, [enableColumnDragging, enhancedColumns, columnOrder.length]);
|
|
358
|
-
(0, use_data_table_api_1.useDataTableApi)({
|
|
359
|
-
table,
|
|
360
|
-
idKey,
|
|
361
|
-
enhancedColumns,
|
|
362
|
-
enablePagination,
|
|
363
|
-
enableColumnPinning,
|
|
364
|
-
initialStateConfig: Object.assign(Object.assign({}, DEFAULT_INITIAL_STATE), initialState),
|
|
365
|
-
selectMode,
|
|
366
|
-
onSelectionChange: handleSelectionStateChange,
|
|
367
|
-
handleColumnFilterStateChange,
|
|
368
|
-
onDataStateChange,
|
|
369
|
-
onFetchData: fetchData,
|
|
370
|
-
exportFilename,
|
|
371
|
-
onExportProgress,
|
|
372
|
-
onExportComplete,
|
|
373
|
-
onExportError,
|
|
374
|
-
onServerExport,
|
|
375
|
-
exportController,
|
|
376
|
-
setExportController,
|
|
377
|
-
isExporting,
|
|
378
|
-
onDataChange: setServerData,
|
|
379
|
-
dataMode,
|
|
380
|
-
}, internalApiRef);
|
|
381
472
|
(0, react_1.useImperativeHandle)(ref, () => internalApiRef.current, []);
|
|
382
473
|
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
383
474
|
table: {
|
|
@@ -505,6 +596,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
505
596
|
pendingFilters: columnFilter.pendingFilters || [],
|
|
506
597
|
pendingLogic: columnFilter.pendingLogic || 'AND',
|
|
507
598
|
});
|
|
599
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
600
|
+
stateLogger.debug(`Adding column filter ${columnId} ${operator} ${value}`, newFilters);
|
|
601
|
+
}
|
|
508
602
|
},
|
|
509
603
|
removeColumnFilter: (filterId) => {
|
|
510
604
|
const columnFilter = table.getState().columnFilter;
|
|
@@ -516,6 +610,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
516
610
|
pendingFilters: columnFilter.pendingFilters || [],
|
|
517
611
|
pendingLogic: columnFilter.pendingLogic || 'AND',
|
|
518
612
|
});
|
|
613
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
614
|
+
stateLogger.debug(`Removing column filter ${filterId}`, newFilters);
|
|
615
|
+
}
|
|
519
616
|
},
|
|
520
617
|
clearAllFilters: () => {
|
|
521
618
|
table.setGlobalFilter('');
|
|
@@ -534,11 +631,17 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
534
631
|
pendingFilters: [],
|
|
535
632
|
pendingLogic: 'AND',
|
|
536
633
|
});
|
|
634
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
635
|
+
stateLogger.debug('Resetting filters');
|
|
636
|
+
}
|
|
537
637
|
},
|
|
538
638
|
},
|
|
539
639
|
sorting: {
|
|
540
640
|
setSorting: (sortingState) => {
|
|
541
641
|
table.setSorting(sortingState);
|
|
642
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
643
|
+
stateLogger.debug(`Setting sorting`, sortingState);
|
|
644
|
+
}
|
|
542
645
|
},
|
|
543
646
|
sortColumn: (columnId, direction) => {
|
|
544
647
|
const column = table.getColumn(columnId);
|
|
@@ -561,23 +664,41 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
561
664
|
pagination: {
|
|
562
665
|
goToPage: (pageIndex) => {
|
|
563
666
|
table.setPageIndex(pageIndex);
|
|
667
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
668
|
+
paginationLogger.debug(`Going to page ${pageIndex}`);
|
|
669
|
+
}
|
|
564
670
|
},
|
|
565
671
|
nextPage: () => {
|
|
566
672
|
table.nextPage();
|
|
673
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
674
|
+
paginationLogger.debug('Next page');
|
|
675
|
+
}
|
|
567
676
|
},
|
|
568
677
|
previousPage: () => {
|
|
569
678
|
table.previousPage();
|
|
679
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
680
|
+
paginationLogger.debug('Previous page');
|
|
681
|
+
}
|
|
570
682
|
},
|
|
571
683
|
setPageSize: (pageSize) => {
|
|
572
684
|
table.setPageSize(pageSize);
|
|
685
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
686
|
+
paginationLogger.debug(`Setting page size to ${pageSize}`);
|
|
687
|
+
}
|
|
573
688
|
},
|
|
574
689
|
goToFirstPage: () => {
|
|
575
690
|
table.setPageIndex(0);
|
|
691
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
692
|
+
paginationLogger.debug('Going to first page');
|
|
693
|
+
}
|
|
576
694
|
},
|
|
577
695
|
goToLastPage: () => {
|
|
578
696
|
const pageCount = table.getPageCount();
|
|
579
697
|
if (pageCount > 0) {
|
|
580
698
|
table.setPageIndex(pageCount - 1);
|
|
699
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
700
|
+
paginationLogger.debug(`Going to last page ${pageCount - 1}`);
|
|
701
|
+
}
|
|
581
702
|
}
|
|
582
703
|
},
|
|
583
704
|
},
|
|
@@ -602,13 +723,20 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
602
723
|
pageSize: ((_a = filters.pagination) === null || _a === void 0 ? void 0 : _a.pageSize) || ((_b = initialStateConfig.pagination) === null || _b === void 0 ? void 0 : _b.pageSize) || 10,
|
|
603
724
|
};
|
|
604
725
|
const allState = table.getState();
|
|
726
|
+
setPagination(pagination);
|
|
605
727
|
onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
|
|
606
728
|
fetchData === null || fetchData === void 0 ? void 0 : fetchData({ pagination });
|
|
729
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
730
|
+
fetchLogger.debug('Refreshing data', { pagination, allState });
|
|
731
|
+
}
|
|
607
732
|
},
|
|
608
733
|
reload: () => {
|
|
609
734
|
const allState = table.getState();
|
|
610
735
|
onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
|
|
611
736
|
onFetchData === null || onFetchData === void 0 ? void 0 : onFetchData({});
|
|
737
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
738
|
+
fetchLogger.debug('Reloading data', allState);
|
|
739
|
+
}
|
|
612
740
|
},
|
|
613
741
|
getAllData: () => {
|
|
614
742
|
var _a;
|
|
@@ -627,6 +755,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
627
755
|
const newData = (_a = table.getRowModel().rows) === null || _a === void 0 ? void 0 : _a.map(row => String(row.original[idKey]) === rowId
|
|
628
756
|
? Object.assign(Object.assign({}, row.original), updates) : row.original);
|
|
629
757
|
setServerData === null || setServerData === void 0 ? void 0 : setServerData(newData || []);
|
|
758
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
759
|
+
fetchLogger.debug(`Updating row ${rowId}`, updates);
|
|
760
|
+
}
|
|
630
761
|
},
|
|
631
762
|
updateRowByIndex: (index, updates) => {
|
|
632
763
|
var _a;
|
|
@@ -634,6 +765,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
634
765
|
if (newData === null || newData === void 0 ? void 0 : newData[index]) {
|
|
635
766
|
newData[index] = Object.assign(Object.assign({}, newData[index]), updates);
|
|
636
767
|
setServerData(newData);
|
|
768
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
769
|
+
fetchLogger.debug(`Updating row by index ${index}`, updates);
|
|
770
|
+
}
|
|
637
771
|
}
|
|
638
772
|
},
|
|
639
773
|
insertRow: (newRow, index) => {
|
|
@@ -646,17 +780,26 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
646
780
|
newData.push(newRow);
|
|
647
781
|
}
|
|
648
782
|
setServerData(newData || []);
|
|
783
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
784
|
+
fetchLogger.debug(`Inserting row`, newRow);
|
|
785
|
+
}
|
|
649
786
|
},
|
|
650
787
|
deleteRow: (rowId) => {
|
|
651
788
|
var _a;
|
|
652
789
|
const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => String(row.original[idKey]) !== rowId);
|
|
653
790
|
setServerData === null || setServerData === void 0 ? void 0 : setServerData((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
|
|
791
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
792
|
+
fetchLogger.debug(`Deleting row ${rowId}`);
|
|
793
|
+
}
|
|
654
794
|
},
|
|
655
795
|
deleteRowByIndex: (index) => {
|
|
656
796
|
var _a;
|
|
657
797
|
const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.map(row => row.original);
|
|
658
798
|
newData.splice(index, 1);
|
|
659
799
|
setServerData(newData);
|
|
800
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
801
|
+
fetchLogger.debug(`Deleting row by index ${index}`);
|
|
802
|
+
}
|
|
660
803
|
},
|
|
661
804
|
deleteSelectedRows: () => {
|
|
662
805
|
var _a;
|
|
@@ -665,6 +808,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
665
808
|
const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => !selectedRowIds.includes(String(row.original[idKey])));
|
|
666
809
|
setServerData((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
|
|
667
810
|
table.resetRowSelection();
|
|
811
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
812
|
+
fetchLogger.debug('Deleting selected rows');
|
|
813
|
+
}
|
|
668
814
|
},
|
|
669
815
|
replaceAllData: (newData) => {
|
|
670
816
|
setServerData === null || setServerData === void 0 ? void 0 : setServerData(newData);
|
|
@@ -821,6 +967,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
821
967
|
sorting: table.getState().sorting,
|
|
822
968
|
pagination: table.getState().pagination,
|
|
823
969
|
};
|
|
970
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
971
|
+
stateLogger.debug('Server export CSV', { currentFilters });
|
|
972
|
+
}
|
|
824
973
|
yield (0, utils_1.exportServerData)(table, {
|
|
825
974
|
format: 'csv',
|
|
826
975
|
filename,
|
|
@@ -840,6 +989,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
840
989
|
onComplete: onExportComplete,
|
|
841
990
|
onError: onExportError,
|
|
842
991
|
});
|
|
992
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
993
|
+
stateLogger.debug('Client export CSV', filename);
|
|
994
|
+
}
|
|
843
995
|
}
|
|
844
996
|
}
|
|
845
997
|
catch (error) {
|
|
@@ -865,6 +1017,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
865
1017
|
sorting: table.getState().sorting,
|
|
866
1018
|
pagination: table.getState().pagination,
|
|
867
1019
|
};
|
|
1020
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
1021
|
+
stateLogger.debug('Server export Excel', { currentFilters });
|
|
1022
|
+
}
|
|
868
1023
|
yield (0, utils_1.exportServerData)(table, {
|
|
869
1024
|
format: 'excel',
|
|
870
1025
|
filename,
|
|
@@ -884,6 +1039,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
884
1039
|
onComplete: onExportComplete,
|
|
885
1040
|
onError: onExportError,
|
|
886
1041
|
});
|
|
1042
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
1043
|
+
stateLogger.debug('Client export Excel', filename);
|
|
1044
|
+
}
|
|
887
1045
|
}
|
|
888
1046
|
}
|
|
889
1047
|
catch (error) {
|
|
@@ -891,6 +1049,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
891
1049
|
message: error.message || 'Export failed',
|
|
892
1050
|
code: 'EXPORT_ERROR',
|
|
893
1051
|
});
|
|
1052
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
1053
|
+
stateLogger.debug('Server export Excel failed', error);
|
|
1054
|
+
}
|
|
894
1055
|
}
|
|
895
1056
|
finally {
|
|
896
1057
|
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
|
|
@@ -904,6 +1065,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
904
1065
|
message: 'No server export function provided',
|
|
905
1066
|
code: 'NO_SERVER_EXPORT',
|
|
906
1067
|
});
|
|
1068
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
1069
|
+
stateLogger.debug('Server export data failed', 'No server export function provided');
|
|
1070
|
+
}
|
|
907
1071
|
return;
|
|
908
1072
|
}
|
|
909
1073
|
try {
|
|
@@ -915,6 +1079,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
915
1079
|
sorting: table.getState().sorting,
|
|
916
1080
|
pagination: table.getState().pagination,
|
|
917
1081
|
};
|
|
1082
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
1083
|
+
stateLogger.debug('Server export data', { currentFilters });
|
|
1084
|
+
}
|
|
918
1085
|
yield (0, utils_1.exportServerData)(table, {
|
|
919
1086
|
format,
|
|
920
1087
|
filename,
|
|
@@ -931,6 +1098,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
931
1098
|
message: error.message || 'Export failed',
|
|
932
1099
|
code: 'EXPORT_ERROR',
|
|
933
1100
|
});
|
|
1101
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
1102
|
+
stateLogger.debug('Server export data failed', error);
|
|
1103
|
+
}
|
|
934
1104
|
}
|
|
935
1105
|
finally {
|
|
936
1106
|
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
|
|
@@ -940,6 +1110,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
940
1110
|
cancelExport: () => {
|
|
941
1111
|
exportController === null || exportController === void 0 ? void 0 : exportController.abort();
|
|
942
1112
|
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
|
|
1113
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
1114
|
+
stateLogger.debug('Export cancelled');
|
|
1115
|
+
}
|
|
943
1116
|
},
|
|
944
1117
|
},
|
|
945
1118
|
}), [
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Row, SortingState, ColumnResizeMode, ColumnPinningState, RowData, PaginationState } from '@tanstack/react-table';
|
|
1
|
+
import { Row, SortingState, ColumnResizeMode, ColumnPinningState, RowData, PaginationState, ColumnDef } from '@tanstack/react-table';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import type { ColumnFilterState, TableFilters, TableState } from '../../types';
|
|
4
|
-
import { DataTableColumn } from '../../types';
|
|
5
4
|
import { DataTableSlots, PartialSlotProps } from '../../types/slots.types';
|
|
6
5
|
import { DataTableSize } from '../../utils/table-helpers';
|
|
7
6
|
import { SelectionState } from '../../features';
|
|
7
|
+
import { DataTableLoggingOptions } from '../../utils/logger';
|
|
8
8
|
export type SelectMode = 'page' | 'all';
|
|
9
9
|
declare module '@tanstack/table-core' {
|
|
10
10
|
interface ColumnMeta<TData extends RowData, TValue> {
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
export interface DataTableProps<T> {
|
|
14
|
-
columns:
|
|
14
|
+
columns: ColumnDef<T, any>[];
|
|
15
15
|
data?: T[];
|
|
16
16
|
totalRow?: number;
|
|
17
17
|
idKey?: keyof T;
|
|
@@ -95,4 +95,5 @@ export interface DataTableProps<T> {
|
|
|
95
95
|
onColumnFilterChange?: (columnFilter: ColumnFilterState) => void;
|
|
96
96
|
slots?: Partial<DataTableSlots<T>>;
|
|
97
97
|
slotProps?: PartialSlotProps<T>;
|
|
98
|
+
logging?: boolean | DataTableLoggingOptions;
|
|
98
99
|
}
|
|
@@ -6,6 +6,7 @@ const react_1 = require("react");
|
|
|
6
6
|
const material_1 = require("@mui/material");
|
|
7
7
|
const icons_material_1 = require("@mui/icons-material");
|
|
8
8
|
const components_1 = require("../components");
|
|
9
|
+
const types_1 = require("../types");
|
|
9
10
|
const generateEmployeeData = () => {
|
|
10
11
|
const departments = [
|
|
11
12
|
{ id: 1, name: 'Engineering', color: '#2196F3' },
|
|
@@ -218,6 +219,10 @@ function AdvancedFeaturesExample() {
|
|
|
218
219
|
pageIndex: 0,
|
|
219
220
|
pageSize: 10,
|
|
220
221
|
},
|
|
222
|
+
columnPinning: {
|
|
223
|
+
left: [types_1.DEFAULT_SELECTION_COLUMN_NAME],
|
|
224
|
+
right: ['actions'],
|
|
225
|
+
},
|
|
221
226
|
columnOrder: ['name', 'department.name', 'salary', 'performance.rating', 'skills'],
|
|
222
227
|
}, tableContainerProps: {
|
|
223
228
|
sx: {
|
|
@@ -35,7 +35,7 @@ function ServerSideFetchingExample() {
|
|
|
35
35
|
const apiRef = (0, react_1.useRef)(null);
|
|
36
36
|
const handleFetchData = (0, react_1.useCallback)((filters) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
37
37
|
var _a, _b, _c;
|
|
38
|
-
console.log('🔄
|
|
38
|
+
console.log('🔄 handleFetchData', { filters });
|
|
39
39
|
setLoading(true);
|
|
40
40
|
setError(null);
|
|
41
41
|
setLastFetchParams(filters);
|
|
@@ -114,13 +114,12 @@ function ServerSideFetchingExample() {
|
|
|
114
114
|
}
|
|
115
115
|
}), [tab]);
|
|
116
116
|
const handleSelectionChange = (0, react_1.useCallback)((selection) => {
|
|
117
|
-
console.log('🔄 Selection changed:', selection);
|
|
118
117
|
setSelectionInfo(selection);
|
|
119
118
|
}, []);
|
|
120
119
|
(0, react_1.useEffect)(() => {
|
|
121
120
|
var _a;
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
if (tab) {
|
|
122
|
+
console.log('🔄 Refreshing data');
|
|
124
123
|
(_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.data.refresh();
|
|
125
124
|
}
|
|
126
125
|
}, [tab]);
|
|
@@ -233,7 +232,7 @@ function ServerSideFetchingExample() {
|
|
|
233
232
|
}, children: "Update Selected" })] })), enableGlobalFilter: true, enableColumnFilter: true, enableSorting: true, enablePagination: true, initialState: {
|
|
234
233
|
pagination: {
|
|
235
234
|
pageIndex: 0,
|
|
236
|
-
pageSize:
|
|
235
|
+
pageSize: 50,
|
|
237
236
|
},
|
|
238
237
|
columnPinning: {
|
|
239
238
|
left: [types_1.DEFAULT_SELECTION_COLUMN_NAME],
|
|
@@ -245,5 +244,9 @@ function ServerSideFetchingExample() {
|
|
|
245
244
|
console.log('Export completed:', result);
|
|
246
245
|
}, onExportError: (error) => {
|
|
247
246
|
console.error('Export error:', error);
|
|
248
|
-
}, enableHover: true, enableStripes: true, tableSize: "medium", enableColumnVisibility: true, enableTableSizeControl: true, enableReset: true, emptyMessage: "No employees found matching your criteria", skeletonRows: 10
|
|
247
|
+
}, enableHover: true, enableStripes: true, tableSize: "medium", enableColumnVisibility: true, enableTableSizeControl: true, enableReset: true, emptyMessage: "No employees found matching your criteria", skeletonRows: 10, slotProps: {
|
|
248
|
+
pagination: {
|
|
249
|
+
rowsPerPageOptions: [5, 10, 20, 50, 100, 200],
|
|
250
|
+
},
|
|
251
|
+
} })] }));
|
|
249
252
|
}
|
|
@@ -3,6 +3,7 @@ import { Ref } from 'react';
|
|
|
3
3
|
import { ColumnFilterState, TableFilters, TableState } from '../types';
|
|
4
4
|
import { DataTableApi } from '../types/data-table-api';
|
|
5
5
|
import { SelectionState } from '../features';
|
|
6
|
+
import { DataTableLoggingOptions } from '../utils/logger';
|
|
6
7
|
interface UseDataTableApiProps<T> {
|
|
7
8
|
table: Table<T>;
|
|
8
9
|
idKey: keyof T;
|
|
@@ -39,6 +40,7 @@ interface UseDataTableApiProps<T> {
|
|
|
39
40
|
setExportController?: (controller: AbortController | null) => void;
|
|
40
41
|
isExporting?: boolean;
|
|
41
42
|
dataMode?: 'client' | 'server';
|
|
43
|
+
logging?: boolean | DataTableLoggingOptions;
|
|
42
44
|
}
|
|
43
45
|
export declare function useDataTableApi<T extends Record<string, any>>(props: UseDataTableApiProps<T>, ref: Ref<DataTableApi<T>>): void;
|
|
44
46
|
export {};
|
|
@@ -4,8 +4,13 @@ exports.useDataTableApi = useDataTableApi;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const export_utils_1 = require("../utils/export-utils");
|
|
7
|
+
const logger_1 = require("../utils/logger");
|
|
7
8
|
function useDataTableApi(props, ref) {
|
|
8
|
-
const { table, idKey, enhancedColumns, enablePagination, enableColumnPinning, initialStateConfig, selectMode = 'page', onSelectionChange, handleColumnFilterStateChange, onDataStateChange, onFetchData, onDataChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, exportController, setExportController, isExporting, dataMode = 'client', } = props;
|
|
9
|
+
const { table, idKey, enhancedColumns, enablePagination, enableColumnPinning, initialStateConfig, selectMode = 'page', onSelectionChange, handleColumnFilterStateChange, onDataStateChange, onFetchData, onDataChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, exportController, setExportController, isExporting, dataMode = 'client', logging, } = props;
|
|
10
|
+
const logger = (0, react_1.useMemo)(() => (0, logger_1.createLogger)('DataTableApi', logging), [logging]);
|
|
11
|
+
const fetchLogger = (0, react_1.useMemo)(() => logger.child('fetch'), [logger]);
|
|
12
|
+
const paginationLogger = (0, react_1.useMemo)(() => logger.child('pagination'), [logger]);
|
|
13
|
+
const stateLogger = (0, react_1.useMemo)(() => logger.child('state'), [logger]);
|
|
9
14
|
const getTableFilters = (0, react_1.useCallback)((withAllState = false) => {
|
|
10
15
|
const state = table.getState();
|
|
11
16
|
return Object.assign({ sorting: state.sorting, globalFilter: state.globalFilter, columnFilter: state.columnFilter, pagination: state.pagination }, (withAllState ? {
|
|
@@ -55,6 +60,9 @@ function useDataTableApi(props, ref) {
|
|
|
55
60
|
newOrder.splice(currentIndex, 1);
|
|
56
61
|
newOrder.splice(toIndex, 0, columnId);
|
|
57
62
|
table.setColumnOrder(newOrder);
|
|
63
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
64
|
+
stateLogger.debug('Column order updated', `${columnId} from ${currentIndex} to ${toIndex}`);
|
|
65
|
+
}
|
|
58
66
|
},
|
|
59
67
|
resetColumnOrder: () => {
|
|
60
68
|
const initialOrder = enhancedColumns.map((col, index) => {
|
|
@@ -67,6 +75,9 @@ function useDataTableApi(props, ref) {
|
|
|
67
75
|
return `column_${index}`;
|
|
68
76
|
});
|
|
69
77
|
table.setColumnOrder(initialOrder);
|
|
78
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
79
|
+
stateLogger.debug('Column order reset', initialOrder);
|
|
80
|
+
}
|
|
70
81
|
},
|
|
71
82
|
},
|
|
72
83
|
columnPinning: {
|
|
@@ -76,6 +87,9 @@ function useDataTableApi(props, ref) {
|
|
|
76
87
|
newPinning.right = (newPinning.right || []).filter(id => id !== columnId);
|
|
77
88
|
newPinning.left = [...(newPinning.left || []).filter(id => id !== columnId), columnId];
|
|
78
89
|
table.setColumnPinning(newPinning);
|
|
90
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
91
|
+
stateLogger.debug('Column pinned left', `${columnId}`);
|
|
92
|
+
}
|
|
79
93
|
},
|
|
80
94
|
pinColumnRight: (columnId) => {
|
|
81
95
|
const currentPinning = table.getState().columnPinning;
|
|
@@ -83,6 +97,9 @@ function useDataTableApi(props, ref) {
|
|
|
83
97
|
newPinning.left = (newPinning.left || []).filter(id => id !== columnId);
|
|
84
98
|
newPinning.right = [...(newPinning.right || []).filter(id => id !== columnId), columnId];
|
|
85
99
|
table.setColumnPinning(newPinning);
|
|
100
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
101
|
+
stateLogger.debug('Column pinned right', `${columnId}`);
|
|
102
|
+
}
|
|
86
103
|
},
|
|
87
104
|
unpinColumn: (columnId) => {
|
|
88
105
|
const currentPinning = table.getState().columnPinning;
|
|
@@ -118,12 +135,21 @@ function useDataTableApi(props, ref) {
|
|
|
118
135
|
filtering: {
|
|
119
136
|
setGlobalFilter: (filter) => {
|
|
120
137
|
table.setGlobalFilter(filter);
|
|
138
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
139
|
+
stateLogger.debug('Global filter set', `${filter}`);
|
|
140
|
+
}
|
|
121
141
|
},
|
|
122
142
|
clearGlobalFilter: () => {
|
|
123
143
|
table.setGlobalFilter('');
|
|
144
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
145
|
+
stateLogger.debug('Global filter cleared');
|
|
146
|
+
}
|
|
124
147
|
},
|
|
125
148
|
setColumnFilters: (filters) => {
|
|
126
149
|
handleColumnFilterStateChange(filters);
|
|
150
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
151
|
+
stateLogger.debug('Column filters set', `${filters}`);
|
|
152
|
+
}
|
|
127
153
|
},
|
|
128
154
|
addColumnFilter: (columnId, operator, value) => {
|
|
129
155
|
const newFilter = {
|
|
@@ -141,6 +167,9 @@ function useDataTableApi(props, ref) {
|
|
|
141
167
|
pendingFilters: columnFilter.pendingFilters || [],
|
|
142
168
|
pendingLogic: columnFilter.pendingLogic || 'AND',
|
|
143
169
|
});
|
|
170
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
171
|
+
stateLogger.debug(`Column filter added ${columnId} ${operator} ${value}`, newFilters);
|
|
172
|
+
}
|
|
144
173
|
},
|
|
145
174
|
removeColumnFilter: (filterId) => {
|
|
146
175
|
const columnFilter = table.getState().columnFilter;
|
|
@@ -152,6 +181,9 @@ function useDataTableApi(props, ref) {
|
|
|
152
181
|
pendingFilters: columnFilter.pendingFilters || [],
|
|
153
182
|
pendingLogic: columnFilter.pendingLogic || 'AND',
|
|
154
183
|
});
|
|
184
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
185
|
+
stateLogger.debug(`Column filter removed ${filterId}`, newFilters);
|
|
186
|
+
}
|
|
155
187
|
},
|
|
156
188
|
clearAllFilters: () => {
|
|
157
189
|
table.setGlobalFilter('');
|
|
@@ -161,6 +193,9 @@ function useDataTableApi(props, ref) {
|
|
|
161
193
|
pendingFilters: [],
|
|
162
194
|
pendingLogic: 'AND',
|
|
163
195
|
});
|
|
196
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
197
|
+
stateLogger.debug('Filters reset');
|
|
198
|
+
}
|
|
164
199
|
},
|
|
165
200
|
resetFilters: () => {
|
|
166
201
|
table.resetGlobalFilter();
|
|
@@ -175,6 +210,9 @@ function useDataTableApi(props, ref) {
|
|
|
175
210
|
sorting: {
|
|
176
211
|
setSorting: (sortingState) => {
|
|
177
212
|
table.setSorting(sortingState);
|
|
213
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
214
|
+
stateLogger.debug('Sorting set', `${sortingState}`);
|
|
215
|
+
}
|
|
178
216
|
},
|
|
179
217
|
sortColumn: (columnId, direction) => {
|
|
180
218
|
const column = table.getColumn(columnId);
|
|
@@ -197,24 +235,42 @@ function useDataTableApi(props, ref) {
|
|
|
197
235
|
pagination: {
|
|
198
236
|
goToPage: (pageIndex) => {
|
|
199
237
|
table.setPageIndex(pageIndex);
|
|
238
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
239
|
+
paginationLogger.debug('Page index set', `${pageIndex}`);
|
|
240
|
+
}
|
|
200
241
|
},
|
|
201
242
|
nextPage: () => {
|
|
202
243
|
table.nextPage();
|
|
244
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
245
|
+
paginationLogger.debug('Next page');
|
|
246
|
+
}
|
|
203
247
|
},
|
|
204
248
|
previousPage: () => {
|
|
205
249
|
table.previousPage();
|
|
250
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
251
|
+
paginationLogger.debug('Previous page');
|
|
252
|
+
}
|
|
206
253
|
},
|
|
207
254
|
setPageSize: (pageSize) => {
|
|
208
255
|
table.setPageSize(pageSize);
|
|
256
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
257
|
+
paginationLogger.debug('Page size set', `${pageSize}`);
|
|
258
|
+
}
|
|
209
259
|
},
|
|
210
260
|
goToFirstPage: () => {
|
|
211
261
|
table.setPageIndex(0);
|
|
262
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
263
|
+
paginationLogger.debug('Page index set to 0');
|
|
264
|
+
}
|
|
212
265
|
},
|
|
213
266
|
goToLastPage: () => {
|
|
214
267
|
const pageCount = table.getPageCount();
|
|
215
268
|
if (pageCount > 0) {
|
|
216
269
|
table.setPageIndex(pageCount - 1);
|
|
217
270
|
}
|
|
271
|
+
if (paginationLogger.isLevelEnabled('debug')) {
|
|
272
|
+
paginationLogger.debug('Page index set to last page', `${pageCount - 1}`);
|
|
273
|
+
}
|
|
218
274
|
},
|
|
219
275
|
},
|
|
220
276
|
selection: {
|
|
@@ -240,12 +296,18 @@ function useDataTableApi(props, ref) {
|
|
|
240
296
|
const allState = getTableFilters(true);
|
|
241
297
|
onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
|
|
242
298
|
onFetchData === null || onFetchData === void 0 ? void 0 : onFetchData(filters);
|
|
299
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
300
|
+
fetchLogger.debug('Data refreshed', filters);
|
|
301
|
+
}
|
|
243
302
|
},
|
|
244
303
|
reload: () => {
|
|
245
304
|
const filters = getTableFilters();
|
|
246
305
|
const allState = getTableFilters(true);
|
|
247
306
|
onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
|
|
248
307
|
onFetchData === null || onFetchData === void 0 ? void 0 : onFetchData(filters);
|
|
308
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
309
|
+
fetchLogger.debug('Data reloaded', filters);
|
|
310
|
+
}
|
|
249
311
|
},
|
|
250
312
|
getAllData: () => {
|
|
251
313
|
var _a;
|
|
@@ -264,6 +326,9 @@ function useDataTableApi(props, ref) {
|
|
|
264
326
|
const newData = (_a = table.getRowModel().rows) === null || _a === void 0 ? void 0 : _a.map(row => String(row.original[idKey]) === rowId
|
|
265
327
|
? Object.assign(Object.assign({}, row.original), updates) : row.original);
|
|
266
328
|
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData || []);
|
|
329
|
+
if (fetchLogger.isLevelEnabled('debug')) {
|
|
330
|
+
fetchLogger.debug('Row updated', `${rowId}`, updates);
|
|
331
|
+
}
|
|
267
332
|
},
|
|
268
333
|
updateRowByIndex: (index, updates) => {
|
|
269
334
|
var _a;
|
|
@@ -283,11 +348,17 @@ function useDataTableApi(props, ref) {
|
|
|
283
348
|
newData.push(newRow);
|
|
284
349
|
}
|
|
285
350
|
onDataChange(newData || []);
|
|
351
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
352
|
+
stateLogger.debug('Row inserted', `${newRow}`, index);
|
|
353
|
+
}
|
|
286
354
|
},
|
|
287
355
|
deleteRow: (rowId) => {
|
|
288
356
|
var _a;
|
|
289
357
|
const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => String(row.original[idKey]) !== rowId);
|
|
290
358
|
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
|
|
359
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
360
|
+
stateLogger.debug('Row deleted', `${rowId}`);
|
|
361
|
+
}
|
|
291
362
|
},
|
|
292
363
|
deleteRowByIndex: (index) => {
|
|
293
364
|
var _a;
|
|
@@ -302,6 +373,9 @@ function useDataTableApi(props, ref) {
|
|
|
302
373
|
const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => !selectedRowIds.includes(String(row.original[idKey])));
|
|
303
374
|
onDataChange((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
|
|
304
375
|
table.resetRowSelection();
|
|
376
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
377
|
+
stateLogger.debug('Selected rows deleted', selectedRowIds);
|
|
378
|
+
}
|
|
305
379
|
},
|
|
306
380
|
replaceAllData: (newData) => {
|
|
307
381
|
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
|
|
@@ -315,6 +389,9 @@ function useDataTableApi(props, ref) {
|
|
|
315
389
|
return updateData ? Object.assign(Object.assign({}, row.original), updateData) : row.original;
|
|
316
390
|
});
|
|
317
391
|
onDataChange(newData || []);
|
|
392
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
393
|
+
stateLogger.debug('Multiple rows updated', updates);
|
|
394
|
+
}
|
|
318
395
|
},
|
|
319
396
|
insertMultipleRows: (newRows, startIndex) => {
|
|
320
397
|
var _a;
|
|
@@ -326,12 +403,18 @@ function useDataTableApi(props, ref) {
|
|
|
326
403
|
newData.push(...newRows);
|
|
327
404
|
}
|
|
328
405
|
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
|
|
406
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
407
|
+
stateLogger.debug('Multiple rows inserted', newRows);
|
|
408
|
+
}
|
|
329
409
|
},
|
|
330
410
|
deleteMultipleRows: (rowIds) => {
|
|
331
411
|
var _a, _b;
|
|
332
412
|
const idsToDelete = new Set(rowIds);
|
|
333
413
|
const newData = (_b = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => !idsToDelete.has(String(row.original[idKey])))) === null || _b === void 0 ? void 0 : _b.map(row => row.original);
|
|
334
414
|
onDataChange(newData);
|
|
415
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
416
|
+
stateLogger.debug('Multiple rows deleted', rowIds);
|
|
417
|
+
}
|
|
335
418
|
},
|
|
336
419
|
updateField: (rowId, fieldName, value) => {
|
|
337
420
|
var _a;
|
|
@@ -458,6 +541,9 @@ function useDataTableApi(props, ref) {
|
|
|
458
541
|
sorting: table.getState().sorting,
|
|
459
542
|
pagination: table.getState().pagination,
|
|
460
543
|
};
|
|
544
|
+
if (stateLogger.isLevelEnabled('debug')) {
|
|
545
|
+
stateLogger.debug('Server export CSV', { currentFilters });
|
|
546
|
+
}
|
|
461
547
|
yield (0, export_utils_1.exportServerData)(table, {
|
|
462
548
|
format: 'csv',
|
|
463
549
|
filename,
|
|
@@ -6,21 +6,14 @@ const react_1 = require("react");
|
|
|
6
6
|
function useDebouncedFetch(onFetchData, delay = 300) {
|
|
7
7
|
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
8
8
|
const debounceTimer = (0, react_1.useRef)(null);
|
|
9
|
-
const lastFetchParams = (0, react_1.useRef)('');
|
|
10
9
|
const debouncedFetch = (0, react_1.useCallback)((filters) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
11
10
|
if (!onFetchData)
|
|
12
11
|
return null;
|
|
13
|
-
const currentParams = JSON.stringify(filters);
|
|
14
12
|
if (debounceTimer.current) {
|
|
15
13
|
clearTimeout(debounceTimer.current);
|
|
16
14
|
}
|
|
17
15
|
return new Promise((resolve) => {
|
|
18
16
|
debounceTimer.current = setTimeout(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
19
|
-
if (lastFetchParams.current === currentParams) {
|
|
20
|
-
resolve(null);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
lastFetchParams.current = currentParams;
|
|
24
17
|
setIsLoading(true);
|
|
25
18
|
try {
|
|
26
19
|
const result = yield onFetchData(filters);
|
package/src/lib/utils/index.d.ts
CHANGED
package/src/lib/utils/index.js
CHANGED
|
@@ -8,3 +8,4 @@ tslib_1.__exportStar(require("./export-utils"), exports);
|
|
|
8
8
|
tslib_1.__exportStar(require("./special-columns.utils"), exports);
|
|
9
9
|
tslib_1.__exportStar(require("./debounced-fetch.utils"), exports);
|
|
10
10
|
tslib_1.__exportStar(require("./slot-helpers"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./logger"), exports);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
|
|
2
|
+
interface ConsoleLike {
|
|
3
|
+
debug?: (...args: unknown[]) => void;
|
|
4
|
+
info?: (...args: unknown[]) => void;
|
|
5
|
+
warn?: (...args: unknown[]) => void;
|
|
6
|
+
error?: (...args: unknown[]) => void;
|
|
7
|
+
log?: (...args: unknown[]) => void;
|
|
8
|
+
}
|
|
9
|
+
export interface DataTableLoggingOptions {
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
level?: LogLevel;
|
|
12
|
+
prefix?: string;
|
|
13
|
+
scope?: string;
|
|
14
|
+
includeTimestamp?: boolean;
|
|
15
|
+
logger?: ConsoleLike;
|
|
16
|
+
}
|
|
17
|
+
type LoggerInput = boolean | DataTableLoggingOptions;
|
|
18
|
+
type ResolvedLoggerConfig = Required<Omit<DataTableLoggingOptions, 'logger'>> & {
|
|
19
|
+
logger: ConsoleLike;
|
|
20
|
+
};
|
|
21
|
+
type LogMethodLevel = Exclude<LogLevel, 'silent'>;
|
|
22
|
+
export interface LoggerInstance {
|
|
23
|
+
debug: (...args: unknown[]) => void;
|
|
24
|
+
info: (...args: unknown[]) => void;
|
|
25
|
+
warn: (...args: unknown[]) => void;
|
|
26
|
+
error: (...args: unknown[]) => void;
|
|
27
|
+
child: (scope: string, overrides?: LoggerInput) => LoggerInstance;
|
|
28
|
+
isLevelEnabled: (level: LogMethodLevel) => boolean;
|
|
29
|
+
config: ResolvedLoggerConfig;
|
|
30
|
+
}
|
|
31
|
+
export declare const createLogger: (scope?: string, input?: LoggerInput, parentConfig?: ResolvedLoggerConfig) => LoggerInstance;
|
|
32
|
+
export declare const configureDataTableLogging: (options: DataTableLoggingOptions) => void;
|
|
33
|
+
export declare const getDataTableLoggingConfig: () => ResolvedLoggerConfig;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDataTableLoggingConfig = exports.configureDataTableLogging = exports.createLogger = void 0;
|
|
4
|
+
const LOG_LEVEL_ORDER = {
|
|
5
|
+
silent: 0,
|
|
6
|
+
error: 1,
|
|
7
|
+
warn: 2,
|
|
8
|
+
info: 3,
|
|
9
|
+
debug: 4,
|
|
10
|
+
};
|
|
11
|
+
const defaultConsole = typeof console !== 'undefined'
|
|
12
|
+
? console
|
|
13
|
+
: {
|
|
14
|
+
log: () => undefined,
|
|
15
|
+
debug: () => undefined,
|
|
16
|
+
info: () => undefined,
|
|
17
|
+
warn: () => undefined,
|
|
18
|
+
error: () => undefined,
|
|
19
|
+
};
|
|
20
|
+
let globalConfig = {
|
|
21
|
+
enabled: false,
|
|
22
|
+
level: 'warn',
|
|
23
|
+
prefix: 'DataTable',
|
|
24
|
+
scope: '',
|
|
25
|
+
includeTimestamp: false,
|
|
26
|
+
logger: defaultConsole,
|
|
27
|
+
};
|
|
28
|
+
const isLevelEnabled = (level, config) => {
|
|
29
|
+
if (!config.enabled) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return LOG_LEVEL_ORDER[level] <= LOG_LEVEL_ORDER[config.level];
|
|
33
|
+
};
|
|
34
|
+
const formatPrefix = (level, config) => {
|
|
35
|
+
const segments = [];
|
|
36
|
+
if (config.prefix) {
|
|
37
|
+
segments.push(config.prefix);
|
|
38
|
+
}
|
|
39
|
+
if (config.scope) {
|
|
40
|
+
segments.push(config.scope);
|
|
41
|
+
}
|
|
42
|
+
const prefix = segments.length > 0 ? `[${segments.join(':')}]` : '';
|
|
43
|
+
return config.includeTimestamp
|
|
44
|
+
? `[${new Date().toISOString()}]${prefix ? ` ${prefix}` : ''} [${level.toUpperCase()}]`
|
|
45
|
+
: `${prefix ? `${prefix} ` : ''}[${level.toUpperCase()}]`;
|
|
46
|
+
};
|
|
47
|
+
const getConsoleMethod = (level, logger) => {
|
|
48
|
+
var _a, _b, _c;
|
|
49
|
+
const methodName = level === 'debug' ? 'debug' : level;
|
|
50
|
+
return (_c = (_b = (_a = logger[methodName]) !== null && _a !== void 0 ? _a : logger.log) !== null && _b !== void 0 ? _b : defaultConsole.log) !== null && _c !== void 0 ? _c : (() => undefined);
|
|
51
|
+
};
|
|
52
|
+
const normaliseInput = (input) => {
|
|
53
|
+
if (typeof input === 'boolean') {
|
|
54
|
+
return { enabled: input };
|
|
55
|
+
}
|
|
56
|
+
return input !== null && input !== void 0 ? input : {};
|
|
57
|
+
};
|
|
58
|
+
const resolveConfig = (scope, input, parent) => {
|
|
59
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
60
|
+
const overrides = normaliseInput(input);
|
|
61
|
+
const base = parent !== null && parent !== void 0 ? parent : globalConfig;
|
|
62
|
+
return {
|
|
63
|
+
enabled: (_a = overrides.enabled) !== null && _a !== void 0 ? _a : base.enabled,
|
|
64
|
+
level: (_b = overrides.level) !== null && _b !== void 0 ? _b : base.level,
|
|
65
|
+
prefix: (_c = overrides.prefix) !== null && _c !== void 0 ? _c : base.prefix,
|
|
66
|
+
scope: (_f = (_e = (_d = overrides.scope) !== null && _d !== void 0 ? _d : scope) !== null && _e !== void 0 ? _e : base.scope) !== null && _f !== void 0 ? _f : '',
|
|
67
|
+
includeTimestamp: (_g = overrides.includeTimestamp) !== null && _g !== void 0 ? _g : base.includeTimestamp,
|
|
68
|
+
logger: (_j = (_h = overrides.logger) !== null && _h !== void 0 ? _h : base.logger) !== null && _j !== void 0 ? _j : defaultConsole,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const createLoggerMethods = (config) => {
|
|
72
|
+
const logWithLevel = (level) => {
|
|
73
|
+
const consoleMethod = getConsoleMethod(level, config.logger);
|
|
74
|
+
return (...args) => {
|
|
75
|
+
if (!isLevelEnabled(level, config)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const prefix = formatPrefix(level, config);
|
|
79
|
+
consoleMethod(prefix, ...args);
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
debug: logWithLevel('debug'),
|
|
84
|
+
info: logWithLevel('info'),
|
|
85
|
+
warn: logWithLevel('warn'),
|
|
86
|
+
error: logWithLevel('error'),
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
const createLogger = (scope, input, parentConfig) => {
|
|
90
|
+
const resolvedConfig = resolveConfig(scope, input, parentConfig);
|
|
91
|
+
const methods = createLoggerMethods(resolvedConfig);
|
|
92
|
+
const child = (childScope, overrides) => {
|
|
93
|
+
const combinedScope = childScope
|
|
94
|
+
? (resolvedConfig.scope ? `${resolvedConfig.scope}.${childScope}` : childScope)
|
|
95
|
+
: resolvedConfig.scope;
|
|
96
|
+
return (0, exports.createLogger)(combinedScope, overrides, resolvedConfig);
|
|
97
|
+
};
|
|
98
|
+
return Object.assign(Object.assign({}, methods), { child, isLevelEnabled: (level) => isLevelEnabled(level, resolvedConfig), config: resolvedConfig });
|
|
99
|
+
};
|
|
100
|
+
exports.createLogger = createLogger;
|
|
101
|
+
const configureDataTableLogging = (options) => {
|
|
102
|
+
globalConfig = resolveConfig(options.scope, options, globalConfig);
|
|
103
|
+
};
|
|
104
|
+
exports.configureDataTableLogging = configureDataTableLogging;
|
|
105
|
+
const getDataTableLoggingConfig = () => (Object.assign({}, globalConfig));
|
|
106
|
+
exports.getDataTableLoggingConfig = getDataTableLoggingConfig;
|