Skip to content

Commit 82faa6d

Browse files
authored
feat(FilterBar): support clearing all filters at once (#7512)
1 parent 84ae471 commit 82faa6d

File tree

4 files changed

+48
-62
lines changed

4 files changed

+48
-62
lines changed

packages/main/src/components/FilterBar/FilterBar.cy.tsx

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ describe('FilterBar.cy.tsx', () => {
7474

7575
it('Selection: FilterGroupItems in Dialog + events', () => {
7676
const TestComp = (props: Omit<FilterBarPropTypes, 'children'>) => {
77-
const [selectedFilters, setSelectedFilters] = useState('');
77+
const [selectedFilters, setSelectedFilters] = useState('0 1 2');
7878
const [closeTrigger, setCloseTrigger] = useState('');
7979
const [savedVisibleFilters, setSavedVisibleFilters] = useState('');
8080
const {
@@ -217,24 +217,17 @@ describe('FilterBar.cy.tsx', () => {
217217
}
218218

219219
const checkboxes = cy.get('[ui5-checkbox]');
220-
checkboxes.should('have.length', 4);
220+
checkboxes.should('have.length', 3);
221221

222-
let selected = '2';
223-
checkboxes.each((item, index, arr) => {
222+
let selected = '0 1 2';
223+
checkboxes.each((item, cbIndex, arr) => {
224224
const wrappedItem = cy.wrap(item);
225225
wrappedItem.should('be.visible');
226+
wrappedItem.realClick();
226227

227-
wrappedItem.click();
228-
229-
if (index === 0) {
230-
// select-all: deselect all - only required is checked
231-
wrappedItem.should('not.have.attr', 'checked');
232-
cy.findByTestId('selected').should('have.text', selected);
233-
const requiredItem = cy.wrap(arr[arr.length - 1]);
234-
requiredItem.should('have.attr', 'checked');
235-
} else if (index !== arr.length - 1) {
236-
wrappedItem.should('have.attr', 'checked');
237-
selected += ` ${index - 1}`;
228+
if (cbIndex !== arr.length - 1) {
229+
wrappedItem.find('[role="checkbox"]').should('have.attr', 'aria-checked', 'false');
230+
selected = selected.split(' ').slice(1).join(' ');
238231
cy.findByTestId('selected').should('have.text', selected);
239232
} else {
240233
// is sometimes not selected, seems to be related to the click target and cypress
@@ -243,7 +236,7 @@ describe('FilterBar.cy.tsx', () => {
243236
}
244237
});
245238

246-
cy.get('@selectSpy').should('have.callCount', 3 * (index + 1));
239+
cy.get('@selectSpy').should('have.callCount', 2 * (index + 1));
247240

248241
cy.findAllByText('INPUT').should('have.length', 2);
249242
cy.findAllByText('SWITCH').should('have.length', 2);
@@ -261,7 +254,7 @@ describe('FilterBar.cy.tsx', () => {
261254
cy.get('@saveSpy').should('have.callCount', saveCallCount);
262255
saveCallCount++;
263256
cy.findByTestId('close-trigger').should('have.text', 'okButtonPressed');
264-
cy.findByTestId('saved-filters').should('have.text', '0 1 2');
257+
cy.findByTestId('saved-filters').should('have.text', '2');
265258
} else {
266259
if (action === 'Reset') {
267260
cy.get('[data-component-name="FilterBarDialogResetMessageBox"]').contains('Cancel').click();
@@ -298,10 +291,10 @@ describe('FilterBar.cy.tsx', () => {
298291
});
299292
});
300293

301-
it('select-all without required', () => {
294+
it('select/clear-all', () => {
302295
const TestComp = (props) => {
303-
const [selectedFilters, setSelectedFilters] = useState('');
304-
const [savedVisibleFilters, setSavedVisibleFilters] = useState('');
296+
const [selectedFilters, setSelectedFilters] = useState('0 1 2 3');
297+
const [savedVisibleFilters, setSavedVisibleFilters] = useState('0 1 2 3');
305298

306299
const handleSelectionChange: FilterBarPropTypes['onFiltersDialogSelectionChange'] = (e) => {
307300
setSelectedFilters(Array.from(e.selectedFilterKeys).join(' '));
@@ -312,20 +305,28 @@ describe('FilterBar.cy.tsx', () => {
312305
return (
313306
<>
314307
<FilterBar {...props} onFiltersDialogSelectionChange={handleSelectionChange} onFiltersDialogSave={handleSave}>
315-
<FilterGroupItem label="INPUT" filterKey="0">
308+
<FilterGroupItem label="INPUT" filterKey="0" hiddenInFilterBar={!savedVisibleFilters.includes('0')}>
316309
<Input placeholder="Placeholder" value="123123" data-testid="INPUT" />
317310
</FilterGroupItem>
318-
<FilterGroupItem label="SWITCH" filterKey="1">
311+
<FilterGroupItem label="SWITCH" filterKey="1" hiddenInFilterBar={!savedVisibleFilters.includes('1')}>
319312
<Switch checked={true} data-testid="SWITCH" />
320313
</FilterGroupItem>
321-
<FilterGroupItem label="SELECT" filterKey="2">
314+
<FilterGroupItem label="SELECT" filterKey="2" hiddenInFilterBar={!savedVisibleFilters.includes('2')}>
322315
<Select data-testid="SELECT">
323316
<Option selected={true}>Option 1</Option>
324317
<Option>Option 2</Option>
325318
<Option>Option 3</Option>
326319
<Option>Option 4</Option>
327320
</Select>
328321
</FilterGroupItem>
322+
<FilterGroupItem
323+
label="Required"
324+
filterKey="3"
325+
hiddenInFilterBar={!savedVisibleFilters.includes('3')}
326+
required
327+
>
328+
<Input placeholder="Placeholder" value="123123" data-testid="INPUT" />
329+
</FilterGroupItem>
329330
</FilterBar>
330331
<hr />
331332
<span>Selected: </span>
@@ -339,22 +340,28 @@ describe('FilterBar.cy.tsx', () => {
339340

340341
cy.mount(<TestComp />);
341342

342-
cy.findByTestId('selected', '0 1 2');
343+
cy.findByTestId('selected').should('have.text', '0 1 2 3');
343344
cy.get('[text="Filters"]').click({ force: true });
344345
cy.get('[ui5-checkbox]').first().click();
345-
cy.findByTestId('selected', '');
346+
cy.findByTestId('selected').should('have.text', '1 2 3');
346347
cy.get('[ui5-checkbox]').eq(1).click();
347-
cy.findByTestId('selected', '0');
348+
cy.findByTestId('selected').should('have.text', '2 3');
348349
cy.get('[ui5-checkbox]').first().click();
349350
cy.get('[ui5-checkbox]').first().click();
350351

351352
cy.findByText('OK').click();
352-
cy.findByTestId('saved', '');
353+
cy.findByTestId('saved').should('have.text', '2 3');
353354

354355
cy.get('[text="Filters"]').click({ force: true });
355356
cy.get('[ui5-checkbox]').first().click();
356357
cy.findByText('OK').click();
357-
cy.findByTestId('saved', '0 1 2');
358+
cy.findByTestId('saved').should('have.text', '2 3 0');
359+
360+
cy.get('[text="Filters"]').click({ force: true });
361+
cy.get('[name="clear-all"]').click();
362+
cy.findByTestId('selected').should('have.text', '3');
363+
cy.findByText('OK').click();
364+
cy.findByTestId('saved').should('have.text', '3');
358365
});
359366

360367
// todo selection, group + list view
@@ -473,25 +480,10 @@ describe('FilterBar.cy.tsx', () => {
473480
cy.get('[text="Filters"]').click({ force: true });
474481
cy.get('[accessible-name="Group View"]').click();
475482

476-
cy.get('[data-component-name="FilterBarDialogGroupTableHeaderRow"]')
477-
.shadow()
478-
.find('[ui5-table-header-cell]')
479-
.should('have.css', 'visibility', 'hidden');
480-
481483
cy.get('[data-component-name="FilterBarDialogTable"][data-is-grouped]')
482484
.shadow()
483485
.find('#no-data-row')
484486
.should('have.css', 'display', 'none');
485-
486-
cy.get('[data-component-name="FilterBarDialogTable"]')
487-
.shadow()
488-
.find('#table')
489-
.should('have.css', 'grid-template-columns', '44px 436px 160px');
490-
491-
cy.get('[data-component-name="FilterBarDialogPanelTable"]')
492-
.shadow()
493-
.find('#table')
494-
.should('have.css', 'grid-template-columns', '44px 436px 160px');
495487
});
496488

497489
it('fire FilterBar events', () => {

packages/main/src/components/FilterBar/FilterBar.stories.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Meta, StoryObj } from '@storybook/react';
2+
import { fn } from '@storybook/test';
23
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel.js';
34
import { useId, useReducer, useRef, useState } from 'react';
45
import { FlexBoxDirection } from '../../enums/index.js';
@@ -42,6 +43,7 @@ const meta = {
4243
</Title>
4344
),
4445
filterContainerWidth: '13.125rem',
46+
onFiltersDialogOpen: fn(),
4547
},
4648
argTypes: {
4749
activeFiltersCount: { control: 'number' },

packages/main/src/components/FilterBar/FilterBarDialog.module.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,7 @@
9797
.inactiveTable {
9898
pointer-events: none;
9999
}
100+
101+
.checkBoxSpacer {
102+
width: calc(var(--_ui5wcr-CheckBoxWidthHeight) - 11px);
103+
}

packages/main/src/components/FilterBar/FilterDialog.tsx

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,25 +73,12 @@ interface ForceRequiredObject {
7373
addCustomCSSWithScoping(
7474
'ui5-table',
7575
`
76-
:host([data-component-name="FilterBarDialogTable"][data-with-value="false"]) #table,
77-
:host([data-component-name="FilterBarDialogPanelTable"][data-with-value="false"]) #table {
78-
grid-template-columns: var(--_ui5wcr-CheckBoxWidthHeight) minmax(3rem, auto) minmax(3rem, 25%) !important;
79-
}
80-
:host([data-component-name="FilterBarDialogTable"][data-is-grouped]) #no-data-row {
76+
:host([data-component-name="FilterBarDialogTable"][data-is-grouped="true"]) #no-data-row {
8177
display: none;
8278
}
8379
`,
8480
);
8581

86-
addCustomCSSWithScoping(
87-
'ui5-table-header-row',
88-
`
89-
:host([data-component-name="FilterBarDialogGroupTableHeaderRow"]) :first-child {
90-
visibility: hidden;
91-
}
92-
`,
93-
);
94-
9582
type ActiveFilterAttributes = 'all' | 'visible' | 'active' | 'visibleAndActive' | 'mandatory';
9683
const getActiveFilters = (
9784
activeFilterAttribute: ActiveFilterAttributes,
@@ -609,20 +596,21 @@ export const FilterDialog = (props: FilterDialogPropTypes) => {
609596
ref={tableRef}
610597
className={!isListView && classNames.inactiveTable}
611598
data-component-name="FilterBarDialogTable"
612-
data-is-grouped={!isListView}
599+
data-is-grouped={!isListView ? 'true' : 'false'}
613600
data-with-value={`${showValues}`}
614601
noData={!isListView ? <span /> : undefined}
615602
tabIndex={!isListView ? -1 : undefined}
616603
features={
617-
<>
618-
<TableSelectionMulti onChange={handleCheckBoxChange} selected={selected} />
619-
</>
604+
<TableSelectionMulti onChange={handleCheckBoxChange} selected={selected} headerSelector="ClearAll" />
620605
}
621606
headerRow={
622607
<TableHeaderRow
623608
data-component-name={!isListView ? 'FilterBarDialogGroupTableHeaderRow' : 'FilterBarDialogTableHeaderRow'}
624609
>
625-
<TableHeaderCell>{filterText}</TableHeaderCell>
610+
<TableHeaderCell>
611+
{!isListView && <div className={classNames.checkBoxSpacer} />}
612+
{filterText}
613+
</TableHeaderCell>
626614
{!showValues && <TableHeaderCell className={classNames.tHactive}>{activeText}</TableHeaderCell>}
627615
</TableHeaderRow>
628616
}

0 commit comments

Comments
 (0)