@patternfly/react-table 6.2.0-prerelease.5 → 6.2.0-prerelease.7
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/CHANGELOG.md +10 -0
- package/components/package.json +1 -1
- package/deprecated/package.json +1 -1
- package/dist/dynamic/components/Table/package.json +1 -1
- package/dist/dynamic/components/Table/utils/decorators/package.json +1 -1
- package/dist/dynamic/components/Table/utils/package.json +1 -1
- package/dist/dynamic/deprecated/components/Table/base/package.json +1 -1
- package/dist/dynamic/deprecated/components/Table/package.json +1 -1
- package/dist/dynamic/deprecated/components/package.json +1 -1
- package/dist/umd/assets/{output-D7Q7dHtz.css → output-B-r1Y0_f.css} +3964 -3965
- package/package.json +3 -3
- package/src/demos/Table.md +5 -1
- package/src/demos/examples/TableColumnManagement.tsx +211 -204
- package/src/demos/examples/TableColumnManagementWithDraggable.tsx +306 -555
|
@@ -1,635 +1,386 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
|
|
2
3
|
import {
|
|
3
4
|
Button,
|
|
4
5
|
Content,
|
|
5
6
|
DataList,
|
|
6
7
|
DataListCheck,
|
|
7
|
-
DataListControl,
|
|
8
|
-
DataListDragButton,
|
|
9
|
-
DataListItem,
|
|
10
|
-
DataListItemRow,
|
|
11
8
|
DataListCell,
|
|
12
9
|
DataListItemCells,
|
|
10
|
+
DataListControl,
|
|
11
|
+
Label,
|
|
13
12
|
Toolbar,
|
|
14
13
|
ToolbarContent,
|
|
15
14
|
ToolbarItem,
|
|
15
|
+
MenuToggle,
|
|
16
16
|
Modal,
|
|
17
|
+
ModalHeader,
|
|
18
|
+
ModalBody,
|
|
19
|
+
ModalFooter,
|
|
17
20
|
OverflowMenu,
|
|
18
21
|
OverflowMenuGroup,
|
|
19
22
|
OverflowMenuItem,
|
|
20
|
-
|
|
23
|
+
PageSection,
|
|
24
|
+
Pagination,
|
|
25
|
+
PaginationVariant
|
|
21
26
|
} from '@patternfly/react-core';
|
|
22
|
-
import { Table
|
|
23
|
-
import
|
|
24
|
-
import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';
|
|
25
|
-
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
|
|
27
|
+
import { Table, TableText, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
|
|
28
|
+
import { DragDropSort } from '@patternfly/react-drag-drop';
|
|
26
29
|
import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';
|
|
27
30
|
import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
|
|
31
|
+
import { DashboardWrapper } from '@patternfly/react-table/dist/esm/demos/DashboardWrapper';
|
|
32
|
+
import { capitalize } from '@patternfly/react-table/src/components/Table/utils/utils';
|
|
33
|
+
import { rows, columns, SampleDataRow } from '@patternfly/react-table/dist/esm/demos/sampleData';
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
title: React.JSX.Element;
|
|
33
|
-
props: {
|
|
34
|
-
column: string;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
| {
|
|
38
|
-
title: string;
|
|
39
|
-
props: {
|
|
40
|
-
column: string;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
)[];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export const TableColumnManagementWithDraggable: React.FunctionComponent = () => {
|
|
47
|
-
const actions = [
|
|
48
|
-
{
|
|
49
|
-
title: <a href="#">Link</a>
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
title: 'Action'
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
isSeparator: true
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
title: <a href="#">Separated link</a>
|
|
59
|
-
}
|
|
60
|
-
];
|
|
61
|
-
const defaultColumns: string[] = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit', ''];
|
|
62
|
-
const defaultRows = [
|
|
63
|
-
{
|
|
64
|
-
cells: [
|
|
65
|
-
{
|
|
66
|
-
title: (
|
|
67
|
-
<React.Fragment>
|
|
68
|
-
<div>Node 1</div>
|
|
69
|
-
<a href="#">siemur/test-space</a>
|
|
70
|
-
</React.Fragment>
|
|
71
|
-
),
|
|
72
|
-
props: { column: 'Repositories' }
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
title: (
|
|
76
|
-
<React.Fragment>
|
|
77
|
-
<CodeBranchIcon key="icon" /> 10
|
|
78
|
-
</React.Fragment>
|
|
79
|
-
),
|
|
80
|
-
props: { column: 'Branches' }
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
title: (
|
|
84
|
-
<React.Fragment>
|
|
85
|
-
<CodeIcon key="icon" /> 25
|
|
86
|
-
</React.Fragment>
|
|
87
|
-
),
|
|
88
|
-
props: { column: 'Pull requests' }
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
title: (
|
|
92
|
-
<React.Fragment>
|
|
93
|
-
<CubeIcon key="icon" /> 5
|
|
94
|
-
</React.Fragment>
|
|
95
|
-
),
|
|
96
|
-
props: { column: 'Workspaces' }
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
title: '2 days ago',
|
|
100
|
-
props: { column: 'Last commit' }
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
title: (
|
|
104
|
-
<React.Fragment>
|
|
105
|
-
<a href="#">Action link</a>
|
|
106
|
-
</React.Fragment>
|
|
107
|
-
),
|
|
108
|
-
props: { column: '' }
|
|
109
|
-
}
|
|
110
|
-
]
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
cells: [
|
|
114
|
-
{
|
|
115
|
-
title: (
|
|
116
|
-
<React.Fragment>
|
|
117
|
-
<div>Node 2</div>
|
|
118
|
-
<a href="#">siemur/test-space</a>
|
|
119
|
-
</React.Fragment>
|
|
120
|
-
),
|
|
121
|
-
props: { column: 'Repositories' }
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
title: (
|
|
125
|
-
<React.Fragment>
|
|
126
|
-
<CodeBranchIcon key="icon" /> 8
|
|
127
|
-
</React.Fragment>
|
|
128
|
-
),
|
|
129
|
-
props: { column: 'Branches' }
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
title: (
|
|
133
|
-
<React.Fragment>
|
|
134
|
-
<CodeIcon key="icon" /> 30
|
|
135
|
-
</React.Fragment>
|
|
136
|
-
),
|
|
137
|
-
props: { column: 'Pull requests' }
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
title: (
|
|
141
|
-
<React.Fragment>
|
|
142
|
-
<CubeIcon key="icon" /> 2
|
|
143
|
-
</React.Fragment>
|
|
144
|
-
),
|
|
145
|
-
props: { column: 'Workspaces' }
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
title: '2 days ago',
|
|
149
|
-
props: { column: 'Last commit' }
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
title: (
|
|
153
|
-
<React.Fragment>
|
|
154
|
-
<a href="#">Action link</a>
|
|
155
|
-
</React.Fragment>
|
|
156
|
-
),
|
|
157
|
-
props: { column: '' }
|
|
158
|
-
}
|
|
159
|
-
]
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
cells: [
|
|
163
|
-
{
|
|
164
|
-
title: (
|
|
165
|
-
<React.Fragment>
|
|
166
|
-
<div>Node 3</div>
|
|
167
|
-
<a href="#">siemur/test-space</a>
|
|
168
|
-
</React.Fragment>
|
|
169
|
-
),
|
|
170
|
-
props: { column: 'Repositories' }
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
title: (
|
|
174
|
-
<React.Fragment>
|
|
175
|
-
<CodeBranchIcon key="icon" /> 12
|
|
176
|
-
</React.Fragment>
|
|
177
|
-
),
|
|
178
|
-
props: { column: 'Branches' }
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
title: (
|
|
182
|
-
<React.Fragment>
|
|
183
|
-
<CodeIcon key="icon" /> 48
|
|
184
|
-
</React.Fragment>
|
|
185
|
-
),
|
|
186
|
-
props: { column: 'Pull requests' }
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
title: (
|
|
190
|
-
<React.Fragment>
|
|
191
|
-
<CubeIcon key="icon" /> 13
|
|
192
|
-
</React.Fragment>
|
|
193
|
-
),
|
|
194
|
-
props: { column: 'Workspaces' }
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
title: '30 days ago',
|
|
198
|
-
props: { column: 'Last commit' }
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
title: (
|
|
202
|
-
<React.Fragment>
|
|
203
|
-
<a href="#">Action link</a>
|
|
204
|
-
</React.Fragment>
|
|
205
|
-
),
|
|
206
|
-
props: { column: '' }
|
|
207
|
-
}
|
|
208
|
-
]
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
cells: [
|
|
212
|
-
{
|
|
213
|
-
title: (
|
|
214
|
-
<React.Fragment>
|
|
215
|
-
<div>Node 4</div>
|
|
216
|
-
<a href="#">siemur/test-space</a>
|
|
217
|
-
</React.Fragment>
|
|
218
|
-
),
|
|
219
|
-
props: { column: 'Repositories' }
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
title: (
|
|
223
|
-
<React.Fragment>
|
|
224
|
-
<CodeBranchIcon key="icon" /> 3
|
|
225
|
-
</React.Fragment>
|
|
226
|
-
),
|
|
227
|
-
props: { column: 'Branches' }
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
title: (
|
|
231
|
-
<React.Fragment>
|
|
232
|
-
<CodeIcon key="icon" /> 8
|
|
233
|
-
</React.Fragment>
|
|
234
|
-
),
|
|
235
|
-
props: { column: 'Pull requests' }
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
title: (
|
|
239
|
-
<React.Fragment>
|
|
240
|
-
<CubeIcon key="icon" /> 20
|
|
241
|
-
</React.Fragment>
|
|
242
|
-
),
|
|
243
|
-
props: { column: 'Workspaces' }
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
title: '8 days ago',
|
|
247
|
-
props: { column: 'Last commit' }
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
title: (
|
|
251
|
-
<React.Fragment>
|
|
252
|
-
<a href="#">Action link</a>
|
|
253
|
-
</React.Fragment>
|
|
254
|
-
),
|
|
255
|
-
props: { column: '' }
|
|
256
|
-
}
|
|
257
|
-
]
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
cells: [
|
|
261
|
-
{
|
|
262
|
-
title: (
|
|
263
|
-
<React.Fragment>
|
|
264
|
-
<div>Node 5</div>
|
|
265
|
-
<a href="#">siemur/test-space</a>
|
|
266
|
-
</React.Fragment>
|
|
267
|
-
),
|
|
268
|
-
props: { column: 'Repositories' }
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
title: (
|
|
272
|
-
<React.Fragment>
|
|
273
|
-
<CodeBranchIcon key="icon" /> 34
|
|
274
|
-
</React.Fragment>
|
|
275
|
-
),
|
|
276
|
-
props: { column: 'Branches' }
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
title: (
|
|
280
|
-
<React.Fragment>
|
|
281
|
-
<CodeIcon key="icon" /> 21
|
|
282
|
-
</React.Fragment>
|
|
283
|
-
),
|
|
284
|
-
props: { column: 'Pull requests' }
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
title: (
|
|
288
|
-
<React.Fragment>
|
|
289
|
-
<CubeIcon key="icon" /> 26
|
|
290
|
-
</React.Fragment>
|
|
291
|
-
),
|
|
292
|
-
props: { column: 'Workspaces' }
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
title: '2 days ago',
|
|
296
|
-
props: { column: 'Last commit' }
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
title: (
|
|
300
|
-
<React.Fragment>
|
|
301
|
-
<a href="#">Action link</a>
|
|
302
|
-
</React.Fragment>
|
|
303
|
-
),
|
|
304
|
-
props: { column: '' }
|
|
305
|
-
}
|
|
306
|
-
]
|
|
307
|
-
}
|
|
308
|
-
];
|
|
35
|
+
export const TableColumnManagement: React.FunctionComponent = () => {
|
|
36
|
+
const defaultColumns = columns;
|
|
37
|
+
const defaultRows = rows;
|
|
309
38
|
|
|
310
39
|
const [filters, setFilters] = React.useState<string[]>([]);
|
|
311
|
-
const [filteredColumns, setFilteredColumns] = React.useState<string[]>(
|
|
312
|
-
const [
|
|
313
|
-
const [
|
|
40
|
+
const [filteredColumns, setFilteredColumns] = React.useState<string[]>(defaultColumns);
|
|
41
|
+
const [filteredRows, setFilteredRows] = React.useState<SampleDataRow[]>(defaultRows);
|
|
42
|
+
const [managedColumns, setManagedColumns] = React.useState<string[]>(defaultColumns);
|
|
43
|
+
const [managedRows, setManagedRows] = React.useState<SampleDataRow[]>(defaultRows);
|
|
314
44
|
const [isModalOpen, setIsModalOpen] = React.useState(false);
|
|
315
|
-
const [
|
|
316
|
-
const [
|
|
317
|
-
const [
|
|
318
|
-
const [check4, setCheck4] = React.useState(true);
|
|
319
|
-
const [check5, setCheck5] = React.useState(true);
|
|
45
|
+
const [page, setPage] = React.useState(1);
|
|
46
|
+
const [perPage, setPerPage] = React.useState(10);
|
|
47
|
+
const [paginatedRows, setPaginatedRows] = React.useState<any[]>(rows);
|
|
320
48
|
|
|
321
|
-
const
|
|
49
|
+
const [columnData, setColumnData] = React.useState(defaultColumns.map((col) => ({ name: col, checked: true })));
|
|
50
|
+
const [initialColData, setInitialColData] = React.useState(columnData);
|
|
51
|
+
|
|
52
|
+
const matchSelectedColumnNameToAttr = (name: string): string => {
|
|
322
53
|
switch (name) {
|
|
323
|
-
case '
|
|
324
|
-
return '
|
|
325
|
-
case '
|
|
326
|
-
return '
|
|
327
|
-
case '
|
|
328
|
-
return '
|
|
329
|
-
case '
|
|
330
|
-
return '
|
|
331
|
-
case '
|
|
332
|
-
return '
|
|
54
|
+
case 'Servers':
|
|
55
|
+
return 'name';
|
|
56
|
+
case 'Threads':
|
|
57
|
+
return 'threads';
|
|
58
|
+
case 'Applications':
|
|
59
|
+
return 'applications';
|
|
60
|
+
case 'Workspaces':
|
|
61
|
+
return 'workspaces';
|
|
62
|
+
case 'Status':
|
|
63
|
+
return 'status';
|
|
64
|
+
case 'Location':
|
|
65
|
+
return 'location';
|
|
66
|
+
case 'Last Modified':
|
|
67
|
+
return 'lastModified';
|
|
68
|
+
case 'URL':
|
|
69
|
+
return 'url';
|
|
333
70
|
default:
|
|
334
71
|
return '';
|
|
335
72
|
}
|
|
336
73
|
};
|
|
337
74
|
|
|
75
|
+
// Pagination logic
|
|
76
|
+
const handleSetPage = (
|
|
77
|
+
_evt: MouseEvent | React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element>,
|
|
78
|
+
newPage: number
|
|
79
|
+
) => {
|
|
80
|
+
setPage(newPage);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const handlePerPageSelect = (
|
|
84
|
+
_evt: MouseEvent | React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element>,
|
|
85
|
+
newPerPage: number
|
|
86
|
+
) => {
|
|
87
|
+
setPerPage(newPerPage);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const renderPagination = (variant: 'top' | 'bottom' | PaginationVariant, isCompact: boolean) => (
|
|
91
|
+
<Pagination
|
|
92
|
+
isCompact={isCompact}
|
|
93
|
+
itemCount={rows.length}
|
|
94
|
+
page={page}
|
|
95
|
+
perPage={perPage}
|
|
96
|
+
onSetPage={handleSetPage}
|
|
97
|
+
onPerPageSelect={handlePerPageSelect}
|
|
98
|
+
variant={variant}
|
|
99
|
+
titles={{
|
|
100
|
+
paginationAriaLabel: `${variant} pagination`
|
|
101
|
+
}}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
React.useEffect(() => {
|
|
106
|
+
setPaginatedRows(managedRows.slice((page - 1) * perPage, page * perPage - 1));
|
|
107
|
+
}, [managedRows, page, perPage]);
|
|
108
|
+
|
|
109
|
+
// Removes attribute from each node object in Data.jsx
|
|
110
|
+
const removePropFromObject = (object: any, keys: string[]): any =>
|
|
111
|
+
keys.reduce((obj, prop) => {
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
113
|
+
const { [prop]: _, ...keep } = obj;
|
|
114
|
+
return keep;
|
|
115
|
+
}, object);
|
|
116
|
+
|
|
117
|
+
// Filters columns out of table that are not selected in the column management modal
|
|
338
118
|
const filterData = (checked: boolean, name: string) => {
|
|
119
|
+
const selectedColumn = matchSelectedColumnNameToAttr(name);
|
|
120
|
+
|
|
121
|
+
const filteredRows: SampleDataRow[] = [];
|
|
339
122
|
if (checked) {
|
|
340
|
-
const updatedFilters = filters.filter((item) => item !==
|
|
341
|
-
|
|
123
|
+
const updatedFilters = filters.filter((item) => item !== selectedColumn);
|
|
124
|
+
|
|
125
|
+
// Only show the names of columns that were selected in the modal
|
|
126
|
+
const filteredColumns = defaultColumns.filter(
|
|
127
|
+
(column) => !updatedFilters.includes(matchSelectedColumnNameToAttr(column))
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// Remove the attributes (i.e. "columns") that were not selected
|
|
131
|
+
defaultRows.forEach((item) => filteredRows.push(removePropFromObject(item, updatedFilters)));
|
|
132
|
+
|
|
342
133
|
setFilters(updatedFilters);
|
|
343
|
-
setFilteredColumns(
|
|
134
|
+
setFilteredColumns(filteredColumns);
|
|
135
|
+
setFilteredRows(filteredRows);
|
|
344
136
|
} else {
|
|
345
137
|
const updatedFilters = filters;
|
|
346
|
-
updatedFilters.push(
|
|
347
|
-
|
|
138
|
+
updatedFilters.push(selectedColumn);
|
|
139
|
+
|
|
140
|
+
// Only show the names of columns that were selected in the modal
|
|
141
|
+
const filteredColumns = managedColumns.filter(
|
|
142
|
+
(column) => !filters.includes(matchSelectedColumnNameToAttr(column))
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// Remove the attributes (i.e. "columns") that were not selected
|
|
146
|
+
managedRows.forEach((item) => filteredRows.push(removePropFromObject(item, updatedFilters)));
|
|
147
|
+
|
|
348
148
|
setFilters(updatedFilters);
|
|
349
|
-
setFilteredColumns(
|
|
149
|
+
setFilteredColumns(filteredColumns);
|
|
150
|
+
setFilteredRows(filteredRows);
|
|
350
151
|
}
|
|
351
152
|
};
|
|
153
|
+
|
|
352
154
|
const unfilterAllData = () => {
|
|
353
155
|
setFilters([]);
|
|
354
156
|
setFilteredColumns(defaultColumns);
|
|
157
|
+
setFilteredRows(defaultRows);
|
|
355
158
|
};
|
|
356
|
-
const handleChange = (event: React.FormEvent<HTMLInputElement>, checked: boolean) => {
|
|
357
|
-
const target = event.currentTarget;
|
|
358
|
-
const name = target.name;
|
|
359
159
|
|
|
360
|
-
|
|
361
|
-
filterData(checked, matchCheckboxNameToColumn(target.name));
|
|
362
|
-
switch (name) {
|
|
363
|
-
case 'check1':
|
|
364
|
-
setCheck1(value);
|
|
365
|
-
break;
|
|
366
|
-
case 'check2':
|
|
367
|
-
setCheck2(value);
|
|
368
|
-
break;
|
|
369
|
-
case 'check3':
|
|
370
|
-
setCheck3(value);
|
|
371
|
-
break;
|
|
372
|
-
case 'check4':
|
|
373
|
-
setCheck4(value);
|
|
374
|
-
break;
|
|
375
|
-
case 'check5':
|
|
376
|
-
setCheck5(value);
|
|
377
|
-
break;
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
const handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => {
|
|
160
|
+
const handleModalToggle = (_event: React.MouseEvent<Element, MouseEvent> | KeyboardEvent) => {
|
|
381
161
|
setIsModalOpen(!isModalOpen);
|
|
162
|
+
setInitialColData(columnData);
|
|
382
163
|
};
|
|
164
|
+
|
|
383
165
|
const onSave = () => {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
.
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
if (indexA > indexB) {
|
|
399
|
-
return 1;
|
|
400
|
-
}
|
|
401
|
-
// a must be equal to b
|
|
402
|
-
return 0;
|
|
403
|
-
});
|
|
404
|
-
orderedRows.push({
|
|
405
|
-
cells: updatedCells
|
|
166
|
+
const orderedFilteredColumns: string[] = [];
|
|
167
|
+
columnData.map((col) => {
|
|
168
|
+
if (filteredColumns.find((filteredCol) => filteredCol === col.name)) {
|
|
169
|
+
orderedFilteredColumns.push(col.name);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const orderedFilteredRows = filteredRows.map((row) => {
|
|
174
|
+
let orderedRow;
|
|
175
|
+
columnData.map((col) => {
|
|
176
|
+
if (filteredColumns.find((filteredCol) => filteredCol === col.name)) {
|
|
177
|
+
const rowField = matchSelectedColumnNameToAttr(col.name);
|
|
178
|
+
orderedRow = { ...orderedRow, [rowField]: row[rowField] };
|
|
179
|
+
}
|
|
406
180
|
});
|
|
181
|
+
return orderedRow;
|
|
407
182
|
});
|
|
408
|
-
|
|
409
|
-
|
|
183
|
+
|
|
184
|
+
setManagedColumns(orderedFilteredColumns);
|
|
185
|
+
setManagedRows(orderedFilteredRows);
|
|
186
|
+
setPaginatedRows(filteredRows);
|
|
410
187
|
setIsModalOpen(!isModalOpen);
|
|
411
188
|
};
|
|
412
189
|
|
|
413
190
|
const selectAllColumns = () => {
|
|
414
191
|
unfilterAllData();
|
|
415
|
-
|
|
416
|
-
setCheck2(true);
|
|
417
|
-
setCheck3(true);
|
|
418
|
-
setCheck4(true);
|
|
419
|
-
setCheck5(true);
|
|
192
|
+
setColumnData(columnData.map((col) => ({ name: col.name, checked: true })));
|
|
420
193
|
};
|
|
421
194
|
|
|
422
195
|
const renderModal = () => (
|
|
423
196
|
<Modal
|
|
424
|
-
title="Manage columns"
|
|
425
197
|
isOpen={isModalOpen}
|
|
426
198
|
variant="small"
|
|
427
|
-
description={
|
|
428
|
-
<Content>
|
|
429
|
-
<p>Selected categories will be displayed in the table.</p>
|
|
430
|
-
<Button isInline onClick={selectAllColumns} variant="link">
|
|
431
|
-
Select all
|
|
432
|
-
</Button>
|
|
433
|
-
</Content>
|
|
434
|
-
}
|
|
435
199
|
onClose={handleModalToggle}
|
|
436
|
-
|
|
200
|
+
aria-labelledby="basic-modal-title"
|
|
201
|
+
aria-describedby="modal-box-body-basic"
|
|
202
|
+
>
|
|
203
|
+
<ModalHeader
|
|
204
|
+
title="Manage columns"
|
|
205
|
+
labelId="basic-modal-title"
|
|
206
|
+
description={
|
|
207
|
+
<Content>
|
|
208
|
+
<p>Selected categories will be displayed in the table.</p>
|
|
209
|
+
<Button isInline onClick={selectAllColumns} variant="secondary">
|
|
210
|
+
Select all
|
|
211
|
+
</Button>
|
|
212
|
+
</Content>
|
|
213
|
+
}
|
|
214
|
+
/>
|
|
215
|
+
<ModalBody id="modal-box-body-basic">
|
|
216
|
+
<DragDropSort
|
|
217
|
+
items={columnData.map((colData) => ({
|
|
218
|
+
id: colData.name,
|
|
219
|
+
content: (
|
|
220
|
+
<>
|
|
221
|
+
<DataListControl>
|
|
222
|
+
<DataListCheck
|
|
223
|
+
aria-labelledby={`table-column-management-item-${colData.name}`}
|
|
224
|
+
isChecked={colData.checked}
|
|
225
|
+
name={`check-${colData.name}`}
|
|
226
|
+
id={`check-${colData.name}`}
|
|
227
|
+
onChange={(event: React.FormEvent<HTMLInputElement>, _checked: boolean) => {
|
|
228
|
+
let newColumnData: { name: string; checked: boolean }[] = [];
|
|
229
|
+
|
|
230
|
+
columnData.map((colData) => {
|
|
231
|
+
if (event.currentTarget.name === `check-${colData.name}`) {
|
|
232
|
+
newColumnData = [...newColumnData, { name: colData.name, checked: !colData.checked }];
|
|
233
|
+
filterData(!colData.checked, colData.name);
|
|
234
|
+
} else {
|
|
235
|
+
newColumnData = [...newColumnData, colData];
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
setColumnData(newColumnData);
|
|
240
|
+
}}
|
|
241
|
+
/>
|
|
242
|
+
</DataListControl>
|
|
243
|
+
<DataListItemCells
|
|
244
|
+
dataListCells={[
|
|
245
|
+
<DataListCell
|
|
246
|
+
id={`table-column-management-item-${colData.name}`}
|
|
247
|
+
key={`table-column-management-item-${colData.name}`}
|
|
248
|
+
>
|
|
249
|
+
<label htmlFor={`check-${colData.name}`}>{colData.name}</label>
|
|
250
|
+
</DataListCell>
|
|
251
|
+
]}
|
|
252
|
+
/>
|
|
253
|
+
</>
|
|
254
|
+
),
|
|
255
|
+
data: colData
|
|
256
|
+
}))}
|
|
257
|
+
onDrop={(_, newItems) => {
|
|
258
|
+
setColumnData(newItems.map((item) => (item as any).data));
|
|
259
|
+
}}
|
|
260
|
+
variant="DataList"
|
|
261
|
+
overlayProps={{ isCompact: true }}
|
|
262
|
+
>
|
|
263
|
+
<DataList aria-label="Table column management" id="table-column-management" isCompact />
|
|
264
|
+
</DragDropSort>
|
|
265
|
+
</ModalBody>
|
|
266
|
+
<ModalFooter>
|
|
437
267
|
<Button key="save" variant="primary" onClick={onSave}>
|
|
438
268
|
Save
|
|
439
|
-
</Button
|
|
440
|
-
<Button
|
|
269
|
+
</Button>
|
|
270
|
+
<Button
|
|
271
|
+
key="cancel"
|
|
272
|
+
variant="link"
|
|
273
|
+
onClick={(event: React.MouseEvent<Element, MouseEvent> | KeyboardEvent) => {
|
|
274
|
+
setColumnData(initialColData);
|
|
275
|
+
handleModalToggle(event);
|
|
276
|
+
}}
|
|
277
|
+
>
|
|
441
278
|
Cancel
|
|
442
279
|
</Button>
|
|
443
|
-
|
|
444
|
-
>
|
|
445
|
-
<DataList aria-label="Table column management" id="table-column-management" isCompact>
|
|
446
|
-
<DataListItem aria-labelledby="table-column-management-item1" id="data1">
|
|
447
|
-
<DataListItemRow>
|
|
448
|
-
<DataListControl>
|
|
449
|
-
<DataListDragButton
|
|
450
|
-
aria-label="Reorder"
|
|
451
|
-
aria-labelledby="table-column-management-item1"
|
|
452
|
-
aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
|
|
453
|
-
aria-pressed="false"
|
|
454
|
-
/>
|
|
455
|
-
<DataListCheck
|
|
456
|
-
aria-labelledby="table-column-management-item1"
|
|
457
|
-
checked={check1}
|
|
458
|
-
name="check1"
|
|
459
|
-
id="check1"
|
|
460
|
-
onChange={handleChange}
|
|
461
|
-
otherControls
|
|
462
|
-
/>
|
|
463
|
-
</DataListControl>
|
|
464
|
-
<DataListItemCells
|
|
465
|
-
dataListCells={[
|
|
466
|
-
<DataListCell id="table-column-management-item1" key="table-column-management-item1">
|
|
467
|
-
<label htmlFor="check1">Repositories</label>
|
|
468
|
-
</DataListCell>
|
|
469
|
-
]}
|
|
470
|
-
/>
|
|
471
|
-
</DataListItemRow>
|
|
472
|
-
</DataListItem>
|
|
473
|
-
<DataListItem aria-labelledby="table-column-management-item2" id="data2">
|
|
474
|
-
<DataListItemRow>
|
|
475
|
-
<DataListControl>
|
|
476
|
-
<DataListDragButton
|
|
477
|
-
aria-label="Reorder"
|
|
478
|
-
aria-labelledby="table-column-management-item2"
|
|
479
|
-
aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
|
|
480
|
-
aria-pressed="false"
|
|
481
|
-
/>
|
|
482
|
-
<DataListCheck
|
|
483
|
-
aria-labelledby="table-column-management-item2"
|
|
484
|
-
checked={check2}
|
|
485
|
-
name="check2"
|
|
486
|
-
id="check2"
|
|
487
|
-
onChange={handleChange}
|
|
488
|
-
otherControls
|
|
489
|
-
/>
|
|
490
|
-
</DataListControl>
|
|
491
|
-
<DataListItemCells
|
|
492
|
-
dataListCells={[
|
|
493
|
-
<DataListCell id="table-column-management-item2" key="table-column-management-item2">
|
|
494
|
-
<label htmlFor="check2">Branches</label>
|
|
495
|
-
</DataListCell>
|
|
496
|
-
]}
|
|
497
|
-
/>
|
|
498
|
-
</DataListItemRow>
|
|
499
|
-
</DataListItem>
|
|
500
|
-
<DataListItem aria-labelledby="table-column-management-item3" id="data3">
|
|
501
|
-
<DataListItemRow>
|
|
502
|
-
<DataListControl>
|
|
503
|
-
<DataListDragButton
|
|
504
|
-
aria-label="Reorder"
|
|
505
|
-
aria-labelledby="table-column-management-item3"
|
|
506
|
-
aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
|
|
507
|
-
aria-pressed="false"
|
|
508
|
-
/>
|
|
509
|
-
<DataListCheck
|
|
510
|
-
aria-labelledby="table-column-management-item3"
|
|
511
|
-
checked={check3}
|
|
512
|
-
name="check3"
|
|
513
|
-
id="check3"
|
|
514
|
-
onChange={handleChange}
|
|
515
|
-
otherControls
|
|
516
|
-
/>
|
|
517
|
-
</DataListControl>
|
|
518
|
-
<DataListItemCells
|
|
519
|
-
dataListCells={[
|
|
520
|
-
<DataListCell id="table-column-management-item3" key="table-column-management-item3">
|
|
521
|
-
<label htmlFor="check3">Pull requests</label>
|
|
522
|
-
</DataListCell>
|
|
523
|
-
]}
|
|
524
|
-
/>
|
|
525
|
-
</DataListItemRow>
|
|
526
|
-
</DataListItem>
|
|
527
|
-
<DataListItem aria-labelledby="table-column-management-item4" id="data4">
|
|
528
|
-
<DataListItemRow>
|
|
529
|
-
<DataListControl>
|
|
530
|
-
<DataListDragButton
|
|
531
|
-
aria-label="Reorder"
|
|
532
|
-
aria-labelledby="table-column-management-item4"
|
|
533
|
-
aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
|
|
534
|
-
aria-pressed="false"
|
|
535
|
-
/>
|
|
536
|
-
<DataListCheck
|
|
537
|
-
aria-labelledby="table-column-management-item4"
|
|
538
|
-
checked={check4}
|
|
539
|
-
name="check4"
|
|
540
|
-
id="check4"
|
|
541
|
-
onChange={handleChange}
|
|
542
|
-
otherControls
|
|
543
|
-
/>
|
|
544
|
-
</DataListControl>
|
|
545
|
-
<DataListItemCells
|
|
546
|
-
dataListCells={[
|
|
547
|
-
<DataListCell id="table-column-management-item4" key="table-column-management-item4">
|
|
548
|
-
<label htmlFor="check4">Workspaces</label>
|
|
549
|
-
</DataListCell>
|
|
550
|
-
]}
|
|
551
|
-
/>
|
|
552
|
-
</DataListItemRow>
|
|
553
|
-
</DataListItem>
|
|
554
|
-
<DataListItem aria-labelledby="table-column-management-item5" id="data5">
|
|
555
|
-
<DataListItemRow>
|
|
556
|
-
<DataListControl>
|
|
557
|
-
<DataListDragButton
|
|
558
|
-
aria-label="Reorder"
|
|
559
|
-
aria-labelledby="table-column-management-item5"
|
|
560
|
-
aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
|
|
561
|
-
aria-pressed="false"
|
|
562
|
-
/>
|
|
563
|
-
<DataListCheck
|
|
564
|
-
aria-labelledby="table-column-management-item5"
|
|
565
|
-
checked={check5}
|
|
566
|
-
name="check5"
|
|
567
|
-
id="check5"
|
|
568
|
-
onChange={handleChange}
|
|
569
|
-
otherControls
|
|
570
|
-
/>
|
|
571
|
-
</DataListControl>
|
|
572
|
-
<DataListItemCells
|
|
573
|
-
dataListCells={[
|
|
574
|
-
<DataListCell id="table-column-management-item5" key="table-column-management-item5">
|
|
575
|
-
<label htmlFor="check5">Last commit</label>
|
|
576
|
-
</DataListCell>
|
|
577
|
-
]}
|
|
578
|
-
/>
|
|
579
|
-
</DataListItemRow>
|
|
580
|
-
</DataListItem>
|
|
581
|
-
</DataList>
|
|
280
|
+
</ModalFooter>
|
|
582
281
|
</Modal>
|
|
583
282
|
);
|
|
584
283
|
|
|
284
|
+
const renderLabel = (labelText: string): JSX.Element => {
|
|
285
|
+
switch (labelText) {
|
|
286
|
+
case 'Running':
|
|
287
|
+
return <Label color="green">{labelText}</Label>;
|
|
288
|
+
case 'Stopped':
|
|
289
|
+
return <Label color="orange">{labelText}</Label>;
|
|
290
|
+
case 'Needs maintenance':
|
|
291
|
+
return <Label color="blue">{labelText}</Label>;
|
|
292
|
+
case 'Down':
|
|
293
|
+
return <Label color="red">{labelText}</Label>;
|
|
294
|
+
default:
|
|
295
|
+
return <></>;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
585
299
|
const toolbarItems = (
|
|
586
300
|
<React.Fragment>
|
|
587
|
-
<
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
<
|
|
592
|
-
<
|
|
593
|
-
<
|
|
594
|
-
<MenuToggle icon={<FilterIcon />}>Name</MenuToggle>
|
|
595
|
-
</OverflowMenuItem>
|
|
596
|
-
<OverflowMenuItem>
|
|
597
|
-
<MenuToggle variant="plain" aria-label="Sort columns" icon={<SortAmountDownIcon />} />
|
|
598
|
-
</OverflowMenuItem>
|
|
599
|
-
<OverflowMenuGroup groupType="button" isPersistent>
|
|
301
|
+
<Toolbar id="page-layout-table-column-management-action-toolbar-top">
|
|
302
|
+
<span id="page-layout-table-column-management-action-toolbar-top-select-checkbox-label" hidden>
|
|
303
|
+
Choose one
|
|
304
|
+
</span>
|
|
305
|
+
<ToolbarContent>
|
|
306
|
+
<ToolbarItem>
|
|
307
|
+
<OverflowMenu breakpoint="md">
|
|
600
308
|
<OverflowMenuItem>
|
|
601
|
-
<
|
|
309
|
+
<MenuToggle icon={<FilterIcon />}>Name</MenuToggle>
|
|
602
310
|
</OverflowMenuItem>
|
|
603
311
|
<OverflowMenuItem>
|
|
604
|
-
<
|
|
605
|
-
|
|
606
|
-
|
|
312
|
+
<MenuToggle
|
|
313
|
+
variant="plain"
|
|
314
|
+
aria-label="Sort columns"
|
|
315
|
+
icon={<SortAmountDownIcon aria-hidden="true" />}
|
|
316
|
+
/>
|
|
607
317
|
</OverflowMenuItem>
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
318
|
+
<OverflowMenuGroup groupType="button" isPersistent>
|
|
319
|
+
<OverflowMenuItem>
|
|
320
|
+
<Button variant="primary">Action</Button>
|
|
321
|
+
</OverflowMenuItem>
|
|
322
|
+
<OverflowMenuItem isPersistent>
|
|
323
|
+
<Button variant="link" onClick={handleModalToggle}>
|
|
324
|
+
Manage columns
|
|
325
|
+
</Button>
|
|
326
|
+
</OverflowMenuItem>
|
|
327
|
+
</OverflowMenuGroup>
|
|
328
|
+
</OverflowMenu>
|
|
329
|
+
</ToolbarItem>
|
|
330
|
+
<ToolbarItem variant="pagination">{renderPagination('top', false)}</ToolbarItem>
|
|
331
|
+
</ToolbarContent>
|
|
332
|
+
</Toolbar>
|
|
612
333
|
</React.Fragment>
|
|
613
334
|
);
|
|
614
335
|
|
|
615
336
|
return (
|
|
616
337
|
<React.Fragment>
|
|
617
|
-
<
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
<
|
|
621
|
-
<
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
338
|
+
<DashboardWrapper hasPageTemplateTitle>
|
|
339
|
+
<PageSection isFilled>
|
|
340
|
+
{toolbarItems}
|
|
341
|
+
<Table variant="compact" aria-label="Column Management Table">
|
|
342
|
+
<Thead>
|
|
343
|
+
<Tr>
|
|
344
|
+
{managedColumns.map((column, columnIndex) => (
|
|
345
|
+
<Th key={columnIndex}>{column}</Th>
|
|
346
|
+
))}
|
|
347
|
+
</Tr>
|
|
348
|
+
</Thead>
|
|
349
|
+
<Tbody>
|
|
350
|
+
{paginatedRows.map((row, rowIndex) => (
|
|
351
|
+
<Tr key={rowIndex}>
|
|
352
|
+
<>
|
|
353
|
+
{Object.entries(row).map(([key, value], idx) =>
|
|
354
|
+
// eslint-disable-next-line no-nested-ternary
|
|
355
|
+
key === 'status' ? (
|
|
356
|
+
<Td width={15} dataLabel="Status" key={`${idx}-${value}`}>
|
|
357
|
+
{renderLabel(value as string)}
|
|
358
|
+
</Td>
|
|
359
|
+
) : key === 'url' ? (
|
|
360
|
+
<Td width={10} dataLabel="URL" modifier="truncate" key={`${idx}-${value}`}>
|
|
361
|
+
<TableText>
|
|
362
|
+
<a href="#">{row.url}</a>
|
|
363
|
+
</TableText>
|
|
364
|
+
</Td>
|
|
365
|
+
) : (
|
|
366
|
+
<Td
|
|
367
|
+
width={key === 'name' ? 15 : 10}
|
|
368
|
+
dataLabel={key === 'lastModified' ? 'Last modified' : capitalize(key)}
|
|
369
|
+
key={`${idx}-${value}`}
|
|
370
|
+
>
|
|
371
|
+
{value as string}
|
|
372
|
+
</Td>
|
|
373
|
+
)
|
|
374
|
+
)}
|
|
375
|
+
</>
|
|
376
|
+
</Tr>
|
|
377
|
+
))}
|
|
378
|
+
</Tbody>
|
|
379
|
+
</Table>
|
|
380
|
+
{renderPagination('bottom', false)}
|
|
381
|
+
{renderModal()}
|
|
382
|
+
</PageSection>
|
|
383
|
+
</DashboardWrapper>
|
|
633
384
|
</React.Fragment>
|
|
634
385
|
);
|
|
635
386
|
};
|