From 1bde21a590f8dd3b50b6e9285e5327361bab2945 Mon Sep 17 00:00:00 2001 From: cjenkscybercom <christina.jenks@knowit.se> Date: Wed, 13 Sep 2023 12:54:39 +0200 Subject: [PATCH] CE-2023: remove JobAsyncTable component, update stories --- src/components/IOC/IOCManage/IOCManage.js | 12 +-- src/components/Job/JobAsyncList.js | 63 -------------- src/components/Job/JobTable.js | 87 +++++++------------ src/components/Job/index.js | 11 +-- src/components/common/Helper.js | 17 +++- .../common/User/UserOperationList.js | 13 +-- .../components/common/job/JobTable.stories.js | 39 ++++----- src/views/jobs/JobListView.js | 12 +-- 8 files changed, 77 insertions(+), 177 deletions(-) delete mode 100644 src/components/Job/JobAsyncList.js diff --git a/src/components/IOC/IOCManage/IOCManage.js b/src/components/IOC/IOCManage/IOCManage.js index e2f767cf..fbbde398 100644 --- a/src/components/IOC/IOCManage/IOCManage.js +++ b/src/components/IOC/IOCManage/IOCManage.js @@ -13,11 +13,11 @@ import { userContext } from "@ess-ics/ce-ui-common"; import AlertMessages from "../AlertMessages"; import { SimpleAccordion } from "../../common/Accordion/SimpleAccordion"; import AccessControl from "../../auth/AccessControl"; -import { JobAsyncList } from "../../Job/JobAsyncList"; import { DeploymentStatus } from "../../../api/DataTypes"; import { IOCService } from "../IOCService"; import useUrlState from "@ahooksjs/use-url-state"; import { serialize, deserialize } from "../../common/URLState/URLState"; +import { JobTable } from "../../Job"; export function IOCManage({ ioc, @@ -42,7 +42,6 @@ export function IOCManage({ const [deployDialogOpen, setDeployDialogOpen] = useState(false); const [undeployDialogOpen, setUndeployDialogOpen] = useState(false); const [deploymentJob, getDeploymentJobById] = useJobById(); - const [operationList, setOperationList] = useState(operations.operationsList); useEffect(() => { if (ioc.activeDeployment?.awxJobId) { @@ -50,10 +49,6 @@ export function IOCManage({ } }, [getDeploymentJobById, ioc.activeDeployment?.awxJobId]); - useEffect(() => { - setOperationList(operations.operationsList); - }, [operations]); - const closeDeployModal = () => { setDeployDialogOpen(false); getIOC(); @@ -220,9 +215,8 @@ export function IOCManage({ setState({ log_open: serialize(expanded) }) } > - <JobAsyncList - jobs={operationList} - setJobs={setOperationList} + <JobTable + jobs={operations.operationsList} pagination={pagination} onPage={onPage} loading={operationsLoading} diff --git a/src/components/Job/JobAsyncList.js b/src/components/Job/JobAsyncList.js deleted file mode 100644 index 33a4743b..00000000 --- a/src/components/Job/JobAsyncList.js +++ /dev/null @@ -1,63 +0,0 @@ -import React, { useEffect } from "react"; -import { useTagsAndCommitIds } from "../../api/SwaggerApi"; -import { JobTable } from "./JobTable"; - -export function JobAsyncList({ - jobs, - setJobs, - rowType, - pagination, - onPage, - loading -}) { - const jobDetailFetchers = jobs?.map((job, index) => ( - <JobDetailFetcher - key={`${job.type}-fetcher-${job.id}`} - deployment={job} - index={index} - setDeployments={setJobs} - /> - )); - return ( - <> - <JobTable - jobs={jobs} - rowType={rowType} - pagination={pagination} - onPage={onPage} - loading={loading} - /> - {jobDetailFetchers} - </> - ); -} - -function onError(message) { - console.warn(message); -} - -export function JobDetailFetcher({ deployment, index, setDeployments }) { - const [tagOrCommitId, getTagOrCommitId] = useTagsAndCommitIds(onError); - - useEffect(() => { - getTagOrCommitId( - deployment.gitProjectId, - deployment.gitReference, - false, - "EQUALS" - ); - }, [deployment, getTagOrCommitId]); - - useEffect(() => { - setDeployments((deployments) => { - deployments[index].sourceVersionShort = - tagOrCommitId?.length === 1 - ? tagOrCommitId[0].shortReference - : deployments[index].gitReference; - deployments[index].host.hostInfoFromCache = false; - return [...deployments]; - }); - }, [index, setDeployments, tagOrCommitId]); - - return null; -} diff --git a/src/components/Job/JobTable.js b/src/components/Job/JobTable.js index 89f0bea5..ffa2c917 100644 --- a/src/components/Job/JobTable.js +++ b/src/components/Job/JobTable.js @@ -1,51 +1,34 @@ import React from "react"; import { Table } from "@ess-ics/ce-ui-common"; -import { Grid, Link } from "@mui/material"; -import { noWrapText } from "../common/Helper"; -import { JobStatusIcon, JobTypeIcon } from "./JobIcons"; +import { Grid } from "@mui/material"; +import { EllipsisTextLink, noWrapText } from "../common/Helper"; +import { JobTypeIcon } from "./JobIcons"; import { formatDate } from "../common/Helper"; const jobLogColumns = [ { field: "type", headerName: "Type", - flex: 0, headerAlign: "center", - align: "center" + align: "center", + maxWidth: 60 }, - { field: "ioc", headerName: "IOC name", width: "15ch", sortable: false }, - { field: "version", headerName: "Revision", width: "10ch", sortable: false }, - { field: "host", headerName: "Host", width: "15ch", sortable: false }, - { field: "user", headerName: "User", width: "10ch", sortable: false }, + { field: "ioc", headerName: "IOC name", minWidth: 120 }, + { field: "version", headerName: "Revision", minWidth: 120 }, + { field: "host", headerName: "Host", minWidth: 120 }, + { field: "user", headerName: "User", minWidth: 100 }, { field: "start", headerName: "Time", - width: "15ch", + minWidth: 120, sortable: false, headerAlign: "right", - textAlign: "right" + align: "right" } ]; const userPageJobLogColumns = [ - { - field: "type", - headerName: "Type", - flex: 0, - headerAlign: "center", - align: "center" - }, - { field: "ioc", headerName: "IOC name", width: "15ch", sortable: false }, - { field: "version", headerName: "Revision", width: "10ch", sortable: false }, - { field: "host", headerName: "Host", width: "15ch", sortable: false }, - { - field: "start", - headerName: "Time", - width: "15ch", - sortable: false, - headerAlign: "right", - textAlign: "right" - } + ...jobLogColumns.filter((it) => it.field !== "user") ]; function createTableRow(job, colorStyle) { @@ -64,36 +47,31 @@ function createTableRow(job, colorStyle) { /> </Grid> ), - status: ( - <Grid - container - direction="column" - justifyContent="center" - alignItems="center" - > - <JobStatusIcon status={job.status} /> - </Grid> + ioc: ( + <EllipsisTextLink + text={job.iocName} + href={`/iocs/${job.iocId}`} + /> ), - ioc: <Link href={`/iocs/${job.iocId}`}>{noWrapText(job.iocName)}</Link>, version: ( - <Link href={`/jobs/${job?.id}`}> - {noWrapText(job.sourceVersionShort ?? job.gitReference)} - </Link> - ), - host: ( - <Link href={`/hosts/${job?.host?.externalHostId}`}> - {noWrapText(job.host?.hostName ?? null)} - </Link> + <EllipsisTextLink + text={job.gitReference} + href={`/jobs/${job?.id}`} + /> ), - network: noWrapText(job.host?.network ?? null), + host: job.host?.hostName ? ( + <EllipsisTextLink + text={job.host?.hostName} + href={`/hosts/${job?.host?.externalHostId}`} + /> + ) : null, user: ( - <Link href={`/user/${job.createdBy}`}>{noWrapText(job.createdBy)}</Link> + <EllipsisTextLink + text={job.createdBy} + href={`/user/${job.createdBy}`} + /> ), - start: noWrapText(formatDate(job.createdAt)), - deploymentFailed: job.status === "FAILED" || job.status === "ERROR", - jobType: job.type, - iocId: job.iocId, - deploymentId: job.deploymentId + start: noWrapText(formatDate(job.createdAt)) }; } @@ -122,7 +100,6 @@ export function JobTable({ pagination={pagination} onPage={onPage} loading={loading} - autoHeight /> ); } diff --git a/src/components/Job/index.js b/src/components/Job/index.js index 16f8a576..daf3a530 100644 --- a/src/components/Job/index.js +++ b/src/components/Job/index.js @@ -1,15 +1,6 @@ -import { JobAsyncList, JobDetailFetcher } from "./JobAsyncList"; import { JobBadge } from "./JobBadge"; import { JobDetails } from "./JobDetails"; import { JobStatusIcon, JobTypeIcon } from "./JobIcons"; import { JobTable } from "./JobTable"; -export { - JobAsyncList, - JobDetailFetcher, - JobBadge, - JobDetails, - JobStatusIcon, - JobTypeIcon, - JobTable -}; +export { JobBadge, JobDetails, JobStatusIcon, JobTypeIcon, JobTable }; diff --git a/src/components/common/Helper.js b/src/components/common/Helper.js index f8e079ff..d71c3104 100644 --- a/src/components/common/Helper.js +++ b/src/components/common/Helper.js @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import moment from "moment"; import { alpha } from "@mui/material/styles"; -import { Typography } from "@mui/material"; +import { Link, Tooltip, Typography, styled } from "@mui/material"; export function formatToList(items) { if (!items) return null; @@ -160,6 +160,21 @@ export function noWrapText(text) { return <Typography noWrap>{text}</Typography>; } +export const EllipsisTextLink = styled(({ text, className, ...props }) => { + return ( + <Tooltip + title={text} + className={className} + > + <Link {...props}>{text}</Link> + </Tooltip> + ); +})({ + textOverflow: "ellipsis", + whiteSpace: "nowrap", + overflow: "hidden" +}); + export function extractMainNetwork(interfaces, defaultReturn = "") { if (!interfaces) { return defaultReturn; diff --git a/src/components/common/User/UserOperationList.js b/src/components/common/User/UserOperationList.js index 6f57ef0f..c90c1957 100644 --- a/src/components/common/User/UserOperationList.js +++ b/src/components/common/User/UserOperationList.js @@ -1,17 +1,13 @@ import React from "react"; import { Card, CardHeader } from "@mui/material"; import { initRequestParams } from "../Helper"; -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { useOperationsSearch } from "../../../api/SwaggerApi"; -import { JobAsyncList } from "../../Job/JobAsyncList"; import { usePagination } from "../../../hooks/pagination"; +import { JobTable } from "../../Job"; export function UserOperationList({ userName }) { const [operations, getOperations, , loading] = useOperationsSearch(); - const [jobList, setJobList] = useState([]); - useEffect(() => { - setJobList(operations.operationsList); - }, [operations, setJobList]); const rowsPerPage = [20, 50]; const { pagination, setPagination } = usePagination({ @@ -47,9 +43,8 @@ export function UserOperationList({ userName }) { component: "h2" }} /> - <JobAsyncList - jobs={jobList} - setJobs={setJobList} + <JobTable + jobs={operations.operationsList} loading={loading} pagination={pagination} onPage={onPage} diff --git a/src/stories/components/common/job/JobTable.stories.js b/src/stories/components/common/job/JobTable.stories.js index 0421e124..b6fa7205 100644 --- a/src/stories/components/common/job/JobTable.stories.js +++ b/src/stories/components/common/job/JobTable.stories.js @@ -1,43 +1,42 @@ import React from "react"; import { RouterHarness } from "../../../../mocks/AppHarness"; import { JobTable } from "../../../../components/Job/JobTable"; -import { hideStorybookControls } from "../../../utils/common-args"; -import { Container } from "@mui/material"; +import { + hideStorybookControls, + paginationNoResults +} from "../../../utils/common-args"; +import { Box } from "@mui/material"; import operationList from "../../../../mocks/fixtures/OperationList.json"; export default { title: "Jobs/JobTable", argTypes: { + rowType: { + options: ["jobLog", "userPageJobLog"], + control: { type: "radio" } + }, jobs: hideStorybookControls, - totalCount: hideStorybookControls, - rowsPerPage: hideStorybookControls, - lazyParams: hideStorybookControls, - columnSort: hideStorybookControls, - setLazyParams: hideStorybookControls, - setColumnSort: hideStorybookControls + pagination: hideStorybookControls, + onPage: hideStorybookControls } }; const Template = (args) => ( <RouterHarness> - <Container> + <Box height="90vh"> <JobTable {...args} /> - </Container> + </Box> </RouterHarness> ); export const Empty = (args) => <Template {...args} />; Empty.args = { + rowType: "jobLog", loading: false, jobs: [], - paginator: true, - totalCount: 0, - rowsPerPage: [5, 10, 20, 50, 100], - lazyParams: { rows: 10, page: 0 }, - columnSort: { sortField: null, sortOrder: null }, - setLazyParams: () => {}, - setColumnSort: () => {} + pagination: paginationNoResults, + onPage: () => {} }; export const EmptyLoading = (args) => <Template {...args} />; @@ -51,12 +50,10 @@ export const Populated = (args) => <Template {...args} />; Populated.args = { ...Empty.args, - totalCount: operationList.totalCount, - jobs: operationList.operations + jobs: operationList.operations, + pagination: { ...paginationNoResults, totalCount: operationList.totalCount } }; Populated.argTypes = { - totalCount: hideStorybookControls, - hosts: hideStorybookControls, loading: hideStorybookControls }; diff --git a/src/views/jobs/JobListView.js b/src/views/jobs/JobListView.js index 79331f48..666d4de8 100644 --- a/src/views/jobs/JobListView.js +++ b/src/views/jobs/JobListView.js @@ -16,22 +16,17 @@ import { initRequestParams } from "../../components/common/Helper"; import { useEffect } from "react"; import { SearchBar } from "../../components/common/SearchBar/SearchBar"; import AccessControl from "../../components/auth/AccessControl"; -import { JobAsyncList } from "../../components/Job/JobAsyncList"; import useUrlState from "@ahooksjs/use-url-state"; import { serialize, deserialize } from "../../components/common/URLState/URLState"; import { usePagination } from "../../hooks/pagination"; +import { JobTable } from "../../components/Job"; export function JobListView() { const [operations, getOperations /* reset*/, , loading] = useOperationsSearch(); - const [jobList, setJobList] = useState([]); - // Sync results with mutatable list - useEffect(() => { - setJobList(operations.operationsList); - }, [operations, setJobList]); const [urlState, setUrlState] = useUrlState( { @@ -167,9 +162,8 @@ export function JobListView() { loading={loading} placeholder="Search in IOC name, user or git reference" > - <JobAsyncList - jobs={jobList} - setJobs={setJobList} + <JobTable + jobs={operations.operationsList} pagination={pagination} onPage={onPage} loading={loading} -- GitLab