@patternfly/react-table 6.0.0-alpha.2 → 6.0.0-alpha.4

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.
Files changed (123) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/components/package.json +1 -1
  3. package/deprecated/package.json +1 -1
  4. package/dist/dynamic/components/Table/package.json +1 -1
  5. package/dist/dynamic/components/Table/utils/decorators/package.json +1 -1
  6. package/dist/dynamic/components/Table/utils/package.json +1 -1
  7. package/dist/dynamic/deprecated/components/Table/base/package.json +1 -1
  8. package/dist/dynamic/deprecated/components/Table/package.json +1 -1
  9. package/dist/dynamic/deprecated/components/package.json +1 -1
  10. package/dist/esm/components/Table/Caption.js +1 -1
  11. package/dist/esm/components/Table/Caption.js.map +1 -1
  12. package/dist/esm/components/Table/CollapseColumn.js +1 -1
  13. package/dist/esm/components/Table/CollapseColumn.js.map +1 -1
  14. package/dist/esm/components/Table/DraggableRowWrapper.js +2 -2
  15. package/dist/esm/components/Table/DraggableRowWrapper.js.map +1 -1
  16. package/dist/esm/components/Table/EditColumn.js +1 -1
  17. package/dist/esm/components/Table/EditColumn.js.map +1 -1
  18. package/dist/esm/components/Table/EditableSelectInputCell.js +2 -2
  19. package/dist/esm/components/Table/EditableSelectInputCell.js.map +1 -1
  20. package/dist/esm/components/Table/EditableTextCell.js +2 -2
  21. package/dist/esm/components/Table/EditableTextCell.js.map +1 -1
  22. package/dist/esm/components/Table/ExpandableRowContent.js +1 -1
  23. package/dist/esm/components/Table/ExpandableRowContent.js.map +1 -1
  24. package/dist/esm/components/Table/HeaderCellInfoWrapper.js +1 -1
  25. package/dist/esm/components/Table/HeaderCellInfoWrapper.js.map +1 -1
  26. package/dist/esm/components/Table/InnerScrollContainer.js +1 -1
  27. package/dist/esm/components/Table/InnerScrollContainer.js.map +1 -1
  28. package/dist/esm/components/Table/OuterScrollContainer.js +1 -1
  29. package/dist/esm/components/Table/OuterScrollContainer.js.map +1 -1
  30. package/dist/esm/components/Table/SortColumn.js +1 -1
  31. package/dist/esm/components/Table/SortColumn.js.map +1 -1
  32. package/dist/esm/components/Table/Table.js +3 -3
  33. package/dist/esm/components/Table/Table.js.map +1 -1
  34. package/dist/esm/components/Table/TableText.js +1 -1
  35. package/dist/esm/components/Table/TableText.js.map +1 -1
  36. package/dist/esm/components/Table/Tbody.js +1 -1
  37. package/dist/esm/components/Table/Tbody.js.map +1 -1
  38. package/dist/esm/components/Table/Td.js +3 -3
  39. package/dist/esm/components/Table/Td.js.map +1 -1
  40. package/dist/esm/components/Table/Th.js +2 -2
  41. package/dist/esm/components/Table/Th.js.map +1 -1
  42. package/dist/esm/components/Table/Thead.js +1 -1
  43. package/dist/esm/components/Table/Thead.js.map +1 -1
  44. package/dist/esm/components/Table/Tr.js +2 -2
  45. package/dist/esm/components/Table/Tr.js.map +1 -1
  46. package/dist/esm/components/Table/TreeRowWrapper.js +2 -2
  47. package/dist/esm/components/Table/TreeRowWrapper.js.map +1 -1
  48. package/dist/esm/components/Table/utils/decorators/cellActions.js +1 -1
  49. package/dist/esm/components/Table/utils/decorators/cellActions.js.map +1 -1
  50. package/dist/esm/components/Table/utils/decorators/cellWidth.js +1 -1
  51. package/dist/esm/components/Table/utils/decorators/cellWidth.js.map +1 -1
  52. package/dist/esm/components/Table/utils/decorators/classNames.js +1 -1
  53. package/dist/esm/components/Table/utils/decorators/classNames.js.map +1 -1
  54. package/dist/esm/components/Table/utils/decorators/collapsible.js +1 -1
  55. package/dist/esm/components/Table/utils/decorators/collapsible.js.map +1 -1
  56. package/dist/esm/components/Table/utils/decorators/compoundExpand.js +1 -1
  57. package/dist/esm/components/Table/utils/decorators/compoundExpand.js.map +1 -1
  58. package/dist/esm/components/Table/utils/decorators/editable.js +1 -1
  59. package/dist/esm/components/Table/utils/decorators/editable.js.map +1 -1
  60. package/dist/esm/components/Table/utils/decorators/favoritable.js +1 -1
  61. package/dist/esm/components/Table/utils/decorators/favoritable.js.map +1 -1
  62. package/dist/esm/components/Table/utils/decorators/info.js +1 -1
  63. package/dist/esm/components/Table/utils/decorators/info.js.map +1 -1
  64. package/dist/esm/components/Table/utils/decorators/selectable.js +2 -2
  65. package/dist/esm/components/Table/utils/decorators/selectable.js.map +1 -1
  66. package/dist/esm/components/Table/utils/decorators/sortable.js +1 -1
  67. package/dist/esm/components/Table/utils/decorators/sortable.js.map +1 -1
  68. package/dist/esm/components/Table/utils/decorators/treeRow.js +2 -2
  69. package/dist/esm/components/Table/utils/decorators/treeRow.js.map +1 -1
  70. package/dist/esm/components/Table/utils/decorators/wrappable.js +1 -1
  71. package/dist/esm/components/Table/utils/decorators/wrappable.js.map +1 -1
  72. package/dist/esm/demos/index.d.ts +2 -0
  73. package/dist/esm/demos/index.d.ts.map +1 -0
  74. package/dist/esm/demos/index.js +2 -0
  75. package/dist/esm/demos/index.js.map +1 -0
  76. package/dist/esm/demos/sampleData.d.ts +13 -0
  77. package/dist/esm/demos/sampleData.d.ts.map +1 -0
  78. package/dist/esm/demos/sampleData.js +764 -0
  79. package/dist/esm/demos/sampleData.js.map +1 -0
  80. package/dist/esm/deprecated/components/Table/Table.js +1 -1
  81. package/dist/esm/deprecated/components/Table/Table.js.map +1 -1
  82. package/dist/esm/index.d.ts +1 -0
  83. package/dist/esm/index.d.ts.map +1 -1
  84. package/dist/esm/index.js +1 -0
  85. package/dist/esm/index.js.map +1 -1
  86. package/dist/js/demos/index.d.ts +2 -0
  87. package/dist/js/demos/index.d.ts.map +1 -0
  88. package/dist/js/demos/index.js +5 -0
  89. package/dist/js/demos/index.js.map +1 -0
  90. package/dist/js/demos/sampleData.d.ts +13 -0
  91. package/dist/js/demos/sampleData.d.ts.map +1 -0
  92. package/dist/js/demos/sampleData.js +767 -0
  93. package/dist/js/demos/sampleData.js.map +1 -0
  94. package/dist/js/index.d.ts +1 -0
  95. package/dist/js/index.d.ts.map +1 -1
  96. package/dist/js/index.js +1 -0
  97. package/dist/js/index.js.map +1 -1
  98. package/dist/umd/react-table.min.js +3 -3
  99. package/package.json +6 -6
  100. package/src/components/Table/examples/TableStickyColumnsAndHeader.tsx +5 -4
  101. package/src/components/Table/utils/transformers.test.tsx +1 -0
  102. package/src/demos/Table.md +159 -0
  103. package/src/demos/examples/TableAutomaticPagination.tsx +101 -0
  104. package/src/{docs/demos/table-demos/BulkSelect.jsx → demos/examples/TableBulkSelect.tsx} +41 -20
  105. package/src/demos/examples/TableColumnManagement.tsx +486 -0
  106. package/src/demos/examples/TableColumnManagementWithDraggable.tsx +641 -0
  107. package/src/{docs/demos/table-demos/Compact.jsx → demos/examples/TableCompact.tsx} +32 -16
  108. package/src/{docs/demos/table-demos/CompoundExpansion.jsx → demos/examples/TableCompoundExpansion.tsx} +25 -12
  109. package/src/demos/examples/TableEmptyStateDefault.tsx +60 -0
  110. package/src/demos/examples/TableEmptyStateError.tsx +53 -0
  111. package/src/demos/examples/TableEmptyStateLoading.tsx +43 -0
  112. package/src/{docs/demos/table-demos/ExpandCollapseAll.jsx → demos/examples/TableExpandCollapseAll.tsx} +17 -10
  113. package/src/demos/examples/TableFilterable.tsx +394 -0
  114. package/src/{docs/demos/table-demos/SortableResponsive.jsx → demos/examples/TableSortableResponsive.tsx} +29 -27
  115. package/src/{docs/demos/table-demos/StaticBottomPagination.jsx → demos/examples/TableStaticBottomPagination.tsx} +22 -9
  116. package/src/{docs/demos/table-demos/StickyFirstColumn.jsx → demos/examples/TableStickyFirstColumn.tsx} +31 -9
  117. package/src/{docs/demos/table-demos/StickyHeader.jsx → demos/examples/TableStickyHeader.tsx} +3 -3
  118. package/src/demos/index.ts +1 -0
  119. package/src/{docs/demos/table-demos/sampleData.js → demos/sampleData.tsx} +88 -77
  120. package/src/deprecated/components/Table/__tests__/Table.test.tsx +4 -9
  121. package/src/index.ts +1 -0
  122. package/src/docs/demos/Table.md +0 -1620
  123. package/src/docs/demos/table-demos/ColumnManagement.jsx +0 -471
