|
| 1 | +import React, { useMemo } from 'react'; |
| 2 | +import { Pagination } from '@patternfly/react-core'; |
| 3 | +import { BrowserRouter, useSearchParams } from 'react-router-dom'; |
| 4 | +import { TreeViewDataItem } from '@patternfly/react-core'; |
| 5 | +import { useDataViewFilters, useDataViewPagination } from '@patternfly/react-data-view/dist/dynamic/Hooks'; |
| 6 | +import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView'; |
| 7 | +import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable'; |
| 8 | +import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar'; |
| 9 | +import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters'; |
| 10 | +import { DataViewTreeFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTreeFilter'; |
| 11 | + |
| 12 | +const perPageOptions = [ |
| 13 | + { title: '5', value: 5 }, |
| 14 | + { title: '10', value: 10 } |
| 15 | +]; |
| 16 | + |
| 17 | +interface Repository { |
| 18 | + name: string; |
| 19 | + workspace: string; |
| 20 | + tags: string[]; |
| 21 | + os: string; |
| 22 | + lastSeen: string; |
| 23 | +} |
| 24 | + |
| 25 | +interface RepositoryFilters { |
| 26 | + name: string; |
| 27 | + workspace: string[]; |
| 28 | + os: string[]; |
| 29 | + tags: string[]; |
| 30 | +} |
| 31 | + |
| 32 | +const repositories: Repository[] = [ |
| 33 | + { name: 'Server-001', workspace: 'Development Workspace', tags: ['web', 'frontend'], os: 'Ubuntu 22.04', lastSeen: '2 hours ago' }, |
| 34 | + { name: 'Server-002', workspace: 'Development Workspace', tags: ['api', 'backend'], os: 'RHEL 9', lastSeen: '5 hours ago' }, |
| 35 | + { name: 'Server-003', workspace: 'Development Workspace', tags: ['database'], os: 'Windows Server 2022', lastSeen: '1 day ago' }, |
| 36 | + { name: 'Server-004', workspace: 'Production Workspace', tags: ['web', 'frontend'], os: 'Ubuntu 22.04', lastSeen: '30 minutes ago' }, |
| 37 | + { name: 'Server-005', workspace: 'Production Workspace', tags: ['api', 'backend'], os: 'Debian 12', lastSeen: '1 hour ago' }, |
| 38 | + { name: 'Server-006', workspace: 'Production Workspace', tags: ['monitoring'], os: 'macOS Ventura', lastSeen: '3 hours ago' }, |
| 39 | + { name: 'Server-007', workspace: 'Production Workspace', tags: ['cache'], os: 'macOS Sonoma', lastSeen: '2 days ago' }, |
| 40 | + { name: 'Server-008', workspace: 'Testing Workspace', tags: ['test', 'frontend'], os: 'CentOS 8', lastSeen: '6 hours ago' }, |
| 41 | + { name: 'Server-009', workspace: 'Testing Workspace', tags: ['test', 'backend'], os: 'Fedora 38', lastSeen: '4 hours ago' } |
| 42 | +]; |
| 43 | + |
| 44 | +const treeOptions: TreeViewDataItem[] = [ |
| 45 | + { |
| 46 | + name: 'Development Workspace', |
| 47 | + id: 'workspace-dev', |
| 48 | + checkProps: { 'aria-label': 'dev-workspace-check', checked: false } |
| 49 | + }, |
| 50 | + { |
| 51 | + name: 'Production Workspace', |
| 52 | + id: 'workspace-prod', |
| 53 | + checkProps: { 'aria-label': 'prod-workspace-check', checked: false } |
| 54 | + }, |
| 55 | + { |
| 56 | + name: 'Testing Workspace', |
| 57 | + id: 'workspace-test', |
| 58 | + checkProps: { 'aria-label': 'test-workspace-check', checked: false } |
| 59 | + } |
| 60 | +]; |
| 61 | + |
| 62 | +const osOptions: TreeViewDataItem[] = [ |
| 63 | + { |
| 64 | + name: 'Linux', |
| 65 | + id: 'os-linux', |
| 66 | + checkProps: { 'aria-label': 'linux-check', checked: false }, |
| 67 | + children: [ |
| 68 | + { |
| 69 | + name: 'Ubuntu 22.04', |
| 70 | + id: 'os-ubuntu', |
| 71 | + checkProps: { checked: false } |
| 72 | + }, |
| 73 | + { |
| 74 | + name: 'RHEL 9', |
| 75 | + id: 'os-rhel', |
| 76 | + checkProps: { checked: false } |
| 77 | + }, |
| 78 | + { |
| 79 | + name: 'Debian 12', |
| 80 | + id: 'os-debian', |
| 81 | + checkProps: { checked: false } |
| 82 | + }, |
| 83 | + { |
| 84 | + name: 'CentOS 8', |
| 85 | + id: 'os-centos', |
| 86 | + checkProps: { checked: false } |
| 87 | + }, |
| 88 | + { |
| 89 | + name: 'Fedora 38', |
| 90 | + id: 'os-fedora', |
| 91 | + checkProps: { checked: false } |
| 92 | + } |
| 93 | + ], |
| 94 | + defaultExpanded: true |
| 95 | + }, |
| 96 | + { |
| 97 | + name: 'Windows', |
| 98 | + id: 'os-windows', |
| 99 | + checkProps: { 'aria-label': 'windows-check', checked: false }, |
| 100 | + children: [ |
| 101 | + { |
| 102 | + name: 'Windows Server 2022', |
| 103 | + id: 'os-windows-2022', |
| 104 | + checkProps: { checked: false } |
| 105 | + } |
| 106 | + ] |
| 107 | + }, |
| 108 | + { |
| 109 | + name: 'macOS', |
| 110 | + id: 'os-macos', |
| 111 | + checkProps: { 'aria-label': 'macos-check', checked: false }, |
| 112 | + children: [ |
| 113 | + { |
| 114 | + name: 'macOS Ventura', |
| 115 | + id: 'os-macos-ventura', |
| 116 | + checkProps: { checked: false } |
| 117 | + }, |
| 118 | + { |
| 119 | + name: 'macOS Sonoma', |
| 120 | + id: 'os-macos-sonoma', |
| 121 | + checkProps: { checked: false } |
| 122 | + } |
| 123 | + ] |
| 124 | + } |
| 125 | +]; |
| 126 | + |
| 127 | +const tagOptions: TreeViewDataItem[] = [ |
| 128 | + { |
| 129 | + name: 'Environment', |
| 130 | + id: 'tags-env', |
| 131 | + checkProps: { 'aria-label': 'env-check', checked: false }, |
| 132 | + children: [ |
| 133 | + { |
| 134 | + name: 'web', |
| 135 | + id: 'tag-web', |
| 136 | + checkProps: { checked: false } |
| 137 | + }, |
| 138 | + { |
| 139 | + name: 'api', |
| 140 | + id: 'tag-api', |
| 141 | + checkProps: { checked: false } |
| 142 | + }, |
| 143 | + { |
| 144 | + name: 'database', |
| 145 | + id: 'tag-database', |
| 146 | + checkProps: { checked: false } |
| 147 | + } |
| 148 | + ], |
| 149 | + defaultExpanded: true |
| 150 | + }, |
| 151 | + { |
| 152 | + name: 'Layer', |
| 153 | + id: 'tags-layer', |
| 154 | + checkProps: { 'aria-label': 'layer-check', checked: false }, |
| 155 | + children: [ |
| 156 | + { |
| 157 | + name: 'frontend', |
| 158 | + id: 'tag-frontend', |
| 159 | + checkProps: { checked: false } |
| 160 | + }, |
| 161 | + { |
| 162 | + name: 'backend', |
| 163 | + id: 'tag-backend', |
| 164 | + checkProps: { checked: false } |
| 165 | + } |
| 166 | + ] |
| 167 | + }, |
| 168 | + { |
| 169 | + name: 'Other', |
| 170 | + id: 'tags-other', |
| 171 | + checkProps: { 'aria-label': 'other-check', checked: false }, |
| 172 | + children: [ |
| 173 | + { |
| 174 | + name: 'monitoring', |
| 175 | + id: 'tag-monitoring', |
| 176 | + checkProps: { checked: false } |
| 177 | + }, |
| 178 | + { |
| 179 | + name: 'cache', |
| 180 | + id: 'tag-cache', |
| 181 | + checkProps: { checked: false } |
| 182 | + }, |
| 183 | + { |
| 184 | + name: 'test', |
| 185 | + id: 'tag-test', |
| 186 | + checkProps: { checked: false } |
| 187 | + } |
| 188 | + ] |
| 189 | + } |
| 190 | +]; |
| 191 | + |
| 192 | +const columns = ['Name', 'Workspace', 'Tags', 'OS', 'Last seen']; |
| 193 | + |
| 194 | +const ouiaId = 'TreeFilterExample'; |
| 195 | + |
| 196 | +const MyTable: React.FunctionComponent = () => { |
| 197 | + const [searchParams, setSearchParams] = useSearchParams(); |
| 198 | + const { filters, onSetFilters, clearAllFilters } = useDataViewFilters<RepositoryFilters>({ |
| 199 | + initialFilters: { name: '', workspace: [], os: [], tags: [] }, |
| 200 | + searchParams, |
| 201 | + setSearchParams |
| 202 | + }); |
| 203 | + const pagination = useDataViewPagination({ perPage: 5 }); |
| 204 | + const { page, perPage } = pagination; |
| 205 | + |
| 206 | + const filteredData = useMemo( |
| 207 | + () => |
| 208 | + repositories.filter( |
| 209 | + (item) => |
| 210 | + (!filters.name || item.name?.toLocaleLowerCase().includes(filters.name?.toLocaleLowerCase())) && |
| 211 | + (!filters.workspace || filters.workspace.length === 0 || filters.workspace.includes(item.workspace)) && |
| 212 | + (!filters.os || filters.os.length === 0 || filters.os.includes(item.os)) && |
| 213 | + (!filters.tags || filters.tags.length === 0 || filters.tags.some(tag => item.tags.includes(tag))) |
| 214 | + ), |
| 215 | + [filters] |
| 216 | + ); |
| 217 | + |
| 218 | + const pageRows = useMemo( |
| 219 | + () => |
| 220 | + filteredData |
| 221 | + .slice((page - 1) * perPage, (page - 1) * perPage + perPage) |
| 222 | + .map((item) => [item.name, item.workspace, item.tags.join(', '), item.os, item.lastSeen]), |
| 223 | + [page, perPage, filteredData] |
| 224 | + ); |
| 225 | + |
| 226 | + return ( |
| 227 | + <DataView> |
| 228 | + <DataViewToolbar |
| 229 | + ouiaId="TreeFilterExampleHeader" |
| 230 | + clearAllFilters={clearAllFilters} |
| 231 | + pagination={<Pagination perPageOptions={perPageOptions} itemCount={filteredData.length} {...pagination} />} |
| 232 | + filters={ |
| 233 | + <DataViewFilters onChange={(_e, values) => onSetFilters(values)} values={filters}> |
| 234 | + <DataViewTreeFilter |
| 235 | + filterId="workspace" |
| 236 | + title="Workspace" |
| 237 | + items={treeOptions} |
| 238 | + /> |
| 239 | + <DataViewTreeFilter |
| 240 | + filterId="os" |
| 241 | + title="Operating System" |
| 242 | + items={osOptions} |
| 243 | + /> |
| 244 | + <DataViewTreeFilter |
| 245 | + filterId="tags" |
| 246 | + title="Tags" |
| 247 | + items={tagOptions} |
| 248 | + /> |
| 249 | + </DataViewFilters> |
| 250 | + } |
| 251 | + /> |
| 252 | + <DataViewTable aria-label="Repositories table" ouiaId={ouiaId} columns={columns} rows={pageRows} /> |
| 253 | + <DataViewToolbar |
| 254 | + ouiaId="TreeFilterExampleFooter" |
| 255 | + pagination={ |
| 256 | + <Pagination isCompact perPageOptions={perPageOptions} itemCount={filteredData.length} {...pagination} /> |
| 257 | + } |
| 258 | + /> |
| 259 | + </DataView> |
| 260 | + ); |
| 261 | +}; |
| 262 | + |
| 263 | +export const TreeFilterExample: React.FunctionComponent = () => ( |
| 264 | + <BrowserRouter> |
| 265 | + <MyTable /> |
| 266 | + </BrowserRouter> |
| 267 | +); |
0 commit comments