Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions cypress/component/DataViewFilterAllSelected.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { mount } from 'cypress/react';
import { BasicExample } from '../../packages/module/patternfly-docs/content/extensions/data-view/examples/Toolbar/AllSelectedExample';

describe('BasicExample Component', () => {
beforeEach(() => {
mount(<BasicExample />);
});

it('displays all rows by default', () => {
cy.get('table tbody tr').should('have.length', 5);
});

it('filters to selected rows when toggled', () => {
cy.get('table tbody tr')
.first()
.find('input[type="checkbox"]')
.check();

cy.get('#selected-row-switch').click();

cy.get('table tbody tr').should('have.length', 1);
});

it('switches back to all when last selected row is unselected', () => {
cy.get('table tbody tr')
.first()
.find('input[type="checkbox"]')
.check();

cy.get('#selected-row-switch').click();

cy.get('table tbody tr').should('have.length', 1);

cy.get('table tbody tr')
.first()
.find('input[type="checkbox"]')
.uncheck();

cy.get('table tbody tr').should('have.length', 5);
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about introducing constants for all/selected strings?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented.

Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React, { useEffect, useMemo, useState } from 'react';
import { Pagination, ToggleGroup, ToggleGroupItem, Tooltip } from '@patternfly/react-core';
import { useDataViewPagination, useDataViewSelection } from '@patternfly/react-data-view/dist/dynamic/Hooks';
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
import { BulkSelect, BulkSelectValue } from '@patternfly/react-component-groups';

const TOGGLE_ALL = 'all';
const TOGGLE_SELECTED = 'selected';

const perPageOptions = [
{ title: '5', value: 5 },
{ title: '10', value: 10 }
];

interface Repository {
name: string;
branches: string | null;
prs: string | null;
workspaces: string;
lastCommit: string;
};

const repositories: Repository[] = [
{ name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
{ name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
{ name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
{ name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
{ name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
{ name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
];

const rows = repositories.map(item => Object.values(item));

const columns = [ 'Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit' ];

const ouiaId = 'LayoutExample';

export const BasicExample: React.FunctionComponent = () => {
const pagination = useDataViewPagination({ perPage: 5 });
const selection = useDataViewSelection({ matchOption: (a, b) => a[0] === b[0] });
const [ selectedToggle, setSelectedToggle ] = useState(TOGGLE_ALL);
const { selected, onSelect } = selection;
const { page, perPage, onSetPage } = pagination;

const pageRows = useMemo(() => (selectedToggle === TOGGLE_SELECTED ? selected : rows).slice((page - 1) * perPage, ((page - 1) * perPage) + perPage), [ page, perPage, selectedToggle, selected ]);

const handleBulkSelect = (value: BulkSelectValue) => {
value === BulkSelectValue.none && onSelect(false);
value === BulkSelectValue.all && onSelect(true, rows);
};

const handleItemClick = (event: React.MouseEvent<any> | React.KeyboardEvent | MouseEvent, _isSelected: boolean) => {

Check warning on line 54 in packages/module/patternfly-docs/content/extensions/data-view/examples/Toolbar/AllSelectedExample.tsx

View workflow job for this annotation

GitHub Actions / call-build-lint-test-workflow / lint

Unexpected any. Specify a different type
const id = event.currentTarget.id;

if (id === TOGGLE_SELECTED && selected.length === 0) {
return;
}

if (selectedToggle !== id) {
setSelectedToggle(id);
onSetPage(undefined, 1);
}
};

useEffect(() => {
if (selected.length === 0) {
setSelectedToggle(TOGGLE_ALL);
}
}, [ selected ]);

return (
<DataView selection={selection}>
<DataViewToolbar
ouiaId='DataViewHeader'
bulkSelect={
<BulkSelect
canSelectAll
isDataPaginated={false}
totalCount={repositories.length}
selectedCount={selected.length}
onSelect={handleBulkSelect}
/>
}
toggleGroup={
<ToggleGroup aria-label="Toggle group to switch between all / selected table rows">
<ToggleGroupItem
text="All"
buttonId={TOGGLE_ALL}
isSelected={selectedToggle === TOGGLE_ALL}
onChange={handleItemClick}
/>
<ToggleGroupItem
id="selected-row-switch"
text="Selected"
buttonId={TOGGLE_SELECTED}
isSelected={selectedToggle === TOGGLE_SELECTED}
onChange={handleItemClick}
aria-disabled={selected.length === 0}
/>
</ToggleGroup>
}
pagination={<Pagination perPageOptions={perPageOptions} itemCount={repositories.length} {...pagination} />}
/>

{selected.length === 0 && (<Tooltip
id="selected-row-switch-tooltip"
content="Select at least one row to enable this filter"
triggerRef={() => document.getElementById('selected-row-switch') as HTMLButtonElement}
/>)}

<DataViewTable aria-label='Repositories table' ouiaId={ouiaId} columns={columns} rows={pageRows} />
</DataView>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ sortValue: 2
propComponents: ['DataViewToolbar', 'DataViewFilters', 'DataViewTextFilter', 'DataViewCheckboxFilter']
sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/Toolbar/Toolbar.md
---
import { useMemo } from 'react';
import { useMemo, useState, useEffect } from 'react';
import { BrowserRouter, useSearchParams } from 'react-router-dom';
import { Pagination, ToggleGroup, ToggleGroupItem } from '@patternfly/react-core';
import { useDataViewPagination, useDataViewSelection, useDataViewFilters } from '@patternfly/react-data-view/dist/dynamic/Hooks';
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
import { BulkSelect, BulkSelectValue, ErrorState, ResponsiveAction, ResponsiveActions, SkeletonTableHead, SkeletonTableBody } from '@patternfly/react-component-groups';
Expand Down Expand Up @@ -140,3 +141,14 @@ This example demonstrates the setup and usage of filters within the data view. I
```js file="./FiltersExample.tsx"

```


## All/selected data switch
All/selected data switch allows users to toggle between displaying the entire table (All) and only the rows they have selected (Selected). If the user deselects the last selected row, the filter automatically switches back to All, displaying all table rows again. Until at least one row is selected, a tooltip with guidance is displayed, and the Selected button does not perform any action. The Selected button is intentionally not disabled for accessibility reasons but instead has `aria-disabled` set.

### All/selected example
This example demonstrates the setup and usage of All/selected row switch.

```js file="./AllSelectedExample.tsx"

```
4 changes: 2 additions & 2 deletions packages/module/patternfly-docs/generated/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module.exports = {
'/extensions/data-view/toolbar/react': {
id: "Toolbar",
title: "Data view toolbar",
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"}]],
examples: ["Toolbar example","Actions example","Pagination example","Selection example","Filtering example"],
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":"All/selected example"}]],
examples: ["Toolbar example","Actions example","Pagination example","Selection example","Filtering example","All/selected example"],
section: "extensions",
subsection: "Data view",
source: "react",
Expand Down
9 changes: 8 additions & 1 deletion packages/module/src/DataViewToolbar/DataViewToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ export interface DataViewToolbarProps extends Omit<PropsWithChildren<ToolbarProp
pagination?: React.ReactNode;
/** React node to display actions */
actions?: React.ReactNode;
/** React node to display toggle group */
toggleGroup?: React.ReactNode;
/** React node to display filters */
filters?: React.ReactNode;
/** React node to display custom filter labels */
customLabelGroupContent?: React.ReactNode;
}

export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions, pagination, filters, customLabelGroupContent, clearAllFilters, children, ...props }: DataViewToolbarProps) => {
export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions, toggleGroup, pagination, filters, customLabelGroupContent, clearAllFilters, children, ...props }: DataViewToolbarProps) => {
const defaultClearFilters = useRef(
<ToolbarItem>
<Button ouiaId={`${ouiaId}-clear-all-filters`} variant="link" onClick={clearAllFilters} isInline>
Expand All @@ -45,6 +47,11 @@ export const DataViewToolbar: React.FC<DataViewToolbarProps> = ({ className, oui
{actions}
</ToolbarItem>
)}
{toggleGroup && (
<ToolbarItem>
{toggleGroup}
</ToolbarItem>
)}
{pagination && (
<ToolbarItem variant={ToolbarItemVariant.pagination} data-ouia-component-id={`${ouiaId}-pagination`}>
{pagination}
Expand Down
Loading