@etsoo/materialui 1.1.91 → 1.1.92
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/lib/DataGridEx.js +3 -2
- package/lib/TableEx.d.ts +5 -5
- package/lib/TableEx.js +16 -18
- package/package.json +5 -5
- package/src/DataGridEx.tsx +4 -2
- package/src/TableEx.tsx +487 -519
package/lib/DataGridEx.js
CHANGED
|
@@ -218,7 +218,7 @@ export function DataGridEx(props) {
|
|
|
218
218
|
/**
|
|
219
219
|
* Item renderer
|
|
220
220
|
*/
|
|
221
|
-
const itemRenderer = ({ columnIndex, rowIndex, style, data, selectedItems }) => {
|
|
221
|
+
const itemRenderer = ({ columnIndex, rowIndex, style, data, selectedItems, setItems }) => {
|
|
222
222
|
// Column
|
|
223
223
|
const { align, cellRenderer = DataGridRenderers.defaultCellRenderer, cellBoxStyle, field, type, valueFormatter, renderProps } = columns[columnIndex];
|
|
224
224
|
// Props
|
|
@@ -261,7 +261,8 @@ export function DataGridEx(props) {
|
|
|
261
261
|
rowIndex,
|
|
262
262
|
columnIndex,
|
|
263
263
|
cellProps,
|
|
264
|
-
renderProps
|
|
264
|
+
renderProps,
|
|
265
|
+
setItems
|
|
265
266
|
});
|
|
266
267
|
return (React.createElement("div", { className: rowClass, style: style, "data-row": rowIndex, "data-column": columnIndex, onMouseDown: selectable && !checkable ? handleMouseDown : undefined, onMouseOver: selectable ? handleMouseOver : undefined, onMouseOut: selectable ? handleMouseOut : undefined, onClick: (event) => onClick && data != null && onClick(event, data), onDoubleClick: (event) => onDoubleClick && data != null && onDoubleClick(event, data) },
|
|
267
268
|
React.createElement(Box, { ...cellProps, onMouseEnter: handleMouseEnter }, child)));
|
package/lib/TableEx.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { GridColumn, GridLoader } from
|
|
2
|
-
import { GridMethodRef } from
|
|
3
|
-
import { DataTypes, IdDefaultType } from
|
|
4
|
-
import { TableProps } from
|
|
5
|
-
import React from
|
|
1
|
+
import { GridColumn, GridLoader } from "@etsoo/react";
|
|
2
|
+
import { GridMethodRef } from "@etsoo/react/lib/components/GridMethodRef";
|
|
3
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
4
|
+
import { TableProps } from "@mui/material";
|
|
5
|
+
import React from "react";
|
|
6
6
|
/**
|
|
7
7
|
* Extended table min width for width-unset column
|
|
8
8
|
*/
|
package/lib/TableEx.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { GridAlignGet, GridSizeGet } from
|
|
2
|
-
import { DataTypes } from
|
|
3
|
-
import { Checkbox, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, useTheme } from
|
|
4
|
-
import React from
|
|
5
|
-
import { DataGridRenderers } from
|
|
1
|
+
import { GridAlignGet, GridSizeGet } from "@etsoo/react";
|
|
2
|
+
import { DataTypes } from "@etsoo/shared";
|
|
3
|
+
import { Checkbox, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, useTheme } from "@mui/material";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { DataGridRenderers } from "./DataGridRenderers";
|
|
6
6
|
/**
|
|
7
7
|
* Extended table min width for width-unset column
|
|
8
8
|
*/
|
|
@@ -17,7 +17,7 @@ export function TableEx(props) {
|
|
|
17
17
|
// Theme
|
|
18
18
|
const theme = useTheme();
|
|
19
19
|
// Destruct
|
|
20
|
-
const { alternatingColors = [theme.palette.action.hover, undefined], autoLoad = true, columns, defaultOrderBy, headerColors = [undefined, undefined], idField =
|
|
20
|
+
const { alternatingColors = [theme.palette.action.hover, undefined], autoLoad = true, columns, defaultOrderBy, headerColors = [undefined, undefined], idField = "id", loadBatchSize, loadData, maxHeight, mRef, onSelectChange, rowHeight = 53, otherHeight = 110, threshold, ...rest } = props;
|
|
21
21
|
const selectable = onSelectChange != null;
|
|
22
22
|
// Rows per page
|
|
23
23
|
let rowsPerPageLocal;
|
|
@@ -27,7 +27,7 @@ export function TableEx(props) {
|
|
|
27
27
|
else
|
|
28
28
|
rowsPerPageLocal = Math.floor((maxHeight - otherHeight) / rowHeight);
|
|
29
29
|
}
|
|
30
|
-
else if (typeof loadBatchSize ===
|
|
30
|
+
else if (typeof loadBatchSize === "number") {
|
|
31
31
|
rowsPerPageLocal = loadBatchSize;
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
@@ -181,14 +181,13 @@ export function TableEx(props) {
|
|
|
181
181
|
React.createElement(Table, { ...rest },
|
|
182
182
|
React.createElement(TableHead, null,
|
|
183
183
|
React.createElement(TableRow, { sx: {
|
|
184
|
-
|
|
184
|
+
"& th": {
|
|
185
185
|
backgroundColor: headerColors[0],
|
|
186
186
|
color: headerColors[1]
|
|
187
187
|
}
|
|
188
188
|
} },
|
|
189
189
|
selectable && (React.createElement(TableCell, { padding: "checkbox" },
|
|
190
|
-
React.createElement(Checkbox, { color: "primary", indeterminate: pageSelectedItems > 0 &&
|
|
191
|
-
pageSelectedItems < rows.length, checked: pageSelectedItems > 0, onChange: (_event, checked) => handleSelectAll(checked) }))),
|
|
190
|
+
React.createElement(Checkbox, { color: "primary", indeterminate: pageSelectedItems > 0 && pageSelectedItems < rows.length, checked: pageSelectedItems > 0, onChange: (_event, checked) => handleSelectAll(checked) }))),
|
|
192
191
|
columns.map((column, index) => {
|
|
193
192
|
// Destruct
|
|
194
193
|
const { align, field, header, minWidth, sortable, sortAsc = true, type, width } = column;
|
|
@@ -198,7 +197,7 @@ export function TableEx(props) {
|
|
|
198
197
|
let sortLabel;
|
|
199
198
|
if (sortable && field != null) {
|
|
200
199
|
const active = orderBy === field;
|
|
201
|
-
sortLabel = (React.createElement(TableSortLabel, { active: active, direction: sortAsc ?
|
|
200
|
+
sortLabel = (React.createElement(TableSortLabel, { active: active, direction: sortAsc ? "asc" : "desc", onClick: (_event) => {
|
|
202
201
|
if (active)
|
|
203
202
|
column.sortAsc = !sortAsc;
|
|
204
203
|
handleSort(field, column.sortAsc);
|
|
@@ -216,18 +215,16 @@ export function TableEx(props) {
|
|
|
216
215
|
} }, sortLabel));
|
|
217
216
|
}))),
|
|
218
217
|
React.createElement(TableBody, { sx: {
|
|
219
|
-
|
|
218
|
+
"& tr:nth-of-type(odd):not(.Mui-selected)": {
|
|
220
219
|
backgroundColor: alternatingColors[0]
|
|
221
220
|
},
|
|
222
|
-
|
|
221
|
+
"& tr:nth-of-type(even):not(.Mui-selected)": {
|
|
223
222
|
backgroundColor: alternatingColors[1]
|
|
224
223
|
}
|
|
225
224
|
} }, [...Array(batchSize)].map((_item, rowIndex) => {
|
|
226
225
|
var _a;
|
|
227
226
|
// Row
|
|
228
|
-
const row = rowIndex < rows.length
|
|
229
|
-
? rows[rowIndex]
|
|
230
|
-
: undefined;
|
|
227
|
+
const row = rowIndex < rows.length ? rows[rowIndex] : undefined;
|
|
231
228
|
// Row id field value
|
|
232
229
|
const rowId = (_a = DataTypes.getValue(row, idField)) !== null && _a !== void 0 ? _a : rowIndex;
|
|
233
230
|
// Selected or not
|
|
@@ -245,7 +242,7 @@ export function TableEx(props) {
|
|
|
245
242
|
};
|
|
246
243
|
const cellProps = {
|
|
247
244
|
align: GridAlignGet(align, type),
|
|
248
|
-
valign:
|
|
245
|
+
valign: "middle"
|
|
249
246
|
};
|
|
250
247
|
const child = row ? (cellRenderer({
|
|
251
248
|
data: row,
|
|
@@ -257,7 +254,8 @@ export function TableEx(props) {
|
|
|
257
254
|
type,
|
|
258
255
|
rowIndex,
|
|
259
256
|
columnIndex,
|
|
260
|
-
cellProps
|
|
257
|
+
cellProps,
|
|
258
|
+
setItems: setRows
|
|
261
259
|
})) : (React.createElement(React.Fragment, null, "\u00A0"));
|
|
262
260
|
return (React.createElement(TableCell, { key: `${rowId}${columnIndex}`, ...cellProps }, child));
|
|
263
261
|
})));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/materialui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.92",
|
|
4
4
|
"description": "TypeScript Material-UI Implementation",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"@emotion/css": "^11.10.6",
|
|
51
51
|
"@emotion/react": "^11.10.6",
|
|
52
52
|
"@emotion/styled": "^11.10.6",
|
|
53
|
-
"@etsoo/appscript": "^1.3.
|
|
53
|
+
"@etsoo/appscript": "^1.3.89",
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.24",
|
|
55
|
-
"@etsoo/react": "^1.6.
|
|
56
|
-
"@etsoo/shared": "^1.1.
|
|
55
|
+
"@etsoo/react": "^1.6.59",
|
|
56
|
+
"@etsoo/shared": "^1.1.99",
|
|
57
57
|
"@mui/icons-material": "^5.11.16",
|
|
58
58
|
"@mui/material": "^5.11.16",
|
|
59
59
|
"@mui/x-data-grid": "^6.0.4",
|
|
@@ -89,6 +89,6 @@
|
|
|
89
89
|
"@typescript-eslint/parser": "^5.57.1",
|
|
90
90
|
"jest": "^29.5.0",
|
|
91
91
|
"jest-environment-jsdom": "^29.5.0",
|
|
92
|
-
"typescript": "^5.0.
|
|
92
|
+
"typescript": "^5.0.4"
|
|
93
93
|
}
|
|
94
94
|
}
|
package/src/DataGridEx.tsx
CHANGED
|
@@ -498,7 +498,8 @@ export function DataGridEx<
|
|
|
498
498
|
rowIndex,
|
|
499
499
|
style,
|
|
500
500
|
data,
|
|
501
|
-
selectedItems
|
|
501
|
+
selectedItems,
|
|
502
|
+
setItems
|
|
502
503
|
}: ScrollerGridItemRendererProps<T>) => {
|
|
503
504
|
// Column
|
|
504
505
|
const {
|
|
@@ -564,7 +565,8 @@ export function DataGridEx<
|
|
|
564
565
|
rowIndex,
|
|
565
566
|
columnIndex,
|
|
566
567
|
cellProps,
|
|
567
|
-
renderProps
|
|
568
|
+
renderProps,
|
|
569
|
+
setItems
|
|
568
570
|
});
|
|
569
571
|
|
|
570
572
|
return (
|
package/src/TableEx.tsx
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from
|
|
10
|
-
import { GridMethodRef } from
|
|
11
|
-
import { DataTypes, IdDefaultType } from
|
|
2
|
+
GridAlignGet,
|
|
3
|
+
GridCellFormatterProps,
|
|
4
|
+
GridColumn,
|
|
5
|
+
GridLoadDataProps,
|
|
6
|
+
GridLoader,
|
|
7
|
+
GridLoaderStates,
|
|
8
|
+
GridSizeGet
|
|
9
|
+
} from "@etsoo/react";
|
|
10
|
+
import { GridMethodRef } from "@etsoo/react/lib/components/GridMethodRef";
|
|
11
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
12
12
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} from
|
|
27
|
-
import React from
|
|
28
|
-
import { DataGridRenderers } from
|
|
13
|
+
Checkbox,
|
|
14
|
+
Paper,
|
|
15
|
+
Table,
|
|
16
|
+
TableBody,
|
|
17
|
+
TableCell,
|
|
18
|
+
TableCellProps,
|
|
19
|
+
TableContainer,
|
|
20
|
+
TableHead,
|
|
21
|
+
TablePagination,
|
|
22
|
+
TableProps,
|
|
23
|
+
TableRow,
|
|
24
|
+
TableSortLabel,
|
|
25
|
+
useTheme
|
|
26
|
+
} from "@mui/material";
|
|
27
|
+
import React from "react";
|
|
28
|
+
import { DataGridRenderers } from "./DataGridRenderers";
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Extended table min width for width-unset column
|
|
@@ -36,65 +36,65 @@ export const TableExMinWidth: number = 180;
|
|
|
36
36
|
* Extended table methods ref
|
|
37
37
|
*/
|
|
38
38
|
export interface TableExMethodRef<T> extends GridMethodRef<T> {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Refresh data
|
|
41
|
+
*/
|
|
42
|
+
refresh(): void;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Extended table props
|
|
47
47
|
*/
|
|
48
48
|
export type TableExProps<
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
T extends object,
|
|
50
|
+
D extends DataTypes.Keys<T>
|
|
51
51
|
> = TableProps &
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
52
|
+
GridLoader<T> & {
|
|
53
|
+
/**
|
|
54
|
+
* Alternating colors for odd/even rows
|
|
55
|
+
*/
|
|
56
|
+
alternatingColors?: [string?, string?];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Columns
|
|
60
|
+
*/
|
|
61
|
+
columns: GridColumn<T>[];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Header cells background color and font color
|
|
65
|
+
*/
|
|
66
|
+
headerColors?: [string?, string?];
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Id field
|
|
70
|
+
*/
|
|
71
|
+
idField?: D;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Max height
|
|
75
|
+
*/
|
|
76
|
+
maxHeight?: number;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Methods
|
|
80
|
+
*/
|
|
81
|
+
mRef?: React.Ref<TableExMethodRef<T>>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* On items select change
|
|
85
|
+
*/
|
|
86
|
+
onSelectChange?: (selectedItems: T[]) => void;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Row height
|
|
90
|
+
*/
|
|
91
|
+
rowHeight?: number;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Header and bottom height
|
|
95
|
+
*/
|
|
96
|
+
otherHeight?: number;
|
|
97
|
+
};
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Extended Table
|
|
@@ -102,458 +102,426 @@ export type TableExProps<
|
|
|
102
102
|
* @returns Component
|
|
103
103
|
*/
|
|
104
104
|
export function TableEx<
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
T extends object,
|
|
106
|
+
D extends DataTypes.Keys<T> = IdDefaultType<T>
|
|
107
107
|
>(props: TableExProps<T, D>) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
isNextPageLoading: false,
|
|
179
|
-
lastLoadedItems: undefined,
|
|
180
|
-
...add
|
|
181
|
-
};
|
|
182
|
-
Object.assign(state, resetState);
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
React.useImperativeHandle(
|
|
186
|
-
mRef,
|
|
187
|
-
() => ({
|
|
188
|
-
/**
|
|
189
|
-
* Refresh data
|
|
190
|
-
*/
|
|
191
|
-
refresh(): void {
|
|
192
|
-
loadDataLocal();
|
|
193
|
-
},
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Reset
|
|
197
|
-
*/
|
|
198
|
-
reset
|
|
199
|
-
}),
|
|
200
|
-
[]
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
// Load data
|
|
204
|
-
const loadDataLocal = () => {
|
|
205
|
-
// Prevent multiple loadings
|
|
206
|
-
if (!state.hasNextPage || state.isNextPageLoading) return;
|
|
207
|
-
|
|
208
|
-
// Update state
|
|
209
|
-
state.isNextPageLoading = true;
|
|
210
|
-
|
|
211
|
-
// Parameters
|
|
212
|
-
const { currentPage, batchSize, orderBy, orderByAsc, data, isMounted } =
|
|
213
|
-
state;
|
|
214
|
-
|
|
215
|
-
const loadProps: GridLoadDataProps = {
|
|
216
|
-
currentPage,
|
|
217
|
-
batchSize,
|
|
218
|
-
orderBy,
|
|
219
|
-
orderByAsc,
|
|
220
|
-
data
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
loadData(loadProps).then((result) => {
|
|
224
|
-
state.isMounted = true;
|
|
225
|
-
if (result == null || isMounted === false) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const newItems = result.length;
|
|
230
|
-
state.lastLoadedItems = newItems;
|
|
231
|
-
state.hasNextPage = newItems >= batchSize;
|
|
232
|
-
state.isNextPageLoading = false;
|
|
233
|
-
|
|
234
|
-
// Update rows
|
|
235
|
-
setRows(result);
|
|
236
|
-
});
|
|
108
|
+
// Theme
|
|
109
|
+
const theme = useTheme();
|
|
110
|
+
|
|
111
|
+
// Destruct
|
|
112
|
+
const {
|
|
113
|
+
alternatingColors = [theme.palette.action.hover, undefined],
|
|
114
|
+
autoLoad = true,
|
|
115
|
+
columns,
|
|
116
|
+
defaultOrderBy,
|
|
117
|
+
headerColors = [undefined, undefined],
|
|
118
|
+
idField = "id" as D,
|
|
119
|
+
loadBatchSize,
|
|
120
|
+
loadData,
|
|
121
|
+
maxHeight,
|
|
122
|
+
mRef,
|
|
123
|
+
onSelectChange,
|
|
124
|
+
rowHeight = 53,
|
|
125
|
+
otherHeight = 110,
|
|
126
|
+
threshold,
|
|
127
|
+
...rest
|
|
128
|
+
} = props;
|
|
129
|
+
|
|
130
|
+
const selectable: boolean = onSelectChange != null;
|
|
131
|
+
|
|
132
|
+
// Rows per page
|
|
133
|
+
let rowsPerPageLocal: number;
|
|
134
|
+
if (maxHeight != null) {
|
|
135
|
+
if (loadBatchSize != null)
|
|
136
|
+
rowsPerPageLocal = GridSizeGet(loadBatchSize, maxHeight);
|
|
137
|
+
else rowsPerPageLocal = Math.floor((maxHeight - otherHeight) / rowHeight);
|
|
138
|
+
} else if (typeof loadBatchSize === "number") {
|
|
139
|
+
rowsPerPageLocal = loadBatchSize;
|
|
140
|
+
} else {
|
|
141
|
+
rowsPerPageLocal = 10;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Rows
|
|
145
|
+
const [rows, updateRows] = React.useState<T[]>([]);
|
|
146
|
+
const setRows = (rows: T[]) => {
|
|
147
|
+
state.loadedItems = rows.length;
|
|
148
|
+
updateRows(rows);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// States
|
|
152
|
+
const stateRefs = React.useRef<GridLoaderStates<T>>({
|
|
153
|
+
autoLoad,
|
|
154
|
+
currentPage: 0,
|
|
155
|
+
loadedItems: 0,
|
|
156
|
+
hasNextPage: true,
|
|
157
|
+
isNextPageLoading: false,
|
|
158
|
+
orderBy: defaultOrderBy,
|
|
159
|
+
orderByAsc: defaultOrderBy
|
|
160
|
+
? columns.find((column) => column.field === defaultOrderBy)?.sortAsc
|
|
161
|
+
: undefined,
|
|
162
|
+
batchSize: rowsPerPageLocal,
|
|
163
|
+
selectedItems: [],
|
|
164
|
+
idCache: {}
|
|
165
|
+
});
|
|
166
|
+
const state = stateRefs.current;
|
|
167
|
+
|
|
168
|
+
// Reset the state and load again
|
|
169
|
+
const reset = (add?: Partial<GridLoaderStates<T>>) => {
|
|
170
|
+
const resetState: Partial<GridLoaderStates<T>> = {
|
|
171
|
+
autoLoad: true,
|
|
172
|
+
currentPage: 0,
|
|
173
|
+
loadedItems: 0,
|
|
174
|
+
hasNextPage: true,
|
|
175
|
+
isNextPageLoading: false,
|
|
176
|
+
lastLoadedItems: undefined,
|
|
177
|
+
...add
|
|
237
178
|
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
179
|
+
Object.assign(state, resetState);
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
React.useImperativeHandle(
|
|
183
|
+
mRef,
|
|
184
|
+
() => ({
|
|
185
|
+
/**
|
|
186
|
+
* Refresh data
|
|
187
|
+
*/
|
|
188
|
+
refresh(): void {
|
|
242
189
|
loadDataLocal();
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Reset
|
|
194
|
+
*/
|
|
195
|
+
reset
|
|
196
|
+
}),
|
|
197
|
+
[]
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Load data
|
|
201
|
+
const loadDataLocal = () => {
|
|
202
|
+
// Prevent multiple loadings
|
|
203
|
+
if (!state.hasNextPage || state.isNextPageLoading) return;
|
|
204
|
+
|
|
205
|
+
// Update state
|
|
206
|
+
state.isNextPageLoading = true;
|
|
207
|
+
|
|
208
|
+
// Parameters
|
|
209
|
+
const { currentPage, batchSize, orderBy, orderByAsc, data, isMounted } =
|
|
210
|
+
state;
|
|
211
|
+
|
|
212
|
+
const loadProps: GridLoadDataProps = {
|
|
213
|
+
currentPage,
|
|
214
|
+
batchSize,
|
|
215
|
+
orderBy,
|
|
216
|
+
orderByAsc,
|
|
217
|
+
data
|
|
243
218
|
};
|
|
244
219
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
const handleSelect = (item: T, checked: Boolean) => {
|
|
253
|
-
const selectedItems = state.selectedItems;
|
|
254
|
-
|
|
255
|
-
const index = selectedItems.findIndex(
|
|
256
|
-
(selectedItem) => selectedItem[idField] === item[idField]
|
|
257
|
-
);
|
|
258
|
-
if (checked) {
|
|
259
|
-
if (index === -1) selectedItems.push(item);
|
|
260
|
-
} else {
|
|
261
|
-
if (index !== -1) selectedItems.splice(index, 1);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (onSelectChange != null) {
|
|
265
|
-
onSelectChange(selectedItems);
|
|
266
|
-
}
|
|
267
|
-
};
|
|
220
|
+
loadData(loadProps).then((result) => {
|
|
221
|
+
state.isMounted = true;
|
|
222
|
+
if (result == null || isMounted === false) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
268
225
|
|
|
269
|
-
|
|
270
|
-
|
|
226
|
+
const newItems = result.length;
|
|
227
|
+
state.lastLoadedItems = newItems;
|
|
228
|
+
state.hasNextPage = newItems >= batchSize;
|
|
229
|
+
state.isNextPageLoading = false;
|
|
271
230
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
231
|
+
// Update rows
|
|
232
|
+
setRows(result);
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const handleChangePage = (_event: unknown, newPage: number) => {
|
|
237
|
+
state.hasNextPage = true;
|
|
238
|
+
state.currentPage = newPage;
|
|
239
|
+
loadDataLocal();
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const handleChangeRowsPerPage = (
|
|
243
|
+
event: React.ChangeEvent<HTMLInputElement>
|
|
244
|
+
) => {
|
|
245
|
+
const batchSize = parseInt(event.target.value);
|
|
246
|
+
reset({ batchSize });
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const handleSelect = (item: T, checked: Boolean) => {
|
|
250
|
+
const selectedItems = state.selectedItems;
|
|
251
|
+
|
|
252
|
+
const index = selectedItems.findIndex(
|
|
253
|
+
(selectedItem) => selectedItem[idField] === item[idField]
|
|
254
|
+
);
|
|
255
|
+
if (checked) {
|
|
256
|
+
if (index === -1) selectedItems.push(item);
|
|
257
|
+
} else {
|
|
258
|
+
if (index !== -1) selectedItems.splice(index, 1);
|
|
259
|
+
}
|
|
276
260
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
});
|
|
261
|
+
if (onSelectChange != null) {
|
|
262
|
+
onSelectChange(selectedItems);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
283
265
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
};
|
|
266
|
+
const handleSelectAll = (checked: boolean) => {
|
|
267
|
+
const selectedItems = state.selectedItems;
|
|
288
268
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
269
|
+
rows.forEach((row) => {
|
|
270
|
+
const index = selectedItems.findIndex(
|
|
271
|
+
(selectedItem) => selectedItem[idField] === row[idField]
|
|
272
|
+
);
|
|
293
273
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
orderBy,
|
|
301
|
-
batchSize,
|
|
302
|
-
selectedItems
|
|
303
|
-
} = state;
|
|
304
|
-
|
|
305
|
-
// Current page selected items
|
|
306
|
-
const pageSelectedItems = selectable
|
|
307
|
-
? rows.reduce((previousValue, currentItem) => {
|
|
308
|
-
if (
|
|
309
|
-
selectedItems.some(
|
|
310
|
-
(item) => item[idField] === currentItem[idField]
|
|
311
|
-
)
|
|
312
|
-
)
|
|
313
|
-
return previousValue + 1;
|
|
314
|
-
|
|
315
|
-
return previousValue;
|
|
316
|
-
}, 0)
|
|
317
|
-
: 0;
|
|
318
|
-
|
|
319
|
-
// Total rows
|
|
320
|
-
const totalRows = hasNextPage
|
|
321
|
-
? -1
|
|
322
|
-
: currentPage * batchSize + (lastLoadedItems ?? 0);
|
|
323
|
-
|
|
324
|
-
// Auto load data when current page is 0
|
|
325
|
-
if (currentPage === 0 && stateAutoLoad && lastLoadedItems == null)
|
|
326
|
-
loadDataLocal();
|
|
274
|
+
if (checked) {
|
|
275
|
+
if (index === -1) selectedItems.push(row);
|
|
276
|
+
} else if (index !== -1) {
|
|
277
|
+
selectedItems.splice(index, 1);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
327
280
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
}}
|
|
281
|
+
if (onSelectChange != null) {
|
|
282
|
+
onSelectChange(selectedItems);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// New sort
|
|
287
|
+
const handleSort = (field: string, asc?: boolean) => {
|
|
288
|
+
reset({ orderBy: field, orderByAsc: asc });
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// Destruct states
|
|
292
|
+
const {
|
|
293
|
+
autoLoad: stateAutoLoad,
|
|
294
|
+
currentPage,
|
|
295
|
+
hasNextPage,
|
|
296
|
+
lastLoadedItems,
|
|
297
|
+
orderBy,
|
|
298
|
+
batchSize,
|
|
299
|
+
selectedItems
|
|
300
|
+
} = state;
|
|
301
|
+
|
|
302
|
+
// Current page selected items
|
|
303
|
+
const pageSelectedItems = selectable
|
|
304
|
+
? rows.reduce((previousValue, currentItem) => {
|
|
305
|
+
if (
|
|
306
|
+
selectedItems.some((item) => item[idField] === currentItem[idField])
|
|
307
|
+
)
|
|
308
|
+
return previousValue + 1;
|
|
309
|
+
|
|
310
|
+
return previousValue;
|
|
311
|
+
}, 0)
|
|
312
|
+
: 0;
|
|
313
|
+
|
|
314
|
+
// Total rows
|
|
315
|
+
const totalRows = hasNextPage
|
|
316
|
+
? -1
|
|
317
|
+
: currentPage * batchSize + (lastLoadedItems ?? 0);
|
|
318
|
+
|
|
319
|
+
// Auto load data when current page is 0
|
|
320
|
+
if (currentPage === 0 && stateAutoLoad && lastLoadedItems == null)
|
|
321
|
+
loadDataLocal();
|
|
322
|
+
|
|
323
|
+
React.useEffect(() => {
|
|
324
|
+
return () => {
|
|
325
|
+
state.isMounted = false;
|
|
326
|
+
};
|
|
327
|
+
}, []);
|
|
328
|
+
|
|
329
|
+
// Layout
|
|
330
|
+
return (
|
|
331
|
+
<Paper>
|
|
332
|
+
<TableContainer sx={{ maxHeight }}>
|
|
333
|
+
<Table {...rest}>
|
|
334
|
+
<TableHead>
|
|
335
|
+
<TableRow
|
|
336
|
+
sx={{
|
|
337
|
+
"& th": {
|
|
338
|
+
backgroundColor: headerColors[0],
|
|
339
|
+
color: headerColors[1]
|
|
340
|
+
}
|
|
341
|
+
}}
|
|
342
|
+
>
|
|
343
|
+
{selectable && (
|
|
344
|
+
<TableCell padding="checkbox">
|
|
345
|
+
<Checkbox
|
|
346
|
+
color="primary"
|
|
347
|
+
indeterminate={
|
|
348
|
+
pageSelectedItems > 0 && pageSelectedItems < rows.length
|
|
349
|
+
}
|
|
350
|
+
checked={pageSelectedItems > 0}
|
|
351
|
+
onChange={(_event, checked) => handleSelectAll(checked)}
|
|
352
|
+
/>
|
|
353
|
+
</TableCell>
|
|
354
|
+
)}
|
|
355
|
+
{columns.map((column, index) => {
|
|
356
|
+
// Destruct
|
|
357
|
+
const {
|
|
358
|
+
align,
|
|
359
|
+
field,
|
|
360
|
+
header,
|
|
361
|
+
minWidth,
|
|
362
|
+
sortable,
|
|
363
|
+
sortAsc = true,
|
|
364
|
+
type,
|
|
365
|
+
width
|
|
366
|
+
} = column;
|
|
367
|
+
|
|
368
|
+
// Header text
|
|
369
|
+
const headerText = header ?? field;
|
|
370
|
+
|
|
371
|
+
// Sortable
|
|
372
|
+
let sortLabel: React.ReactNode;
|
|
373
|
+
if (sortable && field != null) {
|
|
374
|
+
const active = orderBy === field;
|
|
375
|
+
|
|
376
|
+
sortLabel = (
|
|
377
|
+
<TableSortLabel
|
|
378
|
+
active={active}
|
|
379
|
+
direction={sortAsc ? "asc" : "desc"}
|
|
380
|
+
onClick={(_event) => {
|
|
381
|
+
if (active) column.sortAsc = !sortAsc;
|
|
382
|
+
|
|
383
|
+
handleSort(field, column.sortAsc);
|
|
384
|
+
}}
|
|
434
385
|
>
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
})
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
</
|
|
558
|
-
|
|
386
|
+
{headerText}
|
|
387
|
+
</TableSortLabel>
|
|
388
|
+
);
|
|
389
|
+
} else {
|
|
390
|
+
sortLabel = headerText;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return (
|
|
394
|
+
<TableCell
|
|
395
|
+
align={GridAlignGet(align, type)}
|
|
396
|
+
key={field ?? index.toString()}
|
|
397
|
+
width={width}
|
|
398
|
+
sx={{
|
|
399
|
+
minWidth:
|
|
400
|
+
minWidth == null
|
|
401
|
+
? width == null
|
|
402
|
+
? TableExMinWidth
|
|
403
|
+
: undefined
|
|
404
|
+
: minWidth
|
|
405
|
+
}}
|
|
406
|
+
>
|
|
407
|
+
{sortLabel}
|
|
408
|
+
</TableCell>
|
|
409
|
+
);
|
|
410
|
+
})}
|
|
411
|
+
</TableRow>
|
|
412
|
+
</TableHead>
|
|
413
|
+
<TableBody
|
|
414
|
+
sx={{
|
|
415
|
+
"& tr:nth-of-type(odd):not(.Mui-selected)": {
|
|
416
|
+
backgroundColor: alternatingColors[0]
|
|
417
|
+
},
|
|
418
|
+
"& tr:nth-of-type(even):not(.Mui-selected)": {
|
|
419
|
+
backgroundColor: alternatingColors[1]
|
|
420
|
+
}
|
|
421
|
+
}}
|
|
422
|
+
>
|
|
423
|
+
{[...Array(batchSize)].map((_item, rowIndex) => {
|
|
424
|
+
// Row
|
|
425
|
+
const row = rowIndex < rows.length ? rows[rowIndex] : undefined;
|
|
426
|
+
|
|
427
|
+
// Row id field value
|
|
428
|
+
const rowId = DataTypes.getValue(row, idField) ?? rowIndex;
|
|
429
|
+
|
|
430
|
+
// Selected or not
|
|
431
|
+
const isItemSelected = selectable
|
|
432
|
+
? selectedItems.some((item) => item[idField] === rowId)
|
|
433
|
+
: false;
|
|
434
|
+
|
|
435
|
+
return (
|
|
436
|
+
<TableRow
|
|
437
|
+
key={rowId as unknown as React.Key}
|
|
438
|
+
selected={isItemSelected}
|
|
439
|
+
>
|
|
440
|
+
{selectable && (
|
|
441
|
+
<TableCell padding="checkbox">
|
|
442
|
+
{row && (
|
|
443
|
+
<Checkbox
|
|
444
|
+
color="primary"
|
|
445
|
+
checked={isItemSelected}
|
|
446
|
+
onChange={(_event, checked) =>
|
|
447
|
+
handleSelect(row, checked)
|
|
448
|
+
}
|
|
449
|
+
/>
|
|
450
|
+
)}
|
|
451
|
+
</TableCell>
|
|
452
|
+
)}
|
|
453
|
+
{columns.map(
|
|
454
|
+
(
|
|
455
|
+
{
|
|
456
|
+
align,
|
|
457
|
+
cellRenderer = DataGridRenderers.defaultCellRenderer,
|
|
458
|
+
field,
|
|
459
|
+
type,
|
|
460
|
+
valueFormatter
|
|
461
|
+
},
|
|
462
|
+
columnIndex
|
|
463
|
+
) => {
|
|
464
|
+
const formatProps: GridCellFormatterProps<T> = {
|
|
465
|
+
data: row,
|
|
466
|
+
field,
|
|
467
|
+
rowIndex,
|
|
468
|
+
columnIndex
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
const cellProps: TableCellProps = {
|
|
472
|
+
align: GridAlignGet(align, type),
|
|
473
|
+
valign: "middle"
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const child = row ? (
|
|
477
|
+
cellRenderer({
|
|
478
|
+
data: row,
|
|
479
|
+
field,
|
|
480
|
+
formattedValue: valueFormatter
|
|
481
|
+
? valueFormatter(formatProps)
|
|
482
|
+
: undefined,
|
|
483
|
+
selected: isItemSelected,
|
|
484
|
+
type,
|
|
485
|
+
rowIndex,
|
|
486
|
+
columnIndex,
|
|
487
|
+
cellProps,
|
|
488
|
+
setItems: setRows
|
|
489
|
+
})
|
|
490
|
+
) : (
|
|
491
|
+
<React.Fragment> </React.Fragment>
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
return (
|
|
495
|
+
<TableCell
|
|
496
|
+
key={`${rowId}${columnIndex}`}
|
|
497
|
+
{...cellProps}
|
|
498
|
+
>
|
|
499
|
+
{child}
|
|
500
|
+
</TableCell>
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
)}
|
|
504
|
+
</TableRow>
|
|
505
|
+
);
|
|
506
|
+
})}
|
|
507
|
+
</TableBody>
|
|
508
|
+
</Table>
|
|
509
|
+
</TableContainer>
|
|
510
|
+
<TablePagination
|
|
511
|
+
component="div"
|
|
512
|
+
showFirstButton
|
|
513
|
+
count={totalRows}
|
|
514
|
+
rowsPerPage={batchSize}
|
|
515
|
+
page={currentPage}
|
|
516
|
+
onPageChange={handleChangePage}
|
|
517
|
+
onRowsPerPageChange={handleChangeRowsPerPage}
|
|
518
|
+
rowsPerPageOptions={[
|
|
519
|
+
batchSize,
|
|
520
|
+
2 * batchSize,
|
|
521
|
+
5 * batchSize,
|
|
522
|
+
10 * batchSize
|
|
523
|
+
]}
|
|
524
|
+
/>
|
|
525
|
+
</Paper>
|
|
526
|
+
);
|
|
559
527
|
}
|