@@ -1,1620 +0,0 @@
1
- ---
2
- id: Table
3
- section: components
4
- ---
5
-
6
- import {
7
- Checkbox,
8
- Label,
9
- PageSection,
10
- ToolbarExpandIconWrapper,
11
- ToolbarContent,
12
- Toolbar,
13
- ToolbarItem,
14
- SearchInput,
15
- Masthead,
16
- MastheadToggle,
17
- MastheadMain,
18
- MastheadContent,
19
- SkipToContent,
20
- Breadcrumb,
21
- BreadcrumbItem,
22
- Page,
23
- TextContent,
24
- Text,
25
- Divider } from '@patternfly/react-core';
26
- import { Table as TableDeprecated, TableHeader, TableBody } from '@patternfly/react-table/deprecated';
27
-
28
- import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon';
29
- import CloneIcon from '@patternfly/react-icons/dist/esm/icons/clone-icon';
30
- import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon';
31
- import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';
32
- import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
33
- import EditIcon from '@patternfly/react-icons/dist/esm/icons/edit-icon';
34
- import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';
35
- import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
36
- import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
37
- import SyncIcon from '@patternfly/react-icons/dist/esm/icons/sync-icon';
38
- import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
39
- import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
40
- import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
41
- import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon';
42
- import globalDangerColor200 from '@patternfly/react-tokens/dist/esm/global_danger_color_200';
43
- import imgBrand from '@patternfly/react-core/src/components/assets/pfLogo.svg';
44
- import imgAvatar from '@patternfly/react-core/src/components/assets/avatarImg.svg';
45
- import AngleDownIcon from '@patternfly/react-icons/dist/esm/icons/angle-down-icon';
46
- import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
47
- import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
48
- import AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon';
49
- import BlueprintIcon from '@patternfly/react-icons/dist/esm/icons/blueprint-icon';
50
- import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
51
- import { rows, columns } from '@patternfly/react-table/src/docs/demos/table-demos/sampleData';
52
-
53
- ## Demos
54
-
55
- ### Bulk select
56
-
57
- ```js isFullscreen file="./table-demos/BulkSelect.jsx"
58
-
59
- ```
60
-
61
- ### Expand/collapse all
62
-
63
- ```js isFullscreen file="./table-demos/ExpandCollapseAll.jsx"
64
-
65
- ```
66
-
67
- ### Compact
68
-
69
- ```js isFullscreen file="./table-demos/Compact.jsx"
70
-
71
- ```
72
-
73
- ### Compound expansion
74
-
75
- ```js isFullscreen file="./table-demos/CompoundExpansion.jsx"
76
-
77
- ```
78
-
79
- ### Column management
80
-
81
- ```js isFullscreen file="./table-demos/ColumnManagement.jsx"
82
-
83
- ```
84
-
85
- ### Column management with draggable
86
-
87
- ```js
88
- import React from 'react';
89
- import {
90
- Button,
91
- DataList,
92
- DataListCheck,
93
- DataListControl,
94
- DataListDragButton,
95
- DataListItem,
96
- DataListItemRow,
97
- DataListCell,
98
- DataListItemCells,
99
- Toolbar,
100
- ToolbarContent,
101
- ToolbarItem,
102
- Modal,
103
- OverflowMenu,
104
- OverflowMenuGroup,
105
- OverflowMenuItem,
106
- Pagination,
107
- PaginationVariant,
108
- Text,
109
- TextContent,
110
- TextVariants,
111
- MenuToggle
112
- } from '@patternfly/react-core';
113
- import { Table as TableDeprecated, TableHeader, TableBody, TableText } from '@patternfly/react-table/deprecated';
114
- import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon';
115
- import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';
116
- import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
117
- import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';
118
- import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
119
-
120
- class ColumnManagementAction extends React.Component {
121
- constructor(props) {
122
- super(props);
123
- this.actions = [
124
- {
125
- title: <a href="#">Link</a>
126
- },
127
- {
128
- title: 'Action'
129
- },
130
- {
131
- isSeparator: true
132
- },
133
- {
134
- title: <a href="#">Separated link</a>
135
- }
136
- ];
137
- this.defaultColumns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit', ''];
138
- this.defaultRows = [
139
- {
140
- cells: [
141
- {
142
- title: (
143
- <React.Fragment>
144
- <div>Node 1</div>
145
- <a href="#">siemur/test-space</a>
146
- </React.Fragment>
147
- ),
148
- props: { column: 'Repositories' }
149
- },
150
- {
151
- title: (
152
- <React.Fragment>
153
- <CodeBranchIcon key="icon" /> 10
154
- </React.Fragment>
155
- ),
156
- props: { column: 'Branches' }
157
- },
158
- {
159
- title: (
160
- <React.Fragment>
161
- <CodeIcon key="icon" /> 25
162
- </React.Fragment>
163
- ),
164
- props: { column: 'Pull requests' }
165
- },
166
- {
167
- title: (
168
- <React.Fragment>
169
- <CubeIcon key="icon" /> 5
170
- </React.Fragment>
171
- ),
172
- props: { column: 'Workspaces' }
173
- },
174
- {
175
- title: '2 days ago',
176
- props: { column: 'Last commit' }
177
- },
178
- {
179
- title: (
180
- <React.Fragment>
181
- <a href="#">Action link</a>
182
- </React.Fragment>
183
- ),
184
- props: { column: '' }
185
- }
186
- ]
187
- },
188
- {
189
- cells: [
190
- {
191
- title: (
192
- <React.Fragment>
193
- <div>Node 2</div>
194
- <a href="#">siemur/test-space</a>
195
- </React.Fragment>
196
- ),
197
- props: { column: 'Repositories' }
198
- },
199
- {
200
- title: (
201
- <React.Fragment>
202
- <CodeBranchIcon key="icon" /> 8
203
- </React.Fragment>
204
- ),
205
- props: { column: 'Branches' }
206
- },
207
- {
208
- title: (
209
- <React.Fragment>
210
- <CodeIcon key="icon" /> 30
211
- </React.Fragment>
212
- ),
213
- props: { column: 'Pull requests' }
214
- },
215
- {
216
- title: (
217
- <React.Fragment>
218
- <CubeIcon key="icon" /> 2
219
- </React.Fragment>
220
- ),
221
- props: { column: 'Workspaces' }
222
- },
223
- {
224
- title: '2 days ago',
225
- props: { column: 'Last commit' }
226
- },
227
- {
228
- title: (
229
- <React.Fragment>
230
- <a href="#">Action link</a>
231
- </React.Fragment>
232
- ),
233
- props: { column: '' }
234
- }
235
- ]
236
- },
237
- {
238
- cells: [
239
- {
240
- title: (
241
- <React.Fragment>
242
- <div>Node 3</div>
243
- <a href="#">siemur/test-space</a>
244
- </React.Fragment>
245
- ),
246
- props: { column: 'Repositories' }
247
- },
248
- {
249
- title: (
250
- <React.Fragment>
251
- <CodeBranchIcon key="icon" /> 12
252
- </React.Fragment>
253
- ),
254
- props: { column: 'Branches' }
255
- },
256
- {
257
- title: (
258
- <React.Fragment>
259
- <CodeIcon key="icon" /> 48
260
- </React.Fragment>
261
- ),
262
- props: { column: 'Pull requests' }
263
- },
264
- {
265
- title: (
266
- <React.Fragment>
267
- <CubeIcon key="icon" /> 13
268
- </React.Fragment>
269
- ),
270
- props: { column: 'Workspaces' }
271
- },
272
- {
273
- title: '30 days ago',
274
- props: { column: 'Last commit' }
275
- },
276
- {
277
- title: (
278
- <React.Fragment>
279
- <a href="#">Action link</a>
280
- </React.Fragment>
281
- ),
282
- props: { column: '' }
283
- }
284
- ]
285
- },
286
- {
287
- cells: [
288
- {
289
- title: (
290
- <React.Fragment>
291
- <div>Node 4</div>
292
- <a href="#">siemur/test-space</a>
293
- </React.Fragment>
294
- ),
295
- props: { column: 'Repositories' }
296
- },
297
- {
298
- title: (
299
- <React.Fragment>
300
- <CodeBranchIcon key="icon" /> 3
301
- </React.Fragment>
302
- ),
303
- props: { column: 'Branches' }
304
- },
305
- {
306
- title: (
307
- <React.Fragment>
308
- <CodeIcon key="icon" /> 8
309
- </React.Fragment>
310
- ),
311
- props: { column: 'Pull requests' }
312
- },
313
- {
314
- title: (
315
- <React.Fragment>
316
- <CubeIcon key="icon" /> 20
317
- </React.Fragment>
318
- ),
319
- props: { column: 'Workspaces' }
320
- },
321
- {
322
- title: '8 days ago',
323
- props: { column: 'Last commit' }
324
- },
325
- {
326
- title: (
327
- <React.Fragment>
328
- <a href="#">Action link</a>
329
- </React.Fragment>
330
- ),
331
- props: { column: '' }
332
- }
333
- ]
334
- },
335
- {
336
- cells: [
337
- {
338
- title: (
339
- <React.Fragment>
340
- <div>Node 5</div>
341
- <a href="#">siemur/test-space</a>
342
- </React.Fragment>
343
- ),
344
- props: { column: 'Repositories' }
345
- },
346
- {
347
- title: (
348
- <React.Fragment>
349
- <CodeBranchIcon key="icon" /> 34
350
- </React.Fragment>
351
- ),
352
- props: { column: 'Branches' }
353
- },
354
- {
355
- title: (
356
- <React.Fragment>
357
- <CodeIcon key="icon" /> 21
358
- </React.Fragment>
359
- ),
360
- props: { column: 'Pull requests' }
361
- },
362
- {
363
- title: (
364
- <React.Fragment>
365
- <CubeIcon key="icon" /> 26
366
- </React.Fragment>
367
- ),
368
- props: { column: 'Workspaces' }
369
- },
370
- {
371
- title: '2 days ago',
372
- props: { column: 'Last commit' }
373
- },
374
- {
375
- title: (
376
- <React.Fragment>
377
- <a href="#">Action link</a>
378
- </React.Fragment>
379
- ),
380
- props: { column: '' }
381
- }
382
- ]
383
- }
384
- ];
385
- this.state = {
386
- filters: [],
387
- filteredColumns: [],
388
- columns: this.defaultColumns,
389
- rows: this.defaultRows,
390
- canSelectAll: true,
391
- isModalOpen: false,
392
- check1: true,
393
- check2: true,
394
- check3: true,
395
- check4: true,
396
- check5: true,
397
- liveText: '',
398
- id: '',
399
- itemOrder: ['data1', 'data2', 'data3', 'data4', 'data5']
400
- };
401
- this.onSelect = this.onSelect.bind(this);
402
- this.toggleSelect = this.toggleSelect.bind(this);
403
- this.renderModal = this.renderModal.bind(this);
404
- this.matchCheckboxNameToColumn = (name) => {
405
- switch (name) {
406
- case 'check1':
407
- return 'Repositories';
408
- case 'check2':
409
- return 'Branches';
410
- case 'check3':
411
- return 'Pull requests';
412
- case 'check4':
413
- return 'Workspaces';
414
- case 'check5':
415
- return 'Last commit';
416
- }
417
- };
418
- this.matchDataListNameToColumn = (name) => {
419
- switch (name) {
420
- case 'data1':
421
- return 'Repositories';
422
- case 'data2':
423
- return 'Branches';
424
- case 'data3':
425
- return 'Pull requests';
426
- case 'data4':
427
- return 'Workspaces';
428
- case 'data5':
429
- return 'Last commit';
430
- }
431
- };
432
- this.filterData = (checked, name) => {
433
- const { rows, columns, filters } = this.state;
434
- if (checked) {
435
- const updatedFilters = filters.filter((item) => item !== name);
436
- const filteredColumns = this.defaultColumns.filter((column) => !updatedFilters.includes(column));
437
- this.setState({
438
- filters: updatedFilters,
439
- filteredColumns: filteredColumns
440
- });
441
- } else {
442
- let updatedFilters = filters;
443
- updatedFilters.push(name);
444
- const filteredColumns = columns.filter((column) => !filters.includes(column));
445
- this.setState({
446
- filters: updatedFilters,
447
- filteredColumns: filteredColumns
448
- });
449
- }
450
- };
451
- this.unfilterAllData = () => {
452
- this.setState({
453
- filters: [],
454
- filteredColumns: this.defaultColumns
455
- });
456
- };
457
- this.handleChange = (event, checked) => {
458
- const target = event.target;
459
- const value = target.type === 'checkbox' ? target.checked : target.value;
460
- this.filterData(checked, this.matchCheckboxNameToColumn(target.name));
461
- this.setState({
462
- [target.name]: value
463
- });
464
- };
465
- this.handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => {
466
- this.setState(({ isModalOpen }) => ({
467
- isModalOpen: !isModalOpen
468
- }));
469
- };
470
- this.onSave = () => {
471
- const orderedColumns = this.state.itemOrder.map((item) => this.matchDataListNameToColumn(item));
472
- // concat empty string at the end for actions column
473
- const filteredOrderedColumns = orderedColumns
474
- .filter((col) => this.state.filteredColumns.length === 0 || this.state.filteredColumns.indexOf(col) > -1)
475
- .concat(['']);
476
- const orderedRows = [];
477
- this.defaultRows.forEach((row) => {
478
- const updatedCells = row.cells
479
- .filter((cell) => filteredOrderedColumns.indexOf(cell.props.column) > -1)
480
- .sort((cellA, cellB) => {
481
- const indexA = filteredOrderedColumns.indexOf(cellA.props.column);
482
- const indexB = filteredOrderedColumns.indexOf(cellB.props.column);
483
- if (indexA < indexB) {
484
- return -1;
485
- }
486
- if (indexA > indexB) {
487
- return 1;
488
- }
489
- // a must be equal to b
490
- return 0;
491
- });
492
- orderedRows.push({
493
- cells: updatedCells
494
- });
495
- });
496
- this.setState(({ isModalOpen }) => ({
497
- columns: filteredOrderedColumns,
498
- rows: orderedRows,
499
- isModalOpen: !isModalOpen
500
- }));
501
- };
502
-
503
- this.selectAllColumns = () => {
504
- this.unfilterAllData();
505
- this.setState({
506
- check1: true,
507
- check2: true,
508
- check3: true,
509
- check4: true,
510
- check5: true
511
- });
512
- };
513
-
514
- this.onDragStart = (id) => {
515
- this.setState({
516
- id: id,
517
- liveText: `Dragging started for item id: ${id}.`
518
- });
519
- };
520
-
521
- this.onDragMove = (oldIndex, newIndex) => {
522
- const { id } = this.state;
523
- this.setState({
524
- liveText: `Dragging item ${id}.`
525
- });
526
- };
527
-
528
- this.onDragCancel = () => {
529
- this.setState({
530
- liveText: `Dragging cancelled. List is unchanged.`
531
- });
532
- };
533
-
534
- this.onDragFinish = (itemOrder) => {
535
- this.setState({
536
- liveText: `Dragging finished`,
537
- itemOrder
538
- });
539
- };
540
- }
541
-
542
- onSelect(event, isSelected, rowId) {
543
- let rows;
544
- if (rowId === -1) {
545
- rows = this.state.rows.map((oneRow) => {
546
- oneRow.selected = isSelected;
547
- return oneRow;
548
- });
549
- } else {
550
- rows = [...this.state.rows];
551
- rows[rowId] = { ...rows[rowId], selected: isSelected };
552
- }
553
- this.setState({
554
- rows
555
- });
556
- }
557
-
558
- toggleSelect(checked) {
559
- this.setState({
560
- canSelectAll: checked
561
- });
562
- }
563
-
564
- renderModal() {
565
- const { isModalOpen } = this.state;
566
- return (
567
- <Modal
568
- title="Manage columns"
569
- isOpen={isModalOpen}
570
- variant="small"
571
- description={
572
- <TextContent>
573
- <Text component={TextVariants.p}>Selected categories will be displayed in the table.</Text>
574
- <Button isInline onClick={this.selectAllColumns} variant="link">
575
- Select all
576
- </Button>
577
- </TextContent>
578
- }
579
- onClose={this.handleModalToggle}
580
- actions={[
581
- <Button key="save" variant="primary" onClick={this.onSave}>
582
- Save
583
- </Button>,
584
- <Button key="cancel" variant="secondary" onClick={this.handleModalToggle}>
585
- Cancel
586
- </Button>
587
- ]}
588
- >
589
- <DataList
590
- aria-label="Table column management"
591
- id="table-column-management"
592
- isCompact
593
- onDragFinish={this.onDragFinish}
594
- onDragStart={this.onDragStart}
595
- onDragMove={this.onDragMove}
596
- onDragCancel={this.onDragCancel}
597
- itemOrder={this.state.itemOrder}
598
- >
599
- <DataListItem aria-labelledby="table-column-management-item1" id="data1">
600
- <DataListItemRow>
601
- <DataListControl>
602
- <DataListDragButton
603
- aria-label="Reorder"
604
- aria-labelledby="table-column-management-item1"
605
- 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."
606
- aria-pressed="false"
607
- />
608
- <DataListCheck
609
- aria-labelledby="table-column-management-item1"
610
- checked={this.state.check1}
611
- name="check1"
612
- id="check1"
613
- onChange={this.handleChange}
614
- otherControls
615
- />
616
- </DataListControl>
617
- <DataListItemCells
618
- dataListCells={[
619
- <DataListCell id="table-column-management-item1" key="table-column-management-item1">
620
- <label htmlFor="check1">Repositories</label>
621
- </DataListCell>
622
- ]}
623
- />
624
- </DataListItemRow>
625
- </DataListItem>
626
- <DataListItem aria-labelledby="table-column-management-item2" id="data2">
627
- <DataListItemRow>
628
- <DataListControl>
629
- <DataListDragButton
630
- aria-label="Reorder"
631
- aria-labelledby="table-column-management-item2"
632
- 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."
633
- aria-pressed="false"
634
- />
635
- <DataListCheck
636
- aria-labelledby="table-column-management-item2"
637
- checked={this.state.check2}
638
- name="check2"
639
- id="check2"
640
- onChange={this.handleChange}
641
- otherControls
642
- />
643
- </DataListControl>
644
- <DataListItemCells
645
- dataListCells={[
646
- <DataListCell id="table-column-management-item2" key="table-column-management-item2">
647
- <label htmlFor="check2">Branches</label>
648
- </DataListCell>
649
- ]}
650
- />
651
- </DataListItemRow>
652
- </DataListItem>
653
- <DataListItem aria-labelledby="table-column-management-item3" id="data3">
654
- <DataListItemRow>
655
- <DataListControl>
656
- <DataListDragButton
657
- aria-label="Reorder"
658
- aria-labelledby="table-column-management-item3"
659
- 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."
660
- aria-pressed="false"
661
- />
662
- <DataListCheck
663
- aria-labelledby="table-column-management-item3"
664
- checked={this.state.check3}
665
- name="check3"
666
- id="check3"
667
- onChange={this.handleChange}
668
- otherControls
669
- />
670
- </DataListControl>
671
- <DataListItemCells
672
- dataListCells={[
673
- <DataListCell id="table-column-management-item3" key="table-column-management-item3">
674
- <label htmlFor="check3">Pull requests</label>
675
- </DataListCell>
676
- ]}
677
- />
678
- </DataListItemRow>
679
- </DataListItem>
680
- <DataListItem aria-labelledby="table-column-management-item4" id="data4">
681
- <DataListItemRow>
682
- <DataListControl>
683
- <DataListDragButton
684
- aria-label="Reorder"
685
- aria-labelledby="table-column-management-item4"
686
- 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."
687
- aria-pressed="false"
688
- />
689
- <DataListCheck
690
- aria-labelledby="table-column-management-item4"
691
- checked={this.state.check4}
692
- name="check4"
693
- id="check4"
694
- onChange={this.handleChange}
695
- otherControls
696
- />
697
- </DataListControl>
698
- <DataListItemCells
699
- dataListCells={[
700
- <DataListCell id="table-column-management-item4" key="table-column-management-item4">
701
- <label htmlFor="check4">Workspaces</label>
702
- </DataListCell>
703
- ]}
704
- />
705
- </DataListItemRow>
706
- </DataListItem>
707
- <DataListItem aria-labelledby="table-column-management-item5" id="data5">
708
- <DataListItemRow>
709
- <DataListControl>
710
- <DataListDragButton
711
- aria-label="Reorder"
712
- aria-labelledby="table-column-management-item5"
713
- 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."
714
- aria-pressed="false"
715
- />
716
- <DataListCheck
717
- aria-labelledby="table-column-management-item5"
718
- checked={this.state.check5}
719
- name="check5"
720
- id="check5"
721
- onChange={this.handleChange}
722
- otherControls
723
- />
724
- </DataListControl>
725
- <DataListItemCells
726
- dataListCells={[
727
- <DataListCell id="table-column-management-item5" key="table-column-management-item5">
728
- <label htmlFor="check5">Last commit</label>
729
- </DataListCell>
730
- ]}
731
- />
732
- </DataListItemRow>
733
- </DataListItem>
734
- </DataList>
735
- </Modal>
736
- );
737
- }
738
-
739
- render() {
740
- const { canSelectAll, columns, rows } = this.state;
741
-
742
- const toolbarItems = (
743
- <React.Fragment>
744
- <span id="page-layout-table-draggable-column-management-action-toolbar-top-select-checkbox-label" hidden>
745
- Choose one
746
- </span>
747
- <ToolbarContent>
748
- <ToolbarItem variant="overflow-menu">
749
- <OverflowMenu breakpoint="md">
750
- <OverflowMenuItem isPersistent>
751
- <MenuToggle>
752
- <FilterIcon /> Name
753
- </MenuToggle>
754
- </OverflowMenuItem>
755
- <OverflowMenuItem>
756
- <MenuToggle variant="plain" aria-label="Sort columns">
757
- <SortAmountDownIcon aria-hidden="true" />
758
- </MenuToggle>
759
- </OverflowMenuItem>
760
- <OverflowMenuGroup groupType="button" isPersistent>
761
- <OverflowMenuItem>
762
- <Button variant="primary">Action</Button>
763
- </OverflowMenuItem>
764
- <OverflowMenuItem>
765
- <Button variant="link" onClick={this.handleModalToggle}>
766
- Manage columns
767
- </Button>
768
- </OverflowMenuItem>
769
- </OverflowMenuGroup>
770
- </OverflowMenu>
771
- </ToolbarItem>
772
- <ToolbarItem variant="pagination">
773
- <Pagination
774
- itemCount={37}
775
- widgetId="pagination-options-menu"
776
- page={1}
777
- variant={PaginationVariant.top}
778
- isCompact
779
- titles={{
780
- paginationAriaLabel: `Draggable column management top pagination`
781
- }}
782
- />
783
- </ToolbarItem>
784
- </ToolbarContent>
785
- </React.Fragment>
786
- );
787
-
788
- return (
789
- <React.Fragment>
790
- <TableDeprecated
791
- gridBreakPoint="grid-xl"
792
- header={
793
- <React.Fragment>
794
- <Toolbar id="page-layout-table-draggable-column-management-action-toolbar-top">{toolbarItems}</Toolbar>
795
- </React.Fragment>
796
- }
797
- aria-label="This is a table with checkboxes"
798
- id="page-layout-table-draggable-column-management-action-table"
799
- onSelect={this.onSelect}
800
- cells={columns}
801
- rows={rows}
802
- actions={this.actions}
803
- canSelectAll={canSelectAll}
804
- >
805
- <TableHeader />
806
- <TableBody />
807
- </TableDeprecated>
808
- <Pagination
809
- isCompact
810
- id="page-layout-table-draggable-column-management-action-toolbar-bottom"
811
- itemCount={37}
812
- widgetId="pagination-options-menu-bottom"
813
- page={1}
814
- variant={PaginationVariant.bottom}
815
- titles={{
816
- paginationAriaLabel: `Draggable column management bottom pagination`
817
- }}
818
- />
819
- {this.renderModal()}
820
- </React.Fragment>
821
- );
822
- }
823
- }
824
- ```
825
-
826
- ### Filterable
827
-
828
- ```js isFullscreen
829
- import React from 'react';
830
- import {
831
- Badge,
832
- Button,
833
- Bullseye,
834
- EmptyState,
835
- EmptyStateActions,
836
- EmptyStateBody,
837
- EmptyStateIcon,
838
- EmptyStateHeader,
839
- EmptyStateFooter,
840
- Label,
841
- MenuToggle,
842
- MenuToggleElement,
843
- Toolbar,
844
- ToolbarItem,
845
- ToolbarContent,
846
- ToolbarFilter,
847
- ToolbarToggleGroup,
848
- ToolbarGroup,
849
- Title,
850
- Select,
851
- SelectOption,
852
- SearchInput
853
- } from '@patternfly/react-core';
854
- import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
855
- import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';
856
- import { Table, TableText, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
857
- import { rows, columns } from '@patternfly/react-table/src/docs/demos/table-demos/sampleData';
858
-
859
- class FilterTableDemo extends React.Component {
860
- constructor(props) {
861
- super(props);
862
- this.state = {
863
- filters: {
864
- location: [],
865
- name: [],
866
- status: []
867
- },
868
- currentCategory: 'Status',
869
- isFilterDropdownOpen: false,
870
- isCategoryDropdownOpen: false,
871
- nameInput: '',
872
- inputValue: '',
873
- rows: rows.slice(0, 10)
874
- };
875
-
876
- this.onDelete = (type = '', id = '') => {
877
- if (type) {
878
- this.setState((prevState) => {
879
- prevState.filters[type.toLowerCase()] = prevState.filters[type.toLowerCase()].filter((s) => s !== id);
880
- return {
881
- filters: prevState.filters
882
- };
883
- });
884
- } else {
885
- this.setState({
886
- filters: {
887
- location: [],
888
- name: [],
889
- status: []
890
- }
891
- });
892
- }
893
- };
894
-
895
- this.onCategoryToggle = () => {
896
- this.setState({
897
- isCategoryDropdownOpen: !this.state.isCategoryDropdownOpen
898
- });
899
- };
900
-
901
- this.onCategorySelect = (event) => {
902
- this.setState({
903
- currentCategory: event.target.innerText,
904
- isCategoryDropdownOpen: false
905
- });
906
- };
907
-
908
- this.onFilterToggle = () => {
909
- this.setState({
910
- isFilterDropdownOpen: !this.state.isFilterDropdownOpen
911
- });
912
- };
913
-
914
- this.onFilterSelect = (event) => {
915
- this.setState({
916
- isFilterDropdownOpen: !this.state.isFilterDropdownOpen
917
- });
918
- };
919
-
920
- this.onInputChange = (newValue) => {
921
- this.setState({ inputValue: newValue });
922
- };
923
-
924
- this.onStatusSelect = (event, selection) => {
925
- const checked = event.target.checked;
926
- this.setState((prevState) => {
927
- const prevSelections = prevState.filters['status'];
928
- return {
929
- filters: {
930
- ...prevState.filters,
931
- status: checked ? [...prevSelections, selection] : prevSelections.filter((value) => value !== selection)
932
- },
933
- isFilterDropdownOpen: false
934
- };
935
- });
936
- };
937
-
938
- this.onNameInput = (event) => {
939
- if (event.key && event.key !== 'Enter') {
940
- return;
941
- }
942
-
943
- const { inputValue } = this.state;
944
- this.setState((prevState) => {
945
- const prevFilters = prevState.filters['name'];
946
- return {
947
- filters: {
948
- ...prevState.filters,
949
- ['name']: prevFilters.includes(inputValue) ? prevFilters : [...prevFilters, inputValue]
950
- },
951
- inputValue: ''
952
- };
953
- });
954
- };
955
-
956
- this.onLocationSelect = (event, selection) => {
957
- this.setState((prevState) => {
958
- return {
959
- filters: {
960
- ...prevState.filters,
961
- ['location']: [selection]
962
- },
963
- isFilterDropdownOpen: false
964
- };
965
- });
966
- this.onFilterSelect();
967
- };
968
- }
969
-
970
- buildCategoryDropdown() {
971
- const { isCategoryDropdownOpen, currentCategory } = this.state;
972
-
973
- const categoryMenuItems = [
974
- <SelectOption key="cat1" value="Location">Location</SelectOption>,
975
- <SelectOption key="cat2" value="Name">Name</SelectOption>,
976
- <SelectOption key="cat3" value="Status">Status</SelectOption>
977
- ];
978
-
979
- return (
980
- <ToolbarItem>
981
- <Select
982
- onSelect={this.onCategorySelect}
983
- selected={currentCategory}
984
- toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
985
- <MenuToggle
986
- ref={toggleRef}
987
- onClick={this.onCategoryToggle}
988
- isExpanded={isCategoryDropdownOpen}
989
- icon={<FilterIcon />}
990
- style={
991
- {
992
- width: '100%',
993
- verticalAlign: 'text-bottom'
994
- } as React.CSSProperties
995
- }
996
- >
997
- {currentCategory}
998
- </MenuToggle>
999
- )}
1000
- isOpen={isCategoryDropdownOpen}
1001
- >
1002
- {categoryMenuItems}
1003
- </Select>
1004
- </ToolbarItem>
1005
- );
1006
- }
1007
-
1008
- buildFilterDropdown() {
1009
- const { currentCategory, isFilterDropdownOpen, inputValue, filters } = this.state;
1010
-
1011
- const locationMenuItems = [
1012
- <SelectOption key="raleigh" value="Raleigh">Raleigh</SelectOption>,
1013
- <SelectOption key="san francisco" value="San Francisco">San Francisco</SelectOption>,
1014
- <SelectOption key="boston" value="Boston">Boston</SelectOption>,
1015
- <SelectOption key="atlanta" value="Atlanta">Atlanta</SelectOption>,
1016
- ];
1017
-
1018
- const statusMenuItems = [
1019
- <SelectOption
1020
- hasCheckbox
1021
- key="statusRunning"
1022
- value="Running"
1023
- isSelected={filters.status.includes("Running")}
1024
- >
1025
- Running
1026
- </SelectOption>,
1027
- <SelectOption
1028
- hasCheckbox
1029
- key="statusStopped"
1030
- value="Stopped"
1031
- isSelected={filters.status.includes("Stopped")}
1032
- >
1033
- Stopped
1034
- </SelectOption>,
1035
- <SelectOption
1036
- hasCheckbox
1037
- key="statusDown"
1038
- value="Down"
1039
- isSelected={filters.status.includes("Down")}
1040
- >
1041
- Down
1042
- </SelectOption>,
1043
- <SelectOption
1044
- hasCheckbox
1045
- key="statusDegraded"
1046
- value="Degraded"
1047
- isSelected={filters.status.includes("Degraded")}
1048
- >
1049
- Degraded
1050
- </SelectOption>,
1051
- <SelectOption
1052
- hasCheckbox
1053
- key="statusMaint"
1054
- value="Needs maintenance"
1055
- isSelected={filters.status.includes("Needs maintenance")}
1056
- >
1057
- Needs maintenance
1058
- </SelectOption>
1059
- ];
1060
-
1061
- return (
1062
- <React.Fragment>
1063
- <ToolbarFilter
1064
- chips={filters.location}
1065
- deleteChip={this.onDelete}
1066
- categoryName="Location"
1067
- showToolbarItem={currentCategory === 'Location'}
1068
- >
1069
- <Select
1070
- aria-label="Location"
1071
- onSelect={this.onLocationSelect}
1072
- selected={filters.location[0]}
1073
- isOpen={isFilterDropdownOpen}
1074
- minWidth="100px"
1075
- toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
1076
- <MenuToggle
1077
- ref={toggleRef}
1078
- onClick={this.onFilterToggle}
1079
- isExpanded={isFilterDropdownOpen}
1080
- style={
1081
- {
1082
- width: '100%',
1083
- verticalAlign: 'text-bottom'
1084
- } as React.CSSProperties
1085
- }
1086
- >
1087
- {filters.location[0] || `Any`}
1088
- </MenuToggle>
1089
- )}
1090
- >
1091
- {locationMenuItems}
1092
- </Select>
1093
- </ToolbarFilter>
1094
- <ToolbarFilter
1095
- chips={filters.name}
1096
- deleteChip={this.onDelete}
1097
- categoryName="Name"
1098
- showToolbarItem={currentCategory === 'Name'}
1099
- >
1100
- <SearchInput
1101
- aria-label="name filter"
1102
- placeholder="Filter by name..."
1103
- onChange={(_event, value) => this.onInputChange(value)}
1104
- value={inputValue}
1105
- onClear={() => {
1106
- this.onInputChange('');
1107
- }}
1108
- onSearch={this.onNameInput}
1109
- />
1110
- </ToolbarFilter>
1111
- <ToolbarFilter
1112
- chips={filters.status}
1113
- deleteChip={this.onDelete}
1114
- categoryName="Status"
1115
- showToolbarItem={currentCategory === 'Status'}
1116
- >
1117
- <Select
1118
- aria-label="Status"
1119
- isOpen={isFilterDropdownOpen}
1120
- minWidth="100px"
1121
- onSelect={this.onStatusSelect}
1122
- selected={filters.status}
1123
- toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
1124
- <MenuToggle
1125
- ref={toggleRef}
1126
- onClick={this.onFilterToggle}
1127
- isExpanded={isFilterDropdownOpen}
1128
- style={
1129
- {
1130
- width: '100%',
1131
- verticalAlign: 'text-bottom'
1132
- } as React.CSSProperties
1133
- }
1134
- >
1135
- Filter by status
1136
- {filters.status.length > 0 && <Badge isRead>{filters.status.length}</Badge>}
1137
- </MenuToggle>
1138
- )}
1139
- >
1140
- {statusMenuItems}
1141
- </Select>
1142
- </ToolbarFilter>
1143
- </React.Fragment>
1144
- );
1145
- }
1146
-
1147
- renderToolbar() {
1148
- return (
1149
- <Toolbar id="toolbar-with-chip-groups" clearAllFilters={this.onDelete} collapseListedFiltersBreakpoint="xl">
1150
- <ToolbarContent>
1151
- <ToolbarToggleGroup toggleIcon={<FilterIcon />} breakpoint="xl">
1152
- <ToolbarGroup
1153
- variant="filter-group"
1154
- style={{
1155
- lineHeight: '22px',
1156
- alignItems: 'center'
1157
- } as React.CSSProperties}
1158
- >
1159
- {this.buildCategoryDropdown()}
1160
- {this.buildFilterDropdown()}
1161
- </ToolbarGroup>
1162
- </ToolbarToggleGroup>
1163
- </ToolbarContent>
1164
- </Toolbar>
1165
- );
1166
- }
1167
-
1168
- render() {
1169
- const { loading, filters, rows } = this.state;
1170
-
1171
- const filteredRows =
1172
- filters.name.length > 0 || filters.location.length > 0 || filters.status.length > 0
1173
- ? rows.filter((row) => {
1174
- return (
1175
- (filters.name.length === 0 ||
1176
- filters.name.some((name) => row.name.toLowerCase().includes(name.toLowerCase()))) &&
1177
- (filters.location.length === 0 || filters.location.includes(row.location)) &&
1178
- (filters.status.length === 0 || filters.status.includes(row.status))
1179
- );
1180
- })
1181
- : rows;
1182
-
1183
- let tableRows = filteredRows;
1184
- if (!loading && filteredRows.length === 0) {
1185
- tableRows = [
1186
- {
1187
- heightAuto: true,
1188
- cells: [
1189
- {
1190
- props: { colSpan: 8 },
1191
- title: (
1192
- <Bullseye>
1193
- <EmptyState>
1194
- <EmptyStateHeader
1195
- titleText="Clear all filters and try again."
1196
- headingLevel="h5"
1197
- icon={<EmptyStateIcon icon={SearchIcon} />}
1198
- />
1199
- <EmptyStateBody>
1200
- No results match this filter criteria. Remove all filters or clear all filters to show results.
1201
- </EmptyStateBody>
1202
- <EmptyStateFooter>
1203
- <EmptyStateActions>
1204
- <Button
1205
- variant="link"
1206
- onClick={() => {
1207
- this.onDelete(null);
1208
- }}
1209
- >
1210
- Clear all filters
1211
- </Button>
1212
- </EmptyStateActions>
1213
- </EmptyStateFooter>
1214
- </EmptyState>
1215
- </Bullseye>
1216
- )
1217
- }
1218
- ]
1219
- }
1220
- ];
1221
- } else if (loading) {
1222
- tableRows = [
1223
- {
1224
- heightAuto: true,
1225
- cells: [
1226
- {
1227
- props: { colSpan: 8 },
1228
- title: (
1229
- <Title headingLevel="h2" size="3xl">
1230
- Please wait while loading data
1231
- </Title>
1232
- )
1233
- }
1234
- ]
1235
- }
1236
- ];
1237
- }
1238
-
1239
- const renderLabel = labelText => {
1240
- switch (labelText) {
1241
- case 'Running':
1242
- return <Label color="green">{labelText}</Label>;
1243
- case 'Stopped':
1244
- return <Label color="orange">{labelText}</Label>;
1245
- case 'Needs maintenance':
1246
- return <Label color="blue">{labelText}</Label>;
1247
- case 'Down':
1248
- return <Label color="red">{labelText}</Label>;
1249
- }
1250
- };
1251
-
1252
- return (
1253
- <React.Fragment>
1254
- {this.renderToolbar()}
1255
- <Table aria-label="Filterable Table Demo">
1256
- <Thead>
1257
- <Tr>
1258
- <Th key={0}>{columns[0]}</Th>
1259
- <Th key={1}>{columns[1]}</Th>
1260
- <Th key={2}>{columns[2]}</Th>
1261
- <Th key={3}>{columns[3]}</Th>
1262
- <Th key={4}>{columns[4]}</Th>
1263
- <Th key={5}>{columns[5]}</Th>
1264
- <Th key={6}>{columns[6]}</Th>
1265
- <Th key={7} width={10}>
1266
- {columns[7]}
1267
- </Th>
1268
- </Tr>
1269
- </Thead>
1270
- <Tbody>
1271
- {filteredRows.slice(0, 10).map((row, rowIndex) => (
1272
- <Tr key={rowIndex}>
1273
- <>
1274
- <Td dataLabel={columns[0]}>{row.name}</Td>
1275
- <Td dataLabel={columns[1]}>{row.threads}</Td>
1276
- <Td dataLabel={columns[2]}>{row.applications}</Td>
1277
- <Td dataLabel={columns[3]}>{row.workspaces}</Td>
1278
- <Td dataLabel={columns[4]}>{renderLabel(row.status)}</Td>
1279
- <Td dataLabel={columns[5]}>{row.location}</Td>
1280
- <Td dataLabel={columns[6]}>{row.lastModified}</Td>
1281
- <Td dataLabel={columns[7]} modifier="truncate">
1282
- <TableText>
1283
- <a href="#">{row.url}</a>
1284
- </TableText>
1285
- </Td>
1286
- </>
1287
- </Tr>
1288
- ))}
1289
- </Tbody>
1290
- </Table>
1291
- </React.Fragment>
1292
- );
1293
- }
1294
- }
1295
- ```
1296
-
1297
- ### Sortable - responsive
1298
-
1299
- ```js isFullscreen file="./table-demos/SortableResponsive.jsx"
1300
-
1301
- ```
1302
-
1303
- ### Automatic pagination
1304
-
1305
- The below example illustrates the `isLastFullPageShown` prop, which makes the following changes when the user sets the number of items to display per page to an amount that exceeds the remaining amount of data:
1306
-
1307
- - The component automatically changes the page back to the last full page of results, rather than defaulting to the final page of results.
1308
-
1309
- To demonstrate this, navigate to the last page of data below using the `>>` navigation arrows, then use the dropdown selector to change the view to 5 per page.
1310
-
1311
- - The default behavior would show the last page of results, which would only contain the last two rows (rows 11 - 12).
1312
- - The `isLastFullPageShown` prop navigates you back to the previous page which does contain a full page of 5 rows (rows 6 - 10).
1313
-
1314
- ```js isFullscreen
1315
- import React from 'react';
1316
- import { Pagination } from '@patternfly/react-core';
1317
- import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
1318
-
1319
- class ComplexPaginationTableDemo extends React.Component {
1320
- constructor(props) {
1321
- super(props);
1322
- (this.columns = {
1323
- firstColumn: 'First column',
1324
- secondColumn: 'Second column',
1325
- thirdColumn: 'Third column'
1326
- }),
1327
- (this.defaultRows = [
1328
- { firstColumn: 'Row 1 column 1', secondColumn: 'Row 1 column 2', thirdColumn: 'Row 1 column 3' },
1329
- { firstColumn: 'Row 2 column 1', secondColumn: 'Row 2 column 2', thirdColumn: 'Row 2 column 3' },
1330
- { firstColumn: 'Row 3 column 1', secondColumn: 'Row 3 column 2', thirdColumn: 'Row 3 column 3' },
1331
- { firstColumn: 'Row 4 column 1', secondColumn: 'Row 4 column 2', thirdColumn: 'Row 4 column 3' },
1332
- { firstColumn: 'Row 5 column 1', secondColumn: 'Row 5 column 2', thirdColumn: 'Row 5 column 3' },
1333
- { firstColumn: 'Row 6 column 1', secondColumn: 'Row 6 column 2', thirdColumn: 'Row 6 column 3' },
1334
- { firstColumn: 'Row 7 column 1', secondColumn: 'Row 7 column 2', thirdColumn: 'Row 7 column 3' },
1335
- { firstColumn: 'Row 8 column 1', secondColumn: 'Row 8 column 2', thirdColumn: 'Row 8 column 3' },
1336
- { firstColumn: 'Row 9 column 1', secondColumn: 'Row 9 column 2', thirdColumn: 'Row 9 column 3' },
1337
- { firstColumn: 'Row 10 column 1', secondColumn: 'Row 10 column 2', thirdColumn: 'Row 10 column 3' },
1338
- { firstColumn: 'Row 11 column 1', secondColumn: 'Row 11 column 2', thirdColumn: 'Row 11 column 3' },
1339
- { firstColumn: 'Row 12 column 1', secondColumn: 'Row 12 column 2', thirdColumn: 'Row 12 column 3' }
1340
- ]);
1341
- this.defaultPerPage = 10;
1342
- this.state = {
1343
- perPage: this.defaultPerPage,
1344
- page: 1,
1345
- rows: this.defaultRows.slice(0, this.defaultPerPage)
1346
- };
1347
- this.handleSetPage = this.handleSetPage.bind(this);
1348
- this.handlePerPageSelect = this.handlePerPageSelect.bind(this);
1349
- }
1350
-
1351
- handleSetPage(_evt, newPage, perPage, startIdx, endIdx) {
1352
- this.setState({
1353
- page: newPage,
1354
- rows: this.defaultRows.slice(startIdx, endIdx)
1355
- });
1356
- }
1357
-
1358
- handlePerPageSelect(_evt, newPerPage, newPage, startIdx, endIdx) {
1359
- this.setState({
1360
- perPage: newPerPage,
1361
- page: newPage,
1362
- rows: this.defaultRows.slice(startIdx, endIdx)
1363
- });
1364
- }
1365
-
1366
- renderPagination(variant = 'top') {
1367
- const { page, perPage } = this.state;
1368
- return (
1369
- <Pagination
1370
- isCompact
1371
- itemCount={this.defaultRows.length}
1372
- page={page}
1373
- perPage={perPage}
1374
- isLastFullPageShown
1375
- onSetPage={this.handleSetPage}
1376
- onPerPageSelect={this.handlePerPageSelect}
1377
- perPageOptions={[
1378
- { title: '3', value: 3 },
1379
- { title: '5', value: 5 },
1380
- { title: '12', value: 12 },
1381
- { title: '20', value: 20 }
1382
- ]}
1383
- titles={{
1384
- paginationAriaLabel: `${variant} pagination`
1385
- }}
1386
- />
1387
- );
1388
- }
1389
-
1390
- render() {
1391
- return (
1392
- <React.Fragment>
1393
- {this.renderPagination()}
1394
- <Table aria-label="Automated Pagination Table Demo">
1395
- <Thead>
1396
- <Tr>
1397
- <Th>{this.columns.firstColumn}</Th>
1398
- <Th>{this.columns.secondColumn}</Th>
1399
- <Th>{this.columns.thirdColumn}</Th>
1400
- </Tr>
1401
- </Thead>
1402
- <Tbody>
1403
- {this.state.rows.map((row, rowIndex) => (
1404
- <Tr key={rowIndex}>
1405
- <>
1406
- <Td dataLabel={this.columns.firstColumn}>{row.firstColumn}</Td>
1407
- <Td dataLabel={this.columns.secondColumn}>{row.secondColumn}</Td>
1408
- <Td dataLabel={this.columns.thirdColumn}>{row.thirdColumn}</Td>
1409
- </>
1410
- </Tr>
1411
- ))}
1412
- </Tbody>
1413
- </Table>
1414
- </React.Fragment>
1415
- );
1416
- }
1417
- }
1418
- ```
1419
-
1420
- ### Static bottom pagination on mobile
1421
-
1422
- ```js isFullscreen file="table-demos/StaticBottomPagination.jsx"
1423
-
1424
- ```
1425
-
1426
- ### Sticky header
1427
-
1428
- ```js isFullscreen file="./table-demos/StickyHeader.jsx"
1429
-
1430
- ```
1431
-
1432
- ### Sticky first column
1433
-
1434
- ```js isFullscreen file="./table-demos/StickyFirstColumn.jsx"
1435
-
1436
- ```
1437
-
1438
- ### Sticky columns and header with toolbar
1439
-
1440
- A toolbar may be added above a sticky table either inside or outside the `OuterScrollContainer`.
1441
-
1442
- ```ts isFullscreen file="../../components/Table/examples/TableStickyColumnsAndHeader.tsx"
1443
-
1444
- ```
1445
-
1446
- ## Empty states
1447
-
1448
- These examples demonstrate the use of an [Empty State component](/components/empty-state) inside of a [Table](/components/table). Empty states are useful in a table when a filter returns no results, while data is loading, or when any type of error or exception condition occurs.
1449
-
1450
- ### Empty
1451
-
1452
- ```js isFullscreen
1453
- import React from 'react';
1454
- import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
1455
- import {
1456
- Bullseye,
1457
- Button,
1458
- Card,
1459
- EmptyState,
1460
- EmptyStateVariant,
1461
- EmptyStateIcon,
1462
- EmptyStateBody,
1463
- EmptyStateHeader,
1464
- EmptyStateFooter,
1465
- EmptyStateActions,
1466
- PageSection
1467
- } from '@patternfly/react-core';
1468
- import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
1469
- import { DashboardWrapper } from '@patternfly/react-core/src/demos/DashboardWrapper';
1470
-
1471
- export const TableEmptyState: React.FunctionComponent = () => (
1472
- <DashboardWrapper hasPageTemplateTitle>
1473
- <PageSection padding={{ default: 'noPadding', xl: 'padding' }}>
1474
- <Card component="div">
1475
- <Table aria-label="Empty state table">
1476
- <Thead>
1477
- <Tr>
1478
- <Th>Repositories</Th>
1479
- <Th>Branches</Th>
1480
- <Th>Pull requests</Th>
1481
- <Th>Workspaces</Th>
1482
- <Th>Last commit</Th>
1483
- </Tr>
1484
- </Thead>
1485
- <Tbody>
1486
- <Tr>
1487
- <Td colSpan={8}>
1488
- <Bullseye>
1489
- <EmptyState variant={EmptyStateVariant.sm}>
1490
- <EmptyStateHeader
1491
- icon={<EmptyStateIcon icon={SearchIcon} />}
1492
- titleText="No results found"
1493
- headingLevel="h2"
1494
- />
1495
- <EmptyStateBody>
1496
- No results match this filter criteria. Clear all filters and try again.
1497
- </EmptyStateBody>
1498
- <EmptyStateFooter>
1499
- <EmptyStateActions>
1500
- <Button variant="link">Clear all filters</Button>
1501
- </EmptyStateActions>
1502
- </EmptyStateFooter>
1503
- </EmptyState>
1504
- </Bullseye>
1505
- </Td>
1506
- </Tr>
1507
- </Tbody>
1508
- </Table>
1509
- </Card>
1510
- </PageSection>
1511
- </DashboardWrapper>
1512
- );
1513
- ```
1514
-
1515
- ### Loading
1516
-
1517
- ```js isFullscreen
1518
- import React from 'react';
1519
- import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
1520
- import {
1521
- Bullseye,
1522
- Card,
1523
- EmptyState,
1524
- EmptyStateIcon,
1525
- EmptyStateBody,
1526
- EmptyStateHeader,
1527
- PageSection,
1528
- Spinner
1529
- } from '@patternfly/react-core';
1530
- import { DashboardWrapper } from '@patternfly/react-core/src/demos/DashboardWrapper';
1531
-
1532
- export const LoadingStateDemo: React.FunctionComponent = () => (
1533
- <DashboardWrapper hasPageTemplateTitle>
1534
- <PageSection padding={{ default: 'noPadding', xl: 'padding' }}>
1535
- <Card component="div">
1536
- <Table aria-label="Loading table demo">
1537
- <Thead>
1538
- <Tr>
1539
- <Th>Repositories</Th>
1540
- <Th>Branches</Th>
1541
- <Th>Pull requests</Th>
1542
- <Th>Workspaces</Th>
1543
- <Th>Last commit</Th>
1544
- </Tr>
1545
- </Thead>
1546
- <Tbody>
1547
- <Tr>
1548
- <Td colSpan={8}>
1549
- <Bullseye>
1550
- <EmptyState>
1551
- <EmptyStateHeader titleText="Loading" headingLevel="h2" icon={<EmptyStateIcon icon={Spinner} />} />
1552
- </EmptyState>
1553
- </Bullseye>
1554
- </Td>
1555
- </Tr>
1556
- </Tbody>
1557
- </Table>
1558
- </Card>
1559
- </PageSection>
1560
- </DashboardWrapper>
1561
- );
1562
- ```
1563
-
1564
- ### Error
1565
-
1566
- ```js isFullscreen
1567
- import React from 'react';
1568
- import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
1569
- import {
1570
- Bullseye,
1571
- Card,
1572
- EmptyState,
1573
- EmptyStateVariant,
1574
- EmptyStateIcon,
1575
- EmptyStateBody,
1576
- EmptyStateHeader,
1577
- PageSection
1578
- } from '@patternfly/react-core';
1579
- import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
1580
- import globalDangerColor200 from '@patternfly/react-tokens/dist/esm/global_danger_color_200';
1581
- import { DashboardWrapper } from '@patternfly/react-core/src/demos/DashboardWrapper';
1582
-
1583
- export const ErrorStateDemo: React.FunctionComponent = () => (
1584
- <DashboardWrapper hasPageTemplateTitle>
1585
- <PageSection padding={{ default: 'noPadding', xl: 'padding' }}>
1586
- <Card component="div">
1587
- <Table aria-label="Loading table demo">
1588
- <Thead>
1589
- <Tr>
1590
- <Th>Repositories</Th>
1591
- <Th>Branches</Th>
1592
- <Th>Pull requests</Th>
1593
- <Th>Workspaces</Th>
1594
- <Th>Last commit</Th>
1595
- </Tr>
1596
- </Thead>
1597
- <Tbody>
1598
- <Tr>
1599
- <Td colSpan={8}>
1600
- <Bullseye>
1601
- <EmptyState variant={EmptyStateVariant.sm}>
1602
- <EmptyStateHeader
1603
- titleText="Unable to connect"
1604
- icon={<EmptyStateIcon icon={ExclamationCircleIcon} color={globalDangerColor200.value} />}
1605
- headingLevel="h2"
1606
- />
1607
- <EmptyStateBody>
1608
- There was an error retrieving data. Check your connection and reload the page.
1609
- </EmptyStateBody>
1610
- </EmptyState>
1611
- </Bullseye>
1612
- </Td>
1613
- </Tr>
1614
- </Tbody>
1615
- </Table>
1616
- </Card>
1617
- </PageSection>
1618
- </DashboardWrapper>
1619
- );
1620
- ```