diff --git a/src/components/Job/JobDetailsTable.jsx b/src/components/Job/JobDetailsTable.jsx index bf59b5cf0b76e67369ded23ee1ff70e43760ad02..4fd9dca0a58a2316b3d2e3f3f6b5b0bea143518b 100644 --- a/src/components/Job/JobDetailsTable.jsx +++ b/src/components/Job/JobDetailsTable.jsx @@ -1,3 +1,4 @@ +import { useMemo } from "react"; import { EllipsisText, InternalLink, @@ -5,21 +6,24 @@ import { SimpleAccordion } from "@ess-ics/ce-ui-common"; import { Typography, Stack } from "@mui/material"; -import { getNoOfIOCs, isBatchJob } from "./JobUtils"; +import { getNoOfIOCs, getNoOfHosts, isBatchJob } from "./JobUtils"; import { JobRevisionChip } from "./JobRevisionChip"; const columns = [ { field: "ioc", - headerName: "IOC" + headerName: "IOC", + flex: 1 }, { field: "revision", - headerName: "Revision" + headerName: "Revision", + flex: 1 }, { field: "host", - headerName: "Host" + headerName: "Host", + flex: 1 } ]; @@ -45,9 +49,8 @@ const calculateHostText = (job) => { }; const createRow = (job) => { - const shapedHostName = calculateHostText(job); return { - id: job.id, + id: `${job.iocId}${job.host.hostId}`, ioc: ( <InternalLink to={`/iocs/${job.iocId}`} @@ -57,7 +60,7 @@ const createRow = (job) => { <EllipsisText>{job.iocName}</EllipsisText> </InternalLink> ), - host: shapedHostName, + host: calculateHostText(job), revision: ( <JobRevisionChip gitReference={job.gitReference} @@ -67,51 +70,63 @@ const createRow = (job) => { }; }; -const shapeBatchRows = (jobs) => - jobs.reduce((accumulator, job) => { - const ioc = job.iocs.reduce((iocsAccumulator, ioc) => { - return [...iocsAccumulator, { ...{ host: job.host, ...ioc } }]; - }, []); - return [...accumulator, ...ioc]; - }, []); +export const JobDetailsTable = ({ operation }) => { + const isBatchOperation = isBatchJob(operation.action); -export const JobDetailsTable = ({ operation }) => ( - <> - {isBatchJob(operation.type) ? ( - <SimpleAccordion - summary={ - <Stack - flexDirection="row" - alignItems="end" - sx={{ width: "100%" }} - gap={1} - > - {" "} - <Typography - component="h2" - variant="h3" - > - Batch - </Typography> - <Typography - variant="body2" - sx={{ fontWeight: "600", marginRight: "10px" }} + const noOfIOCs = useMemo(() => { + if (isBatchOperation) { + return getNoOfIOCs(operation.jobs); + } + }, [operation, isBatchOperation]); + + const noOfHosts = useMemo(() => { + if (isBatchOperation) { + return getNoOfHosts(operation.jobs); + } + }, [operation, isBatchOperation]); + + return ( + <> + {isBatchJob(operation.action) ? ( + <SimpleAccordion + summary={ + <Stack + flexDirection="row" + alignItems="end" + sx={{ width: "100%" }} + gap={1} > - {getNoOfIOCs(operation.jobs)} IOCs, {operation.jobs.length} Hosts - </Typography> - </Stack> - } - > + {" "} + <Typography + component="h2" + variant="h3" + > + Batch + </Typography> + <Typography + variant="body2" + sx={{ fontWeight: "600", marginRight: "10px" }} + > + {noOfIOCs} {noOfIOCs > 1 ? "IOCs" : "IOC"} + {", "} + {noOfHosts} {noOfHosts > 1 ? "Hosts" : "Host"} + </Typography> + </Stack> + } + > + <Table + columns={columns} + disableColumnSorting + rows={operation.jobs.map((job) => createRow(job))} + /> + </SimpleAccordion> + ) : ( <Table columns={columns} - rows={shapeBatchRows(operation.jobs).map((job) => createRow(job))} + disableColumnSorting + rows={[operation].map((job) => createRow(job))} /> - </SimpleAccordion> - ) : ( - <Table - columns={columns} - rows={[operation].map((job) => createRow(job))} - /> - )} - </> -); + )} + </> + ); +}; diff --git a/src/components/Job/JobTable/JobDetailsColumn.jsx b/src/components/Job/JobTable/JobDetailsColumn.jsx index 9fa29fd749fbbc0fd089f265a02f6157536e97c1..3cdc3111dbf62cef10bae84236e63ea1ed023b1f 100644 --- a/src/components/Job/JobTable/JobDetailsColumn.jsx +++ b/src/components/Job/JobTable/JobDetailsColumn.jsx @@ -1,54 +1,75 @@ +import { useMemo } from "react"; import { Stack, Typography } from "@mui/material"; import { InternalLink } from "@ess-ics/ce-ui-common"; -import { getNoOfIOCs, isBatchJob } from "../JobUtils"; +import { getNoOfIOCs, getNoOfHosts, isBatchJob } from "../JobUtils"; import { ActionTypeIconText } from "../JobIcons"; import { ACTION_TYPES } from "../JobData"; import { JobRevisionChip } from "../JobRevisionChip"; -export const JobDetailsColumn = ({ job }) => ( - <Stack> - <ActionTypeIconText action={job.action} /> - {!isBatchJob(job.type) ? ( - <Stack> - <Stack - flexDirection="row" - gap={1} - alignItems="center" - flexWrap="wrap" - > - <InternalLink - to={`/iocs/${job.iocId}`} - label={`IOC Details, ${job.iocName}`} +export const JobDetailsColumn = ({ job }) => { + const isBatchOperation = isBatchJob(job.action); + + const noOfIOCs = useMemo(() => { + if (isBatchOperation) { + return getNoOfIOCs(job.jobs); + } + }, [job, isBatchOperation]); + + const noOfHosts = useMemo(() => { + if (isBatchOperation) { + return getNoOfHosts(job.jobs); + } + }, [job, isBatchOperation]); + + return ( + <Stack> + <ActionTypeIconText action={job.action} /> + {!isBatchOperation ? ( + <Stack> + <Stack + flexDirection="row" + gap={1} + alignItems="center" + flexWrap="wrap" > - {job.iocName} - </InternalLink> - {job.type === ACTION_TYPES.DEPLOY && ( - <JobRevisionChip - gitReference={job.gitReference} - gitProjectId={job.gitProjectId} - /> - )} - </Stack> - <Stack - flexDirection="row" - gap={1} - alignItems="baseline" - flexWrap="wrap" - > - <InternalLink - to={`/hosts/${job?.host?.hostId}`} - label={`Host details, ${job.host?.hostName}`} + <InternalLink + to={`/iocs/${job.iocId}`} + label={`IOC Details, ${job.iocName}`} + > + {job.iocName} + </InternalLink> + {job.type === ACTION_TYPES.DEPLOY && ( + <JobRevisionChip + gitReference={job.gitReference} + gitProjectId={job.gitProjectId} + /> + )} + </Stack> + <Stack + flexDirection="row" + gap={1} + alignItems="baseline" + flexWrap="wrap" > - {job.host.hostName} - </InternalLink> - <Typography variant="body2">{job.host.network}</Typography> + <InternalLink + to={`/hosts/${job?.host?.hostId}`} + label={`Host details, ${job.host?.hostName}`} + > + {job.host.hostName} + </InternalLink> + <Typography variant="body2">{job.host.network}</Typography> + </Stack> + </Stack> + ) : ( + <Stack> + <Typography variant="body2"> + {noOfIOCs} {noOfIOCs > 1 ? "IOCs" : "IOC"} + </Typography> + <Typography variant="body2"> + {noOfHosts} {noOfHosts > 1 ? "Hosts" : "Host"} + </Typography> </Stack> - </Stack> - ) : ( - <Stack> - <Typography variant="body2">{getNoOfIOCs(job.jobs)} IOCs</Typography> - <Typography variant="body2">{job.jobs.length} Hosts</Typography> - </Stack> - )} - </Stack> -); + )} + </Stack> + ); +}; diff --git a/src/components/Job/JobUtils.js b/src/components/Job/JobUtils.js index cf6114bfffd932cf024d3c9de6d4fd5aa6f67b22..986a7dcfa1021e143dbbda575328a743f904cc2f 100644 --- a/src/components/Job/JobUtils.js +++ b/src/components/Job/JobUtils.js @@ -3,12 +3,8 @@ import { ACTION_TYPES } from "./JobData"; export const isBatchJob = (type) => type === ACTION_TYPES.BATCH_DEPLOY || type === ACTION_TYPES.BATCH_UNDEPLOY; -export const getNoOfIOCs = (jobs) => { - let count = 0; - jobs.forEach((job) => { - job.iocs.forEach(() => { - count += 1; - }); - }); - return count; -}; +export const getNoOfIOCs = (jobs) => + [...new Set(jobs.map((job) => job.iocId))].length; + +export const getNoOfHosts = (jobs) => + [...new Set(jobs.map((job) => job.host.hostId))].length; diff --git a/src/mocks/fixtures/Jobs.json b/src/mocks/fixtures/Jobs.json index d73e0c37519cd4e9d9ca0987384bbd07ac2a8f32..fa0b3d12c72ce895b58e7d4ec0ee9ed57d71896f 100644 --- a/src/mocks/fixtures/Jobs.json +++ b/src/mocks/fixtures/Jobs.json @@ -163,8 +163,6 @@ "createdAt": "2024-09-06T10:32:38.428+0200", "finishedAt": "2024-09-06T10:35:12.947+0200", "action": "BATCH_DEPLOY", - "iocName": "MOCK:TEST-4", - "iocId": 56, "deploymentId": 538, "gitProjectId": 13224, "gitReference": "5d102879ee4cfcbaeda3277f4bdc397c58c59970", @@ -173,36 +171,32 @@ "gitShortReference": "525c1a89", "jobs": [ { + "iocId": 3536, + "iocName": "MOCK:TEST-2", + "gitProjectId": 5959, + "gitReference": "0a5b165b7c80e43d1b29ca1aa31fa2861d5536dc", + "host": { + "hostId": "MTUxX3RydWU=", + "hostName": "ccce-test-ioc-01", + "network": "CSLab-GeneralLab", + "fqdn": "ccce-test-ioc-01.cslab.esss.lu.se", + "netBoxHostFromCache": true + } + }, + { + "iocId": 3537, + "iocName": "MOCK:TEST-6", + "gitProjectId": 595958, + "gitReference": "engineer_set", "host": { "hostId": "MTUxX3RydWU=", "hostName": "ccce-test-ioc-01", "network": "CSLab-GeneralLab", "fqdn": "ccce-test-ioc-01.cslab.esss.lu.se", "netBoxHostFromCache": true - }, - "iocs": [ - { - "id": 3536, - "iocName": "MOCK:TEST-2", - "gitProjectId": 5959, - "gitReference": "0a5b165b7c80e43d1b29ca1aa31fa2861d5536dc" - }, - { - "id": 3535, - "iocName": "MOCK:TEST-6", - "gitProjectId": 595958, - "gitReference": "engineer_set" - } - ] + } } ], - "host": { - "hostId": "MTUxX3RydWU=", - "hostName": "ccce-test-ioc-01", - "network": "CSLab-GeneralLab", - "fqdn": "ccce-test-ioc-01.cslab.esss.lu.se", - "netBoxHostFromCache": true - }, "awxJobId": 7472, "jobUrl": "https://awx-lab-01.cslab.esss.lu.se/#/jobs/playbook/7472", "alerts": [], @@ -233,8 +227,6 @@ "createdAt": "2024-09-06T14:31:17.365+0200", "finishedAt": "2024-09-06T14:33:40.559+0200", "action": "BATCH_UNDEPLOY", - "iocName": "MOCK:TEST-5", - "iocId": 56, "deploymentId": 543, "gitProjectId": 13224, "gitReference": "5d102879ee4cfcbaeda3277f4bdc397c58c59970", @@ -243,59 +235,58 @@ "gitShortReference": "9d9b0474", "jobs": [ { + "iocId": 7070, + "iocName": "MOCK:TEST-17", + "gitProjectId": 595959, + "gitReference": "engineer_set", "host": { "hostId": "MTUyX3RydWU=", "hostName": "ccce-test-ioc-56-test", "network": "CSLab-GeneralLab", "fqdn": "ccce-test-ioc-02.test1", "netBoxHostFromCache": true - }, - "iocs": [ - { - "id": 7070, - "iocName": "MOCK:TEST-17", - "gitProjectId": 595959, - "gitReference": "engineer_set" - }, - { - "id": 7071, - "iocName": "MOCK:TEST-3", - "gitProjectId": 595959, - "gitReference": "engineer_set" - } - ] + } }, { + "iocId": 7071, + "iocName": "MOCK:TEST-3", + "gitProjectId": 595959, + "gitReference": "engineer_set", "host": { "hostId": "MTUyX3RydWU=", + "hostName": "ccce-test-ioc-56-test", + "network": "CSLab-GeneralLab", + "fqdn": "ccce-test-ioc-02.test1", + "netBoxHostFromCache": true + } + }, + { + "iocId": 3731, + "iocName": "MOCK:TEST-89", + "gitProjectId": 595959, + "gitReference": "engineer_set", + "host": { + "hostId": "MTUyX3RydWU=", + "hostName": "ccce-test-ioc-56-test", + "network": "CSLab-GeneralLab", + "fqdn": "ccce-test-ioc-02.test1", + "netBoxHostFromCache": true + } + }, + { + "iocId": 3731, + "iocName": "MOCK:TEST-16", + "gitProjectId": 595959, + "gitReference": "engineer_set", + "host": { + "hostId": "AnotherHost", "hostName": "ccce-test-ioc-test", "network": "CSLab-GeneralLab", - "fqdn": "ccce-test-ioc-02.cslab.test2", + "fqdn": "AnotherHost.fqdn", "netBoxHostFromCache": true - }, - "iocs": [ - { - "id": 3731, - "iocName": "MOCK:TEST-16", - "gitProjectId": 595959, - "gitReference": "engineer_set" - }, - { - "id": 6661, - "iocName": "MOCK:TEST-25", - "gitProjectId": 595959, - "gitReference": "engineer_set" - } - ] + } } ], - "host": { - "hostId": "MTUyX3RydWU=", - "hostName": "ccce-test-ioc-02", - "network": "CSLab-GeneralLab", - "fqdn": "ccce-test-ioc-02.cslab.esss.lu.se", - "netBoxHostFromCache": true - }, "awxJobId": 7471, "jobUrl": "https://awx-lab-01.cslab.esss.lu.se/#/jobs/command/7471", "alerts": null,