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,630 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Typography } from '@mui/material';
|
|
3
|
+
import { Toolbar } from '@mui/material';
|
|
4
|
+
import { IconButton } from '@mui/material';
|
|
5
|
+
import { Menu } from '@mui/material';
|
|
6
|
+
import { MenuItem } from '@mui/material';
|
|
7
|
+
import { ListItemIcon } from '@mui/material';
|
|
8
|
+
import { ListItemText } from '@mui/material';
|
|
9
|
+
import Popover from './Popover';
|
|
10
|
+
import TableFilter from './TableFilter';
|
|
11
|
+
import TableViewCol from './TableViewCol';
|
|
12
|
+
import TableSearch from './TableSearch';
|
|
13
|
+
import { Search as SearchIcon } from '@mui/icons-material';
|
|
14
|
+
import DownloadIcon from '@mui/icons-material/CloudDownload';
|
|
15
|
+
import { Print as PrintIcon } from '@mui/icons-material';
|
|
16
|
+
import { ViewColumn as ViewColumnIcon } from '@mui/icons-material';
|
|
17
|
+
import FilterIcon from '@mui/icons-material/FilterList';
|
|
18
|
+
import { FileDownload as FileDownloadIcon } from '@mui/icons-material';
|
|
19
|
+
import { PictureAsPdf as PictureAsPdfIcon } from '@mui/icons-material';
|
|
20
|
+
import { TableChart as TableChartIcon } from '@mui/icons-material';
|
|
21
|
+
import html2canvas from 'html2canvas';
|
|
22
|
+
import jsPDF from 'jspdf';
|
|
23
|
+
import find from 'lodash.find';
|
|
24
|
+
import { withStyles } from 'tss-react/mui';
|
|
25
|
+
import { createCSVDownload, downloadCSV } from '../utils';
|
|
26
|
+
import MuiTooltip from '@mui/material/Tooltip';
|
|
27
|
+
|
|
28
|
+
export const defaultToolbarStyles = (theme) => ({
|
|
29
|
+
root: {
|
|
30
|
+
'@media print': {
|
|
31
|
+
display: 'none',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
fullWidthRoot: {},
|
|
35
|
+
left: {
|
|
36
|
+
flex: '1 1 auto',
|
|
37
|
+
},
|
|
38
|
+
fullWidthLeft: {
|
|
39
|
+
flex: '1 1 auto',
|
|
40
|
+
},
|
|
41
|
+
actions: {
|
|
42
|
+
flex: '1 1 auto',
|
|
43
|
+
textAlign: 'right',
|
|
44
|
+
},
|
|
45
|
+
fullWidthActions: {
|
|
46
|
+
flex: '1 1 auto',
|
|
47
|
+
textAlign: 'right',
|
|
48
|
+
},
|
|
49
|
+
titleRoot: {},
|
|
50
|
+
titleText: {},
|
|
51
|
+
fullWidthTitleText: {
|
|
52
|
+
textAlign: 'left',
|
|
53
|
+
},
|
|
54
|
+
icon: {
|
|
55
|
+
'&:hover': {
|
|
56
|
+
color: theme.palette.primary.main,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
iconActive: {
|
|
60
|
+
color: theme.palette.primary.main,
|
|
61
|
+
},
|
|
62
|
+
filterPaper: {
|
|
63
|
+
maxWidth: '50%',
|
|
64
|
+
},
|
|
65
|
+
filterCloseIcon: {
|
|
66
|
+
position: 'absolute',
|
|
67
|
+
right: 0,
|
|
68
|
+
top: 0,
|
|
69
|
+
zIndex: 100,
|
|
70
|
+
},
|
|
71
|
+
searchIcon: {
|
|
72
|
+
display: 'inline-flex',
|
|
73
|
+
marginTop: '10px',
|
|
74
|
+
marginRight: '8px',
|
|
75
|
+
},
|
|
76
|
+
exportMenu: {
|
|
77
|
+
'& .MuiPaper-root': {
|
|
78
|
+
borderRadius: '8px',
|
|
79
|
+
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',
|
|
80
|
+
border: '1px solid #e5e7eb',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
exportMenuItem: {
|
|
84
|
+
'&:hover': {
|
|
85
|
+
backgroundColor: '#f3f4f6',
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
[theme.breakpoints.down('md')]: {
|
|
89
|
+
titleRoot: {},
|
|
90
|
+
titleText: {
|
|
91
|
+
fontSize: '16px',
|
|
92
|
+
},
|
|
93
|
+
spacer: {
|
|
94
|
+
display: 'none',
|
|
95
|
+
},
|
|
96
|
+
left: {
|
|
97
|
+
// flex: "1 1 40%",
|
|
98
|
+
padding: '8px 0px',
|
|
99
|
+
},
|
|
100
|
+
actions: {
|
|
101
|
+
// flex: "1 1 60%",
|
|
102
|
+
textAlign: 'right',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
[theme.breakpoints.down('sm')]: {
|
|
106
|
+
root: {
|
|
107
|
+
display: 'block',
|
|
108
|
+
'@media print': {
|
|
109
|
+
display: 'none !important',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
left: {
|
|
113
|
+
padding: '8px 0px 0px 0px',
|
|
114
|
+
},
|
|
115
|
+
titleText: {
|
|
116
|
+
textAlign: 'center',
|
|
117
|
+
},
|
|
118
|
+
actions: {
|
|
119
|
+
textAlign: 'center',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
'@media screen and (max-width: 480px)': {},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const RESPONSIVE_FULL_WIDTH_NAME = 'scrollFullHeightFullWidth';
|
|
126
|
+
|
|
127
|
+
class TableToolbar extends React.Component {
|
|
128
|
+
state = {
|
|
129
|
+
iconActive: null,
|
|
130
|
+
showSearch: Boolean(
|
|
131
|
+
this.props.searchText ||
|
|
132
|
+
this.props.options.searchText ||
|
|
133
|
+
this.props.options.searchOpen ||
|
|
134
|
+
this.props.options.searchAlwaysOpen,
|
|
135
|
+
),
|
|
136
|
+
searchText: this.props.searchText || null,
|
|
137
|
+
anchorEl: null,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
componentDidUpdate(prevProps) {
|
|
141
|
+
if (this.props.searchText !== prevProps.searchText) {
|
|
142
|
+
this.setState({ searchText: this.props.searchText });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
handleCSVDownload = () => {
|
|
147
|
+
this.handleExportMenuClose();
|
|
148
|
+
const { data, displayData, columns, options, columnOrder } = this.props;
|
|
149
|
+
let dataToDownload = []; //cloneDeep(data);
|
|
150
|
+
let columnsToDownload = [];
|
|
151
|
+
let columnOrderCopy = Array.isArray(columnOrder) ? columnOrder.slice(0) : [];
|
|
152
|
+
|
|
153
|
+
if (columnOrderCopy.length === 0) {
|
|
154
|
+
columnOrderCopy = columns.map((item, idx) => idx);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
data.forEach((row) => {
|
|
158
|
+
let newRow = { index: row.index, data: [] };
|
|
159
|
+
columnOrderCopy.forEach((idx) => {
|
|
160
|
+
newRow.data.push(row.data[idx]);
|
|
161
|
+
});
|
|
162
|
+
dataToDownload.push(newRow);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
columnOrderCopy.forEach((idx) => {
|
|
166
|
+
columnsToDownload.push(columns[idx]);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (options.downloadOptions && options.downloadOptions.filterOptions) {
|
|
170
|
+
// check rows first:
|
|
171
|
+
if (options.downloadOptions.filterOptions.useDisplayedRowsOnly) {
|
|
172
|
+
let filteredDataToDownload = displayData.map((row, index) => {
|
|
173
|
+
let i = -1;
|
|
174
|
+
|
|
175
|
+
// Help to preserve sort order in custom render columns
|
|
176
|
+
row.index = index;
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
data: row.data.map((column) => {
|
|
180
|
+
i += 1;
|
|
181
|
+
|
|
182
|
+
// if we have a custom render, which will appear as a react element, we must grab the actual value from data
|
|
183
|
+
// that matches the dataIndex and column
|
|
184
|
+
// TODO: Create a utility function for checking whether or not something is a react object
|
|
185
|
+
let val =
|
|
186
|
+
typeof column === 'object' && column !== null && !Array.isArray(column)
|
|
187
|
+
? find(data, (d) => d.index === row.dataIndex).data[i]
|
|
188
|
+
: column;
|
|
189
|
+
val = typeof val === 'function' ? find(data, (d) => d.index === row.dataIndex).data[i] : val;
|
|
190
|
+
return val;
|
|
191
|
+
}),
|
|
192
|
+
};
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
dataToDownload = [];
|
|
196
|
+
filteredDataToDownload.forEach((row) => {
|
|
197
|
+
let newRow = { index: row.index, data: [] };
|
|
198
|
+
columnOrderCopy.forEach((idx) => {
|
|
199
|
+
newRow.data.push(row.data[idx]);
|
|
200
|
+
});
|
|
201
|
+
dataToDownload.push(newRow);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// now, check columns:
|
|
206
|
+
if (options.downloadOptions.filterOptions.useDisplayedColumnsOnly) {
|
|
207
|
+
columnsToDownload = columnsToDownload.filter((_) => _.display === 'true');
|
|
208
|
+
|
|
209
|
+
dataToDownload = dataToDownload.map((row) => {
|
|
210
|
+
row.data = row.data.filter((_, index) => columns[columnOrderCopy[index]].display === 'true');
|
|
211
|
+
return row;
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
createCSVDownload(columnsToDownload, dataToDownload, options, downloadCSV);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
handleExportMenuOpen = (event) => {
|
|
219
|
+
this.setState({ anchorEl: event.currentTarget });
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
handleExportMenuClose = () => {
|
|
223
|
+
this.setState({ anchorEl: null });
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
exportToCSV = () => {
|
|
227
|
+
this.handleCSVDownload();
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
exportToExcel = () => {
|
|
231
|
+
this.handleCSVDownload(); // For now, same as CSV
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
exportToPDF = async () => {
|
|
235
|
+
this.handleExportMenuClose();
|
|
236
|
+
const { tableRef } = this.props;
|
|
237
|
+
if (!tableRef()) return;
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const canvas = await html2canvas(tableRef(), {
|
|
241
|
+
scale: 2,
|
|
242
|
+
useCORS: true,
|
|
243
|
+
allowTaint: true,
|
|
244
|
+
backgroundColor: '#ffffff',
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const imgData = canvas.toDataURL('image/png');
|
|
248
|
+
const pdf = new jsPDF('p', 'mm', 'a4');
|
|
249
|
+
const imgWidth = 210;
|
|
250
|
+
const pageHeight = 295;
|
|
251
|
+
const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
|
252
|
+
let heightLeft = imgHeight;
|
|
253
|
+
let position = 0;
|
|
254
|
+
|
|
255
|
+
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
|
256
|
+
heightLeft -= pageHeight;
|
|
257
|
+
|
|
258
|
+
while (heightLeft >= 0) {
|
|
259
|
+
position = heightLeft - imgHeight;
|
|
260
|
+
pdf.addPage();
|
|
261
|
+
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
|
262
|
+
heightLeft -= pageHeight;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
pdf.save('table-export.pdf');
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error('Print error:', error);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
handleCustomExport = (type) => {
|
|
272
|
+
this.handleExportMenuClose();
|
|
273
|
+
const { onExport } = this.props.options || {};
|
|
274
|
+
if (onExport && typeof onExport === 'function') {
|
|
275
|
+
onExport(type);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
setActiveIcon = (iconName) => {
|
|
280
|
+
this.setState(
|
|
281
|
+
(prevState) => ({
|
|
282
|
+
showSearch: this.isSearchShown(iconName),
|
|
283
|
+
iconActive: iconName,
|
|
284
|
+
prevIconActive: prevState.iconActive,
|
|
285
|
+
}),
|
|
286
|
+
() => {
|
|
287
|
+
const { iconActive, prevIconActive } = this.state;
|
|
288
|
+
|
|
289
|
+
if (iconActive === 'filter') {
|
|
290
|
+
this.props.setTableAction('onFilterDialogOpen');
|
|
291
|
+
if (this.props.options.onFilterDialogOpen) {
|
|
292
|
+
this.props.options.onFilterDialogOpen();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (iconActive === undefined && prevIconActive === 'filter') {
|
|
296
|
+
this.props.setTableAction('onFilterDialogClose');
|
|
297
|
+
if (this.props.options.onFilterDialogClose) {
|
|
298
|
+
this.props.options.onFilterDialogClose();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
isSearchShown = (iconName) => {
|
|
306
|
+
if (this.props.options.searchAlwaysOpen) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
let nextVal = false;
|
|
311
|
+
if (this.state.showSearch) {
|
|
312
|
+
if (this.state.searchText) {
|
|
313
|
+
nextVal = true;
|
|
314
|
+
} else {
|
|
315
|
+
const { onSearchClose } = this.props.options;
|
|
316
|
+
this.props.setTableAction('onSearchClose');
|
|
317
|
+
if (onSearchClose) onSearchClose();
|
|
318
|
+
nextVal = false;
|
|
319
|
+
}
|
|
320
|
+
} else if (iconName === 'search') {
|
|
321
|
+
nextVal = this.showSearch();
|
|
322
|
+
}
|
|
323
|
+
return nextVal;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
getActiveIcon = (styles, iconName) => {
|
|
327
|
+
let isActive = this.state.iconActive === iconName;
|
|
328
|
+
if (iconName === 'search') {
|
|
329
|
+
const { showSearch, searchText } = this.state;
|
|
330
|
+
isActive = isActive || showSearch || searchText;
|
|
331
|
+
}
|
|
332
|
+
return isActive ? styles.iconActive : styles.icon;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
showSearch = () => {
|
|
336
|
+
this.props.setTableAction('onSearchOpen');
|
|
337
|
+
!!this.props.options.onSearchOpen && this.props.options.onSearchOpen();
|
|
338
|
+
return true;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
hideSearch = () => {
|
|
342
|
+
const { onSearchClose } = this.props.options;
|
|
343
|
+
|
|
344
|
+
this.props.setTableAction('onSearchClose');
|
|
345
|
+
if (onSearchClose) onSearchClose();
|
|
346
|
+
this.props.searchClose();
|
|
347
|
+
|
|
348
|
+
this.setState(() => ({
|
|
349
|
+
iconActive: null,
|
|
350
|
+
showSearch: false,
|
|
351
|
+
searchText: null,
|
|
352
|
+
}));
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
handleSearch = (value) => {
|
|
356
|
+
this.setState({ searchText: value });
|
|
357
|
+
this.props.searchTextUpdate(value);
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
handleSearchIconClick = () => {
|
|
361
|
+
const { showSearch, searchText } = this.state;
|
|
362
|
+
if (showSearch && !searchText) {
|
|
363
|
+
this.hideSearch();
|
|
364
|
+
} else {
|
|
365
|
+
this.setActiveIcon('search');
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
handlePrint = async () => {
|
|
370
|
+
try {
|
|
371
|
+
const tableElement = this.props.tableRef();
|
|
372
|
+
if (!tableElement) return;
|
|
373
|
+
|
|
374
|
+
const canvas = await html2canvas(tableElement, {
|
|
375
|
+
scale: 2,
|
|
376
|
+
useCORS: true,
|
|
377
|
+
allowTaint: true,
|
|
378
|
+
backgroundColor: '#ffffff',
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const imgData = canvas.toDataURL('image/png');
|
|
382
|
+
const pdf = new jsPDF('p', 'mm', 'a4');
|
|
383
|
+
const imgWidth = 210;
|
|
384
|
+
const pageHeight = 295;
|
|
385
|
+
const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
|
386
|
+
let heightLeft = imgHeight;
|
|
387
|
+
|
|
388
|
+
let position = 0;
|
|
389
|
+
|
|
390
|
+
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
|
391
|
+
heightLeft -= pageHeight;
|
|
392
|
+
|
|
393
|
+
while (heightLeft >= 0) {
|
|
394
|
+
position = heightLeft - imgHeight;
|
|
395
|
+
pdf.addPage();
|
|
396
|
+
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
|
|
397
|
+
heightLeft -= pageHeight;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
pdf.save('table-export.pdf');
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.error('Print error:', error);
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
render() {
|
|
407
|
+
const {
|
|
408
|
+
data,
|
|
409
|
+
options,
|
|
410
|
+
classes,
|
|
411
|
+
columns,
|
|
412
|
+
filterData,
|
|
413
|
+
filterList,
|
|
414
|
+
filterUpdate,
|
|
415
|
+
resetFilters,
|
|
416
|
+
toggleViewColumn,
|
|
417
|
+
updateColumns,
|
|
418
|
+
title,
|
|
419
|
+
components = {},
|
|
420
|
+
updateFilterByType,
|
|
421
|
+
} = this.props;
|
|
422
|
+
const { icons = {} } = components;
|
|
423
|
+
|
|
424
|
+
const Tooltip = components.Tooltip || MuiTooltip;
|
|
425
|
+
const TableViewColComponent = components.TableViewCol || TableViewCol;
|
|
426
|
+
const TableFilterComponent = components.TableFilter || TableFilter;
|
|
427
|
+
const SearchIconComponent = icons.SearchIcon || SearchIcon;
|
|
428
|
+
const DownloadIconComponent = icons.DownloadIcon || DownloadIcon;
|
|
429
|
+
const PrintIconComponent = icons.PrintIcon || PrintIcon;
|
|
430
|
+
const ViewColumnIconComponent = icons.ViewColumnIcon || ViewColumnIcon;
|
|
431
|
+
const FilterIconComponent = icons.FilterIcon || FilterIcon;
|
|
432
|
+
const { search, downloadCsv, print, viewColumns, filterTable } = options.textLabels.toolbar;
|
|
433
|
+
const { showSearch, searchText } = this.state;
|
|
434
|
+
|
|
435
|
+
const filterPopoverExit = () => {
|
|
436
|
+
this.setState({ hideFilterPopover: false });
|
|
437
|
+
this.setActiveIcon();
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
const closeFilterPopover = () => {
|
|
441
|
+
this.setState({ hideFilterPopover: true });
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
return (
|
|
445
|
+
<Toolbar
|
|
446
|
+
className={options.responsive !== RESPONSIVE_FULL_WIDTH_NAME ? classes.root : classes.fullWidthRoot}
|
|
447
|
+
role={'toolbar'}
|
|
448
|
+
aria-label={'Table Toolbar'}>
|
|
449
|
+
<div className={options.responsive !== RESPONSIVE_FULL_WIDTH_NAME ? classes.left : classes.fullWidthLeft}>
|
|
450
|
+
{showSearch === true ? (
|
|
451
|
+
options.customSearchRender ? (
|
|
452
|
+
options.customSearchRender(searchText, this.handleSearch, this.hideSearch, options)
|
|
453
|
+
) : (
|
|
454
|
+
<TableSearch
|
|
455
|
+
searchText={searchText}
|
|
456
|
+
onSearch={this.handleSearch}
|
|
457
|
+
onHide={this.hideSearch}
|
|
458
|
+
options={options}
|
|
459
|
+
/>
|
|
460
|
+
)
|
|
461
|
+
) : typeof title !== 'string' ? (
|
|
462
|
+
title
|
|
463
|
+
) : (
|
|
464
|
+
<div className={classes.titleRoot} aria-hidden={'true'}>
|
|
465
|
+
<Typography
|
|
466
|
+
variant="h6"
|
|
467
|
+
className={
|
|
468
|
+
options.responsive !== RESPONSIVE_FULL_WIDTH_NAME ? classes.titleText : classes.fullWidthTitleText
|
|
469
|
+
}>
|
|
470
|
+
{title}
|
|
471
|
+
</Typography>
|
|
472
|
+
</div>
|
|
473
|
+
)}
|
|
474
|
+
</div>
|
|
475
|
+
<div className={options.responsive !== RESPONSIVE_FULL_WIDTH_NAME ? classes.actions : classes.fullWidthActions}>
|
|
476
|
+
{!(options.search === false || options.search === 'false' || options.searchAlwaysOpen === true) && (
|
|
477
|
+
<Tooltip title={search} disableFocusListener>
|
|
478
|
+
<IconButton
|
|
479
|
+
aria-label={search}
|
|
480
|
+
data-testid={search + '-iconButton'}
|
|
481
|
+
ref={(el) => (this.searchButton = el)}
|
|
482
|
+
classes={{ root: this.getActiveIcon(classes, 'search') }}
|
|
483
|
+
disabled={options.search === 'disabled'}
|
|
484
|
+
onClick={this.handleSearchIconClick}>
|
|
485
|
+
<SearchIconComponent />
|
|
486
|
+
</IconButton>
|
|
487
|
+
</Tooltip>
|
|
488
|
+
)}
|
|
489
|
+
{!(options.download === false || options.download === 'false') && (
|
|
490
|
+
<>
|
|
491
|
+
<Tooltip title="Export Options" disableFocusListener>
|
|
492
|
+
<IconButton
|
|
493
|
+
data-testid="export-menu-iconButton"
|
|
494
|
+
aria-label="Export Options"
|
|
495
|
+
classes={{ root: classes.icon }}
|
|
496
|
+
disabled={options.download === 'disabled'}
|
|
497
|
+
onClick={this.handleExportMenuOpen}>
|
|
498
|
+
<FileDownloadIcon />
|
|
499
|
+
</IconButton>
|
|
500
|
+
</Tooltip>
|
|
501
|
+
<Menu
|
|
502
|
+
anchorEl={this.state.anchorEl}
|
|
503
|
+
open={Boolean(this.state.anchorEl)}
|
|
504
|
+
onClose={this.handleExportMenuClose}
|
|
505
|
+
classes={{ paper: classes.exportMenu }}
|
|
506
|
+
anchorOrigin={{
|
|
507
|
+
vertical: 'bottom',
|
|
508
|
+
horizontal: 'right',
|
|
509
|
+
}}
|
|
510
|
+
transformOrigin={{
|
|
511
|
+
vertical: 'top',
|
|
512
|
+
horizontal: 'right',
|
|
513
|
+
}}>
|
|
514
|
+
<MenuItem onClick={this.exportToCSV} className={classes.exportMenuItem}>
|
|
515
|
+
<ListItemIcon>
|
|
516
|
+
<TableChartIcon fontSize="small" />
|
|
517
|
+
</ListItemIcon>
|
|
518
|
+
<ListItemText>Export to CSV</ListItemText>
|
|
519
|
+
</MenuItem>
|
|
520
|
+
<MenuItem onClick={this.exportToExcel} className={classes.exportMenuItem}>
|
|
521
|
+
<ListItemIcon>
|
|
522
|
+
<DownloadIcon fontSize="small" />
|
|
523
|
+
</ListItemIcon>
|
|
524
|
+
<ListItemText>Export to Excel</ListItemText>
|
|
525
|
+
</MenuItem>
|
|
526
|
+
<MenuItem onClick={this.exportToPDF} className={classes.exportMenuItem}>
|
|
527
|
+
<ListItemIcon>
|
|
528
|
+
<PictureAsPdfIcon fontSize="small" />
|
|
529
|
+
</ListItemIcon>
|
|
530
|
+
<ListItemText>Export to PDF</ListItemText>
|
|
531
|
+
</MenuItem>
|
|
532
|
+
{this.props.options?.onExport && (
|
|
533
|
+
<MenuItem onClick={() => this.handleCustomExport('custom')} className={classes.exportMenuItem}>
|
|
534
|
+
<ListItemIcon>
|
|
535
|
+
<FileDownloadIcon fontSize="small" />
|
|
536
|
+
</ListItemIcon>
|
|
537
|
+
<ListItemText>Custom Export</ListItemText>
|
|
538
|
+
</MenuItem>
|
|
539
|
+
)}
|
|
540
|
+
</Menu>
|
|
541
|
+
</>
|
|
542
|
+
)}
|
|
543
|
+
{!(options.print === false || options.print === 'false') && (
|
|
544
|
+
<Tooltip title={print}>
|
|
545
|
+
<span>
|
|
546
|
+
<IconButton
|
|
547
|
+
data-testid={print + '-iconButton'}
|
|
548
|
+
aria-label={print}
|
|
549
|
+
disabled={options.print === 'disabled'}
|
|
550
|
+
onClick={this.handlePrint}
|
|
551
|
+
classes={{ root: classes.icon }}>
|
|
552
|
+
<PrintIconComponent />
|
|
553
|
+
</IconButton>
|
|
554
|
+
</span>
|
|
555
|
+
</Tooltip>
|
|
556
|
+
)}
|
|
557
|
+
{!(options.viewColumns === false || options.viewColumns === 'false') && (
|
|
558
|
+
<Popover
|
|
559
|
+
refExit={this.setActiveIcon.bind(null)}
|
|
560
|
+
classes={{ closeIcon: classes.filterCloseIcon }}
|
|
561
|
+
hide={options.viewColumns === 'disabled'}
|
|
562
|
+
trigger={
|
|
563
|
+
<Tooltip title={viewColumns} disableFocusListener>
|
|
564
|
+
<span>
|
|
565
|
+
<IconButton
|
|
566
|
+
data-testid={viewColumns + '-iconButton'}
|
|
567
|
+
aria-label={viewColumns}
|
|
568
|
+
classes={{ root: this.getActiveIcon(classes, 'viewcolumns') }}
|
|
569
|
+
disabled={options.viewColumns === 'disabled'}
|
|
570
|
+
onClick={this.setActiveIcon.bind(null, 'viewcolumns')}>
|
|
571
|
+
<ViewColumnIconComponent />
|
|
572
|
+
</IconButton>
|
|
573
|
+
</span>
|
|
574
|
+
</Tooltip>
|
|
575
|
+
}
|
|
576
|
+
content={
|
|
577
|
+
<TableViewColComponent
|
|
578
|
+
data={data}
|
|
579
|
+
columns={columns}
|
|
580
|
+
options={options}
|
|
581
|
+
onColumnUpdate={toggleViewColumn}
|
|
582
|
+
updateColumns={updateColumns}
|
|
583
|
+
components={components}
|
|
584
|
+
/>
|
|
585
|
+
}
|
|
586
|
+
/>
|
|
587
|
+
)}
|
|
588
|
+
{!(options.filter === false || options.filter === 'false') && (
|
|
589
|
+
<Popover
|
|
590
|
+
refExit={filterPopoverExit}
|
|
591
|
+
hide={this.state.hideFilterPopover || options.filter === 'disabled'}
|
|
592
|
+
classes={{ paper: classes.filterPaper, closeIcon: classes.filterCloseIcon }}
|
|
593
|
+
trigger={
|
|
594
|
+
<Tooltip title={filterTable} disableFocusListener>
|
|
595
|
+
<span>
|
|
596
|
+
<IconButton
|
|
597
|
+
data-testid={filterTable + '-iconButton'}
|
|
598
|
+
aria-label={filterTable}
|
|
599
|
+
classes={{ root: this.getActiveIcon(classes, 'filter') }}
|
|
600
|
+
disabled={options.filter === 'disabled'}
|
|
601
|
+
onClick={this.setActiveIcon.bind(null, 'filter')}>
|
|
602
|
+
<FilterIconComponent />
|
|
603
|
+
</IconButton>
|
|
604
|
+
</span>
|
|
605
|
+
</Tooltip>
|
|
606
|
+
}
|
|
607
|
+
content={
|
|
608
|
+
<TableFilterComponent
|
|
609
|
+
customFooter={options.customFilterDialogFooter}
|
|
610
|
+
columns={columns}
|
|
611
|
+
options={options}
|
|
612
|
+
filterList={filterList}
|
|
613
|
+
filterData={filterData}
|
|
614
|
+
onFilterUpdate={filterUpdate}
|
|
615
|
+
onFilterReset={resetFilters}
|
|
616
|
+
handleClose={closeFilterPopover}
|
|
617
|
+
updateFilterByType={updateFilterByType}
|
|
618
|
+
components={components}
|
|
619
|
+
/>
|
|
620
|
+
}
|
|
621
|
+
/>
|
|
622
|
+
)}
|
|
623
|
+
{options.customToolbar && options.customToolbar({ displayData: this.props.displayData })}
|
|
624
|
+
</div>
|
|
625
|
+
</Toolbar>
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
export default withStyles(TableToolbar, defaultToolbarStyles, { name: 'MUIDataTableToolbar' });
|