diff --git a/ui/apps/platform/cypress/helpers/clusters.js b/ui/apps/platform/cypress/helpers/clusters.js index e8594ba79b1fa..5100fa139374b 100644 --- a/ui/apps/platform/cypress/helpers/clusters.js +++ b/ui/apps/platform/cypress/helpers/clusters.js @@ -123,3 +123,26 @@ export function visitClusterByNameWithFixtureMetadataDatetime( cy.get(selectors.clusterSidePanelHeading).contains(clusterName); }); } + +export function visitDashboardWithNoClusters() { + cy.intercept('POST', api.graphql('summary_counts'), { + body: { + data: { + clusterCount: 0, + nodeCount: 3, + violationCount: 20, + deploymentCount: 35, + imageCount: 31, + secretCount: 15, + }, + }, + }).as('summary_counts'); + cy.intercept('GET', api.clusters.list, { + clusters: [], + }).as('clusters'); + + // visitMainDashboard(); // with a count of 0 clusters, app should redirect to the clusters pages + cy.visit('/main/dashboard'); // with a count of 0 clusters, app should redirect to the clusters pages + + cy.wait(['@summary_counts', '@clusters']); +} diff --git a/ui/apps/platform/cypress/integration/clusters/clusters.test.js b/ui/apps/platform/cypress/integration/clusters/clusters.test.js index a16330aa09f86..aaed31e2fec42 100644 --- a/ui/apps/platform/cypress/integration/clusters/clusters.test.js +++ b/ui/apps/platform/cypress/integration/clusters/clusters.test.js @@ -1,6 +1,6 @@ import cloneDeep from 'lodash/cloneDeep'; -import { selectors } from '../../constants/ClustersPage'; +import { clustersUrl, selectors } from '../../constants/ClustersPage'; import { clusters as clustersApi } from '../../constants/apiEndpoints'; import withAuth from '../../helpers/basicAuth'; import { @@ -9,6 +9,7 @@ import { visitClustersWithFixtureMetadataDatetime, visitClusterByNameWithFixture, visitClusterByNameWithFixtureMetadataDatetime, + visitDashboardWithNoClusters, } from '../../helpers/clusters'; import { hasFeatureFlag } from '../../helpers/features'; @@ -48,6 +49,24 @@ describe('Clusters page', () => { }); }); }); + + describe('when no secured clusters are added yet (only applies to Cloud Service)', () => { + it('should should redirect to the Clusters page', () => { + visitDashboardWithNoClusters(); + + cy.url().should('contain', `${clustersUrl}`); + + cy.get(selectors.clustersListHeading); + + cy.get( + 'p:contains("You have successfully deployed a Red Hat Advanced Cluster Security platform.")' + ); + + cy.get('h2:contains("Configure the clusters you want to secure.")'); + + cy.get('a:contains("View instructions")'); + }); + }); }); describe('Cluster Certificate Expiration', () => { diff --git a/ui/apps/platform/src/Containers/Clusters/AddClusterPrompt.tsx b/ui/apps/platform/src/Containers/Clusters/AddClusterPrompt.tsx new file mode 100644 index 0000000000000..3d6e56df1ab7a --- /dev/null +++ b/ui/apps/platform/src/Containers/Clusters/AddClusterPrompt.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { + Alert, + AlertVariant, + Button, + ButtonVariant, + Flex, + FlexItem, + Text, + TextContent, + TextVariants, +} from '@patternfly/react-core'; + +import SecurityFullColorPink from 'images/Security_FullColor_Pink.svg'; + +function AddClusterPrompt() { + return ( + <> + +

+ You have successfully deployed a Red Hat Advanced Cluster Security platform. Now + you can configure the clusters you want to secure. +

+
+ + + + + + + + Configure the clusters you want to secure. + + + Follow the instructions to add secured clusters for Central to monitor. +
+ Upon successful installation, secured clusters are listed here. +
+
+
+ + + +
+ + ); +} + +export default AddClusterPrompt; diff --git a/ui/apps/platform/src/Containers/Clusters/ClustersTablePanel.js b/ui/apps/platform/src/Containers/Clusters/ClustersTablePanel.js index a665ac844b5cc..a1e6e6502195c 100644 --- a/ui/apps/platform/src/Containers/Clusters/ClustersTablePanel.js +++ b/ui/apps/platform/src/Containers/Clusters/ClustersTablePanel.js @@ -28,6 +28,7 @@ import { filterAllowedSearch, convertToRestSearch } from 'utils/searchUtils'; import AutoUpgradeToggle from './Components/AutoUpgradeToggle'; import { clusterTablePollingInterval, getUpgradeableClusters } from './cluster.helpers'; import { getColumnsForClusters } from './clustersTableColumnDescriptors'; +import AddClusterPrompt from './AddClusterPrompt'; function ClustersTablePanel({ selectedClusterId, setSelectedClusterId, searchOptions }) { const { hasReadWriteAccess } = usePermissions(); @@ -46,6 +47,7 @@ function ClustersTablePanel({ selectedClusterId, setSelectedClusterId, searchOpt const [pollingCount, setPollingCount] = useState(0); const [tableRef, setTableRef] = useState(null); const [showDialog, setShowDialog] = useState(false); + const [fetchingClusters, setFetchingClusters] = useState(false); // Handle changes to applied search options. const [isViewFiltered, setIsViewFiltered] = useState(false); @@ -84,10 +86,16 @@ function ClustersTablePanel({ selectedClusterId, setSelectedClusterId, searchOpt )); function refreshClusterList(restSearch) { - return fetchClustersWithRetentionInfo(restSearch).then((clustersResponse) => { - setCurrentClusters(clustersResponse.clusters); - setClusterIdToRetentionInfo(clustersResponse.clusterIdToRetentionInfo); - }); + setFetchingClusters(true); + return fetchClustersWithRetentionInfo(restSearch) + .then((clustersResponse) => { + setCurrentClusters(clustersResponse.clusters); + setClusterIdToRetentionInfo(clustersResponse.clusterIdToRetentionInfo); + setFetchingClusters(false); + }) + .catch(() => { + setFetchingClusters(false); + }); } const filteredSearch = filterAllowedSearch(searchOptions, pageSearch || {}); @@ -263,23 +271,28 @@ function ClustersTablePanel({ selectedClusterId, setSelectedClusterId, searchOpt {messages} )} -
- { - setTableRef(table); - }} - rows={currentClusters} - columns={clusterColumns} - onRowClick={setSelectedClusterId} - toggleRow={toggleCluster} - toggleSelectAll={toggleAllClusters} - selection={checkedClusterIds} - selectedRowId={selectedClusterId} - noDataText="No clusters to show." - minRows={20} - pageSize={pageSize} - /> -
+ {(!fetchingClusters || pollingCount > 0) && currentClusters.length <= 0 && ( + + )} + {(!fetchingClusters || pollingCount > 0) && currentClusters.length > 0 && ( +
+ { + setTableRef(table); + }} + rows={currentClusters} + columns={clusterColumns} + onRowClick={setSelectedClusterId} + toggleRow={toggleCluster} + toggleSelectAll={toggleAllClusters} + selection={checkedClusterIds} + selectedRowId={selectedClusterId} + noDataText="No clusters to show." + minRows={20} + pageSize={pageSize} + /> +
+ )} (CLUSTER_COUNT, { + onCompleted: (data) => { + if (hasClusterWritePermission && data?.clusterCount < 1) { + history.push(clustersBasePath); + } + }, + }); + // Render Body and NavigationSideBar only when feature flags and permissions are available. if (isLoadingFeatureFlags || isLoadingPermissions) { return ; diff --git a/ui/apps/platform/src/images/Security_FullColor_Pink.svg b/ui/apps/platform/src/images/Security_FullColor_Pink.svg new file mode 100644 index 0000000000000..1981315d47c5c --- /dev/null +++ b/ui/apps/platform/src/images/Security_FullColor_Pink.svg @@ -0,0 +1 @@ + \ No newline at end of file