|
|
|
@ -1,36 +1,54 @@ |
|
|
|
|
import styles from './styles.module.css' |
|
|
|
|
import {useEffect, useState} from "react"; |
|
|
|
|
import DeleteForever from "@mui/icons-material/DeleteForever"; |
|
|
|
|
import StopCircle from "@mui/icons-material/StopCircle"; |
|
|
|
|
import PauseCircleOutline from "@mui/icons-material/PauseCircleOutline"; |
|
|
|
|
import PlayCircleOutline from "@mui/icons-material/PlayCircleOutline"; |
|
|
|
|
import HourglassEmpty from "@mui/icons-material/HourglassEmpty"; |
|
|
|
|
import CheckCircleOutline from "@mui/icons-material/CheckCircleOutline"; |
|
|
|
|
import ErrorOutline from "@mui/icons-material/ErrorOutline"; |
|
|
|
|
import Replay from "@mui/icons-material/Replay"; |
|
|
|
|
import RunCircle from "@mui/icons-material/RunCircle"; |
|
|
|
|
import {IconButton, LinearProgress, Table, TableBody, TableCell, TableHead, TableRow} from "@mui/material"; |
|
|
|
|
|
|
|
|
|
export interface ProcessExceptionInterface { |
|
|
|
|
message: string, |
|
|
|
|
file: string, |
|
|
|
|
line: bigint, |
|
|
|
|
code: bigint, |
|
|
|
|
line: number, |
|
|
|
|
code: number, |
|
|
|
|
trace: any[], |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface ProcessProgressInterface { |
|
|
|
|
total: bigint, |
|
|
|
|
progress: bigint, |
|
|
|
|
total: number, |
|
|
|
|
progress: number, |
|
|
|
|
memory: any[], |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface ProcessInterface { |
|
|
|
|
id: string, |
|
|
|
|
lock: string|null, |
|
|
|
|
containerUuid: string|null, |
|
|
|
|
pid: bigint|null, |
|
|
|
|
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, |
|
|
|
|
exception: ProcessExceptionInterface | null, |
|
|
|
|
progress: ProcessProgressInterface | null, |
|
|
|
|
createdAt: string, |
|
|
|
|
updatedAt: string|null, |
|
|
|
|
startedAt: string|null, |
|
|
|
|
pausedAt: string|null, |
|
|
|
|
cancelledAt: string|null |
|
|
|
|
completedAt: string|null |
|
|
|
|
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() { |
|
|
|
@ -40,7 +58,6 @@ export default function Processes() { |
|
|
|
|
let response = await fetch('http://fmw.sipachev.sv/system-monitoring/processes', { |
|
|
|
|
method: 'GET', |
|
|
|
|
headers: { |
|
|
|
|
'Content-Type': 'application/json;charset=utf-8', |
|
|
|
|
'X-Plugin-Token': 'passw0rd' |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
@ -53,28 +70,88 @@ export default function Processes() { |
|
|
|
|
refreshProcesses() |
|
|
|
|
}, []) |
|
|
|
|
|
|
|
|
|
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) |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<div className={styles.processes}> |
|
|
|
|
{processes.map((process: ProcessInterface, index: number) => ( |
|
|
|
|
<div className={styles.process} key={index}> |
|
|
|
|
<div> |
|
|
|
|
{process.name} |
|
|
|
|
</div> |
|
|
|
|
<div> |
|
|
|
|
{!process.progress && 'N/A'} |
|
|
|
|
{process.progress && <span> |
|
|
|
|
{`${process.progress.progress}`} / {`${process.progress.total}`} - 50% [53Mb] / 20 sec |
|
|
|
|
</span>} |
|
|
|
|
</div> |
|
|
|
|
<div> |
|
|
|
|
{process.completedAt && <button>Repeat</button>} |
|
|
|
|
{process.pausedAt && <button>Play</button>} |
|
|
|
|
{!process.pausedAt && !process.completedAt && !process.cancelledAt && <button>Pause</button>} |
|
|
|
|
{!process.completedAt && !process.cancelledAt && <button>Stop</button>} |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
))} |
|
|
|
|
</div> |
|
|
|
|
<Table> |
|
|
|
|
<TableHead> |
|
|
|
|
<TableRow> |
|
|
|
|
<TableCell>Name</TableCell> |
|
|
|
|
<TableCell>Progress</TableCell> |
|
|
|
|
<TableCell>Action</TableCell> |
|
|
|
|
<TableCell>Status</TableCell> |
|
|
|
|
</TableRow> |
|
|
|
|
</TableHead> |
|
|
|
|
<TableBody> |
|
|
|
|
{processes.map((process: ProcessInterface, index: number) => ( |
|
|
|
|
<TableRow key={process.id}> |
|
|
|
|
<TableCell>{process.name}</TableCell> |
|
|
|
|
<TableCell> |
|
|
|
|
{!process.progress && <LinearProgress/>} |
|
|
|
|
{process.progress && <LinearProgress value={progress(process.progress)}/>} |
|
|
|
|
{process.progress && <span> |
|
|
|
|
{`${process.progress.progress}`} / {`${process.progress.total}`} - 50% [53Mb] / 20 sec |
|
|
|
|
</span>} |
|
|
|
|
{canPlay(process) && <IconButton aria-label="Play"> |
|
|
|
|
<PlayCircleOutline/> |
|
|
|
|
</IconButton>} |
|
|
|
|
{canPause(process) && <IconButton aria-label="Pause"> |
|
|
|
|
<PauseCircleOutline/> |
|
|
|
|
</IconButton>} |
|
|
|
|
{canStop(process) && <IconButton aria-label="Stop"> |
|
|
|
|
<StopCircle/> |
|
|
|
|
</IconButton>} |
|
|
|
|
</TableCell> |
|
|
|
|
<TableCell> |
|
|
|
|
{canRepeat(process) && <IconButton aria-label="Repeat"> |
|
|
|
|
<Replay/> |
|
|
|
|
</IconButton>} |
|
|
|
|
{canKill(process) && <IconButton aria-label="Kill"> |
|
|
|
|
<DeleteForever/> |
|
|
|
|
</IconButton>} |
|
|
|
|
</TableCell> |
|
|
|
|
<TableCell> |
|
|
|
|
{Status.Error === status(process) && <IconButton aria-label="Error"> |
|
|
|
|
<ErrorOutline/> |
|
|
|
|
</IconButton>} |
|
|
|
|
{Status.Success === status(process) && <IconButton aria-label="Success"> |
|
|
|
|
<CheckCircleOutline/> |
|
|
|
|
</IconButton>} |
|
|
|
|
{Status.Running === status(process) && <IconButton aria-label="Running"> |
|
|
|
|
<RunCircle/> |
|
|
|
|
</IconButton>} |
|
|
|
|
{Status.Cancelled === status(process) && <IconButton aria-label="Cancelled"> |
|
|
|
|
<StopCircle/> |
|
|
|
|
</IconButton>} |
|
|
|
|
{Status.Wait === status(process) && <IconButton aria-label="Wait"> |
|
|
|
|
<HourglassEmpty/> |
|
|
|
|
</IconButton>} |
|
|
|
|
</TableCell> |
|
|
|
|
</TableRow> |
|
|
|
|
))} |
|
|
|
|
</TableBody> |
|
|
|
|
</Table> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|