85 lines
3.3 KiB
TypeScript
85 lines
3.3 KiB
TypeScript
import {
|
|
Chip,
|
|
Paper,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
} from "@mui/material";
|
|
import type { BackupJob, BackupRun } from "../types/backups";
|
|
|
|
interface Props {
|
|
jobs: BackupJob[];
|
|
latestRuns: Map<string, BackupRun>;
|
|
}
|
|
|
|
function formatInterval(seconds: number | null): string {
|
|
if (!seconds) return "N/A";
|
|
if (seconds < 60) return `${seconds}s`;
|
|
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
|
|
return `${Math.floor(seconds / 86400)}d`;
|
|
}
|
|
|
|
function formatTimestamp(ts: number | null): string {
|
|
if (!ts) return "Never";
|
|
return new Date(ts * 1000).toLocaleString();
|
|
}
|
|
|
|
export default function BackupJobsTable({ jobs, latestRuns }: Props) {
|
|
return (
|
|
<TableContainer component={Paper}>
|
|
<Table>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell>Name</TableCell>
|
|
<TableCell>Source</TableCell>
|
|
<TableCell>Target</TableCell>
|
|
<TableCell>Schedule</TableCell>
|
|
<TableCell>Last Status</TableCell>
|
|
<TableCell>Last Run</TableCell>
|
|
<TableCell>Next Expected</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{jobs.map((job) => {
|
|
const run = latestRuns.get(job.id);
|
|
const status = run?.status ?? "unknown";
|
|
const nextExpected = run && job.schedule_interval_seconds
|
|
? run.started_at + job.schedule_interval_seconds
|
|
: null;
|
|
|
|
return (
|
|
<TableRow key={job.id} hover>
|
|
<TableCell>{job.name}</TableCell>
|
|
<TableCell>{job.source ?? "—"}</TableCell>
|
|
<TableCell>{job.target ?? "—"}</TableCell>
|
|
<TableCell>{formatInterval(job.schedule_interval_seconds)}</TableCell>
|
|
<TableCell>
|
|
<Chip
|
|
label={status}
|
|
color={
|
|
status === "success"
|
|
? "success"
|
|
: status === "failure"
|
|
? "error"
|
|
: status === "in_progress"
|
|
? "warning"
|
|
: "default"
|
|
}
|
|
size="small"
|
|
/>
|
|
</TableCell>
|
|
<TableCell>{formatTimestamp(run?.started_at ?? null)}</TableCell>
|
|
<TableCell>{formatTimestamp(nextExpected)}</TableCell>
|
|
</TableRow>
|
|
);
|
|
})}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
);
|
|
}
|