From 503cffcd3cf7eff61cf7f1d3ed6209ce9b4d72da Mon Sep 17 00:00:00 2001
From: Martin Michalik <62351699+xmicha82@users.noreply.github.com>
Date: Tue, 17 Dec 2024 13:22:33 +0100
Subject: [PATCH] fix(RHINENG-11976): Fix table loading states (#843)
Fixes https://issues.redhat.com/browse/RHINENG-11976.
---
cypress/utils/table.js | 2 +-
package-lock.json | 45 +++----
package.json | 1 +
.../AffectedClustersTable.cy.js | 6 +-
.../AffectedClustersTable.js | 116 +++++++++---------
.../ClusterRules/ClusterRules.cy.js | 10 +-
src/Components/ClusterRules/ClusterRules.js | 107 ++++++++--------
.../ClustersListTable/ClustersListTable.cy.js | 6 +-
.../ClustersListTable/ClustersListTable.js | 92 +++++++-------
src/Components/RecsListTable/RecsListTable.js | 93 +++++++-------
src/Components/WorkloadRules/WorkloadRules.js | 108 ++++++++--------
.../WorkloadsListTable/WorkloadsListTable.js | 97 ++++++++-------
12 files changed, 357 insertions(+), 326 deletions(-)
diff --git a/cypress/utils/table.js b/cypress/utils/table.js
index ea666b72..a403b8ec 100644
--- a/cypress/utils/table.js
+++ b/cypress/utils/table.js
@@ -176,9 +176,9 @@ function checkSorting(
}
});
} else {
+ cy.get(header).find('button').click();
cy.get(header)
.find('button')
- .click()
.click() // TODO dblclick fails for unknown reason in RecsListTable when sorting by Clusters
.then(() => {
if (validateURL) {
diff --git a/package-lock.json b/package-lock.json
index bda90f29..79366cfd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "1.17.2",
"hasInstallScript": true,
"dependencies": {
+ "@patternfly/react-component-groups": "^5.4.0",
"@patternfly/react-core": "^5.4.8",
"@patternfly/react-icons": "^5.4.2",
"@patternfly/react-table": "^5.4.5",
@@ -4049,14 +4050,14 @@
"dev": true
},
"node_modules/@patternfly/react-component-groups": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@patternfly/react-component-groups/-/react-component-groups-5.0.0.tgz",
- "integrity": "sha512-ON4h4SKOCgLRgZLd/FOj44wU19ytvFPjflxPSYU0KfCWlVgb6F62+l316/Va/tzDo/AwZypnUxOEksXDv+C2+A==",
- "dependencies": {
- "@patternfly/react-core": "^5.1.1",
- "@patternfly/react-icons": "^5.1.1",
- "@patternfly/react-table": "^5.1.1",
- "clsx": "^2.0.0",
+ "version": "5.5.5",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-component-groups/-/react-component-groups-5.5.5.tgz",
+ "integrity": "sha512-Cgp1XxyBWnEDKAQsP+B7A4wlz6Bcp0bjwSMamdOiCR4GALtpBXXGrv6daAomoVCkL9l3zibcAfm/o9d9XBE9Ag==",
+ "dependencies": {
+ "@patternfly/react-core": "^5.4.1",
+ "@patternfly/react-icons": "^5.4.0",
+ "@patternfly/react-table": "^5.4.1",
+ "clsx": "^2.1.1",
"react-jss": "^10.10.0"
},
"peerDependencies": {
@@ -9549,9 +9550,9 @@
}
},
"node_modules/clsx": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
- "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"engines": {
"node": ">=6"
}
@@ -32120,14 +32121,14 @@
"dev": true
},
"@patternfly/react-component-groups": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@patternfly/react-component-groups/-/react-component-groups-5.0.0.tgz",
- "integrity": "sha512-ON4h4SKOCgLRgZLd/FOj44wU19ytvFPjflxPSYU0KfCWlVgb6F62+l316/Va/tzDo/AwZypnUxOEksXDv+C2+A==",
- "requires": {
- "@patternfly/react-core": "^5.1.1",
- "@patternfly/react-icons": "^5.1.1",
- "@patternfly/react-table": "^5.1.1",
- "clsx": "^2.0.0",
+ "version": "5.5.5",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-component-groups/-/react-component-groups-5.5.5.tgz",
+ "integrity": "sha512-Cgp1XxyBWnEDKAQsP+B7A4wlz6Bcp0bjwSMamdOiCR4GALtpBXXGrv6daAomoVCkL9l3zibcAfm/o9d9XBE9Ag==",
+ "requires": {
+ "@patternfly/react-core": "^5.4.1",
+ "@patternfly/react-icons": "^5.4.0",
+ "@patternfly/react-table": "^5.4.1",
+ "clsx": "^2.1.1",
"react-jss": "^10.10.0"
}
},
@@ -36295,9 +36296,9 @@
}
},
"clsx": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
- "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg=="
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="
},
"co": {
"version": "4.6.0",
diff --git a/package.json b/package.json
index a4846f54..f4a2c136 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"postinstall": "ts-patch install"
},
"dependencies": {
+ "@patternfly/react-component-groups": "^5.4.0",
"@patternfly/react-core": "^5.4.8",
"@patternfly/react-icons": "^5.4.2",
"@patternfly/react-table": "^5.4.5",
diff --git a/src/Components/AffectedClustersTable/AffectedClustersTable.cy.js b/src/Components/AffectedClustersTable/AffectedClustersTable.cy.js
index 346884f7..45ed0421 100644
--- a/src/Components/AffectedClustersTable/AffectedClustersTable.cy.js
+++ b/src/Components/AffectedClustersTable/AffectedClustersTable.cy.js
@@ -163,13 +163,14 @@ describe('non-empty successful affected clusters table', () => {
});
it('renders table header', () => {
+ cy.get('[data-ouia-component-id=SkeletonTable-tr-0]').should('not.exist');
checkTableHeaders(TABLE_HEADERS);
});
it('rows show cluster names instead uuids when available', () => {
const names = _.map(data, 'name');
// Wait for skeleton to disappear
- cy.get('[data-ouia-component-id=loading-skeleton]').should('not.exist');
+ cy.get('[data-ouia-component-id=SkeletonTable-tr-0]').should('not.exist');
cy.get(`td[data-label="Name"]`)
.then(($els) => {
return _.map(Cypress.$.makeArray($els), 'innerText');
@@ -178,7 +179,7 @@ describe('non-empty successful affected clusters table', () => {
});
it('names of rows are links', () => {
- cy.get('[data-ouia-component-id=loading-skeleton]').should('not.exist');
+ cy.get('[data-ouia-component-id=SkeletonTable-tr-0]').should('not.exist');
cy.get(TABLE)
.find(TABLE_ROW)
.each(($el, index) => {
@@ -641,6 +642,7 @@ describe('empty successful affected clusters table', () => {
});
it('renders table headers', () => {
+ cy.get('[data-ouia-component-id=SkeletonTable-tr-0]').should('not.exist');
checkTableHeaders(TABLE_HEADERS);
});
});
diff --git a/src/Components/AffectedClustersTable/AffectedClustersTable.js b/src/Components/AffectedClustersTable/AffectedClustersTable.js
index 534db44c..451ac259 100644
--- a/src/Components/AffectedClustersTable/AffectedClustersTable.js
+++ b/src/Components/AffectedClustersTable/AffectedClustersTable.js
@@ -30,7 +30,6 @@ import {
AFFECTED_CLUSTERS_VERSION_CELL,
FILTER_CATEGORIES,
} from '../../AppConstants';
-import Loading from '../Loading/Loading';
import {
AFFECTED_CLUSTERS_INITIAL_STATE,
resetFilters,
@@ -45,6 +44,7 @@ import {
addFilterParam as _addFilterParam,
} from '../Common/Tables';
import { BASE_PATH } from '../../Routes';
+import { SkeletonTable } from '@patternfly/react-component-groups';
const AffectedClustersTable = ({ query, rule, afterDisableFn }) => {
const intl = useIntl();
@@ -97,7 +97,7 @@ const AffectedClustersTable = ({ query, rule, afterDisableFn }) => {
type: conditionalFilterType.text,
filterValues: {
id: 'name-filter',
- key: 'name-filter',
+ // key: 'name-filter',
onChange: (event, value) => addFilterParam('text', value),
value: filters.text,
},
@@ -108,7 +108,7 @@ const AffectedClustersTable = ({ query, rule, afterDisableFn }) => {
type: conditionalFilterType.checkbox,
filterValues: {
id: 'version-filter',
- key: 'version-filter',
+ // key: 'version-filter',
onChange: (event, value) => addFilterParam('version', value),
value: filters.version,
items: uniqBy(
@@ -384,59 +384,65 @@ const AffectedClustersTable = ({ query, rule, afterDisableFn }) => {
],
}}
/>
-
c.title)}
+ isSelectable
+ variant="compact"
+ />
+ ) : (
+
+ ) : noInput ? (
+
+ ) : (
+
+ ),
},
- title: errorState ? (
-
- ) : loadingState ? (
-
- ) : noInput ? (
-
- ) : (
-
- ),
- },
- ],
- },
- ]
- ) : successState ? (
- displayedRows
- ) : (
-
- )
- }
- sortBy={{
- index: filters.sortIndex,
- direction: filters.sortDirection,
- }}
- onSort={onSort}
- canSelectAll={false}
- onSelect={displayedRows?.length > 0 ? onSelect : undefined}
- actions={[
- {
- title: 'Disable recommendation for cluster',
- onClick: (event, rowIndex) =>
- handleModalToggle(true, filteredRows[rowIndex].id),
- },
- ]}
- >
-
-
-
+ ],
+ },
+ ]
+ ) : successState ? (
+ displayedRows
+ ) : (
+
+ )
+ }
+ sortBy={{
+ index: filters.sortIndex,
+ direction: filters.sortDirection,
+ }}
+ onSort={onSort}
+ canSelectAll={false}
+ onSelect={displayedRows?.length > 0 ? onSelect : undefined}
+ actions={[
+ {
+ title: 'Disable recommendation for cluster',
+ onClick: (event, rowIndex) =>
+ handleModalToggle(true, filteredRows[rowIndex].id),
+ },
+ ]}
+ >
+
+
+
+ )}
{
it('expand one row then sort', () => {
cy.get('#expandable-toggle2').click();
- cy.get(TABLE)
- .find('th[data-label=Description]')
- .find('button')
- .click()
- .click();
+ cy.get(TABLE).find('th[data-label=Description]').find('button').click();
+ cy.get(TABLE).find('th[data-label=Description]').find('button').click();
cy.get(EXPANDABLES).should('have.length', 2);
});
@@ -413,7 +410,8 @@ describe('cluster rules table testing the first query parameter', () => {
if (order === 'ascending') {
cy.get(header).find('button').click();
} else {
- cy.get(header).find('button').click().click();
+ cy.get(header).find('button').click();
+ cy.get(header).find('button').click();
}
let sortedDescriptions = _.map(
_.orderBy(
diff --git a/src/Components/ClusterRules/ClusterRules.js b/src/Components/ClusterRules/ClusterRules.js
index 59c97a35..8916f065 100644
--- a/src/Components/ClusterRules/ClusterRules.js
+++ b/src/Components/ClusterRules/ClusterRules.js
@@ -15,6 +15,7 @@ import {
TableHeader,
} from '@patternfly/react-table/deprecated';
import { Tooltip } from '@patternfly/react-core';
+import { SkeletonTable } from '@patternfly/react-component-groups';
import { TooltipPosition } from '@patternfly/react-core/dist/js/components/Tooltip';
import PrimaryToolbar from '@redhat-cloud-services/frontend-components/PrimaryToolbar';
@@ -50,7 +51,6 @@ import {
updateClusterRulesFilters,
} from '../../Services/Filters';
import { getErrorKey, getPluginName } from '../../Utilities/Rule';
-import Loading from '../Loading/Loading';
import { useGetClusterByIdQuery } from '../../Services/SmartProxy';
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
@@ -456,57 +456,62 @@ const ClusterRules = () => {
: activeFiltersConfig
}
/>
- // no Insights results received yet
+ {loadingState ? (
+ c.title)}
+ variant="compact"
+ />
+ ) : (
+ // no Insights results received yet
+ ) : (
+ // any other problem
+ )
+ ) : noInput ? (
+
) : (
- // any other problem
- )
- ) : loadingState ? (
-
- ) : noInput ? (
-
- ) : (
-
- ),
- },
- ],
- },
- ]
- ) : successState ? (
- displayedRows
- ) : (
-
- )
- }
- cells={CLUSTER_RULES_COLUMNS}
- sortBy={{
- index: filters.sortIndex,
- direction: filters.sortDirection,
- }}
- onSort={onSort}
- variant={TableVariant.compact}
- isStickyHeader
- canCollapseAll
- >
-
-
-
+
+ ),
+ },
+ ],
+ },
+ ]
+ ) : successState ? (
+ displayedRows
+ ) : (
+
+ )
+ }
+ cells={CLUSTER_RULES_COLUMNS}
+ sortBy={{
+ index: filters.sortIndex,
+ direction: filters.sortDirection,
+ }}
+ onSort={onSort}
+ variant={TableVariant.compact}
+ isStickyHeader
+ canCollapseAll
+ >
+
+
+
+ )}
);
};
diff --git a/src/Components/ClustersListTable/ClustersListTable.cy.js b/src/Components/ClustersListTable/ClustersListTable.cy.js
index b3f8afd1..1faa93bd 100644
--- a/src/Components/ClustersListTable/ClustersListTable.cy.js
+++ b/src/Components/ClustersListTable/ClustersListTable.cy.js
@@ -581,7 +581,7 @@ describe('clusters list table', () => {
it('rows show cluster names instead uuids when available', () => {
const names = _.map(data, 'name');
- cy.get('[data-ouia-component-id=loading-skeleton]').should('not.exist');
+ cy.get('[data-ouia-component-id=SkeletonTable-tr-0]').should('not.exist');
cy.get(`td[data-label="Name"]`)
.then(($els) => {
return _.map(Cypress.$.makeArray($els), 'innerText');
@@ -590,7 +590,7 @@ describe('clusters list table', () => {
});
it('names of rows are links', () => {
- cy.get('[data-ouia-component-id=loading-skeleton]').should('not.exist');
+ cy.get('[data-ouia-component-id=SkeletonTable-tr-0]').should('not.exist');
cy.get(TBODY)
.children()
.each(($el, index) => {
@@ -604,7 +604,7 @@ describe('clusters list table', () => {
});
it('total risk hits are mapped correctly', () => {
- cy.get('[data-ouia-component-id=loading-skeleton]').should('not.exist');
+ cy.get('[data-ouia-component-id=SkeletonTable-tr-0]').should('not.exist');
cy.get('table')
.find(TBODY)
.find(ROW)
diff --git a/src/Components/ClustersListTable/ClustersListTable.js b/src/Components/ClustersListTable/ClustersListTable.js
index 067ade85..a381e6e5 100644
--- a/src/Components/ClustersListTable/ClustersListTable.js
+++ b/src/Components/ClustersListTable/ClustersListTable.js
@@ -15,6 +15,7 @@ import {
TableHeader,
} from '@patternfly/react-table/deprecated';
import { Label, Pagination, Tooltip } from '@patternfly/react-core';
+import { SkeletonTable } from '@patternfly/react-component-groups';
import { PaginationVariant } from '@patternfly/react-core/dist/js/components/Pagination/Pagination';
import PrimaryToolbar from '@redhat-cloud-services/frontend-components/PrimaryToolbar/PrimaryToolbar';
import DateFormat from '@redhat-cloud-services/frontend-components/DateFormat';
@@ -44,7 +45,7 @@ import {
compareSemVer,
toValidSemVer,
} from '../Common/Tables';
-import Loading from '../Loading/Loading';
+// import Loading from '../Loading/Loading';
import messages from '../../Messages';
import {
ErrorState,
@@ -414,49 +415,54 @@ const ClustersListTable = ({
filterConfig={{ items: filterConfigItems }}
activeFiltersConfig={activeFiltersConfig}
/>
- c.title)}
+ variant="compact"
+ />
+ ) : (
+
+ ) : (
+
+ ),
},
- title: errorState ? (
-
- ) : loadingState ? (
-
- ) : (
-
- ),
- },
- ],
- },
- ]
- ) : successState ? (
- displayedRows
- ) : (
-
- )
- }
- sortBy={{
- index: filters.sortIndex,
- direction: filters.sortDirection,
- }}
- onSort={onSort}
- isStickyHeader
- >
-
-
-
+ ],
+ },
+ ]
+ ) : successState ? (
+ displayedRows
+ ) : (
+
+ )
+ }
+ sortBy={{
+ index: filters.sortIndex,
+ direction: filters.sortDirection,
+ }}
+ onSort={onSort}
+ isStickyHeader
+ >
+
+
+
+ )}
{
}}
activeFiltersConfig={errorState ? undefined : activeFiltersConfig}
/>
- c.title)}
+ variant="compact"
+ />
+ ) : (
+ : ,
},
- title: errorState ? (
-
- ) : loadingState ? (
-
- ) : (
-
- ),
- },
- ],
- },
- ]
- ) : successState ? (
- displayedRows
- ) : (
-
- )
- }
- onCollapse={handleOnCollapse} // TODO: set undefined when there is an empty state
- sortBy={{
- index: filters.sortIndex,
- direction: filters.sortDirection,
- }}
- onSort={onSort}
- actionResolver={actionResolver}
- isStickyHeader
- ouiaSafe={!loadingState}
- canCollapseAll
- >
-
-
-
+ ],
+ },
+ ]
+ ) : successState ? (
+ displayedRows
+ ) : (
+
+ )
+ }
+ onCollapse={handleOnCollapse} // TODO: set undefined when there is an empty state
+ sortBy={{
+ index: filters.sortIndex,
+ direction: filters.sortDirection,
+ }}
+ onSort={onSort}
+ actionResolver={actionResolver}
+ isStickyHeader
+ ouiaSafe={!loadingState}
+ canCollapseAll
+ >
+
+
+
+ )}
{
const dispatch = useDispatch();
@@ -277,57 +277,63 @@ const WorkloadRules = ({ workload, namespaceName }) => {
: activeFiltersConfig
}
/>
-
+ {loadingState ? (
+ c.title)}
+ isExpandable
+ variant="compact"
+ />
+ ) : (
+
+ ) : (
+
+ )
+ ) : noMatchingRecs ? (
+
) : (
-
- )
- ) : loadingState ? (
-
- ) : noMatchingRecs ? (
-
- ) : (
-
- ),
- },
- ],
- },
- ]
- ) : successState ? (
- displayedRows
- ) : (
-
- )
- }
- variant={TableVariant.compact}
- isStickyHeader
- canCollapseAll
- sortBy={{
- index: filters.sortIndex,
- direction: filters.sortDirection,
- }}
- onSort={onSort}
- >
-
-
-
+
+ ),
+ },
+ ],
+ },
+ ]
+ ) : successState ? (
+ displayedRows
+ ) : (
+
+ )
+ }
+ variant={TableVariant.compact}
+ isStickyHeader
+ canCollapseAll
+ sortBy={{
+ index: filters.sortIndex,
+ direction: filters.sortDirection,
+ }}
+ onSort={onSort}
+ >
+
+
+
+ )}
);
};
diff --git a/src/Components/WorkloadsListTable/WorkloadsListTable.js b/src/Components/WorkloadsListTable/WorkloadsListTable.js
index a48c1e3c..58ec27a9 100644
--- a/src/Components/WorkloadsListTable/WorkloadsListTable.js
+++ b/src/Components/WorkloadsListTable/WorkloadsListTable.js
@@ -22,6 +22,7 @@ import DateFormat from '@redhat-cloud-services/frontend-components/DateFormat';
import { Link, useLocation } from 'react-router-dom';
import { BASE_PATH } from '../../Routes';
import { Pagination } from '@patternfly/react-core';
+import { SkeletonTable } from '@patternfly/react-component-groups';
import { conditionalFilterType } from '@redhat-cloud-services/frontend-components/ConditionalFilter/conditionalFilterConstants';
import { useDispatch, useSelector } from 'react-redux';
import {
@@ -44,7 +45,6 @@ import {
NoMatchingWorkloads,
NoDVOInstalledOrDataCollected,
} from '../MessageState/EmptyStates';
-import Loading from '../Loading/Loading';
import ShieldSet from '../ShieldSet';
import { filtersAreApplied } from '../../Utilities/Workloads';
@@ -212,7 +212,7 @@ const WorkloadsListTable = ({
label: 'Cluster name',
type: 'text',
filterValues: {
- key: 'cluster_name',
+ // key: 'cluster_name',
onChange: (_event, value) =>
updateFilters({ ...filters, offset: 0, cluster_name: value }),
value: filters.cluster_name,
@@ -223,7 +223,7 @@ const WorkloadsListTable = ({
label: 'Namespace name',
type: 'text',
filterValues: {
- key: 'namespace_name',
+ // key: 'namespace_name',
onChange: (_event, value) =>
updateFilters({ ...filters, offset: 0, namespace_name: value }),
value: filters.namespace_name,
@@ -236,7 +236,7 @@ const WorkloadsListTable = ({
id: WORKLOADS_TABLE_FILTER_CATEGORIES.severity.urlParam,
value: `checkbox-${WORKLOADS_TABLE_FILTER_CATEGORIES.severity.urlParam}`,
filterValues: {
- key: `${WORKLOADS_TABLE_FILTER_CATEGORIES.severity.urlParam}-filter`,
+ // key: `${WORKLOADS_TABLE_FILTER_CATEGORIES.severity.urlParam}-filter`,
onChange: (_event, value) => addFilterParam('severity', value),
value: filters.severity,
items: WORKLOADS_TABLE_FILTER_CATEGORIES.severity.values,
@@ -312,49 +312,54 @@ const WorkloadsListTable = ({
isError ? { showDeleteButton: false } : activeFiltersConfig
}
/>
- c.title)}
+ variant="compact"
+ />
+ ) : (
+
+ ) : (
+
+ ),
},
- title: errorState ? (
-
- ) : loadingState ? (
-
- ) : (
-
- ),
- },
- ],
- },
- ]
- ) : successState ? (
- rows
- ) : (
-
- )
- }
- isStickyHeader
- sortBy={{
- index: filters.sortIndex,
- direction: filters.sortDirection,
- }}
- onSort={onSort}
- >
-
-
-
+ ],
+ },
+ ]
+ ) : successState ? (
+ rows
+ ) : (
+
+ )
+ }
+ isStickyHeader
+ sortBy={{
+ index: filters.sortIndex,
+ direction: filters.sortDirection,
+ }}
+ onSort={onSort}
+ >
+
+
+
+ )}