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"; export interface ProcessExceptionInterface { message: string, file: string, line: number, code: number, trace: any[], } export interface ProcessProgressInterface { total: number, progress: number, memory: any[], } export interface ProcessInterface { id: string, lock: string | null, containerUuid: string | null, pid: bigint | null, name: string, options: Record, arguments: Record, 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 } enum Status { Wait, Running, Cancelled, Error, Success } export default function Processes() { const [processes, setProcesses] = useState([]); const [page, setPage] = useState(0); const [count, setCount] = useState(0); const [open, setOpen] = useState(false); const [selectedProcess, setSelectedProcess] = useState(null); let refreshLock = false let refreshProcesses = async () => { if (refreshLock) { return } refreshLock = true let response = await fetch('http://fmw.sipachev.sv/system-monitoring/processes?' + new URLSearchParams({ page: page + 1, limit: 20, }), { method: 'GET', headers: { 'X-Plugin-Token': 'passw0rd', 'X-Pagination-Count': '0', }, }); const processes: ProcessInterface[] = await response.json() setProcesses(processes) setCount(Number(response.headers.get('X-Pagination-Count'))) refreshLock = false } let output = async (process: ProcessInterface) => { let response = await fetch(`http://fmw.sipachev.sv/system-monitoring/processes/${process.id}/output`, { method: 'GET', headers: { 'X-Plugin-Token': 'passw0rd', 'X-Pagination-Count': '0', }, }); const output: string = await response.text() 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 let canPlay = (process: ProcessInterface) => !isFinished(process) && process.progress && process.pausedAt let canPause = (process: ProcessInterface) => !isFinished(process) && process.progress && !process.pausedAt let canRepeat = (process: ProcessInterface) => isFinished(process) let canStop = (process: ProcessInterface) => !isFinished(process) && process.progress let canKill = (process: ProcessInterface) => !isFinished(process) && process.startedAt let progress = (progress: ProcessProgressInterface) => progress.progress / progress.total * 100 let status = (process: ProcessInterface): Status => { if (process.cancelledAt && process.completedAt) { return Status.Cancelled } if (process.exception && process.completedAt) { return Status.Error } if (!process.exception && process.completedAt) { return Status.Success } if (process.startedAt && !process.completedAt) { return Status.Running } return Status.Wait } 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 let url = `http://fmw.sipachev.sv/system-monitoring/processes/${selectedProcess.id}/repeat` let data = { requestId: dialogId } let response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json;charset=utf-8', 'X-Plugin-Token': 'passw0rd' }, body: JSON.stringify(data) }); lock = false setSelectedProcess(null) setOpen(false) } return ( <> Name Progress Status Action Created {processes.map((process: ProcessInterface, index: number) => ( {process.name} {!process.progress && !isFinished(process) && } {!process.progress && isFinished(process) && } {process.progress && } {process.progress && {`${process.progress.progress}`} / {`${process.progress.total}`} - 50% [53Mb] / 20 sec } {canPlay(process) && } {canPause(process) && } {canStop(process) && } {Status.Error === status(process) && } {Status.Success === status(process) && } {Status.Running === status(process) && } {Status.Cancelled === status(process) && } {Status.Wait === status(process) && } {canRepeat(process) && openRepeatDialog(process)} title={`Repeat`} aria-label="Repeat"> } {canKill(process) && } {process?.outputId && output(process)} aria-label="Output"> } {new Date(process.createdAt).toLocaleDateString()} ))}
{ setSelectedProcess(null) setOpen(false) }}/> ) }