Newer
Older
import {
TableContainer,
Paper,
Table,
TableHead,
TableRow,
TableCell,
TableBody,
CircularProgress,
Typography,

Fabien Amarger
committed
IconButton,
Tooltip,
Box,
Menu,
MenuItem,
} from "@mui/material";
import CheckIcon from "@mui/icons-material/Check";
import CloseIcon from "@mui/icons-material/Close";
import ScheduleIcon from "@mui/icons-material/Schedule";

Fabien Amarger
committed
import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
import { ImportProcess } from "@/types";
import { useGetImportProcesses } from "@/hooks/useGetImportProcesses";
import { ErrorScreen } from "./ErrorScreen";
import { LoadingScreen } from "./LoadingScreen";

Fabien Amarger
committed
import { downloadFile, openFile } from "@/utils";
import { ButtonTooltip } from "./ButtonTooltip";
import { useState, useEffect } from "react";
export interface ImportProcessTableProps {
dataServiceEid?: number;
recipeEid?: number;
projectEid?: number;

Fabien Amarger
committed
async function showFile(url?: string) {
if (url) {
const fileToOpen = await downloadFile(url);
openFile(fileToOpen);
} else {
console.error("No file to open");

Fabien Amarger
committed
}
}
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}

Fabien Amarger
committed
<TableCell width={50}>Dataset</TableCell>
<TableCell width={50}>Log</TableCell>
<TableCell width={50}>SHACL</TableCell>
</TableRow>
</TableHead>
<TableBody>

Fabien Amarger
committed
{importProcessList.map((row, i) => (
<ImportProcessTableRow
key={i}
importProcess={row}
showProjectColumn={showProjectColumn}
/>
))}
</TableBody>
</Table>
</TableContainer>
);
}

Fabien Amarger
committed
function ImportProcessTableRow({
importProcess,

Fabien Amarger
committed
}: {
importProcess: ImportProcess;

Fabien Amarger
committed
}) {
const hasLog = importProcess.log_url != null;

Fabien Amarger
committed
return (
<TableRow key={importProcess.eid}>
<TableCell component="th" scope="row">
{importProcess.eid}
</TableCell>

Fabien Amarger
committed
<TableCell>{importProcess.recipe}</TableCell>
<TableCell>
<StateIcon state={importProcess.state} />
</TableCell>
{showProjectColumn ? (
<TableCell>{importProcess.project}</TableCell>
) : null}
<DatasetButton importProcess={importProcess} />

Fabien Amarger
committed
<TableCell>
<ButtonTooltip
title={hasLog ? "Voir le fichier de log" : "Aucun log disponible"}
>
<IconButton
color="primary"
disabled={!hasLog}
onClick={() => showFile(importProcess.log_url)}
>
{hasLog ? <Visibility /> : <VisibilityOff />}
</IconButton>
</ButtonTooltip>
</TableCell>
<ShaclButton importProcess={importProcess} />

Fabien Amarger
committed
</TableRow>
);
}
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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 ? <Visibility /> : <VisibilityOff />}
</IconButton>
</ButtonTooltip>
<Menu
id="dataset-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "dataset-menu",
}}
>
<MenuItem
onClick={() => {
showFile(importProcess.input_dataset_url);
handleClose();
}}
disabled={importProcess.input_dataset_url == null}
>
Entrée
</MenuItem>
<MenuItem
onClick={() => {
showFile(importProcess.output_dataset_url);
handleClose();
}}
disabled={importProcess.output_dataset_url == null}
>
Sortie
</MenuItem>
</Menu>
</TableCell>
);
}
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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"
onClick={() => showFile(importProcess.shacl_report_url)}
>
<Visibility color="warning" />
</IconButton>
</ButtonTooltip>
</TableCell>
);
}
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} />;
}
}