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