diff --git a/__tests__/pages/Sites/Site.spec.tsx b/__tests__/pages/Sites/Site.spec.tsx index a4fe5948..28a27788 100644 --- a/__tests__/pages/Sites/Site.spec.tsx +++ b/__tests__/pages/Sites/Site.spec.tsx @@ -4,6 +4,8 @@ import { fireEvent, render, screen, waitForElementToBeRemoved, waitFor } from '@ import { Server } from 'miragejs'; import * as router from 'react-router'; +import { ProcessesRoutesPaths } from '@pages/Processes/Processes.enum'; + import processesData from '../../../mocks/data/PROCESSES.json'; import sitesData from '../../../mocks/data/SITES.json'; import { loadMockServer } from '../../../mocks/server'; @@ -64,21 +66,24 @@ describe('Site component', () => { await waitFor(() => { expect(screen.getByText(siteResults[0].name)).toBeInTheDocument(); expect(screen.getByText(siteResults[0].nameSpace)).toBeInTheDocument(); - expect(screen.getByText(processResults[0].name)).toBeInTheDocument(); }); }); - it('Should ensure the Site details component renders with correct link href after loading page', async () => { + it('Should ensure the Site processes component renders with correct link href after loading page', async () => { await waitForElementToBeRemoved(() => screen.queryByTestId(getTestsIds.loadingView()), { timeout: waitForElementToBeRemovedTimeout }); - fireEvent.click(screen.getByText(SiteLabels.Details)); + fireEvent.click(screen.getByText(SiteLabels.Processes)); + + await waitFor(() => { + expect(screen.getByText(processResults[0].name)).toBeInTheDocument(); + }); await waitFor(() => { expect(screen.getByRole('link', { name: processResults[0].name })).toHaveAttribute( 'href', - `#/processes/${processResults[0].name}@${processResults[0].identity}` + `#${ProcessesRoutesPaths.Processes}/${processResults[0].name}@${processResults[0].identity}` ); }); }); diff --git a/cypress/e2e/skupper-console/sites/site.cy.ts b/cypress/e2e/skupper-console/sites/site.cy.ts index bb862527..31f9ad6c 100644 --- a/cypress/e2e/skupper-console/sites/site.cy.ts +++ b/cypress/e2e/skupper-console/sites/site.cy.ts @@ -1,6 +1,6 @@ import { getTestsIds } from '@config/testIds'; -context('Sites', () => { +context('Site Detail', () => { const testId = `${getTestsIds.siteView('site-1')}`; beforeEach(() => { @@ -20,6 +20,14 @@ context('Sites', () => { link.click(); cy.url().should('eq', expectedUrl); }); +}); + +context('Site Processes', () => { + const testId = `${getTestsIds.siteView('site-1')}`; + + beforeEach(() => { + cy.visit('#/sites/site%201@site-1?type=Processes'); + }); it('should navigate to the correct process page when clicking on a link', () => { const expectedUrl = 'http://localhost:3000/#/processes/process%20payment%201@process-payment-1?type=Overview'; diff --git a/package.json b/package.json index 041d81e1..371b0d62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "skupper-web-console", - "version": "1.8.0", + "version": "2.0.0", "description": "Skupper Web Console", "license": "Apache-2.0", "keywords": [ @@ -59,7 +59,7 @@ "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", "@types/jest": "^29.5.13", - "@types/react": "^18.3.5", + "@types/react": "^18.3.6", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^8.5.0", "@typescript-eslint/parser": "^8.5.0", diff --git a/src/pages/Sites/components/Details.tsx b/src/pages/Sites/components/Details.tsx index c6b3ce0c..0eb20a93 100644 --- a/src/pages/Sites/components/Details.tsx +++ b/src/pages/Sites/components/Details.tsx @@ -18,8 +18,6 @@ import { import { Link } from 'react-router-dom'; import ResourceIcon from '@core/components/ResourceIcon'; -import SKEmptyData from '@core/components/SkEmptyData'; -import { ProcessesRoutesPaths } from '@pages/Processes/Processes.enum'; import { SiteResponse } from '@sk-types/REST.interfaces'; import { useSiteDetailsData } from '../hooks/useSiteDetailsData'; @@ -31,7 +29,7 @@ interface DetailsProps { } const Details: FC = function ({ site: { identity: id, nameSpace, siteVersion, platform } }) { - const { sites, links, processes } = useSiteDetailsData(id); + const { sites, links } = useSiteDetailsData(id); const { linkSiteIds } = SitesController.bindLinksWithSiteIds( sites.filter(({ identity }) => identity === id), @@ -40,8 +38,8 @@ const Details: FC = function ({ site: { identity: id, nameSpace, s const linkedSites = sites.filter(({ identity }) => linkSiteIds.map(({ targetId }) => targetId).includes(identity)); return ( - - + + {SiteLabels.Details} @@ -55,72 +53,28 @@ const Details: FC = function ({ site: { identity: id, nameSpace, s {platform} {SiteLabels.SiteVersion} {siteVersion} + {SiteLabels.Links} + + + {linkedSites.length + ? linkedSites.map(({ identity, name: linkedSiteName }) => ( + + + + + {linkedSiteName} + + + + )) + : '-'} + + - - - - - {SiteLabels.Links} - - - {(!!linkedSites.length && ( - - {linkedSites.map(({ identity, name: linkedSiteName }) => ( - - - - {linkedSiteName} - - - ))} - - )) || } - - - - - {/* - - - {SiteLabels.Hosts} - - - {(!!hosts.length && ( - - {hosts.map(({ identity, provider, name: hostName }) => ( - {provider ? `${provider} (${hostName})` : hostName} - ))} - - )) || } - - - */} - - - - - {SiteLabels.Processes} - - - {(!!processes.length && ( - - {processes.map(({ identity, name: processName }) => ( - - - - {processName} - - - ))} - - )) || } - - - ); }; diff --git a/src/pages/Sites/components/ProcessList.tsx b/src/pages/Sites/components/ProcessList.tsx new file mode 100644 index 00000000..6892abbf --- /dev/null +++ b/src/pages/Sites/components/ProcessList.tsx @@ -0,0 +1,32 @@ +import { FC } from 'react'; + +import SkTable from '@core/components/SkTable'; +import { CustomProcessCells, processesTableColumns } from '@pages/Processes/Processes.constants'; +import { ProcessesLabels } from '@pages/Processes/Processes.enum'; +import { SiteResponse } from '@sk-types/REST.interfaces'; + +import { useSiteProcessListData } from '../hooks/useSiteProcessListData'; + +interface ProcessListProps { + site: SiteResponse; +} + +const ProcessList: FC = function ({ site: { identity: id } }) { + const { processes } = useSiteProcessListData(id); + + return ( + + ); +}; + +export default ProcessList; diff --git a/src/pages/Sites/hooks/useSiteDetailsData.ts b/src/pages/Sites/hooks/useSiteDetailsData.ts index 1cb23026..66728732 100644 --- a/src/pages/Sites/hooks/useSiteDetailsData.ts +++ b/src/pages/Sites/hooks/useSiteDetailsData.ts @@ -1,30 +1,24 @@ import { useSuspenseQueries } from '@tanstack/react-query'; import { RESTApi } from '@API/REST.api'; -import { Direction, Role } from '@API/REST.enum'; +import { Direction } from '@API/REST.enum'; import { UPDATE_INTERVAL } from '@config/config'; import { QueriesSites } from '../Sites.enum'; -const processQueryParams = { processRole: [Role.Remote, Role.External], endTime: 0 }; const linkQueryParams = { direction: Direction.Outgoing }; export const useSiteDetailsData = (id: string) => { - const [{ data: sites }, { data: links }, { data: processes }] = useSuspenseQueries({ + const [{ data: sites }, { data: links }] = useSuspenseQueries({ queries: [ { queryKey: [QueriesSites.GetSites], queryFn: () => RESTApi.fetchSites(), refetchInterval: UPDATE_INTERVAL }, { queryKey: [QueriesSites.GetLinksBySiteId, id, linkQueryParams], queryFn: () => RESTApi.fetchLinksBySite(id, linkQueryParams), refetchInterval: UPDATE_INTERVAL - }, - { - queryKey: [QueriesSites.GetProcessesBySiteId, { ...processQueryParams, parent: id }], - queryFn: () => RESTApi.fetchProcesses({ ...processQueryParams, parent: id }), - refetchInterval: UPDATE_INTERVAL } ] }); - return { sites: sites.results, links: links.results, processes: processes.results }; + return { sites: sites.results, links: links.results }; }; diff --git a/src/pages/Sites/hooks/useSiteProcessListData.ts b/src/pages/Sites/hooks/useSiteProcessListData.ts new file mode 100644 index 00000000..9632457c --- /dev/null +++ b/src/pages/Sites/hooks/useSiteProcessListData.ts @@ -0,0 +1,19 @@ +import { useSuspenseQuery } from '@tanstack/react-query'; + +import { RESTApi } from '@API/REST.api'; +import { Role } from '@API/REST.enum'; +import { UPDATE_INTERVAL } from '@config/config'; + +import { QueriesSites } from '../Sites.enum'; + +const processQueryParams = { processRole: [Role.Remote, Role.External], endTime: 0 }; + +export const useSiteProcessListData = (id: string) => { + const { data: processes } = useSuspenseQuery({ + queryKey: [QueriesSites.GetProcessesBySiteId, { ...processQueryParams, parent: id }], + queryFn: () => RESTApi.fetchProcesses({ ...processQueryParams, parent: id }), + refetchInterval: UPDATE_INTERVAL + }); + + return { processes: processes.results }; +}; diff --git a/src/pages/Sites/views/Site.tsx b/src/pages/Sites/views/Site.tsx index f3b16447..8012cb70 100644 --- a/src/pages/Sites/views/Site.tsx +++ b/src/pages/Sites/views/Site.tsx @@ -11,6 +11,7 @@ import useUpdateQueryStringValueWithoutNavigation from 'hooks/useUpdateQueryStri import Details from '../components/Details'; import Overview from '../components/Overview.'; +import ProcessList from '../components/ProcessList'; import { useSiteData } from '../hooks/useSiteData'; import { SiteLabels } from '../Sites.enum'; @@ -34,6 +35,7 @@ const SiteContent: FC = function ({ id, defaultTab }) { {SiteLabels.Overview}} /> {SiteLabels.Details}} /> + {SiteLabels.Processes}} /> ); }; @@ -48,6 +50,7 @@ const SiteContent: FC = function ({ id, defaultTab }) { <> {tabSelected === SiteLabels.Overview && } {tabSelected === SiteLabels.Details &&
} + {tabSelected === SiteLabels.Processes && } } /> diff --git a/yarn.lock b/yarn.lock index 43cd0000..569eae84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1952,10 +1952,10 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/react@^18.3.5": - version "18.3.5" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.5.tgz#5f524c2ad2089c0ff372bbdabc77ca2c4dbadf8f" - integrity sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA== +"@types/react@^18.3.6": + version "18.3.6" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.6.tgz#1cb5895c5ea0d99d8bc7d659e42f72713cbd3942" + integrity sha512-CnGaRYNu2iZlkGXGrOYtdg5mLK8neySj0woZ4e2wF/eli2E6Sazmq5X+Nrj6OBrrFVQfJWTUFeqAzoRhWQXYvg== dependencies: "@types/prop-types" "*" csstype "^3.0.2"