Skip to content
Snippets Groups Projects
ImportProcessTable.tsx 7.01 KiB
Newer Older
import {
  TableContainer,
  Paper,
  Table,
  TableHead,
  TableRow,
  TableCell,
  TableBody,
  CircularProgress,
  Typography,
} from "@mui/material";
import CheckIcon from "@mui/icons-material/Check";
import CloseIcon from "@mui/icons-material/Close";
import ScheduleIcon from "@mui/icons-material/Schedule";
import DownloadIcon from "@mui/icons-material/Download";
import FileDownloadOffIcon from "@mui/icons-material/FileDownloadOff";
import { ImportProcess } from "@/types";
import { useGetImportProcesses } from "@/hooks/useGetImportProcesses";
import { ErrorScreen } from "./ErrorScreen";
import { LoadingScreen } from "./LoadingScreen";
import { ButtonTooltip } from "./ButtonTooltip";
import { useState, useEffect } from "react";
import { getFileNameFromURL } from "@/utils";
export interface ImportProcessTableProps {
  dataServiceEid?: number;
  recipeEid?: number;
  projectEid?: number;
  showProjectColumn?: boolean;
const REFRESH_INTERVAL = 5000;

export function ImportProcessTable(props: ImportProcessTableProps) {
  const {
    data: importProcessList,
    error,
    loading,
  } = useGetImportProcesses(props);

  const showProjectColumn = props.showProjectColumn !== false;

  useEffect(() => {
    const interval = setInterval(refresh, REFRESH_INTERVAL);
    return () => clearInterval(interval);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (error) {
    return <ErrorScreen message={error} />;
  }

  if (loading && !importProcessList) {
    return <LoadingScreen />;
  }

  if (!importProcessList) {
    return <ErrorScreen />;
  }

  if (importProcessList.length === 0) {
    return (
      <Typography variant="subtitle1" color={"GrayText"}>
        Aucun import process
      </Typography>
    );
  }
  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell>eid</TableCell>
            <TableCell>Date</TableCell>
            <TableCell>Recette</TableCell>
            <TableCell>État</TableCell>
            {showProjectColumn ? <TableCell>Projet</TableCell> : null}
            <TableCell width={50}>Dataset</TableCell>
            <TableCell width={50}>Log</TableCell>
            <TableCell width={50}>SHACL</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
            <ImportProcessTableRow
              key={i}
              importProcess={row}
              showProjectColumn={showProjectColumn}
            />
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}
function ImportProcessTableRow({
  importProcess,
  showProjectColumn,
  showProjectColumn: boolean;
Arnaud Vergnet's avatar
Arnaud Vergnet committed
  const dateObj = new Date(importProcess.date);

  return (
    <TableRow key={importProcess.eid}>
      <TableCell component="th" scope="row">
        {importProcess.eid}
      </TableCell>
Arnaud Vergnet's avatar
Arnaud Vergnet committed
      <TableCell>{dateObj.toLocaleString()}</TableCell>
      <TableCell>{importProcess.recipe}</TableCell>
      <TableCell>
        <StateIcon state={importProcess.state} />
      </TableCell>
      {showProjectColumn ? (
        <TableCell>{importProcess.project}</TableCell>
      ) : null}
      <DatasetButton importProcess={importProcess} />
      <TableCell>
        <ButtonTooltip
          title={hasLog ? "Voir le fichier de log" : "Aucun log disponible"}
        >
          <IconButton
            color="primary"
            disabled={!hasLog}
            href={importProcess.log_url ?? ""}
            download={getFileNameFromURL(importProcess.log_url)}
            {hasLog ? <DownloadIcon /> : <FileDownloadOffIcon />}
      <ShaclButton importProcess={importProcess} />
function DatasetButton({ importProcess }: { importProcess: ImportProcess }) {
  const hasDataset =
    importProcess.input_dataset_url != null ||
    importProcess.output_dataset_url != null;

  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
  const open = Boolean(anchorEl);
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };
  const handleClose = () => {
    setAnchorEl(null);
  };

  return (
    <TableCell>
      <ButtonTooltip
        title={
          hasDataset ? "Voir le fichier de Dataset" : "Aucun Dataset disponible"
        }
      >
        <IconButton
          color="primary"
          disabled={!hasDataset}
          onClick={handleClick}
        >
          {hasDataset ? <DownloadIcon /> : <FileDownloadOffIcon />}
        </IconButton>
      </ButtonTooltip>
      <Menu
        id="dataset-menu"
        anchorEl={anchorEl}
        open={open}
        onClose={handleClose}
        MenuListProps={{
          "aria-labelledby": "dataset-menu",
        }}
      >
        <DatasetMenuItem
          text="Entrée"
          url={importProcess.input_dataset_url}
          onClick={handleClose}
        />
        <DatasetMenuItem
          text="Sortie"
          url={importProcess.output_dataset_url}
          onClick={handleClose}
        />
function DatasetMenuItem({
  text,
  url,
  onClick,
}: {
  text: string;
  url?: string;
  onClick: () => void;
}) {
  if (!url) {
    return (
      <MenuItem onClick={onClick} disabled={true}>
        {text}
      </MenuItem>
    );
  }

  // Putting href and download props directly on the MenuItem does not work
  return (
    <a
      href={url}
      download={getFileNameFromURL(url)}
      style={{
        color: "inherit",
        textDecoration: "inherit",
      }}
    >
      <MenuItem onClick={onClick} disabled={false}>
        {text}
      </MenuItem>
    </a>
  );
}

function ShaclButton({ importProcess }: { importProcess: ImportProcess }) {
  if (importProcess.shacl_valid) {
    return (
      <TableCell>
        <Tooltip title="La validation SHACL a réussi">
          <Box
            style={{
              display: "flex",
              justifyContent: "center",
              alignItems: "center",
            }}
          >
            <CheckIcon />
          </Box>
        </Tooltip>
      </TableCell>
    );
  }
  return (
    <TableCell>
      <ButtonTooltip title={"Voir le rapport d'erreur SHACL"}>
        <IconButton
          color="primary"
          href={importProcess.shacl_report_url ?? ""}
          download={getFileNameFromURL(importProcess.shacl_report_url)}
          <DownloadIcon color="warning" />
function StateIcon({ state }: { state: ImportProcess["state"] }) {
  if (state === "successful") {
    return <CheckIcon />;
  }
  if (state === "error") {
    return <CloseIcon color="error" />;
  }
  if (state === "waiting") {
    return <ScheduleIcon color="warning" />;
  }
  if (state === "ongoing") {
    return <CircularProgress size={20} />;
  }
}