Skip to content

Commit f69beec

Browse files
committed
feat: add "expand all" option to table header
HMS-10728 Adds "expand all" option to the tables that have expandable rows -- Advisoreis and SystemAdvisories.
1 parent 018be3c commit f69beec

13 files changed

Lines changed: 227 additions & 101 deletions

File tree

src/PresentationalComponents/TableView/TableView.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import PropTypes from 'prop-types';
2+
import React, { useState, useMemo } from 'react';
13
import { TableVariant } from '@patternfly/react-table';
24
import { Table, TableBody, TableHeader } from '@patternfly/react-table/deprecated';
35
import { PrimaryToolbar } from '@redhat-cloud-services/frontend-components/PrimaryToolbar';
46
import { SkeletonTable } from '@redhat-cloud-services/frontend-components/SkeletonTable';
5-
import PropTypes from 'prop-types';
6-
import React from 'react';
77
import AsyncRemediationButton from '../../SmartComponents/Remediation/AsyncRemediationButton';
88
import { arrayFromObj, buildActiveFilterConfig, convertLimitOffset } from '../../Utilities/Helpers';
99
import { useRemoveFilter, useBulkSelectConfig } from '../../Utilities/hooks';
@@ -39,7 +39,7 @@ const TableView = ({
3939
actionsToggle,
4040
hasColumnManagement,
4141
}) => {
42-
const [page, perPage] = React.useMemo(
42+
const [page, perPage] = useMemo(
4343
() => convertLimitOffset(metadata.limit, metadata.offset),
4444
[metadata.limit, metadata.offset],
4545
);
@@ -48,13 +48,13 @@ const TableView = ({
4848
const selectedCount = selectedRows && arrayFromObj(selectedRows).length;
4949
const { code, hasError, isLoading } = status;
5050
const bulkSelectConfig = useBulkSelectConfig(selectedCount, onSelect, metadata, rows, onCollapse);
51-
const activeFiltersConfig = React.useMemo(
51+
const activeFiltersConfig = useMemo(
5252
() => buildActiveFilterConfig(filter, search, deleteFilters, searchChipLabel, defaultFilters),
5353
[defaultFilters, deleteFilters, filter, search, searchChipLabel],
5454
);
5555

56-
const [isColumnMgmtModalOpen, setColumnMgmtModalOpen] = React.useState(false);
57-
const [appliedColumns, setAppliedColumns] = React.useState(columns);
56+
const [isColumnMgmtModalOpen, setColumnMgmtModalOpen] = useState(false);
57+
const [appliedColumns, setAppliedColumns] = useState(columns);
5858

5959
const shownColumns = hasColumnManagement
6060
? appliedColumns?.filter((column) => column.isShown)
@@ -70,7 +70,7 @@ const TableView = ({
7070
: rows;
7171

7272
return (
73-
<React.Fragment>
73+
<>
7474
<ColumnManagementModal
7575
appliedColumns={appliedColumns}
7676
applyColumns={(newColumns) => setAppliedColumns(newColumns)}
@@ -85,7 +85,7 @@ const TableView = ({
8585
metadata={metadata}
8686
/>
8787
) : (
88-
<React.Fragment>
88+
<>
8989
<PrimaryToolbar
9090
pagination={
9191
isLoading ? (
@@ -163,6 +163,7 @@ const TableView = ({
163163
variant={compact && TableVariant.compact}
164164
actions={actionsConfig}
165165
actionsToggle={actionsToggle}
166+
canCollapseAll
166167
>
167168
<TableHeader />
168169
<TableBody />
@@ -177,9 +178,9 @@ const TableView = ({
177178
onPerPageSelect={onPerPageSelect}
178179
paginationOUIA={`bottom-${paginationOUIA}`}
179180
/>
180-
</React.Fragment>
181+
</>
181182
)}
182-
</React.Fragment>
183+
</>
183184
);
184185
};
185186

src/PresentationalComponents/TableView/__snapshots__/TableView.test.js.snap

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ exports[`TableView Should open remediation modal 1`] = `
354354
aria-label="Go to previous page"
355355
class="pf-v6-c-button pf-m-plain"
356356
data-action="previous"
357-
data-ouia-component-id="OUIA-Generated-Button-plain-25"
357+
data-ouia-component-id="OUIA-Generated-Button-plain-27"
358358
data-ouia-component-type="PF6/Button"
359359
data-ouia-safe="true"
360360
type="button"
@@ -385,7 +385,7 @@ exports[`TableView Should open remediation modal 1`] = `
385385
aria-label="Go to next page"
386386
class="pf-v6-c-button pf-m-plain"
387387
data-action="next"
388-
data-ouia-component-id="OUIA-Generated-Button-plain-26"
388+
data-ouia-component-id="OUIA-Generated-Button-plain-28"
389389
data-ouia-component-type="PF6/Button"
390390
data-ouia-safe="true"
391391
type="button"
@@ -516,7 +516,7 @@ exports[`TableView Should open remediation modal 1`] = `
516516
aria-label="Go to first page"
517517
class="pf-v6-c-button pf-m-plain"
518518
data-action="first"
519-
data-ouia-component-id="OUIA-Generated-Button-plain-27"
519+
data-ouia-component-id="OUIA-Generated-Button-plain-29"
520520
data-ouia-component-type="PF6/Button"
521521
data-ouia-safe="true"
522522
type="button"
@@ -547,7 +547,7 @@ exports[`TableView Should open remediation modal 1`] = `
547547
aria-label="Go to previous page"
548548
class="pf-v6-c-button pf-m-plain"
549549
data-action="previous"
550-
data-ouia-component-id="OUIA-Generated-Button-plain-28"
550+
data-ouia-component-id="OUIA-Generated-Button-plain-30"
551551
data-ouia-component-type="PF6/Button"
552552
data-ouia-safe="true"
553553
type="button"
@@ -597,7 +597,7 @@ exports[`TableView Should open remediation modal 1`] = `
597597
aria-label="Go to next page"
598598
class="pf-v6-c-button pf-m-plain"
599599
data-action="next"
600-
data-ouia-component-id="OUIA-Generated-Button-plain-29"
600+
data-ouia-component-id="OUIA-Generated-Button-plain-31"
601601
data-ouia-component-type="PF6/Button"
602602
data-ouia-safe="true"
603603
type="button"
@@ -628,7 +628,7 @@ exports[`TableView Should open remediation modal 1`] = `
628628
aria-label="Go to last page"
629629
class="pf-v6-c-button pf-m-plain"
630630
data-action="last"
631-
data-ouia-component-id="OUIA-Generated-Button-plain-30"
631+
data-ouia-component-id="OUIA-Generated-Button-plain-32"
632632
data-ouia-component-type="PF6/Button"
633633
data-ouia-safe="true"
634634
type="button"
@@ -1686,7 +1686,7 @@ exports[`TableView TableView 2`] = `
16861686
aria-label="Go to previous page"
16871687
class="pf-v6-c-button pf-m-plain"
16881688
data-action="previous"
1689-
data-ouia-component-id="OUIA-Generated-Button-plain-19"
1689+
data-ouia-component-id="OUIA-Generated-Button-plain-21"
16901690
data-ouia-component-type="PF6/Button"
16911691
data-ouia-safe="true"
16921692
type="button"
@@ -1717,7 +1717,7 @@ exports[`TableView TableView 2`] = `
17171717
aria-label="Go to next page"
17181718
class="pf-v6-c-button pf-m-plain"
17191719
data-action="next"
1720-
data-ouia-component-id="OUIA-Generated-Button-plain-20"
1720+
data-ouia-component-id="OUIA-Generated-Button-plain-22"
17211721
data-ouia-component-type="PF6/Button"
17221722
data-ouia-safe="true"
17231723
type="button"
@@ -1848,7 +1848,7 @@ exports[`TableView TableView 2`] = `
18481848
aria-label="Go to first page"
18491849
class="pf-v6-c-button pf-m-plain"
18501850
data-action="first"
1851-
data-ouia-component-id="OUIA-Generated-Button-plain-21"
1851+
data-ouia-component-id="OUIA-Generated-Button-plain-23"
18521852
data-ouia-component-type="PF6/Button"
18531853
data-ouia-safe="true"
18541854
type="button"
@@ -1879,7 +1879,7 @@ exports[`TableView TableView 2`] = `
18791879
aria-label="Go to previous page"
18801880
class="pf-v6-c-button pf-m-plain"
18811881
data-action="previous"
1882-
data-ouia-component-id="OUIA-Generated-Button-plain-22"
1882+
data-ouia-component-id="OUIA-Generated-Button-plain-24"
18831883
data-ouia-component-type="PF6/Button"
18841884
data-ouia-safe="true"
18851885
type="button"
@@ -1929,7 +1929,7 @@ exports[`TableView TableView 2`] = `
19291929
aria-label="Go to next page"
19301930
class="pf-v6-c-button pf-m-plain"
19311931
data-action="next"
1932-
data-ouia-component-id="OUIA-Generated-Button-plain-23"
1932+
data-ouia-component-id="OUIA-Generated-Button-plain-25"
19331933
data-ouia-component-type="PF6/Button"
19341934
data-ouia-safe="true"
19351935
type="button"
@@ -1960,7 +1960,7 @@ exports[`TableView TableView 2`] = `
19601960
aria-label="Go to last page"
19611961
class="pf-v6-c-button pf-m-plain"
19621962
data-action="last"
1963-
data-ouia-component-id="OUIA-Generated-Button-plain-24"
1963+
data-ouia-component-id="OUIA-Generated-Button-plain-26"
19641964
data-ouia-component-type="PF6/Button"
19651965
data-ouia-safe="true"
19661966
type="button"
@@ -2439,12 +2439,46 @@ exports[`TableView test table props TableView 1`] = `
24392439
data-ouia-safe="true"
24402440
>
24412441
<th
2442-
class="pf-v6-c-table__th"
2442+
class="pf-v6-c-table__th pf-v6-c-table__toggle"
24432443
data-key="0"
24442444
data-label=""
24452445
scope=""
24462446
tabindex="-1"
2447-
/>
2447+
>
2448+
<button
2449+
aria-expanded="false"
2450+
aria-label="Expand all rows"
2451+
aria-labelledby="simple-node-1 expandable-toggle-1"
2452+
class="pf-v6-c-button pf-m-plain"
2453+
data-ouia-component-id="OUIA-Generated-Button-plain-9"
2454+
data-ouia-component-type="PF6/Button"
2455+
data-ouia-safe="true"
2456+
id="expandable-toggle-1"
2457+
type="button"
2458+
>
2459+
<span
2460+
class="pf-v6-c-button__icon"
2461+
>
2462+
<div
2463+
class="pf-v6-c-table__toggle-icon"
2464+
>
2465+
<svg
2466+
aria-hidden="true"
2467+
class="pf-v6-svg"
2468+
fill="currentColor"
2469+
height="1em"
2470+
role="img"
2471+
viewBox="0 0 320 512"
2472+
width="1em"
2473+
>
2474+
<path
2475+
d="M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z"
2476+
/>
2477+
</svg>
2478+
</div>
2479+
</span>
2480+
</button>
2481+
</th>
24482482
<th
24492483
class="pf-v6-c-table__th"
24502484
data-key="1"
@@ -2533,7 +2567,7 @@ exports[`TableView test table props TableView 1`] = `
25332567
aria-label="Go to first page"
25342568
class="pf-v6-c-button pf-m-plain"
25352569
data-action="first"
2536-
data-ouia-component-id="OUIA-Generated-Button-plain-9"
2570+
data-ouia-component-id="OUIA-Generated-Button-plain-10"
25372571
data-ouia-component-type="PF6/Button"
25382572
data-ouia-safe="true"
25392573
type="button"
@@ -2564,7 +2598,7 @@ exports[`TableView test table props TableView 1`] = `
25642598
aria-label="Go to previous page"
25652599
class="pf-v6-c-button pf-m-plain"
25662600
data-action="previous"
2567-
data-ouia-component-id="OUIA-Generated-Button-plain-10"
2601+
data-ouia-component-id="OUIA-Generated-Button-plain-11"
25682602
data-ouia-component-type="PF6/Button"
25692603
data-ouia-safe="true"
25702604
type="button"
@@ -2619,7 +2653,7 @@ exports[`TableView test table props TableView 1`] = `
26192653
aria-label="Go to next page"
26202654
class="pf-v6-c-button pf-m-plain"
26212655
data-action="next"
2622-
data-ouia-component-id="OUIA-Generated-Button-plain-11"
2656+
data-ouia-component-id="OUIA-Generated-Button-plain-12"
26232657
data-ouia-component-type="PF6/Button"
26242658
data-ouia-safe="true"
26252659
type="button"
@@ -2650,7 +2684,7 @@ exports[`TableView test table props TableView 1`] = `
26502684
aria-label="Go to last page"
26512685
class="pf-v6-c-button pf-m-plain"
26522686
data-action="last"
2653-
data-ouia-component-id="OUIA-Generated-Button-plain-12"
2687+
data-ouia-component-id="OUIA-Generated-Button-plain-13"
26542688
data-ouia-component-type="PF6/Button"
26552689
data-ouia-safe="true"
26562690
type="button"

src/SmartComponents/Advisories/Advisories.js

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Main } from '@redhat-cloud-services/frontend-components/Main';
2-
import React, { Fragment, useEffect, useLayoutEffect } from 'react';
2+
import React, { useEffect, useState, useMemo, useCallback, useLayoutEffect } from 'react';
33
import { useDispatch, useSelector } from 'react-redux';
44
import messages from '../../Messages';
55
import publishDateFilter from '../../PresentationalComponents/Filters/PublishDateFilter';
@@ -11,7 +11,7 @@ import TableView from '../../PresentationalComponents/TableView/TableView';
1111
import { advisoriesColumns } from '../../PresentationalComponents/TableView/TableViewAssets';
1212
import {
1313
changeAdvisoryListParams,
14-
expandAdvisoryRow,
14+
expandAdvisoryRows,
1515
fetchApplicableAdvisories,
1616
selectAdvisoryRow,
1717
} from '../../store/Actions/Actions';
@@ -54,7 +54,7 @@ const Advisories = () => {
5454
}, [chrome]);
5555

5656
const dispatch = useDispatch();
57-
const [firstMount, setFirstMount] = React.useState(true);
57+
const [firstMount, setFirstMount] = useState(true);
5858
const advisories = useSelector(({ AdvisoryListStore }) => AdvisoryListStore.rows);
5959
const expandedRows = useSelector(({ AdvisoryListStore }) => AdvisoryListStore.expandedRows);
6060
const queryParams = useSelector(({ AdvisoryListStore }) => AdvisoryListStore?.queryParams);
@@ -63,12 +63,12 @@ const Advisories = () => {
6363
const status = useSelector(({ AdvisoryListStore }) => AdvisoryListStore.status);
6464
const areAllSelected = useSelector(({ SystemsStore }) => SystemsStore?.areAllSelected);
6565

66-
const rows = React.useMemo(
66+
const rows = useMemo(
6767
() => createAdvisoriesRows(advisories, expandedRows, selectedRows),
6868
[advisories, expandedRows, selectedRows],
6969
);
7070

71-
const [isRemediationLoading, setRemediationLoading] = React.useState(false);
71+
const [isRemediationLoading, setRemediationLoading] = useState(false);
7272

7373
useLayoutEffect(() => {
7474
if (firstMount) {
@@ -80,13 +80,28 @@ const Advisories = () => {
8080
}
8181
}, [JSON.stringify(queryParams), firstMount]);
8282

83-
const onCollapse = React.useCallback((_, rowId, value) =>
84-
dispatch(
85-
expandAdvisoryRow({
86-
rowId: getRowIdByIndexExpandable(advisories, rowId),
87-
value,
88-
}),
89-
),
83+
const onCollapse = useCallback(
84+
(_, rowId, value) => {
85+
let changes = [];
86+
if (rowId === undefined) {
87+
// toggle all
88+
changes = advisories.map((advisory) => ({
89+
rowId: advisory.id,
90+
value,
91+
}));
92+
} else {
93+
// toggle single
94+
changes = [
95+
{
96+
rowId: getRowIdByIndexExpandable(advisories, rowId),
97+
value,
98+
},
99+
];
100+
}
101+
102+
return dispatch(expandAdvisoryRows(changes));
103+
},
104+
[JSON.stringify(advisories)],
90105
);
91106

92107
const onSelect = useOnSelect(rows, selectedRows, {
@@ -97,10 +112,7 @@ const Advisories = () => {
97112
});
98113

99114
const onSort = useSortColumn(advisoriesColumns, apply, 2);
100-
const sortBy = React.useMemo(
101-
() => createSortBy(advisoriesColumns, metadata.sort, 2),
102-
[metadata.sort],
103-
);
115+
const sortBy = useMemo(() => createSortBy(advisoriesColumns, metadata.sort, 2), [metadata.sort]);
104116

105117
const onExport = useOnExport(
106118
'advisories',
@@ -127,10 +139,10 @@ const Advisories = () => {
127139
);
128140

129141
return (
130-
<React.Fragment>
142+
<>
131143
<Header
132144
title={
133-
<Fragment>
145+
<>
134146
{intl.formatMessage(messages.titlesPatchAdvisories)}
135147
<Popover
136148
headerContent='About advisories'
@@ -164,7 +176,7 @@ const Advisories = () => {
164176
/>
165177
</Icon>
166178
</Popover>
167-
</Fragment>
179+
</>
168180
}
169181
headerOUIA='advisories'
170182
/>
@@ -207,7 +219,7 @@ const Advisories = () => {
207219
hasColumnManagement
208220
/>
209221
</Main>
210-
</React.Fragment>
222+
</>
211223
);
212224
};
213225

0 commit comments

Comments
 (0)