Skip to content

Commit 0927a2e

Browse files
committed
All/selected row switch
1 parent 2b82628 commit 0927a2e

File tree

4 files changed

+142
-4
lines changed

4 files changed

+142
-4
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import React, { useEffect, useMemo, useState } from 'react';
2+
import { Pagination, ToggleGroup, ToggleGroupItem } from '@patternfly/react-core';
3+
import { useDataViewPagination, useDataViewSelection } from '@patternfly/react-data-view/dist/dynamic/Hooks';
4+
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
5+
import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
6+
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
7+
import { BulkSelect, BulkSelectValue } from '@patternfly/react-component-groups';
8+
9+
const perPageOptions = [
10+
{ title: '5', value: 5 },
11+
{ title: '10', value: 10 }
12+
];
13+
14+
interface Repository {
15+
name: string;
16+
branches: string | null;
17+
prs: string | null;
18+
workspaces: string;
19+
lastCommit: string;
20+
};
21+
22+
const repositories: Repository[] = [
23+
{ name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
24+
{ name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
25+
{ name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
26+
{ name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
27+
{ name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
28+
{ name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
29+
];
30+
31+
const rows = repositories.map(item => Object.values(item));
32+
33+
const columns = [ 'Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit' ];
34+
35+
const ouiaId = 'LayoutExample';
36+
37+
export const BasicExample: React.FunctionComponent = () => {
38+
const pagination = useDataViewPagination({ perPage: 5 });
39+
const selection = useDataViewSelection({ matchOption: (a, b) => a[0] === b[0] });
40+
const [ selectedToggle, setSelectedToggle ] = useState('all')
41+
const { selected, onSelect } = selection;
42+
const { page, perPage, onSetPage } = pagination;
43+
44+
const pageRows = useMemo(() => (selectedToggle === 'selected' ? selected : rows).slice((page - 1) * perPage, ((page - 1) * perPage) + perPage), [ page, perPage, selectedToggle ]);
45+
46+
const handleBulkSelect = (value: BulkSelectValue) => {
47+
value === BulkSelectValue.none && onSelect(false);
48+
value === BulkSelectValue.all && onSelect(true, rows);
49+
};
50+
51+
const handleItemClick = (event, _isSelected: boolean) => {
52+
const id = event.currentTarget.id;
53+
if (selectedToggle !== id) {
54+
setSelectedToggle(id);
55+
onSetPage(undefined, 1);
56+
}
57+
};
58+
59+
useEffect(() => {
60+
if (selected.length === 0) {
61+
setSelectedToggle('all');
62+
}
63+
}, [ selected ]);
64+
65+
return (
66+
<DataView selection={selection}>
67+
<DataViewToolbar
68+
ouiaId='DataViewHeader'
69+
bulkSelect={
70+
<BulkSelect
71+
canSelectAll
72+
isDataPaginated={false}
73+
totalCount={repositories.length}
74+
selectedCount={selected.length}
75+
onSelect={handleBulkSelect}
76+
/>
77+
}
78+
toggleGroup={<ToggleGroup aria-label="Default with single selectable">
79+
<ToggleGroupItem
80+
text="All"
81+
buttonId="all"
82+
isSelected={selectedToggle === 'all'}
83+
onChange={handleItemClick}
84+
/>
85+
<ToggleGroupItem
86+
isDisabled={selected.length === 0}
87+
text="Selected"
88+
buttonId="selected"
89+
isSelected={selectedToggle === 'selected'}
90+
onChange={handleItemClick}
91+
/>
92+
</ToggleGroup>
93+
}
94+
pagination={<Pagination perPageOptions={perPageOptions} itemCount={repositories.length} {...pagination} />}
95+
/>
96+
<DataViewTable aria-label='Repositories table' ouiaId={ouiaId} columns={columns} rows={pageRows} />
97+
</DataView>
98+
);
99+
};

packages/module/patternfly-docs/content/extensions/data-view/examples/Toolbar/Toolbar.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ sortValue: 2
1515
propComponents: ['DataViewToolbar', 'DataViewFilters', 'DataViewTextFilter', 'DataViewCheckboxFilter']
1616
sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/Toolbar/Toolbar.md
1717
---
18-
import { useMemo } from 'react';
18+
import { useMemo, useState, useEffect } from 'react';
1919
import { BrowserRouter, useSearchParams } from 'react-router-dom';
20+
import { Pagination, ToggleGroup, ToggleGroupItem } from '@patternfly/react-core';
2021
import { useDataViewPagination, useDataViewSelection, useDataViewFilters } from '@patternfly/react-data-view/dist/dynamic/Hooks';
2122
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
2223
import { BulkSelect, BulkSelectValue, ErrorState, ResponsiveAction, ResponsiveActions, SkeletonTableHead, SkeletonTableBody } from '@patternfly/react-component-groups';
@@ -140,3 +141,34 @@ This example demonstrates the setup and usage of filters within the data view. I
140141
```js file="./FiltersExample.tsx"
141142

142143
```
144+
145+
146+
## All/selected data switch
147+
To allow users to filter data records in the data view, add filtering support that displays the applied filter chips.
148+
149+
The data view toolbar can include a set of filters by passing a React node to the `filters` property. You can use the predefined components `<DataViewFilters>`, `<DataViewTextFilter>`, and `<DataViewCheckboxFilter>` to customize and handle filtering directly in the toolbar. The `<DataViewFilters>` component is a wrapper that allows conditional filtering using multiple attributes. If you need just a single filter, you can use `<DataViewTextFilter>`, `<DataViewCheckboxFilter>`, or a different filter component alone. Props of these filter components are listed in the [props section of this page](#props).
150+
151+
You can either pass a `value` and `onChange` event to every filter separately, or you can pass `values` and `onChange` to the `<DataViewFilters>` wrapper, which makes them available to its children. Props directly passed to child filters have a higher priority than the "inherited" ones.
152+
153+
### Filters state
154+
155+
The `useDataViewFilters` hook manages the filter state of the data view. It allows you to define default filter values, synchronize filter state with URL parameters, and handle filter changes efficiently.
156+
157+
**Initial values:**
158+
- `initialFilters` object with default filter values (if the filter param allows multiple values, pass an array).
159+
- Optional `searchParams` object for managing URL-based filter state.
160+
- Optional `setSearchParams` function to update the URL when filters are modified.
161+
162+
The `useDataViewFilters` hook works well with the [React Router](https://reactrouter.com/) library to support URL-based filtering. Alternatively, you can manage the filter state in the URL using `URLSearchParams` and `window.history.pushState` APIs, or other routing libraries. If no URL parameters are provided, the filter state is managed internally.
163+
164+
**Return values:**
165+
- `filters` object representing the current filter values.
166+
- `onSetFilters` function to update the filter state.
167+
- `clearAllFilters` function to reset all filters to their initial values.
168+
169+
### All/selected example
170+
This example demonstrates the setup and usage of filters within the data view. It includes text filters for different attributes, the ability to clear all filters, and persistence of filter state in the URL.
171+
172+
```js file="./AllSelectedExample.tsx"
173+
174+
```

packages/module/patternfly-docs/generated/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ module.exports = {
22
'/extensions/data-view/toolbar/react': {
33
id: "Toolbar",
44
title: "Data view toolbar",
5-
toc: [[{"text":"Toolbar example"}],{"text":"Toolbar actions"},[{"text":"Actions example"}],{"text":"Pagination"},[{"text":"Pagination state"},{"text":"Pagination example"}],{"text":"Selection"},[{"text":"Selection state"},{"text":"Selection example"}],{"text":"Filters"},[{"text":"Filters state"},{"text":"Filtering example"}]],
6-
examples: ["Toolbar example","Actions example","Pagination example","Selection example","Filtering example"],
5+
toc: [[{"text":"Toolbar example"}],{"text":"Toolbar actions"},[{"text":"Actions example"}],{"text":"Pagination"},[{"text":"Pagination state"},{"text":"Pagination example"}],{"text":"Selection"},[{"text":"Selection state"},{"text":"Selection example"}],{"text":"Filters"},[{"text":"Filters state"},{"text":"Filtering example"}],{"text":"All/selected data switch"},[{"text":"Filters state","id":"filters-state-0"},{"text":"All/selected example"}]],
6+
examples: ["Toolbar example","Actions example","Pagination example","Selection example","Filtering example","All/selected example"],
77
section: "extensions",
88
subsection: "Data view",
99
source: "react",

packages/module/src/DataViewToolbar/DataViewToolbar.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ export interface DataViewToolbarProps extends Omit<PropsWithChildren<ToolbarProp
1313
pagination?: React.ReactNode;
1414
/** React node to display actions */
1515
actions?: React.ReactNode;
16+
/** React node to display toggle group */
17+
toggleGroup?: React.ReactNode;
1618
/** React node to display filters */
1719
filters?: React.ReactNode;
1820
/** React node to display custom filter labels */
1921
customLabelGroupContent?: React.ReactNode;
2022
}
2123

22-
export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions, pagination, filters, customLabelGroupContent, clearAllFilters, children, ...props }: DataViewToolbarProps) => {
24+
export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions, toggleGroup, pagination, filters, customLabelGroupContent, clearAllFilters, children, ...props }: DataViewToolbarProps) => {
2325
const defaultClearFilters = useRef(
2426
<ToolbarItem>
2527
<Button ouiaId={`${ouiaId}-clear-all-filters`} variant="link" onClick={clearAllFilters} isInline>
@@ -45,6 +47,11 @@ export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, oui
4547
{actions}
4648
</ToolbarItem>
4749
)}
50+
{toggleGroup && (
51+
<ToolbarItem>
52+
{toggleGroup}
53+
</ToolbarItem>
54+
)}
4855
{pagination && (
4956
<ToolbarItem variant={ToolbarItemVariant.pagination} data-ouia-component-id={`${ouiaId}-pagination`}>
5057
{pagination}

0 commit comments

Comments
 (0)