You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fms/components/elements/processes/index.tsx

219 lines
9.0 KiB

import styles from './styles.module.css'
import {useEffect, useState} from "react"
import DeleteForeverOutlined from "@mui/icons-material/DeleteForeverOutlined"
import StopCircleOutlined from "@mui/icons-material/StopCircleOutlined"
import PauseCircleOutline from "@mui/icons-material/PauseCircleOutline"
import PlayCircleOutline from "@mui/icons-material/PlayCircleOutline"
import HourglassEmptyOutlined from "@mui/icons-material/HourglassEmptyOutlined"
import CheckCircleOutline from "@mui/icons-material/CheckCircleOutline"
import ErrorOutline from "@mui/icons-material/ErrorOutline"
import ReplayOutlined from "@mui/icons-material/ReplayOutlined"
import RunCircleOutlined from "@mui/icons-material/RunCircleOutlined"
import FactCheckOutlined from "@mui/icons-material/FactCheckOutlined"
import {IconButton, LinearProgress, TableContainer, Table, TableBody, TableCell, TableHead, TableRow, TablePagination} from "@mui/material"
import ConfirmDialog from "../confirm-dialog";
import smClient from "../../../api/sm/sm-client";
export interface ProcessExceptionInterface {
message: string,
file: string,
line: number,
code: number,
trace: any[],
}
export interface ProcessProgressInterface {
total: number,
progress: number,
memory: any[],
remaining: string
percent: number
}
export interface ProcessInterface {
id: string,
lock: string | null,
containerUuid: string | null,
pid: bigint | null,
name: string,
options: Record<string, any>,
arguments: Record<string, any>,
exception: ProcessExceptionInterface | null,
progress: ProcessProgressInterface | null,
outputId: string | null,
createdAt: string,
updatedAt: string | null,
startedAt: string | null,
pausedAt: string | null,
cancelledAt: string | null
completedAt: string | null
status: Status
canPlay: boolean
canPause: boolean
canRepeat: boolean
canStop: boolean
canKill: boolean
}
enum Status {
Wait = 'wait',
Running = 'running',
Cancelled = 'cancelled',
Error = 'error',
Success = 'success',
}
export default function Processes() {
const [processes, setProcesses] = useState<ProcessInterface[]>([]);
const [page, setPage] = useState<number>(0);
const [count, setCount] = useState<number>(0);
const [open, setOpen] = useState<boolean>(false);
const [selectedProcess, setSelectedProcess] = useState<ProcessInterface | null>(null);
let refreshLock = false
let refreshProcesses = async () => {
if (refreshLock) {
return
}
refreshLock = true
const { data: processes, headers } = await smClient.getProcesses({
page: page + 1,
limit: 20,
})
setProcesses(processes)
setCount(Number(headers.get('X-Pagination-Count')))
refreshLock = false
}
let output = async (process: ProcessInterface) => {
const { data: output } = await smClient.getProcessOutput({
id: process.id
})
let a = document.createElement("a");
let file = new Blob([output], {type: 'plain/text'});
a.href = URL.createObjectURL(file);
a.download = `${process.id}.txt`;
a.click();
}
useEffect(() => {
const timer = setInterval(() => refreshProcesses(), 1000)
return () => clearInterval(timer);
}, [page]);
let isFinished = (process: ProcessInterface) => process.cancelledAt || process.completedAt
const handleChangePage = (event: any, page: number) => {
setPage(page);
}
const openRepeatDialog = (process: ProcessInterface) => {
setSelectedProcess(process)
setOpen(true)
}
let lock = false
const repeat = async (dialogId: string) => {
if (lock) {
return
}
if (!selectedProcess) {
return
}
lock = true
await smClient.repeatProcess({
id: selectedProcess.id,
requestId: dialogId
})
lock = false
setSelectedProcess(null)
setOpen(false)
}
return (
<>
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>Progress</TableCell>
<TableCell>Status</TableCell>
<TableCell>Action</TableCell>
<TableCell>Created</TableCell>
</TableRow>
</TableHead>
<TableBody>
{processes.map((process: ProcessInterface, index: number) => (
<TableRow key={process.id}>
<TableCell>{process.name}</TableCell>
<TableCell>
{!process.progress && !isFinished(process) && <LinearProgress/>}
{!process.progress && isFinished(process) && <LinearProgress variant="determinate" value={100}/>}
{process.progress && <LinearProgress variant="determinate" value={process.progress.percent}/>}
{process.progress && <span>
{`${process.progress.progress}`} / {`${process.progress.total}`} - {process.progress.percent}% [{process.progress.memory}] / {process.progress.remaining}
</span>}
{process.canPlay && <IconButton title={`Play`} aria-label="Play">
<PlayCircleOutline/>
</IconButton>}
{process.canPause && <IconButton title={`Pause`} aria-label="Pause">
<PauseCircleOutline/>
</IconButton>}
{process.canStop && <IconButton title={`Stop`} aria-label="Stop">
<StopCircleOutlined/>
</IconButton>}
</TableCell>
<TableCell>
{Status.Error === process.status && <IconButton title={`Error`} aria-label="Error">
<ErrorOutline/>
</IconButton>}
{Status.Success === process.status && <IconButton title={`Success`} aria-label="Success">
<CheckCircleOutline/>
</IconButton>}
{Status.Running === process.status && <IconButton title={`Running`} aria-label="Running">
<RunCircleOutlined/>
</IconButton>}
{Status.Cancelled === process.status && <IconButton title={`Cancelled`} aria-label="Cancelled">
<StopCircleOutlined/>
</IconButton>}
{Status.Wait === process.status && <IconButton title={`Wait`} aria-label="Wait">
<HourglassEmptyOutlined/>
</IconButton>}
</TableCell>
<TableCell>
{process.canRepeat && <IconButton onClick={() => openRepeatDialog(process)} title={`Repeat`} aria-label="Repeat">
<ReplayOutlined/>
</IconButton>}
{process.canKill && <IconButton title={`Kill`} aria-label="Kill">
<DeleteForeverOutlined/>
</IconButton>}
{process?.outputId && <IconButton title={`Output`} onClick={() => output(process)} aria-label="Output">
<FactCheckOutlined/>
</IconButton>}
</TableCell>
<TableCell title={new Date(process.createdAt).toLocaleString()}>
{new Date(process.createdAt).toLocaleDateString()}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
component="div"
count={count}
rowsPerPage={20}
page={page}
onPageChange={handleChangePage}
/>
<ConfirmDialog open={open} text={'!!!'} agreeCallback={repeat} closeCallback={() => {
setSelectedProcess(null)
setOpen(false)
}}/>
</>
)
}