mui-table-2026 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/package.json +115 -0
- package/src/MUIDataTable.js +2107 -0
- package/src/components/ExpandButton.js +39 -0
- package/src/components/JumpToPage.js +96 -0
- package/src/components/Popover.js +89 -0
- package/src/components/TableBody.js +338 -0
- package/src/components/TableBodyCell.js +276 -0
- package/src/components/TableBodyRow.js +98 -0
- package/src/components/TableFilter.js +421 -0
- package/src/components/TableFilterList.js +136 -0
- package/src/components/TableFilterListItem.js +20 -0
- package/src/components/TableFooter.js +74 -0
- package/src/components/TableHead.js +171 -0
- package/src/components/TableHeadCell.js +320 -0
- package/src/components/TableHeadRow.js +29 -0
- package/src/components/TablePagination.js +152 -0
- package/src/components/TableResize.js +288 -0
- package/src/components/TableSearch.js +89 -0
- package/src/components/TableSelectCell.js +163 -0
- package/src/components/TableToolbar.js +630 -0
- package/src/components/TableToolbarSelect.js +91 -0
- package/src/components/TableViewCol.js +101 -0
- package/src/hooks/useColumnDrop.js +186 -0
- package/src/index.js +44 -0
- package/src/localStorage/index.js +2 -0
- package/src/localStorage/load.js +10 -0
- package/src/localStorage/save.js +5 -0
- package/src/plug-ins/DebounceSearchRender.js +118 -0
- package/src/textLabels.js +39 -0
- package/src/utils.js +150 -0
|
@@ -0,0 +1,2107 @@
|
|
|
1
|
+
import { Paper } from '@mui/material';
|
|
2
|
+
import { Table as MuiTable } from '@mui/material';
|
|
3
|
+
import { Tooltip as MuiTooltip } from '@mui/material';
|
|
4
|
+
import { withStyles } from 'tss-react/mui';
|
|
5
|
+
import clsx from 'clsx';
|
|
6
|
+
import assignwith from 'lodash.assignwith';
|
|
7
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
8
|
+
import find from 'lodash.find';
|
|
9
|
+
import isEqual from 'lodash.isequal';
|
|
10
|
+
import isUndefined from 'lodash.isundefined';
|
|
11
|
+
import merge from 'lodash.merge';
|
|
12
|
+
import PropTypes from 'prop-types';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import DefaultTableBody from './components/TableBody';
|
|
15
|
+
import DefaultTableFilter from './components/TableFilter';
|
|
16
|
+
import DefaultTableFilterList from './components/TableFilterList';
|
|
17
|
+
import DefaultTableFooter from './components/TableFooter';
|
|
18
|
+
import DefaultTableHead from './components/TableHead';
|
|
19
|
+
import DefaultTableResize from './components/TableResize';
|
|
20
|
+
import DefaultTableToolbar from './components/TableToolbar';
|
|
21
|
+
import DefaultTableToolbarSelect from './components/TableToolbarSelect';
|
|
22
|
+
import getTextLabels from './textLabels';
|
|
23
|
+
import { buildMap, getCollatorComparator, getPageValue, sortCompare, warnDeprecated, warnInfo } from './utils';
|
|
24
|
+
import { DndProvider } from 'react-dnd';
|
|
25
|
+
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
26
|
+
import { load, save } from './localStorage';
|
|
27
|
+
|
|
28
|
+
const defaultTableStyles = (theme) => ({
|
|
29
|
+
root: {
|
|
30
|
+
'& .datatables-noprint': {
|
|
31
|
+
'@media print': {
|
|
32
|
+
display: 'none',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
// Modern table styling
|
|
36
|
+
borderRadius: '8px',
|
|
37
|
+
overflow: 'hidden',
|
|
38
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
39
|
+
|
|
40
|
+
backgroundColor: '#ffffff',
|
|
41
|
+
// Z-index management
|
|
42
|
+
'& .MuiPopper-root': {
|
|
43
|
+
zIndex: 9999,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
paper: {
|
|
47
|
+
isolation: 'auto',
|
|
48
|
+
// Modern paper styling
|
|
49
|
+
borderRadius: '8px',
|
|
50
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
51
|
+
border: '1px solid #e5e7eb',
|
|
52
|
+
overflow: 'hidden',
|
|
53
|
+
},
|
|
54
|
+
paperResponsiveScrollFullHeightFullWidth: {
|
|
55
|
+
position: 'absolute',
|
|
56
|
+
},
|
|
57
|
+
tableRoot: {
|
|
58
|
+
outline: 'none',
|
|
59
|
+
borderTop: '2px solid #e5e7eb',
|
|
60
|
+
},
|
|
61
|
+
responsiveBase: {
|
|
62
|
+
overflow: 'auto',
|
|
63
|
+
'@media print': {
|
|
64
|
+
height: 'auto !important',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
// deprecated, but continuing support through v3.x
|
|
69
|
+
responsiveScroll: {
|
|
70
|
+
overflow: 'auto',
|
|
71
|
+
height: '100%',
|
|
72
|
+
},
|
|
73
|
+
// deprecated, but continuing support through v3.x
|
|
74
|
+
responsiveScrollMaxHeight: {
|
|
75
|
+
overflow: 'auto',
|
|
76
|
+
height: '100%',
|
|
77
|
+
},
|
|
78
|
+
// deprecated, but continuing support through v3.x
|
|
79
|
+
responsiveScrollFullHeight: {
|
|
80
|
+
height: '100%',
|
|
81
|
+
},
|
|
82
|
+
// deprecated, but continuing support through v3.x
|
|
83
|
+
responsiveStacked: {
|
|
84
|
+
overflow: 'auto',
|
|
85
|
+
[theme.breakpoints.down('md')]: {
|
|
86
|
+
overflow: 'hidden',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
// deprecated, but continuing support through v3.x
|
|
90
|
+
responsiveStackedFullWidth: {},
|
|
91
|
+
caption: {
|
|
92
|
+
position: 'absolute',
|
|
93
|
+
left: '-3000px',
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
liveAnnounce: {
|
|
97
|
+
border: '0',
|
|
98
|
+
clip: 'rect(0 0 0 0)',
|
|
99
|
+
height: '1px',
|
|
100
|
+
margin: '-1px',
|
|
101
|
+
overflow: 'hidden',
|
|
102
|
+
padding: '0',
|
|
103
|
+
position: 'absolute',
|
|
104
|
+
width: '1px',
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const TABLE_LOAD = {
|
|
109
|
+
INITIAL: 1,
|
|
110
|
+
UPDATE: 2,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// Populate this list with anything that might render in the toolbar to determine if we hide the toolbar
|
|
114
|
+
const TOOLBAR_ITEMS = ['title', 'filter', 'search', 'print', 'download', 'viewColumns', 'customToolbar'];
|
|
115
|
+
|
|
116
|
+
const hasToolbarItem = (options, title) => {
|
|
117
|
+
options.title = title;
|
|
118
|
+
|
|
119
|
+
return !isUndefined(find(TOOLBAR_ITEMS, (i) => options[i]));
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Select Toolbar Placement options
|
|
123
|
+
const STP = {
|
|
124
|
+
REPLACE: 'replace',
|
|
125
|
+
ABOVE: 'above',
|
|
126
|
+
NONE: 'none',
|
|
127
|
+
ALWAYS: 'always',
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
class MUIDataTable extends React.Component {
|
|
131
|
+
static propTypes = {
|
|
132
|
+
/** Title of the table */
|
|
133
|
+
title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
|
|
134
|
+
/** Data used to describe table */
|
|
135
|
+
data: PropTypes.array.isRequired,
|
|
136
|
+
/** Columns used to describe table */
|
|
137
|
+
columns: PropTypes.PropTypes.arrayOf(
|
|
138
|
+
PropTypes.oneOfType([
|
|
139
|
+
PropTypes.string,
|
|
140
|
+
PropTypes.shape({
|
|
141
|
+
label: PropTypes.string,
|
|
142
|
+
name: PropTypes.string.isRequired,
|
|
143
|
+
options: PropTypes.shape({
|
|
144
|
+
display: PropTypes.oneOf(['true', 'false', 'excluded', 'always', true, false]),
|
|
145
|
+
empty: PropTypes.bool,
|
|
146
|
+
filter: PropTypes.bool,
|
|
147
|
+
sort: PropTypes.bool,
|
|
148
|
+
print: PropTypes.bool,
|
|
149
|
+
searchable: PropTypes.bool,
|
|
150
|
+
download: PropTypes.bool,
|
|
151
|
+
viewColumns: PropTypes.bool,
|
|
152
|
+
filterList: PropTypes.array,
|
|
153
|
+
filterOptions: PropTypes.oneOfType([
|
|
154
|
+
PropTypes.array,
|
|
155
|
+
PropTypes.shape({
|
|
156
|
+
names: PropTypes.array,
|
|
157
|
+
logic: PropTypes.func,
|
|
158
|
+
display: PropTypes.func,
|
|
159
|
+
}),
|
|
160
|
+
]),
|
|
161
|
+
filterType: PropTypes.oneOf(['dropdown', 'checkbox', 'multiselect', 'textField', 'custom']),
|
|
162
|
+
customHeadRender: PropTypes.func,
|
|
163
|
+
customBodyRender: PropTypes.func,
|
|
164
|
+
customBodyRenderLite: PropTypes.func,
|
|
165
|
+
customHeadLabelRender: PropTypes.func,
|
|
166
|
+
customFilterListOptions: PropTypes.oneOfType([
|
|
167
|
+
PropTypes.shape({
|
|
168
|
+
render: PropTypes.func,
|
|
169
|
+
update: PropTypes.func,
|
|
170
|
+
}),
|
|
171
|
+
]),
|
|
172
|
+
customFilterListRender: PropTypes.func,
|
|
173
|
+
setCellProps: PropTypes.func,
|
|
174
|
+
setCellHeaderProps: PropTypes.func,
|
|
175
|
+
sortThirdClickReset: PropTypes.bool,
|
|
176
|
+
sortDescFirst: PropTypes.bool,
|
|
177
|
+
}),
|
|
178
|
+
}),
|
|
179
|
+
]),
|
|
180
|
+
).isRequired,
|
|
181
|
+
/** Options used to describe table */
|
|
182
|
+
options: PropTypes.shape({
|
|
183
|
+
caseSensitive: PropTypes.bool,
|
|
184
|
+
columnOrder: PropTypes.array,
|
|
185
|
+
count: PropTypes.number,
|
|
186
|
+
confirmFilters: PropTypes.bool,
|
|
187
|
+
consoleWarnings: PropTypes.bool,
|
|
188
|
+
customFilterDialogFooter: PropTypes.func,
|
|
189
|
+
customFooter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
|
190
|
+
customRowRender: PropTypes.func,
|
|
191
|
+
customSearch: PropTypes.func,
|
|
192
|
+
customSearchRender: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
|
193
|
+
customSort: PropTypes.func,
|
|
194
|
+
customToolbar: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
|
195
|
+
customToolbarSelect: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
|
196
|
+
draggableColumns: PropTypes.object,
|
|
197
|
+
enableNestedDataAccess: PropTypes.string,
|
|
198
|
+
expandableRows: PropTypes.bool,
|
|
199
|
+
expandableRowsHeader: PropTypes.bool,
|
|
200
|
+
expandableRowsOnClick: PropTypes.bool,
|
|
201
|
+
disableToolbarSelect: PropTypes.bool,
|
|
202
|
+
download: PropTypes.oneOf([true, false, 'true', 'false', 'disabled']),
|
|
203
|
+
downloadOptions: PropTypes.shape({
|
|
204
|
+
filename: PropTypes.string,
|
|
205
|
+
separator: PropTypes.string,
|
|
206
|
+
filterOptions: PropTypes.shape({
|
|
207
|
+
useDisplayedColumnsOnly: PropTypes.bool,
|
|
208
|
+
useDisplayedRowsOnly: PropTypes.bool,
|
|
209
|
+
}),
|
|
210
|
+
}),
|
|
211
|
+
filter: PropTypes.oneOf([true, false, 'true', 'false', 'disabled']),
|
|
212
|
+
filterArrayFullMatch: PropTypes.bool,
|
|
213
|
+
filterType: PropTypes.oneOf(['dropdown', 'checkbox', 'multiselect', 'textField', 'custom']),
|
|
214
|
+
fixedHeader: PropTypes.bool,
|
|
215
|
+
fixedSelectColumn: PropTypes.bool,
|
|
216
|
+
getTextLabels: PropTypes.func,
|
|
217
|
+
isRowExpandable: PropTypes.func,
|
|
218
|
+
isRowSelectable: PropTypes.func,
|
|
219
|
+
jumpToPage: PropTypes.bool,
|
|
220
|
+
onDownload: PropTypes.func,
|
|
221
|
+
onFilterChange: PropTypes.func,
|
|
222
|
+
onFilterChipClose: PropTypes.func,
|
|
223
|
+
onFilterConfirm: PropTypes.func,
|
|
224
|
+
onFilterDialogOpen: PropTypes.func,
|
|
225
|
+
onFilterDialogClose: PropTypes.func,
|
|
226
|
+
onRowClick: PropTypes.func,
|
|
227
|
+
onRowsExpand: PropTypes.func,
|
|
228
|
+
onRowExpansionChange: PropTypes.func,
|
|
229
|
+
onRowsSelect: PropTypes.func,
|
|
230
|
+
onRowSelectionChange: PropTypes.func,
|
|
231
|
+
onTableChange: PropTypes.func,
|
|
232
|
+
onTableInit: PropTypes.func,
|
|
233
|
+
page: PropTypes.number,
|
|
234
|
+
pagination: PropTypes.bool,
|
|
235
|
+
print: PropTypes.oneOf([true, false, 'true', 'false', 'disabled']),
|
|
236
|
+
searchProps: PropTypes.object,
|
|
237
|
+
selectableRows: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['none', 'single', 'multiple'])]),
|
|
238
|
+
selectableRowsHeader: PropTypes.bool,
|
|
239
|
+
selectableRowsHideCheckboxes: PropTypes.bool,
|
|
240
|
+
selectableRowsOnClick: PropTypes.bool,
|
|
241
|
+
serverSide: PropTypes.bool,
|
|
242
|
+
tableId: PropTypes.string,
|
|
243
|
+
tableBodyHeight: PropTypes.string,
|
|
244
|
+
tableBodyMaxHeight: PropTypes.string,
|
|
245
|
+
renderExpandableRow: PropTypes.func,
|
|
246
|
+
resizableColumns: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
|
247
|
+
responsive: PropTypes.oneOf(['standard', 'vertical', 'verticalAlways', 'simple']),
|
|
248
|
+
rowHover: PropTypes.bool,
|
|
249
|
+
rowsExpanded: PropTypes.array,
|
|
250
|
+
rowsPerPage: PropTypes.number,
|
|
251
|
+
rowsPerPageOptions: PropTypes.array,
|
|
252
|
+
rowsSelected: PropTypes.array,
|
|
253
|
+
search: PropTypes.oneOf([true, false, 'true', 'false', 'disabled']),
|
|
254
|
+
searchOpen: PropTypes.bool,
|
|
255
|
+
searchAlwaysOpen: PropTypes.bool,
|
|
256
|
+
searchPlaceholder: PropTypes.string,
|
|
257
|
+
searchText: PropTypes.string,
|
|
258
|
+
setFilterChipProps: PropTypes.func,
|
|
259
|
+
setRowProps: PropTypes.func,
|
|
260
|
+
selectToolbarPlacement: PropTypes.oneOfType([
|
|
261
|
+
PropTypes.bool,
|
|
262
|
+
PropTypes.oneOf([STP.REPLACE, STP.ABOVE, STP.NONE, STP.ALWAYS]),
|
|
263
|
+
]),
|
|
264
|
+
setTableProps: PropTypes.func,
|
|
265
|
+
sort: PropTypes.bool,
|
|
266
|
+
sortOrder: PropTypes.object,
|
|
267
|
+
storageKey: PropTypes.string,
|
|
268
|
+
viewColumns: PropTypes.oneOf([true, false, 'true', 'false', 'disabled']),
|
|
269
|
+
}),
|
|
270
|
+
/** Pass and use className to style MUIDataTable as desired */
|
|
271
|
+
className: PropTypes.string,
|
|
272
|
+
components: PropTypes.objectOf(PropTypes.any),
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
static defaultProps = {
|
|
276
|
+
title: '',
|
|
277
|
+
options: {},
|
|
278
|
+
data: [],
|
|
279
|
+
columns: [],
|
|
280
|
+
components: {
|
|
281
|
+
TableBody: DefaultTableBody,
|
|
282
|
+
TableFilter: DefaultTableFilter,
|
|
283
|
+
TableFilterList: DefaultTableFilterList,
|
|
284
|
+
TableFooter: DefaultTableFooter,
|
|
285
|
+
TableHead: DefaultTableHead,
|
|
286
|
+
TableResize: DefaultTableResize,
|
|
287
|
+
TableToolbar: DefaultTableToolbar,
|
|
288
|
+
TableToolbarSelect: DefaultTableToolbarSelect,
|
|
289
|
+
Tooltip: MuiTooltip,
|
|
290
|
+
icons: {},
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
constructor(props) {
|
|
295
|
+
super(props);
|
|
296
|
+
this.tableRef = React.createRef();
|
|
297
|
+
this.tableContent = React.createRef();
|
|
298
|
+
this.draggableHeadCellRefs = {};
|
|
299
|
+
this.resizeHeadCellRefs = {};
|
|
300
|
+
this.timers = {};
|
|
301
|
+
this.setHeadResizeable = () => {};
|
|
302
|
+
this.updateDividers = () => {};
|
|
303
|
+
|
|
304
|
+
let defaultState = {
|
|
305
|
+
activeColumn: null,
|
|
306
|
+
announceText: null,
|
|
307
|
+
count: 0,
|
|
308
|
+
columns: [],
|
|
309
|
+
expandedRows: {
|
|
310
|
+
data: [],
|
|
311
|
+
lookup: {},
|
|
312
|
+
},
|
|
313
|
+
data: [],
|
|
314
|
+
displayData: [],
|
|
315
|
+
filterData: [],
|
|
316
|
+
filterList: [],
|
|
317
|
+
page: 0,
|
|
318
|
+
previousSelectedRow: null,
|
|
319
|
+
rowsPerPage: 10,
|
|
320
|
+
searchProps: {},
|
|
321
|
+
searchText: null,
|
|
322
|
+
selectedRows: {
|
|
323
|
+
data: [],
|
|
324
|
+
lookup: {},
|
|
325
|
+
},
|
|
326
|
+
showResponsive: false,
|
|
327
|
+
sortOrder: {},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
this.mergeDefaultOptions(props);
|
|
331
|
+
|
|
332
|
+
const restoredState = load(props.options.storageKey);
|
|
333
|
+
this.state = Object.assign(defaultState, restoredState ? restoredState : this.getInitTableOptions());
|
|
334
|
+
|
|
335
|
+
this.setTableData = this.setTableData.bind(this);
|
|
336
|
+
|
|
337
|
+
this.setTableData(props, TABLE_LOAD.INITIAL, true, null, true);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
componentDidMount() {
|
|
341
|
+
this.setHeadResizeable(this.resizeHeadCellRefs, this.tableRef);
|
|
342
|
+
|
|
343
|
+
// When we have a search, we must reset page to view it unless on serverSide since paging is handled by the user.
|
|
344
|
+
if (this.props.options.searchText && !this.props.options.serverSide) this.setState({ page: 0 });
|
|
345
|
+
|
|
346
|
+
this.setTableInit('tableInitialized');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
componentDidUpdate(prevProps) {
|
|
350
|
+
if (
|
|
351
|
+
this.props.data !== prevProps.data ||
|
|
352
|
+
this.props.columns !== prevProps.columns ||
|
|
353
|
+
this.props.options !== prevProps.options
|
|
354
|
+
) {
|
|
355
|
+
this.updateOptions(this.options, this.props);
|
|
356
|
+
|
|
357
|
+
var didDataUpdate = this.props.data !== prevProps.data;
|
|
358
|
+
if (this.props.data && prevProps.data) {
|
|
359
|
+
didDataUpdate = didDataUpdate && this.props.data.length === prevProps.data.length;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
this.setTableData(this.props, TABLE_LOAD.INITIAL, didDataUpdate, () => {
|
|
363
|
+
this.setTableAction('propsUpdate');
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (this.props.options.searchText !== prevProps.options.searchText && !this.props.options.serverSide) {
|
|
368
|
+
// When we have a search, we must reset page to view it unless on serverSide since paging is handled by the user.
|
|
369
|
+
this.setState({ page: 0 });
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (
|
|
373
|
+
this.options.resizableColumns === true ||
|
|
374
|
+
(this.options.resizableColumns && this.options.resizableColumns.enabled)
|
|
375
|
+
) {
|
|
376
|
+
this.setHeadResizeable(this.resizeHeadCellRefs, this.tableRef);
|
|
377
|
+
this.updateDividers();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
updateOptions(options, props) {
|
|
382
|
+
// set backwards compatibility options
|
|
383
|
+
if (props.options.disableToolbarSelect === true && props.options.selectToolbarPlacement === undefined) {
|
|
384
|
+
// if deprecated option disableToolbarSelect is set and selectToolbarPlacement is default then use it
|
|
385
|
+
props.options.selectToolbarPlacement = STP.NONE;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// provide default tableId when no tableId has been passed as prop
|
|
389
|
+
if (!props.options.tableId) {
|
|
390
|
+
props.options.tableId = (Math.random() + '').replace(/\./, '');
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
this.options = assignwith(options, props.options, (objValue, srcValue, key) => {
|
|
394
|
+
// Merge any default options that are objects, as they will be overwritten otherwise
|
|
395
|
+
if (key === 'textLabels' || key === 'downloadOptions') return merge(objValue, srcValue);
|
|
396
|
+
return;
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
this.handleOptionDeprecation(props);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
getDefaultOptions = () => ({
|
|
403
|
+
caseSensitive: false,
|
|
404
|
+
consoleWarnings: true,
|
|
405
|
+
disableToolbarSelect: false,
|
|
406
|
+
download: true,
|
|
407
|
+
downloadOptions: {
|
|
408
|
+
filename: 'tableDownload.csv',
|
|
409
|
+
separator: ',',
|
|
410
|
+
},
|
|
411
|
+
draggableColumns: {
|
|
412
|
+
enabled: false,
|
|
413
|
+
transitionTime: 300,
|
|
414
|
+
},
|
|
415
|
+
elevation: 4,
|
|
416
|
+
enableNestedDataAccess: '',
|
|
417
|
+
expandableRows: false,
|
|
418
|
+
expandableRowsHeader: true,
|
|
419
|
+
expandableRowsOnClick: false,
|
|
420
|
+
filter: true,
|
|
421
|
+
filterArrayFullMatch: true,
|
|
422
|
+
filterType: 'dropdown',
|
|
423
|
+
fixedHeader: true,
|
|
424
|
+
fixedSelectColumn: true,
|
|
425
|
+
pagination: true,
|
|
426
|
+
print: true,
|
|
427
|
+
resizableColumns: false,
|
|
428
|
+
responsive: 'vertical',
|
|
429
|
+
rowHover: true,
|
|
430
|
+
//rowsPerPage: 10,
|
|
431
|
+
rowsPerPageOptions: [10, 15, 100],
|
|
432
|
+
search: true,
|
|
433
|
+
selectableRows: 'multiple',
|
|
434
|
+
selectableRowsHideCheckboxes: false,
|
|
435
|
+
selectableRowsOnClick: false,
|
|
436
|
+
selectableRowsHeader: true,
|
|
437
|
+
serverSide: false,
|
|
438
|
+
serverSideFilterList: null,
|
|
439
|
+
setTableProps: () => ({}),
|
|
440
|
+
sort: true,
|
|
441
|
+
sortFilterList: true,
|
|
442
|
+
tableBodyHeight: 'auto',
|
|
443
|
+
tableBodyMaxHeight: null, // if set, it will override tableBodyHeight
|
|
444
|
+
sortOrder: {},
|
|
445
|
+
textLabels: getTextLabels(),
|
|
446
|
+
viewColumns: true,
|
|
447
|
+
selectToolbarPlacement: STP.REPLACE,
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
warnDep = (msg, consoleWarnings) => {
|
|
451
|
+
warnDeprecated(msg, this.options.consoleWarnings);
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
warnInfo = (msg, consoleWarnings) => {
|
|
455
|
+
warnInfo(msg, this.options.consoleWarnings);
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
handleOptionDeprecation = (props) => {
|
|
459
|
+
if (typeof this.options.selectableRows === 'boolean') {
|
|
460
|
+
this.warnDep(
|
|
461
|
+
'Using a boolean for selectableRows has been deprecated. Please use string option: multiple | single | none',
|
|
462
|
+
);
|
|
463
|
+
this.options.selectableRows = this.options.selectableRows ? 'multiple' : 'none';
|
|
464
|
+
}
|
|
465
|
+
if (['standard', 'vertical', 'verticalAlways', 'simple'].indexOf(this.options.responsive) === -1) {
|
|
466
|
+
if (
|
|
467
|
+
[
|
|
468
|
+
'scrollMaxHeight',
|
|
469
|
+
'scrollFullHeight',
|
|
470
|
+
'stacked',
|
|
471
|
+
'stackedFullWidth',
|
|
472
|
+
'scrollFullHeightFullWidth',
|
|
473
|
+
'scroll',
|
|
474
|
+
].indexOf(this.options.responsive) !== -1
|
|
475
|
+
) {
|
|
476
|
+
this.warnDep(
|
|
477
|
+
this.options.responsive +
|
|
478
|
+
' has been deprecated, but will still work in version 3.x. Please use string option: standard | vertical | simple. More info: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
479
|
+
);
|
|
480
|
+
} else {
|
|
481
|
+
this.warnInfo(
|
|
482
|
+
this.options.responsive +
|
|
483
|
+
' is not recognized as a valid input for responsive option. Please use string option: standard | vertical | simple. More info: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if (this.options.onRowsSelect) {
|
|
488
|
+
this.warnDep(
|
|
489
|
+
'onRowsSelect has been renamed onRowSelectionChange. More info: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
if (this.options.onRowsExpand) {
|
|
493
|
+
this.warnDep(
|
|
494
|
+
'onRowsExpand has been renamed onRowExpansionChange. More info: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (this.options.fixedHeaderOptions) {
|
|
498
|
+
if (
|
|
499
|
+
typeof this.options.fixedHeaderOptions.yAxis !== 'undefined' &&
|
|
500
|
+
typeof this.options.fixedHeader === 'undefined'
|
|
501
|
+
) {
|
|
502
|
+
this.options.fixedHeader = this.options.fixedHeaderOptions.yAxis;
|
|
503
|
+
}
|
|
504
|
+
if (
|
|
505
|
+
typeof this.options.fixedHeaderOptions.xAxis !== 'undefined' &&
|
|
506
|
+
typeof this.options.fixedSelectColumn === 'undefined'
|
|
507
|
+
) {
|
|
508
|
+
this.options.fixedSelectColumn = this.options.fixedHeaderOptions.xAxis;
|
|
509
|
+
}
|
|
510
|
+
this.warnDep(
|
|
511
|
+
'fixedHeaderOptions will still work but has been deprecated in favor of fixedHeader and fixedSelectColumn. More info: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
if (this.options.serverSideFilterList) {
|
|
515
|
+
this.warnDep(
|
|
516
|
+
'serverSideFilterList will still work but has been deprecated in favor of the confirmFilters option. See this example for details: https://github.com/gregnb/mui-datatables/blob/master/examples/serverside-filters/index.js More info here: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
props.columns.map((c) => {
|
|
521
|
+
if (c.options && c.options.customFilterListRender) {
|
|
522
|
+
this.warnDep(
|
|
523
|
+
'The customFilterListRender option has been deprecated. It is being replaced by customFilterListOptions.render (Specify customFilterListOptions: { render: Function } in column options.)',
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
if (this.options.disableToolbarSelect === true) {
|
|
529
|
+
this.warnDep(
|
|
530
|
+
'disableToolbarSelect has been deprecated but will still work in version 3.x. It is being replaced by "selectToolbarPlacement"="none". More info: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// only give this warning message in newer browsers
|
|
535
|
+
if (Object.values) {
|
|
536
|
+
if (Object.values(STP).indexOf(this.options.selectToolbarPlacement) === -1) {
|
|
537
|
+
this.warnDep(
|
|
538
|
+
'Invalid option value for selectToolbarPlacement. Please check the documentation: https://github.com/gregnb/mui-datatables#options',
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/*
|
|
545
|
+
* React currently does not support deep merge for defaultProps. Objects are overwritten
|
|
546
|
+
*/
|
|
547
|
+
mergeDefaultOptions(props) {
|
|
548
|
+
const defaultOptions = this.getDefaultOptions();
|
|
549
|
+
const theProps = Object.assign({}, props);
|
|
550
|
+
theProps.options = theProps.options || {};
|
|
551
|
+
|
|
552
|
+
this.updateOptions(defaultOptions, theProps);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
validateOptions(options) {
|
|
556
|
+
if (options.serverSide && options.onTableChange === undefined) {
|
|
557
|
+
throw Error('onTableChange callback must be provided when using serverSide option');
|
|
558
|
+
}
|
|
559
|
+
if (options.expandableRows && options.renderExpandableRow === undefined) {
|
|
560
|
+
throw Error('renderExpandableRow must be provided when using expandableRows option');
|
|
561
|
+
}
|
|
562
|
+
if (options.rowsSelected && Array.isArray(options.rowsSelected) && options.rowsSelected.some(isNaN)) {
|
|
563
|
+
warnInfo('When using the rowsSelected option, must be provided an array of numbers only.');
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
setTableAction = (action) => {
|
|
568
|
+
if (typeof this.options.onTableChange === 'function') {
|
|
569
|
+
this.options.onTableChange(action, this.state);
|
|
570
|
+
}
|
|
571
|
+
if (this.options.storageKey) {
|
|
572
|
+
save(this.options.storageKey, this.state);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
setTableInit = (action) => {
|
|
577
|
+
if (typeof this.options.onTableInit === 'function') {
|
|
578
|
+
this.options.onTableInit(action, this.state);
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
getInitTableOptions() {
|
|
583
|
+
const optionNames = ['rowsPerPage', 'page', 'rowsSelected', 'rowsPerPageOptions'];
|
|
584
|
+
const optState = optionNames.reduce((acc, cur) => {
|
|
585
|
+
if (this.options[cur] !== undefined) {
|
|
586
|
+
acc[cur] = this.options[cur];
|
|
587
|
+
}
|
|
588
|
+
return acc;
|
|
589
|
+
}, {});
|
|
590
|
+
|
|
591
|
+
this.validateOptions(optState);
|
|
592
|
+
return optState;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
setHeadCellRef = (index, pos, el) => {
|
|
596
|
+
this.draggableHeadCellRefs[index] = el;
|
|
597
|
+
this.resizeHeadCellRefs[pos] = el;
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
// must be arrow function on local field to refer to the correct instance when passed around
|
|
601
|
+
// assigning it as arrow function in the JSX would cause hard to track re-render errors
|
|
602
|
+
getTableContentRef = () => this.tableContent.current;
|
|
603
|
+
|
|
604
|
+
/*
|
|
605
|
+
* Build the source table data
|
|
606
|
+
*
|
|
607
|
+
* newColumns - columns from the options object.
|
|
608
|
+
* prevColumns - columns object saved onto ths state.
|
|
609
|
+
* newColumnOrder - columnOrder from the options object.
|
|
610
|
+
* prevColumnOrder - columnOrder object saved onto the state.
|
|
611
|
+
*/
|
|
612
|
+
|
|
613
|
+
buildColumns = (newColumns, prevColumns = [], newColumnOrder, prevColumnOrder = []) => {
|
|
614
|
+
let columnData = [];
|
|
615
|
+
let filterData = [];
|
|
616
|
+
let filterList = [];
|
|
617
|
+
let columnOrder = [];
|
|
618
|
+
|
|
619
|
+
newColumns.forEach((column, colIndex) => {
|
|
620
|
+
let columnOptions = {
|
|
621
|
+
display: 'true',
|
|
622
|
+
empty: false,
|
|
623
|
+
filter: true,
|
|
624
|
+
sort: true,
|
|
625
|
+
print: true,
|
|
626
|
+
searchable: true,
|
|
627
|
+
download: true,
|
|
628
|
+
viewColumns: true,
|
|
629
|
+
sortCompare: null,
|
|
630
|
+
sortThirdClickReset: false,
|
|
631
|
+
sortDescFirst: false,
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
columnOrder.push(colIndex);
|
|
635
|
+
const options = { ...column.options };
|
|
636
|
+
|
|
637
|
+
if (typeof column === 'object') {
|
|
638
|
+
if (options) {
|
|
639
|
+
if (options.display !== undefined) {
|
|
640
|
+
options.display = options.display.toString();
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if (options.sortDirection === null || options.sortDirection) {
|
|
644
|
+
this.warnDep(
|
|
645
|
+
'The sortDirection column field has been deprecated. Please use the sortOrder option on the options object. More info: https://github.com/gregnb/mui-datatables/tree/master/docs/v2_to_v3_guide.md',
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// remember stored version of display if not overwritten
|
|
651
|
+
if (
|
|
652
|
+
typeof options.display === 'undefined' &&
|
|
653
|
+
prevColumns[colIndex] &&
|
|
654
|
+
prevColumns[colIndex].name === column.name &&
|
|
655
|
+
prevColumns[colIndex].display
|
|
656
|
+
) {
|
|
657
|
+
options.display = prevColumns[colIndex].display;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
columnOptions = {
|
|
661
|
+
name: column.name,
|
|
662
|
+
label: column.label ? column.label : column.name,
|
|
663
|
+
...columnOptions,
|
|
664
|
+
...options,
|
|
665
|
+
};
|
|
666
|
+
} else {
|
|
667
|
+
// remember stored version of display if not overwritten
|
|
668
|
+
if (prevColumns[colIndex] && prevColumns[colIndex].display) {
|
|
669
|
+
options.display = prevColumns[colIndex].display;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
columnOptions = { ...columnOptions, ...options, name: column, label: column };
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
columnData.push(columnOptions);
|
|
676
|
+
|
|
677
|
+
filterData[colIndex] = [];
|
|
678
|
+
filterList[colIndex] = [];
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
if (Array.isArray(newColumnOrder)) {
|
|
682
|
+
columnOrder = newColumnOrder;
|
|
683
|
+
} else if (
|
|
684
|
+
Array.isArray(prevColumnOrder) &&
|
|
685
|
+
Array.isArray(newColumns) &&
|
|
686
|
+
Array.isArray(prevColumns) &&
|
|
687
|
+
newColumns.length === prevColumns.length
|
|
688
|
+
) {
|
|
689
|
+
columnOrder = prevColumnOrder;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
return { columns: columnData, filterData, filterList, columnOrder };
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
transformData = (columns, data) => {
|
|
696
|
+
const { enableNestedDataAccess } = this.options;
|
|
697
|
+
const leaf = (obj, path) =>
|
|
698
|
+
(enableNestedDataAccess ? path.split(enableNestedDataAccess) : path.split()).reduce(
|
|
699
|
+
(value, el) => (value ? value[el] : undefined),
|
|
700
|
+
obj,
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
const transformedData = Array.isArray(data[0])
|
|
704
|
+
? data.map((row) => {
|
|
705
|
+
let i = -1;
|
|
706
|
+
|
|
707
|
+
return columns.map((col) => {
|
|
708
|
+
if (!col.empty) i++;
|
|
709
|
+
return col.empty ? undefined : row[i];
|
|
710
|
+
});
|
|
711
|
+
})
|
|
712
|
+
: data.map((row) => columns.map((col) => leaf(row, col.name)));
|
|
713
|
+
|
|
714
|
+
return transformedData;
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
setTableData(props, status, dataUpdated, callback = () => {}, fromConstructor = false) {
|
|
718
|
+
let tableData = [];
|
|
719
|
+
let { columns, filterData, filterList, columnOrder } = this.buildColumns(
|
|
720
|
+
props.columns,
|
|
721
|
+
this.state.columns,
|
|
722
|
+
this.options.columnOrder,
|
|
723
|
+
this.state.columnOrder,
|
|
724
|
+
);
|
|
725
|
+
|
|
726
|
+
let sortIndex = null;
|
|
727
|
+
let sortDirection = 'none';
|
|
728
|
+
let tableMeta;
|
|
729
|
+
|
|
730
|
+
let sortOrder;
|
|
731
|
+
if (this.options.sortOrder && this.options.sortOrder.direction && this.options.sortOrder.name) {
|
|
732
|
+
sortOrder = Object.assign({}, this.options.sortOrder);
|
|
733
|
+
} else {
|
|
734
|
+
sortOrder = Object.assign({}, this.state.sortOrder);
|
|
735
|
+
|
|
736
|
+
// if no sortOrder, check and see if there's a sortDirection on one of the columns (deprecation notice for this is given above)
|
|
737
|
+
if (!sortOrder.direction) {
|
|
738
|
+
props.columns.forEach((column, colIndex) => {
|
|
739
|
+
if (column.options && (column.options.sortDirection === 'asc' || column.options.sortDirection === 'desc')) {
|
|
740
|
+
sortOrder.name = column.name;
|
|
741
|
+
sortOrder.sortDirection = column.sortDirection;
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const data = status === TABLE_LOAD.INITIAL ? this.transformData(columns, props.data) : props.data;
|
|
748
|
+
let searchText = status === TABLE_LOAD.INITIAL ? this.options.searchText : null;
|
|
749
|
+
|
|
750
|
+
if (typeof this.options.searchText === 'undefined' && typeof this.state.searchText !== 'undefined') {
|
|
751
|
+
searchText = this.state.searchText;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
let rowsPerPage = this.state.rowsPerPage;
|
|
755
|
+
if (typeof this.options.rowsPerPage === 'number') {
|
|
756
|
+
rowsPerPage = this.options.rowsPerPage;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
let page = this.state.page;
|
|
760
|
+
if (typeof this.options.page === 'number') {
|
|
761
|
+
page = this.options.page;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
columns.forEach((column, colIndex) => {
|
|
765
|
+
for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {
|
|
766
|
+
let value = status === TABLE_LOAD.INITIAL ? data[rowIndex][colIndex] : data[rowIndex].data[colIndex];
|
|
767
|
+
|
|
768
|
+
if (typeof tableData[rowIndex] === 'undefined') {
|
|
769
|
+
tableData.push({
|
|
770
|
+
index: status === TABLE_LOAD.INITIAL ? rowIndex : data[rowIndex].index,
|
|
771
|
+
data: status === TABLE_LOAD.INITIAL ? data[rowIndex] : data[rowIndex].data,
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (column.filter !== false) {
|
|
776
|
+
if (typeof column.customBodyRender === 'function') {
|
|
777
|
+
const rowData = tableData[rowIndex].data;
|
|
778
|
+
tableMeta = this.getTableMeta(rowIndex, colIndex, rowData, column, data, this.state, tableData);
|
|
779
|
+
const funcResult = column.customBodyRender(value, tableMeta);
|
|
780
|
+
|
|
781
|
+
if (React.isValidElement(funcResult) && funcResult.props.value) {
|
|
782
|
+
value = funcResult.props.value;
|
|
783
|
+
} else if (typeof funcResult === 'string') {
|
|
784
|
+
value = funcResult;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
|
|
789
|
+
// it's extremely rare but possible to create an object without a toString method, ex: var x = Object.create(null);
|
|
790
|
+
// so this check has to be made
|
|
791
|
+
value = value.toString ? value.toString() : '';
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (filterData[colIndex].indexOf(value) < 0 && !Array.isArray(value)) {
|
|
795
|
+
filterData[colIndex].push(value);
|
|
796
|
+
} else if (Array.isArray(value)) {
|
|
797
|
+
value.forEach((element) => {
|
|
798
|
+
let elmVal;
|
|
799
|
+
if ((typeof element === 'object' && element !== null) || typeof element === 'function') {
|
|
800
|
+
elmVal = element.toString ? element.toString() : '';
|
|
801
|
+
} else {
|
|
802
|
+
elmVal = element;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
if (filterData[colIndex].indexOf(elmVal) < 0) {
|
|
806
|
+
filterData[colIndex].push(elmVal);
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
if (column.filterOptions) {
|
|
814
|
+
if (Array.isArray(column.filterOptions)) {
|
|
815
|
+
filterData[colIndex] = cloneDeep(column.filterOptions);
|
|
816
|
+
this.warnDep(
|
|
817
|
+
'filterOptions must now be an object. see https://github.com/gregnb/mui-datatables/tree/master/examples/customize-filter example',
|
|
818
|
+
);
|
|
819
|
+
} else if (Array.isArray(column.filterOptions.names)) {
|
|
820
|
+
filterData[colIndex] = cloneDeep(column.filterOptions.names);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (column.filterList) {
|
|
825
|
+
filterList[colIndex] = cloneDeep(column.filterList);
|
|
826
|
+
} else if (
|
|
827
|
+
this.state.filterList &&
|
|
828
|
+
this.state.filterList[colIndex] &&
|
|
829
|
+
this.state.filterList[colIndex].length > 0
|
|
830
|
+
) {
|
|
831
|
+
filterList[colIndex] = cloneDeep(this.state.filterList[colIndex]);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if (this.options.sortFilterList) {
|
|
835
|
+
const comparator = getCollatorComparator();
|
|
836
|
+
filterData[colIndex].sort(comparator);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
if (column.name === sortOrder.name) {
|
|
840
|
+
sortDirection = sortOrder.direction;
|
|
841
|
+
sortIndex = colIndex;
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
let selectedRowsData = {
|
|
846
|
+
data: [],
|
|
847
|
+
lookup: {},
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
let expandedRowsData = {
|
|
851
|
+
data: [],
|
|
852
|
+
lookup: {},
|
|
853
|
+
};
|
|
854
|
+
|
|
855
|
+
if (TABLE_LOAD.INITIAL) {
|
|
856
|
+
// Multiple row selection customization
|
|
857
|
+
if (this.options.rowsSelected && this.options.rowsSelected.length && this.options.selectableRows === 'multiple') {
|
|
858
|
+
this.options.rowsSelected
|
|
859
|
+
.filter((selectedRowIndex) => selectedRowIndex === 0 || (Number(selectedRowIndex) && selectedRowIndex > 0))
|
|
860
|
+
.forEach((row) => {
|
|
861
|
+
let rowPos = row;
|
|
862
|
+
|
|
863
|
+
for (let cIndex = 0; cIndex < this.state.displayData.length; cIndex++) {
|
|
864
|
+
if (this.state.displayData[cIndex].dataIndex === row) {
|
|
865
|
+
rowPos = cIndex;
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
selectedRowsData.data.push({ index: rowPos, dataIndex: row });
|
|
871
|
+
selectedRowsData.lookup[row] = true;
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
// Single row selection customization
|
|
875
|
+
} else if (
|
|
876
|
+
this.options.rowsSelected &&
|
|
877
|
+
this.options.rowsSelected.length === 1 &&
|
|
878
|
+
this.options.selectableRows === 'single'
|
|
879
|
+
) {
|
|
880
|
+
let rowPos = this.options.rowsSelected[0];
|
|
881
|
+
|
|
882
|
+
for (let cIndex = 0; cIndex < this.state.displayData.length; cIndex++) {
|
|
883
|
+
if (this.state.displayData[cIndex].dataIndex === this.options.rowsSelected[0]) {
|
|
884
|
+
rowPos = cIndex;
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
selectedRowsData.data.push({ index: rowPos, dataIndex: this.options.rowsSelected[0] });
|
|
890
|
+
selectedRowsData.lookup[this.options.rowsSelected[0]] = true;
|
|
891
|
+
} else if (
|
|
892
|
+
this.options.rowsSelected &&
|
|
893
|
+
this.options.rowsSelected.length > 1 &&
|
|
894
|
+
this.options.selectableRows === 'single'
|
|
895
|
+
) {
|
|
896
|
+
console.error(
|
|
897
|
+
'Multiple values provided for selectableRows, but selectableRows set to "single". Either supply only a single value or use "multiple".',
|
|
898
|
+
);
|
|
899
|
+
} else if (typeof this.options.rowsSelected === 'undefined' && dataUpdated === false) {
|
|
900
|
+
if (this.state.selectedRows) {
|
|
901
|
+
selectedRowsData = Object.assign({}, this.state.selectedRows);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
if (this.options.rowsExpanded && this.options.rowsExpanded.length && this.options.expandableRows) {
|
|
906
|
+
this.options.rowsExpanded.forEach((row) => {
|
|
907
|
+
let rowPos = row;
|
|
908
|
+
|
|
909
|
+
for (let cIndex = 0; cIndex < this.state.displayData.length; cIndex++) {
|
|
910
|
+
if (this.state.displayData[cIndex].dataIndex === row) {
|
|
911
|
+
rowPos = cIndex;
|
|
912
|
+
break;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
expandedRowsData.data.push({ index: rowPos, dataIndex: row });
|
|
917
|
+
expandedRowsData.lookup[row] = true;
|
|
918
|
+
});
|
|
919
|
+
} else if (typeof this.options.rowsExpanded === 'undefined' && dataUpdated === false && this.state.expandedRows) {
|
|
920
|
+
expandedRowsData = Object.assign({}, this.state.expandedRows);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
if (!this.options.serverSide && sortIndex !== null) {
|
|
925
|
+
const sortedData = this.sortTable(tableData, sortIndex, sortDirection, columns[sortIndex].sortCompare);
|
|
926
|
+
tableData = sortedData.data;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/* set source data and display Data set source set */
|
|
930
|
+
let stateUpdates = {
|
|
931
|
+
columns: columns,
|
|
932
|
+
filterData: filterData,
|
|
933
|
+
filterList: filterList,
|
|
934
|
+
searchText: searchText,
|
|
935
|
+
selectedRows: selectedRowsData,
|
|
936
|
+
expandedRows: expandedRowsData,
|
|
937
|
+
count: this.options.count,
|
|
938
|
+
data: tableData,
|
|
939
|
+
sortOrder: sortOrder,
|
|
940
|
+
rowsPerPage,
|
|
941
|
+
page,
|
|
942
|
+
displayData: this.getDisplayData(columns, tableData, filterList, searchText, tableMeta, props),
|
|
943
|
+
columnOrder,
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
if (fromConstructor) {
|
|
947
|
+
this.state = Object.assign({}, this.state, stateUpdates);
|
|
948
|
+
} else {
|
|
949
|
+
this.setState(stateUpdates, callback);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/*
|
|
954
|
+
* Build the table data used to display to the user (ie: after filter/search applied)
|
|
955
|
+
*/
|
|
956
|
+
computeDisplayRow(
|
|
957
|
+
columns,
|
|
958
|
+
row,
|
|
959
|
+
rowIndex,
|
|
960
|
+
filterList,
|
|
961
|
+
searchText,
|
|
962
|
+
dataForTableMeta,
|
|
963
|
+
options,
|
|
964
|
+
props,
|
|
965
|
+
currentTableData,
|
|
966
|
+
) {
|
|
967
|
+
let isFiltered = false;
|
|
968
|
+
let isSearchFound = false;
|
|
969
|
+
let displayRow = [];
|
|
970
|
+
|
|
971
|
+
for (let index = 0; index < row.length; index++) {
|
|
972
|
+
let columnDisplay = row[index];
|
|
973
|
+
let columnValue = row[index];
|
|
974
|
+
let column = columns[index];
|
|
975
|
+
|
|
976
|
+
if (column.customBodyRenderLite) {
|
|
977
|
+
displayRow.push(column.customBodyRenderLite);
|
|
978
|
+
} else if (column.customBodyRender) {
|
|
979
|
+
const tableMeta = this.getTableMeta(
|
|
980
|
+
rowIndex,
|
|
981
|
+
index,
|
|
982
|
+
row,
|
|
983
|
+
column,
|
|
984
|
+
dataForTableMeta,
|
|
985
|
+
{
|
|
986
|
+
...this.state,
|
|
987
|
+
filterList: filterList,
|
|
988
|
+
searchText: searchText,
|
|
989
|
+
},
|
|
990
|
+
currentTableData,
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
const funcResult = column.customBodyRender(
|
|
994
|
+
columnValue,
|
|
995
|
+
tableMeta,
|
|
996
|
+
this.updateDataCol.bind(null, rowIndex, index),
|
|
997
|
+
);
|
|
998
|
+
columnDisplay = funcResult;
|
|
999
|
+
|
|
1000
|
+
/* drill down to get the value of a cell */
|
|
1001
|
+
columnValue =
|
|
1002
|
+
typeof funcResult === 'string' || !funcResult
|
|
1003
|
+
? funcResult
|
|
1004
|
+
: funcResult.props && funcResult.props.value
|
|
1005
|
+
? funcResult.props.value
|
|
1006
|
+
: columnValue;
|
|
1007
|
+
|
|
1008
|
+
displayRow.push(columnDisplay);
|
|
1009
|
+
} else {
|
|
1010
|
+
displayRow.push(columnDisplay);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
const columnVal = columnValue === null || columnValue === undefined ? '' : columnValue.toString();
|
|
1014
|
+
|
|
1015
|
+
const filterVal = filterList[index];
|
|
1016
|
+
const caseSensitive = options.caseSensitive;
|
|
1017
|
+
const filterType = column.filterType || options.filterType;
|
|
1018
|
+
if (filterVal.length || filterType === 'custom') {
|
|
1019
|
+
if (column.filterOptions && column.filterOptions.logic) {
|
|
1020
|
+
if (column.filterOptions.logic(columnValue, filterVal, row)) isFiltered = true;
|
|
1021
|
+
} else if (filterType === 'textField' && !this.hasSearchText(columnVal, filterVal, caseSensitive)) {
|
|
1022
|
+
isFiltered = true;
|
|
1023
|
+
} else if (
|
|
1024
|
+
filterType !== 'textField' &&
|
|
1025
|
+
Array.isArray(columnValue) === false &&
|
|
1026
|
+
filterVal.indexOf(columnValue) < 0
|
|
1027
|
+
) {
|
|
1028
|
+
isFiltered = true;
|
|
1029
|
+
} else if (filterType !== 'textField' && Array.isArray(columnValue)) {
|
|
1030
|
+
if (options.filterArrayFullMatch) {
|
|
1031
|
+
//true if every filterVal exists in columnVal, false otherwise
|
|
1032
|
+
const isFullMatch = filterVal.every((el) => {
|
|
1033
|
+
return columnValue.indexOf(el) >= 0;
|
|
1034
|
+
});
|
|
1035
|
+
//if it is not a fullMatch, filter row out
|
|
1036
|
+
if (!isFullMatch) {
|
|
1037
|
+
isFiltered = true;
|
|
1038
|
+
}
|
|
1039
|
+
} else {
|
|
1040
|
+
const isAnyMatch = filterVal.some((el) => {
|
|
1041
|
+
return columnValue.indexOf(el) >= 0;
|
|
1042
|
+
});
|
|
1043
|
+
//if no value matches, filter row out
|
|
1044
|
+
if (!isAnyMatch) {
|
|
1045
|
+
isFiltered = true;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
if (
|
|
1052
|
+
searchText &&
|
|
1053
|
+
column.display !== 'excluded' &&
|
|
1054
|
+
this.hasSearchText(columnVal, searchText, caseSensitive) &&
|
|
1055
|
+
column.display !== 'false' &&
|
|
1056
|
+
column.searchable
|
|
1057
|
+
) {
|
|
1058
|
+
isSearchFound = true;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
const { customSearch } = props.options;
|
|
1063
|
+
|
|
1064
|
+
if (searchText && customSearch) {
|
|
1065
|
+
const customSearchResult = customSearch(searchText, row, columns);
|
|
1066
|
+
if (typeof customSearchResult !== 'boolean') {
|
|
1067
|
+
console.error('customSearch must return a boolean');
|
|
1068
|
+
} else {
|
|
1069
|
+
isSearchFound = customSearchResult;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
if (options.serverSide) {
|
|
1074
|
+
if (customSearch) {
|
|
1075
|
+
console.warn('Server-side filtering is enabled, hence custom search will be ignored.');
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
return displayRow;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
if (isFiltered || (searchText && !isSearchFound)) return null;
|
|
1082
|
+
else return displayRow;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
hasSearchText = (toSearch, toFind, caseSensitive) => {
|
|
1086
|
+
let stack = toSearch.toString();
|
|
1087
|
+
let needle = toFind.toString();
|
|
1088
|
+
|
|
1089
|
+
if (!caseSensitive) {
|
|
1090
|
+
needle = needle.toLowerCase();
|
|
1091
|
+
stack = stack.toLowerCase();
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
return stack.indexOf(needle) >= 0;
|
|
1095
|
+
};
|
|
1096
|
+
|
|
1097
|
+
updateDataCol = (row, index, value) => {
|
|
1098
|
+
this.setState((prevState) => {
|
|
1099
|
+
let changedData = cloneDeep(prevState.data);
|
|
1100
|
+
let filterData = cloneDeep(prevState.filterData);
|
|
1101
|
+
|
|
1102
|
+
const tableMeta = this.getTableMeta(
|
|
1103
|
+
row,
|
|
1104
|
+
index,
|
|
1105
|
+
row,
|
|
1106
|
+
prevState.columns[index],
|
|
1107
|
+
prevState.data,
|
|
1108
|
+
prevState,
|
|
1109
|
+
prevState.data,
|
|
1110
|
+
);
|
|
1111
|
+
const funcResult = prevState.columns[index].customBodyRender(value, tableMeta);
|
|
1112
|
+
|
|
1113
|
+
const filterValue =
|
|
1114
|
+
React.isValidElement(funcResult) && funcResult.props.value
|
|
1115
|
+
? funcResult.props.value
|
|
1116
|
+
: prevState['data'][row][index];
|
|
1117
|
+
|
|
1118
|
+
const prevFilterIndex = filterData[index].indexOf(filterValue);
|
|
1119
|
+
filterData[index].splice(prevFilterIndex, 1, filterValue);
|
|
1120
|
+
|
|
1121
|
+
changedData[row].data[index] = value;
|
|
1122
|
+
|
|
1123
|
+
if (this.options.sortFilterList) {
|
|
1124
|
+
const comparator = getCollatorComparator();
|
|
1125
|
+
filterData[index].sort(comparator);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
return {
|
|
1129
|
+
data: changedData,
|
|
1130
|
+
filterData: filterData,
|
|
1131
|
+
displayData: this.getDisplayData(
|
|
1132
|
+
prevState.columns,
|
|
1133
|
+
changedData,
|
|
1134
|
+
prevState.filterList,
|
|
1135
|
+
prevState.searchText,
|
|
1136
|
+
null,
|
|
1137
|
+
this.props,
|
|
1138
|
+
),
|
|
1139
|
+
};
|
|
1140
|
+
});
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
getTableMeta = (rowIndex, colIndex, rowData, columnData, tableData, curState, currentTableData) => {
|
|
1144
|
+
const { columns, data, displayData, filterData, ...tableState } = curState;
|
|
1145
|
+
|
|
1146
|
+
return {
|
|
1147
|
+
rowIndex: rowIndex,
|
|
1148
|
+
columnIndex: colIndex,
|
|
1149
|
+
columnData: columnData,
|
|
1150
|
+
rowData: rowData,
|
|
1151
|
+
tableData: tableData,
|
|
1152
|
+
tableState: tableState,
|
|
1153
|
+
currentTableData: currentTableData,
|
|
1154
|
+
};
|
|
1155
|
+
};
|
|
1156
|
+
|
|
1157
|
+
getDisplayData(columns, data, filterList, searchText, tableMeta, props) {
|
|
1158
|
+
let newRows = [];
|
|
1159
|
+
const dataForTableMeta = tableMeta ? tableMeta.tableData : props.data;
|
|
1160
|
+
|
|
1161
|
+
for (let index = 0; index < data.length; index++) {
|
|
1162
|
+
const value = data[index].data;
|
|
1163
|
+
const displayRow = this.computeDisplayRow(
|
|
1164
|
+
columns,
|
|
1165
|
+
value,
|
|
1166
|
+
index,
|
|
1167
|
+
filterList,
|
|
1168
|
+
searchText,
|
|
1169
|
+
dataForTableMeta,
|
|
1170
|
+
this.options,
|
|
1171
|
+
props,
|
|
1172
|
+
data,
|
|
1173
|
+
);
|
|
1174
|
+
|
|
1175
|
+
if (displayRow) {
|
|
1176
|
+
newRows.push({
|
|
1177
|
+
data: displayRow,
|
|
1178
|
+
dataIndex: data[index].index,
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
return newRows;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
toggleViewColumn = (index) => {
|
|
1186
|
+
this.setState(
|
|
1187
|
+
(prevState) => {
|
|
1188
|
+
const columns = cloneDeep(prevState.columns);
|
|
1189
|
+
columns[index].display = columns[index].display === 'true' ? 'false' : 'true';
|
|
1190
|
+
return {
|
|
1191
|
+
columns: columns,
|
|
1192
|
+
};
|
|
1193
|
+
},
|
|
1194
|
+
() => {
|
|
1195
|
+
this.setTableAction('viewColumnsChange');
|
|
1196
|
+
var cb = this.options.onViewColumnsChange || this.options.onColumnViewChange;
|
|
1197
|
+
|
|
1198
|
+
if (cb) {
|
|
1199
|
+
cb(this.state.columns[index].name, this.state.columns[index].display === 'true' ? 'add' : 'remove');
|
|
1200
|
+
}
|
|
1201
|
+
},
|
|
1202
|
+
);
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
updateColumns = (newColumns) => {
|
|
1206
|
+
this.setState(
|
|
1207
|
+
(prevState) => {
|
|
1208
|
+
return {
|
|
1209
|
+
columns: newColumns,
|
|
1210
|
+
};
|
|
1211
|
+
},
|
|
1212
|
+
() => {
|
|
1213
|
+
this.setTableAction('viewColumnsChange');
|
|
1214
|
+
var cb = this.options.onViewColumnsChange || this.options.onColumnViewChange;
|
|
1215
|
+
|
|
1216
|
+
if (cb) {
|
|
1217
|
+
cb(null, 'update', newColumns);
|
|
1218
|
+
}
|
|
1219
|
+
},
|
|
1220
|
+
);
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
getSortDirectionLabel(sortOrder) {
|
|
1224
|
+
switch (sortOrder.direction) {
|
|
1225
|
+
case 'asc':
|
|
1226
|
+
return 'ascending';
|
|
1227
|
+
case 'desc':
|
|
1228
|
+
return 'descending';
|
|
1229
|
+
case 'none':
|
|
1230
|
+
return 'none';
|
|
1231
|
+
default:
|
|
1232
|
+
return '';
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
getTableProps() {
|
|
1237
|
+
const { classes } = this.props;
|
|
1238
|
+
const tableProps = this.options.setTableProps() || {};
|
|
1239
|
+
|
|
1240
|
+
tableProps.className = clsx(classes.tableRoot, tableProps.className);
|
|
1241
|
+
|
|
1242
|
+
return tableProps;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
toggleSortColumn = (index) => {
|
|
1246
|
+
this.setState(
|
|
1247
|
+
(prevState) => {
|
|
1248
|
+
let columns = cloneDeep(prevState.columns);
|
|
1249
|
+
let data = prevState.data;
|
|
1250
|
+
let newOrder = columns[index].sortDescFirst ? 'desc' : 'asc'; // default
|
|
1251
|
+
|
|
1252
|
+
let sequenceOrder = ['asc', 'desc'];
|
|
1253
|
+
if (columns[index].sortDescFirst) {
|
|
1254
|
+
sequenceOrder = ['desc', 'asc'];
|
|
1255
|
+
}
|
|
1256
|
+
if (columns[index].sortThirdClickReset) {
|
|
1257
|
+
sequenceOrder.push('none');
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
if (columns[index].name === this.state.sortOrder.name) {
|
|
1261
|
+
let pos = sequenceOrder.indexOf(this.state.sortOrder.direction);
|
|
1262
|
+
if (pos !== -1) {
|
|
1263
|
+
pos++;
|
|
1264
|
+
if (pos >= sequenceOrder.length) pos = 0;
|
|
1265
|
+
newOrder = sequenceOrder[pos];
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
const newSortOrder = {
|
|
1270
|
+
name: columns[index].name,
|
|
1271
|
+
direction: newOrder,
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
const orderLabel = this.getSortDirectionLabel(newSortOrder);
|
|
1275
|
+
const announceText = `Table now sorted by ${columns[index].name} : ${orderLabel}`;
|
|
1276
|
+
|
|
1277
|
+
let newState = {
|
|
1278
|
+
columns: columns,
|
|
1279
|
+
announceText: announceText,
|
|
1280
|
+
activeColumn: index,
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1283
|
+
if (this.options.serverSide) {
|
|
1284
|
+
newState = {
|
|
1285
|
+
...newState,
|
|
1286
|
+
data: prevState.data,
|
|
1287
|
+
displayData: prevState.displayData,
|
|
1288
|
+
selectedRows: prevState.selectedRows,
|
|
1289
|
+
sortOrder: newSortOrder,
|
|
1290
|
+
};
|
|
1291
|
+
} else {
|
|
1292
|
+
const sortedData = this.sortTable(data, index, newOrder, columns[index].sortCompare);
|
|
1293
|
+
|
|
1294
|
+
newState = {
|
|
1295
|
+
...newState,
|
|
1296
|
+
data: sortedData.data,
|
|
1297
|
+
displayData: this.getDisplayData(
|
|
1298
|
+
columns,
|
|
1299
|
+
sortedData.data,
|
|
1300
|
+
prevState.filterList,
|
|
1301
|
+
prevState.searchText,
|
|
1302
|
+
null,
|
|
1303
|
+
this.props,
|
|
1304
|
+
),
|
|
1305
|
+
selectedRows: sortedData.selectedRows,
|
|
1306
|
+
sortOrder: newSortOrder,
|
|
1307
|
+
previousSelectedRow: null,
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
return newState;
|
|
1312
|
+
},
|
|
1313
|
+
() => {
|
|
1314
|
+
this.setTableAction('sort');
|
|
1315
|
+
|
|
1316
|
+
if (this.options.onColumnSortChange) {
|
|
1317
|
+
this.options.onColumnSortChange(this.state.sortOrder.name, this.state.sortOrder.direction);
|
|
1318
|
+
}
|
|
1319
|
+
},
|
|
1320
|
+
);
|
|
1321
|
+
};
|
|
1322
|
+
|
|
1323
|
+
changeRowsPerPage = (rows) => {
|
|
1324
|
+
const rowCount = this.options.count || this.state.displayData.length;
|
|
1325
|
+
|
|
1326
|
+
this.setState(
|
|
1327
|
+
() => ({
|
|
1328
|
+
rowsPerPage: rows,
|
|
1329
|
+
page: getPageValue(rowCount, rows, this.state.page),
|
|
1330
|
+
}),
|
|
1331
|
+
() => {
|
|
1332
|
+
this.setTableAction('changeRowsPerPage');
|
|
1333
|
+
|
|
1334
|
+
if (this.options.onChangeRowsPerPage) {
|
|
1335
|
+
this.options.onChangeRowsPerPage(this.state.rowsPerPage);
|
|
1336
|
+
}
|
|
1337
|
+
},
|
|
1338
|
+
);
|
|
1339
|
+
};
|
|
1340
|
+
|
|
1341
|
+
changePage = (page) => {
|
|
1342
|
+
this.setState(
|
|
1343
|
+
() => ({
|
|
1344
|
+
page: page,
|
|
1345
|
+
}),
|
|
1346
|
+
() => {
|
|
1347
|
+
this.setTableAction('changePage');
|
|
1348
|
+
if (this.options.onChangePage) {
|
|
1349
|
+
this.options.onChangePage(this.state.page);
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
);
|
|
1353
|
+
};
|
|
1354
|
+
|
|
1355
|
+
searchClose = () => {
|
|
1356
|
+
this.setState(
|
|
1357
|
+
(prevState) => ({
|
|
1358
|
+
searchText: null,
|
|
1359
|
+
displayData: this.options.serverSide
|
|
1360
|
+
? prevState.displayData
|
|
1361
|
+
: this.getDisplayData(prevState.columns, prevState.data, prevState.filterList, null, null, this.props),
|
|
1362
|
+
}),
|
|
1363
|
+
() => {
|
|
1364
|
+
this.setTableAction('search');
|
|
1365
|
+
if (this.options.onSearchChange) {
|
|
1366
|
+
this.options.onSearchChange(this.state.searchText);
|
|
1367
|
+
}
|
|
1368
|
+
},
|
|
1369
|
+
);
|
|
1370
|
+
};
|
|
1371
|
+
|
|
1372
|
+
searchTextUpdate = (text) => {
|
|
1373
|
+
this.setState(
|
|
1374
|
+
(prevState) => ({
|
|
1375
|
+
searchText: text && text.length ? text : null,
|
|
1376
|
+
page: 0,
|
|
1377
|
+
displayData: this.options.serverSide
|
|
1378
|
+
? prevState.displayData
|
|
1379
|
+
: this.getDisplayData(prevState.columns, prevState.data, prevState.filterList, text, null, this.props),
|
|
1380
|
+
}),
|
|
1381
|
+
() => {
|
|
1382
|
+
this.setTableAction('search');
|
|
1383
|
+
if (this.options.onSearchChange) {
|
|
1384
|
+
this.options.onSearchChange(this.state.searchText);
|
|
1385
|
+
}
|
|
1386
|
+
},
|
|
1387
|
+
);
|
|
1388
|
+
};
|
|
1389
|
+
|
|
1390
|
+
resetFilters = () => {
|
|
1391
|
+
this.setState(
|
|
1392
|
+
(prevState) => {
|
|
1393
|
+
const filterList = prevState.columns.map(() => []);
|
|
1394
|
+
|
|
1395
|
+
return {
|
|
1396
|
+
filterList: filterList,
|
|
1397
|
+
displayData: this.options.serverSide
|
|
1398
|
+
? prevState.displayData
|
|
1399
|
+
: this.getDisplayData(
|
|
1400
|
+
prevState.columns,
|
|
1401
|
+
prevState.data,
|
|
1402
|
+
filterList,
|
|
1403
|
+
prevState.searchText,
|
|
1404
|
+
null,
|
|
1405
|
+
this.props,
|
|
1406
|
+
),
|
|
1407
|
+
};
|
|
1408
|
+
},
|
|
1409
|
+
() => {
|
|
1410
|
+
this.setTableAction('resetFilters');
|
|
1411
|
+
if (this.options.onFilterChange) {
|
|
1412
|
+
this.options.onFilterChange(null, this.state.filterList, 'reset', null);
|
|
1413
|
+
}
|
|
1414
|
+
},
|
|
1415
|
+
);
|
|
1416
|
+
};
|
|
1417
|
+
|
|
1418
|
+
updateFilterByType = (filterList, index, value, type, customUpdate) => {
|
|
1419
|
+
const filterPos = filterList[index].findIndex((filter) => isEqual(filter, value));
|
|
1420
|
+
|
|
1421
|
+
switch (type) {
|
|
1422
|
+
case 'checkbox':
|
|
1423
|
+
filterPos >= 0 ? filterList[index].splice(filterPos, 1) : filterList[index].push(value);
|
|
1424
|
+
break;
|
|
1425
|
+
case 'chip':
|
|
1426
|
+
filterPos >= 0 ? filterList[index].splice(filterPos, 1) : filterList[index].push(value);
|
|
1427
|
+
break;
|
|
1428
|
+
case 'multiselect':
|
|
1429
|
+
filterList[index] = value === '' ? [] : value;
|
|
1430
|
+
break;
|
|
1431
|
+
case 'dropdown':
|
|
1432
|
+
filterList[index] = value;
|
|
1433
|
+
break;
|
|
1434
|
+
case 'custom':
|
|
1435
|
+
if (customUpdate) {
|
|
1436
|
+
filterList = customUpdate(filterList, filterPos, index);
|
|
1437
|
+
} else {
|
|
1438
|
+
filterList[index] = value;
|
|
1439
|
+
}
|
|
1440
|
+
break;
|
|
1441
|
+
default:
|
|
1442
|
+
filterList[index] = filterPos >= 0 || value === '' ? [] : [value];
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
|
|
1446
|
+
filterUpdate = (index, value, column, type, customUpdate, next) => {
|
|
1447
|
+
this.setState(
|
|
1448
|
+
(prevState) => {
|
|
1449
|
+
const filterList = cloneDeep(prevState.filterList);
|
|
1450
|
+
this.updateFilterByType(filterList, index, value, type, customUpdate);
|
|
1451
|
+
|
|
1452
|
+
return {
|
|
1453
|
+
page: 0,
|
|
1454
|
+
filterList: filterList,
|
|
1455
|
+
displayData: this.options.serverSide
|
|
1456
|
+
? prevState.displayData
|
|
1457
|
+
: this.getDisplayData(
|
|
1458
|
+
prevState.columns,
|
|
1459
|
+
prevState.data,
|
|
1460
|
+
filterList,
|
|
1461
|
+
prevState.searchText,
|
|
1462
|
+
null,
|
|
1463
|
+
this.props,
|
|
1464
|
+
),
|
|
1465
|
+
previousSelectedRow: null,
|
|
1466
|
+
};
|
|
1467
|
+
},
|
|
1468
|
+
() => {
|
|
1469
|
+
this.setTableAction('filterChange');
|
|
1470
|
+
if (this.options.onFilterChange) {
|
|
1471
|
+
this.options.onFilterChange(column, this.state.filterList, type, index, this.state.displayData);
|
|
1472
|
+
}
|
|
1473
|
+
next && next(this.state.filterList);
|
|
1474
|
+
},
|
|
1475
|
+
);
|
|
1476
|
+
};
|
|
1477
|
+
|
|
1478
|
+
// Collapses or expands all expanded rows
|
|
1479
|
+
toggleAllExpandableRows = () => {
|
|
1480
|
+
let expandedRowsData = [...this.state.expandedRows.data];
|
|
1481
|
+
const { isRowExpandable } = this.options;
|
|
1482
|
+
let affecttedRows = [];
|
|
1483
|
+
|
|
1484
|
+
if (expandedRowsData.length > 0) {
|
|
1485
|
+
// collapse all
|
|
1486
|
+
for (let ii = expandedRowsData.length - 1; ii >= 0; ii--) {
|
|
1487
|
+
let item = expandedRowsData[ii];
|
|
1488
|
+
if (!isRowExpandable || (isRowExpandable && isRowExpandable(item.dataIndex, this.state.expandedRows))) {
|
|
1489
|
+
affecttedRows.push(expandedRowsData.splice(ii, 1));
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
} else {
|
|
1493
|
+
// expand all
|
|
1494
|
+
for (let ii = 0; ii < this.state.data.length; ii++) {
|
|
1495
|
+
let item = this.state.data[ii];
|
|
1496
|
+
if (!isRowExpandable || (isRowExpandable && isRowExpandable(item.dataIndex, this.state.expandedRows))) {
|
|
1497
|
+
if (this.state.expandedRows.lookup[item.index] !== true) {
|
|
1498
|
+
let newItem = {
|
|
1499
|
+
index: ii,
|
|
1500
|
+
dataIndex: item.index,
|
|
1501
|
+
};
|
|
1502
|
+
expandedRowsData.push(newItem);
|
|
1503
|
+
affecttedRows.push(newItem);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
this.setState(
|
|
1510
|
+
{
|
|
1511
|
+
expandedRows: {
|
|
1512
|
+
lookup: buildMap(expandedRowsData),
|
|
1513
|
+
data: expandedRowsData,
|
|
1514
|
+
},
|
|
1515
|
+
},
|
|
1516
|
+
() => {
|
|
1517
|
+
this.setTableAction('expandRow');
|
|
1518
|
+
if (this.options.onRowExpansionChange) {
|
|
1519
|
+
this.options.onRowExpansionChange(
|
|
1520
|
+
affecttedRows,
|
|
1521
|
+
this.state.expandedRows.data,
|
|
1522
|
+
this.state.expandedRows.data.map((item) => item.dataIndex),
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
},
|
|
1526
|
+
);
|
|
1527
|
+
};
|
|
1528
|
+
|
|
1529
|
+
areAllRowsExpanded = () => {
|
|
1530
|
+
return this.state.expandedRows.data.length === this.state.data.length;
|
|
1531
|
+
};
|
|
1532
|
+
|
|
1533
|
+
updateColumnOrder = (columnOrder, columnIndex, newPosition) => {
|
|
1534
|
+
this.setState(
|
|
1535
|
+
(prevState) => {
|
|
1536
|
+
return {
|
|
1537
|
+
columnOrder,
|
|
1538
|
+
};
|
|
1539
|
+
},
|
|
1540
|
+
() => {
|
|
1541
|
+
this.setTableAction('columnOrderChange');
|
|
1542
|
+
if (this.options.onColumnOrderChange) {
|
|
1543
|
+
this.options.onColumnOrderChange(this.state.columnOrder, columnIndex, newPosition);
|
|
1544
|
+
}
|
|
1545
|
+
},
|
|
1546
|
+
);
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
selectRowDelete = () => {
|
|
1550
|
+
const { selectedRows, data, filterList } = this.state;
|
|
1551
|
+
|
|
1552
|
+
const selectedMap = buildMap(selectedRows.data);
|
|
1553
|
+
const cleanRows = data.filter(({ index }) => !selectedMap[index]);
|
|
1554
|
+
|
|
1555
|
+
if (this.options.onRowsDelete) {
|
|
1556
|
+
if (
|
|
1557
|
+
this.options.onRowsDelete(
|
|
1558
|
+
selectedRows,
|
|
1559
|
+
cleanRows.map((ii) => ii.data),
|
|
1560
|
+
) === false
|
|
1561
|
+
)
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
this.setTableData(
|
|
1566
|
+
{
|
|
1567
|
+
columns: this.props.columns,
|
|
1568
|
+
data: cleanRows,
|
|
1569
|
+
options: {
|
|
1570
|
+
filterList: filterList,
|
|
1571
|
+
},
|
|
1572
|
+
},
|
|
1573
|
+
TABLE_LOAD.UPDATE,
|
|
1574
|
+
true,
|
|
1575
|
+
() => {
|
|
1576
|
+
this.setTableAction('rowDelete');
|
|
1577
|
+
},
|
|
1578
|
+
);
|
|
1579
|
+
};
|
|
1580
|
+
|
|
1581
|
+
toggleExpandRow = (row) => {
|
|
1582
|
+
const { dataIndex } = row;
|
|
1583
|
+
const { isRowExpandable } = this.options;
|
|
1584
|
+
let { expandedRows } = this.state;
|
|
1585
|
+
const expandedRowsData = [...expandedRows.data];
|
|
1586
|
+
let shouldCollapseExpandedRow = false;
|
|
1587
|
+
let hasRemovedRow = false;
|
|
1588
|
+
let removedRow = [];
|
|
1589
|
+
|
|
1590
|
+
for (var cIndex = 0; cIndex < expandedRowsData.length; cIndex++) {
|
|
1591
|
+
if (expandedRowsData[cIndex].dataIndex === dataIndex) {
|
|
1592
|
+
shouldCollapseExpandedRow = true;
|
|
1593
|
+
break;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
if (shouldCollapseExpandedRow) {
|
|
1598
|
+
if ((isRowExpandable && isRowExpandable(dataIndex, expandedRows)) || !isRowExpandable) {
|
|
1599
|
+
removedRow = expandedRowsData.splice(cIndex, 1);
|
|
1600
|
+
hasRemovedRow = true;
|
|
1601
|
+
}
|
|
1602
|
+
} else {
|
|
1603
|
+
if (isRowExpandable && isRowExpandable(dataIndex, expandedRows)) expandedRowsData.push(row);
|
|
1604
|
+
else if (!isRowExpandable) expandedRowsData.push(row);
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
this.setState(
|
|
1608
|
+
{
|
|
1609
|
+
curExpandedRows: hasRemovedRow ? removedRow : [row],
|
|
1610
|
+
expandedRows: {
|
|
1611
|
+
lookup: buildMap(expandedRowsData),
|
|
1612
|
+
data: expandedRowsData,
|
|
1613
|
+
},
|
|
1614
|
+
},
|
|
1615
|
+
() => {
|
|
1616
|
+
this.setTableAction('rowExpansionChange');
|
|
1617
|
+
if (this.options.onRowExpansionChange || this.options.onRowsExpand) {
|
|
1618
|
+
let expandCallback = this.options.onRowExpansionChange || this.options.onRowsExpand;
|
|
1619
|
+
expandCallback(this.state.curExpandedRows, this.state.expandedRows.data);
|
|
1620
|
+
}
|
|
1621
|
+
},
|
|
1622
|
+
);
|
|
1623
|
+
};
|
|
1624
|
+
|
|
1625
|
+
selectRowUpdate = (type, value, shiftAdjacentRows = []) => {
|
|
1626
|
+
// safety check
|
|
1627
|
+
const { selectableRows } = this.options;
|
|
1628
|
+
if (selectableRows === 'none') {
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
if (type === 'head') {
|
|
1633
|
+
const { isRowSelectable } = this.options;
|
|
1634
|
+
this.setState(
|
|
1635
|
+
(prevState) => {
|
|
1636
|
+
const { displayData, selectedRows: prevSelectedRows } = prevState;
|
|
1637
|
+
const selectedRowsLen = prevState.selectedRows.data.length;
|
|
1638
|
+
let isDeselect =
|
|
1639
|
+
selectedRowsLen === displayData.length || (selectedRowsLen < displayData.length && selectedRowsLen > 0);
|
|
1640
|
+
|
|
1641
|
+
let selectedRows = displayData.reduce((arr, d, i) => {
|
|
1642
|
+
const selected = isRowSelectable ? isRowSelectable(displayData[i].dataIndex, prevSelectedRows) : true;
|
|
1643
|
+
selected && arr.push({ index: i, dataIndex: displayData[i].dataIndex });
|
|
1644
|
+
return arr;
|
|
1645
|
+
}, []);
|
|
1646
|
+
|
|
1647
|
+
let newRows = [...selectedRows];
|
|
1648
|
+
let selectedMap = buildMap(newRows);
|
|
1649
|
+
|
|
1650
|
+
// if the select toolbar is disabled, the rules are a little different
|
|
1651
|
+
if (this.options.selectToolbarPlacement === STP.NONE) {
|
|
1652
|
+
if (selectedRowsLen > displayData.length) {
|
|
1653
|
+
isDeselect = true;
|
|
1654
|
+
} else {
|
|
1655
|
+
for (let ii = 0; ii < displayData.length; ii++) {
|
|
1656
|
+
if (!selectedMap[displayData[ii].dataIndex]) {
|
|
1657
|
+
isDeselect = true;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
if (isDeselect) {
|
|
1664
|
+
newRows = prevState.selectedRows.data.filter(({ dataIndex }) => !selectedMap[dataIndex]);
|
|
1665
|
+
selectedMap = buildMap(newRows);
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
return {
|
|
1669
|
+
curSelectedRows: newRows,
|
|
1670
|
+
selectedRows: {
|
|
1671
|
+
data: newRows,
|
|
1672
|
+
lookup: selectedMap,
|
|
1673
|
+
},
|
|
1674
|
+
previousSelectedRow: null,
|
|
1675
|
+
};
|
|
1676
|
+
},
|
|
1677
|
+
() => {
|
|
1678
|
+
this.setTableAction('rowSelectionChange');
|
|
1679
|
+
if (this.options.onRowSelectionChange) {
|
|
1680
|
+
this.options.onRowSelectionChange(
|
|
1681
|
+
this.state.curSelectedRows,
|
|
1682
|
+
this.state.selectedRows.data,
|
|
1683
|
+
this.state.selectedRows.data.map((item) => item.dataIndex),
|
|
1684
|
+
);
|
|
1685
|
+
} else if (this.options.onRowsSelect) {
|
|
1686
|
+
this.options.onRowsSelect(
|
|
1687
|
+
this.state.curSelectedRows,
|
|
1688
|
+
this.state.selectedRows.data,
|
|
1689
|
+
this.state.selectedRows.data.map((item) => item.dataIndex),
|
|
1690
|
+
);
|
|
1691
|
+
}
|
|
1692
|
+
},
|
|
1693
|
+
);
|
|
1694
|
+
} else if (type === 'cell') {
|
|
1695
|
+
this.setState(
|
|
1696
|
+
(prevState) => {
|
|
1697
|
+
const { dataIndex } = value;
|
|
1698
|
+
let selectedRows = [...prevState.selectedRows.data];
|
|
1699
|
+
let rowPos = -1;
|
|
1700
|
+
|
|
1701
|
+
for (let cIndex = 0; cIndex < selectedRows.length; cIndex++) {
|
|
1702
|
+
if (selectedRows[cIndex].dataIndex === dataIndex) {
|
|
1703
|
+
rowPos = cIndex;
|
|
1704
|
+
break;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
if (rowPos >= 0) {
|
|
1709
|
+
selectedRows.splice(rowPos, 1);
|
|
1710
|
+
|
|
1711
|
+
// handle rows affected by shift+click
|
|
1712
|
+
if (shiftAdjacentRows.length > 0) {
|
|
1713
|
+
let shiftAdjacentMap = buildMap(shiftAdjacentRows);
|
|
1714
|
+
for (let cIndex = selectedRows.length - 1; cIndex >= 0; cIndex--) {
|
|
1715
|
+
if (shiftAdjacentMap[selectedRows[cIndex].dataIndex]) {
|
|
1716
|
+
selectedRows.splice(cIndex, 1);
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
} else if (selectableRows === 'single') {
|
|
1721
|
+
selectedRows = [value];
|
|
1722
|
+
} else {
|
|
1723
|
+
// multiple
|
|
1724
|
+
selectedRows.push(value);
|
|
1725
|
+
|
|
1726
|
+
// handle rows affected by shift+click
|
|
1727
|
+
if (shiftAdjacentRows.length > 0) {
|
|
1728
|
+
let selectedMap = buildMap(selectedRows);
|
|
1729
|
+
shiftAdjacentRows.forEach((aRow) => {
|
|
1730
|
+
if (!selectedMap[aRow.dataIndex]) {
|
|
1731
|
+
selectedRows.push(aRow);
|
|
1732
|
+
}
|
|
1733
|
+
});
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
return {
|
|
1738
|
+
selectedRows: {
|
|
1739
|
+
lookup: buildMap(selectedRows),
|
|
1740
|
+
data: selectedRows,
|
|
1741
|
+
},
|
|
1742
|
+
previousSelectedRow: value,
|
|
1743
|
+
};
|
|
1744
|
+
},
|
|
1745
|
+
() => {
|
|
1746
|
+
this.setTableAction('rowSelectionChange');
|
|
1747
|
+
if (this.options.onRowSelectionChange) {
|
|
1748
|
+
this.options.onRowSelectionChange(
|
|
1749
|
+
[value],
|
|
1750
|
+
this.state.selectedRows.data,
|
|
1751
|
+
this.state.selectedRows.data.map((item) => item.dataIndex),
|
|
1752
|
+
);
|
|
1753
|
+
} else if (this.options.onRowsSelect) {
|
|
1754
|
+
this.options.onRowsSelect(
|
|
1755
|
+
[value],
|
|
1756
|
+
this.state.selectedRows.data,
|
|
1757
|
+
this.state.selectedRows.data.map((item) => item.dataIndex),
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
},
|
|
1761
|
+
);
|
|
1762
|
+
} else if (type === 'custom') {
|
|
1763
|
+
const { displayData } = this.state;
|
|
1764
|
+
|
|
1765
|
+
const data = value.map((row) => ({ index: row, dataIndex: displayData[row].dataIndex }));
|
|
1766
|
+
const lookup = buildMap(data);
|
|
1767
|
+
|
|
1768
|
+
this.setState(
|
|
1769
|
+
{
|
|
1770
|
+
selectedRows: { data, lookup },
|
|
1771
|
+
previousSelectedRow: null,
|
|
1772
|
+
},
|
|
1773
|
+
() => {
|
|
1774
|
+
this.setTableAction('rowSelectionChange');
|
|
1775
|
+
if (this.options.onRowSelectionChange) {
|
|
1776
|
+
this.options.onRowSelectionChange(
|
|
1777
|
+
this.state.selectedRows.data,
|
|
1778
|
+
this.state.selectedRows.data,
|
|
1779
|
+
this.state.selectedRows.data.map((item) => item.dataIndex),
|
|
1780
|
+
);
|
|
1781
|
+
} else if (this.options.onRowsSelect) {
|
|
1782
|
+
this.options.onRowsSelect(
|
|
1783
|
+
this.state.selectedRows.data,
|
|
1784
|
+
this.state.selectedRows.data,
|
|
1785
|
+
this.state.selectedRows.data.map((item) => item.dataIndex),
|
|
1786
|
+
);
|
|
1787
|
+
}
|
|
1788
|
+
},
|
|
1789
|
+
);
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
|
|
1793
|
+
sortTable(data, col, order, columnSortCompare = null) {
|
|
1794
|
+
let hasCustomTableSort = this.options.customSort && !columnSortCompare;
|
|
1795
|
+
let meta = { selectedRows: this.state.selectedRows }; // meta for customSort
|
|
1796
|
+
let dataSrc = hasCustomTableSort
|
|
1797
|
+
? this.options.customSort(data, col, order || (this.options.sortDescFirst ? 'desc' : 'asc'), meta)
|
|
1798
|
+
: data;
|
|
1799
|
+
|
|
1800
|
+
// reset the order by index
|
|
1801
|
+
let noSortData;
|
|
1802
|
+
if (order === 'none') {
|
|
1803
|
+
noSortData = data.reduce((r, i) => {
|
|
1804
|
+
r[i.index] = i;
|
|
1805
|
+
return r;
|
|
1806
|
+
}, []);
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
let sortedData = dataSrc.map((row, sIndex) => ({
|
|
1810
|
+
data: row.data[col],
|
|
1811
|
+
rowData: row.data,
|
|
1812
|
+
position: sIndex,
|
|
1813
|
+
rowSelected: this.state.selectedRows.lookup[row.index] ? true : false,
|
|
1814
|
+
}));
|
|
1815
|
+
|
|
1816
|
+
if (!hasCustomTableSort) {
|
|
1817
|
+
const sortFn = columnSortCompare || sortCompare;
|
|
1818
|
+
sortedData.sort(sortFn(order));
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
let tableData = [];
|
|
1822
|
+
let selectedRows = [];
|
|
1823
|
+
|
|
1824
|
+
for (let i = 0; i < sortedData.length; i++) {
|
|
1825
|
+
const row = sortedData[i];
|
|
1826
|
+
tableData.push(dataSrc[row.position]);
|
|
1827
|
+
if (row.rowSelected) {
|
|
1828
|
+
selectedRows.push({ index: i, dataIndex: dataSrc[row.position].index });
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
return {
|
|
1833
|
+
data: order === 'none' ? noSortData : tableData,
|
|
1834
|
+
selectedRows: {
|
|
1835
|
+
lookup: buildMap(selectedRows),
|
|
1836
|
+
data: selectedRows,
|
|
1837
|
+
},
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
render() {
|
|
1842
|
+
const {
|
|
1843
|
+
classes,
|
|
1844
|
+
className,
|
|
1845
|
+
title,
|
|
1846
|
+
components: {
|
|
1847
|
+
TableBody,
|
|
1848
|
+
TableFilterList,
|
|
1849
|
+
TableFooter,
|
|
1850
|
+
TableHead,
|
|
1851
|
+
TableResize,
|
|
1852
|
+
TableToolbar,
|
|
1853
|
+
TableToolbarSelect,
|
|
1854
|
+
DragDropBackend = HTML5Backend,
|
|
1855
|
+
},
|
|
1856
|
+
} = this.props;
|
|
1857
|
+
const {
|
|
1858
|
+
announceText,
|
|
1859
|
+
activeColumn,
|
|
1860
|
+
data,
|
|
1861
|
+
displayData,
|
|
1862
|
+
columns,
|
|
1863
|
+
page,
|
|
1864
|
+
filterData,
|
|
1865
|
+
filterList,
|
|
1866
|
+
selectedRows,
|
|
1867
|
+
previousSelectedRow,
|
|
1868
|
+
expandedRows,
|
|
1869
|
+
searchText,
|
|
1870
|
+
sortOrder,
|
|
1871
|
+
serverSideFilterList,
|
|
1872
|
+
columnOrder,
|
|
1873
|
+
} = this.state;
|
|
1874
|
+
|
|
1875
|
+
const TableBodyComponent = TableBody || DefaultTableBody;
|
|
1876
|
+
const TableFilterListComponent = TableFilterList || DefaultTableFilterList;
|
|
1877
|
+
const TableFooterComponent = TableFooter || DefaultTableFooter;
|
|
1878
|
+
const TableHeadComponent = TableHead || DefaultTableHead;
|
|
1879
|
+
const TableResizeComponent = TableResize || DefaultTableResize;
|
|
1880
|
+
const TableToolbarComponent = TableToolbar || DefaultTableToolbar;
|
|
1881
|
+
const TableToolbarSelectComponent = TableToolbarSelect || DefaultTableToolbarSelect;
|
|
1882
|
+
|
|
1883
|
+
const rowCount = this.state.count || displayData.length;
|
|
1884
|
+
const rowsPerPage = this.options.pagination ? this.state.rowsPerPage : displayData.length;
|
|
1885
|
+
const showToolbar = hasToolbarItem(this.options, title);
|
|
1886
|
+
const columnNames = columns.map((column) => ({
|
|
1887
|
+
name: column.name,
|
|
1888
|
+
filterType: column.filterType || this.options.filterType,
|
|
1889
|
+
}));
|
|
1890
|
+
const responsiveOption = this.options.responsive;
|
|
1891
|
+
let paperClasses = `${classes.paper} ${className}`;
|
|
1892
|
+
let maxHeight = this.options.tableBodyMaxHeight;
|
|
1893
|
+
let responsiveClass;
|
|
1894
|
+
|
|
1895
|
+
switch (responsiveOption) {
|
|
1896
|
+
// deprecated
|
|
1897
|
+
case 'scroll':
|
|
1898
|
+
responsiveClass = classes.responsiveScroll;
|
|
1899
|
+
maxHeight = '499px';
|
|
1900
|
+
break;
|
|
1901
|
+
// deprecated
|
|
1902
|
+
case 'scrollMaxHeight':
|
|
1903
|
+
responsiveClass = classes.responsiveScrollMaxHeight;
|
|
1904
|
+
maxHeight = '499px';
|
|
1905
|
+
break;
|
|
1906
|
+
// deprecated
|
|
1907
|
+
case 'scrollFullHeight':
|
|
1908
|
+
responsiveClass = classes.responsiveScrollFullHeight;
|
|
1909
|
+
maxHeight = 'none';
|
|
1910
|
+
break;
|
|
1911
|
+
// deprecated
|
|
1912
|
+
case 'scrollFullHeightFullWidth':
|
|
1913
|
+
responsiveClass = classes.responsiveScrollFullHeight;
|
|
1914
|
+
paperClasses = `${classes.paperResponsiveScrollFullHeightFullWidth} ${className}`;
|
|
1915
|
+
break;
|
|
1916
|
+
// deprecated
|
|
1917
|
+
case 'stacked':
|
|
1918
|
+
responsiveClass = classes.responsiveStacked;
|
|
1919
|
+
maxHeight = 'none';
|
|
1920
|
+
break;
|
|
1921
|
+
// deprecated
|
|
1922
|
+
case 'stackedFullWidth':
|
|
1923
|
+
responsiveClass = classes.responsiveStackedFullWidth;
|
|
1924
|
+
paperClasses = `${classes.paperResponsiveScrollFullHeightFullWidth} ${className}`;
|
|
1925
|
+
maxHeight = 'none';
|
|
1926
|
+
break;
|
|
1927
|
+
|
|
1928
|
+
default:
|
|
1929
|
+
responsiveClass = classes.responsiveBase;
|
|
1930
|
+
break;
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
var tableHeightVal = {};
|
|
1934
|
+
if (maxHeight) {
|
|
1935
|
+
tableHeightVal.maxHeight = maxHeight;
|
|
1936
|
+
}
|
|
1937
|
+
if (this.options.tableBodyHeight) {
|
|
1938
|
+
tableHeightVal.height = this.options.tableBodyHeight;
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
const tableProps = this.options.setTableProps ? this.options.setTableProps() || {} : {};
|
|
1942
|
+
const tableClassNames = clsx(classes.tableRoot, tableProps.className);
|
|
1943
|
+
delete tableProps.className; // remove className from props to avoid the className being applied twice
|
|
1944
|
+
|
|
1945
|
+
const dndProps = {};
|
|
1946
|
+
if (typeof window !== 'undefined') {
|
|
1947
|
+
dndProps.context = window;
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
return (
|
|
1951
|
+
<Paper elevation={this.options.elevation} ref={this.tableContent} className={paperClasses}>
|
|
1952
|
+
{(this.options.selectToolbarPlacement === STP.ALWAYS ||
|
|
1953
|
+
(selectedRows.data.length > 0 && this.options.selectToolbarPlacement !== STP.NONE)) && (
|
|
1954
|
+
<TableToolbarSelectComponent
|
|
1955
|
+
options={this.options}
|
|
1956
|
+
selectedRows={selectedRows}
|
|
1957
|
+
onRowsDelete={this.selectRowDelete}
|
|
1958
|
+
displayData={displayData}
|
|
1959
|
+
selectRowUpdate={this.selectRowUpdate}
|
|
1960
|
+
components={this.props.components}
|
|
1961
|
+
/>
|
|
1962
|
+
)}
|
|
1963
|
+
{(selectedRows.data.length === 0 ||
|
|
1964
|
+
[STP.ABOVE, STP.NONE].indexOf(this.options.selectToolbarPlacement) !== -1) &&
|
|
1965
|
+
showToolbar && (
|
|
1966
|
+
<TableToolbarComponent
|
|
1967
|
+
columns={columns}
|
|
1968
|
+
columnOrder={columnOrder}
|
|
1969
|
+
displayData={displayData}
|
|
1970
|
+
data={data}
|
|
1971
|
+
filterData={filterData}
|
|
1972
|
+
filterList={filterList}
|
|
1973
|
+
filterUpdate={this.filterUpdate}
|
|
1974
|
+
updateFilterByType={this.updateFilterByType}
|
|
1975
|
+
options={this.options}
|
|
1976
|
+
resetFilters={this.resetFilters}
|
|
1977
|
+
searchText={searchText}
|
|
1978
|
+
searchTextUpdate={this.searchTextUpdate}
|
|
1979
|
+
searchClose={this.searchClose}
|
|
1980
|
+
tableRef={this.getTableContentRef}
|
|
1981
|
+
title={title}
|
|
1982
|
+
toggleViewColumn={this.toggleViewColumn}
|
|
1983
|
+
updateColumns={this.updateColumns}
|
|
1984
|
+
setTableAction={this.setTableAction}
|
|
1985
|
+
components={this.props.components}
|
|
1986
|
+
/>
|
|
1987
|
+
)}
|
|
1988
|
+
<TableFilterListComponent
|
|
1989
|
+
options={this.options}
|
|
1990
|
+
serverSideFilterList={this.props.options.serverSideFilterList}
|
|
1991
|
+
filterListRenderers={columns.map((c) => {
|
|
1992
|
+
if (c.customFilterListOptions && c.customFilterListOptions.render) return c.customFilterListOptions.render;
|
|
1993
|
+
// DEPRECATED: This option is being replaced with customFilterListOptions.render
|
|
1994
|
+
if (c.customFilterListRender) return c.customFilterListRender;
|
|
1995
|
+
|
|
1996
|
+
return (f) => f;
|
|
1997
|
+
})}
|
|
1998
|
+
customFilterListUpdate={columns.map((c) => {
|
|
1999
|
+
return c.customFilterListOptions && c.customFilterListOptions.update
|
|
2000
|
+
? c.customFilterListOptions.update
|
|
2001
|
+
: null;
|
|
2002
|
+
})}
|
|
2003
|
+
filterList={filterList}
|
|
2004
|
+
filterUpdate={this.filterUpdate}
|
|
2005
|
+
columnNames={columnNames}
|
|
2006
|
+
/>
|
|
2007
|
+
<div style={{ position: 'relative', ...tableHeightVal }} className={responsiveClass}>
|
|
2008
|
+
{(this.options.resizableColumns === true ||
|
|
2009
|
+
(this.options.resizableColumns && this.options.resizableColumns.enabled)) && (
|
|
2010
|
+
<TableResizeComponent
|
|
2011
|
+
key={rowCount}
|
|
2012
|
+
columnOrder={columnOrder}
|
|
2013
|
+
updateDividers={(fn) => (this.updateDividers = fn)}
|
|
2014
|
+
setResizeable={(fn) => (this.setHeadResizeable = fn)}
|
|
2015
|
+
options={this.props.options}
|
|
2016
|
+
tableId={this.options.tableId}
|
|
2017
|
+
/>
|
|
2018
|
+
)}
|
|
2019
|
+
{(() => {
|
|
2020
|
+
const components = (
|
|
2021
|
+
<MuiTable
|
|
2022
|
+
ref={(el) => (this.tableRef = el)}
|
|
2023
|
+
tabIndex={'0'}
|
|
2024
|
+
role={'grid'}
|
|
2025
|
+
className={tableClassNames}
|
|
2026
|
+
{...tableProps}>
|
|
2027
|
+
<caption className={classes.caption}>{title}</caption>
|
|
2028
|
+
<TableHeadComponent
|
|
2029
|
+
columns={columns}
|
|
2030
|
+
activeColumn={activeColumn}
|
|
2031
|
+
data={displayData}
|
|
2032
|
+
count={rowCount}
|
|
2033
|
+
page={page}
|
|
2034
|
+
rowsPerPage={rowsPerPage}
|
|
2035
|
+
selectedRows={selectedRows}
|
|
2036
|
+
selectRowUpdate={this.selectRowUpdate}
|
|
2037
|
+
toggleSort={this.toggleSortColumn}
|
|
2038
|
+
setCellRef={this.setHeadCellRef}
|
|
2039
|
+
expandedRows={expandedRows}
|
|
2040
|
+
areAllRowsExpanded={this.areAllRowsExpanded}
|
|
2041
|
+
toggleAllExpandableRows={this.toggleAllExpandableRows}
|
|
2042
|
+
options={this.options}
|
|
2043
|
+
sortOrder={sortOrder}
|
|
2044
|
+
columnOrder={columnOrder}
|
|
2045
|
+
updateColumnOrder={this.updateColumnOrder}
|
|
2046
|
+
draggableHeadCellRefs={this.draggableHeadCellRefs}
|
|
2047
|
+
tableRef={this.getTableContentRef}
|
|
2048
|
+
tableId={this.options.tableId}
|
|
2049
|
+
timers={this.timers}
|
|
2050
|
+
components={this.props.components}
|
|
2051
|
+
/>
|
|
2052
|
+
<TableBodyComponent
|
|
2053
|
+
data={displayData}
|
|
2054
|
+
count={rowCount}
|
|
2055
|
+
columns={columns}
|
|
2056
|
+
page={page}
|
|
2057
|
+
rowsPerPage={rowsPerPage}
|
|
2058
|
+
selectedRows={selectedRows}
|
|
2059
|
+
selectRowUpdate={this.selectRowUpdate}
|
|
2060
|
+
previousSelectedRow={previousSelectedRow}
|
|
2061
|
+
expandedRows={expandedRows}
|
|
2062
|
+
toggleExpandRow={this.toggleExpandRow}
|
|
2063
|
+
options={this.options}
|
|
2064
|
+
columnOrder={columnOrder}
|
|
2065
|
+
filterList={filterList}
|
|
2066
|
+
components={this.props.components}
|
|
2067
|
+
tableId={this.options.tableId}
|
|
2068
|
+
/>
|
|
2069
|
+
{this.options.customTableBodyFooterRender
|
|
2070
|
+
? this.options.customTableBodyFooterRender({
|
|
2071
|
+
data: displayData,
|
|
2072
|
+
count: rowCount,
|
|
2073
|
+
columns,
|
|
2074
|
+
selectedRows,
|
|
2075
|
+
selectableRows: this.options.selectableRows,
|
|
2076
|
+
})
|
|
2077
|
+
: null}
|
|
2078
|
+
</MuiTable>
|
|
2079
|
+
);
|
|
2080
|
+
if (DragDropBackend) {
|
|
2081
|
+
return (
|
|
2082
|
+
<DndProvider backend={DragDropBackend} {...dndProps}>
|
|
2083
|
+
{components}
|
|
2084
|
+
</DndProvider>
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
return components;
|
|
2089
|
+
})()}
|
|
2090
|
+
</div>
|
|
2091
|
+
<TableFooterComponent
|
|
2092
|
+
options={this.options}
|
|
2093
|
+
page={page}
|
|
2094
|
+
rowCount={rowCount}
|
|
2095
|
+
rowsPerPage={rowsPerPage}
|
|
2096
|
+
changeRowsPerPage={this.changeRowsPerPage}
|
|
2097
|
+
changePage={this.changePage}
|
|
2098
|
+
/>
|
|
2099
|
+
<div className={classes.liveAnnounce} aria-live={'polite'}>
|
|
2100
|
+
{announceText}
|
|
2101
|
+
</div>
|
|
2102
|
+
</Paper>
|
|
2103
|
+
);
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
export default withStyles(MUIDataTable, defaultTableStyles, { name: 'MUIDataTable' });
|