feat(web): schedule control, next-run, broken badge, run-log modal

This commit is contained in:
2026-07-03 13:19:14 +07:00
parent d2c69c6a5e
commit e8acab6920
5 changed files with 147 additions and 2 deletions
+55
View File
@@ -0,0 +1,55 @@
import { useEffect, useState } from 'react'
import { Modal } from './Modal'
import { StatusBadge } from './StatusBadge'
import { listRuns, type Run } from '../api'
const fmt = (iso: string | null) => (iso ? new Date(iso).toLocaleString() : '—')
export function RunLogModal({ taskId, open, onClose }: { taskId: number; open: boolean; onClose: () => void }) {
const [runs, setRuns] = useState<Run[] | null>(null)
useEffect(() => {
if (!open) return
setRuns(null)
listRuns(taskId).then((r) => setRuns(r ?? [])).catch(() => setRuns([]))
}, [open, taskId])
return (
<Modal open={open} title="Run log" onClose={onClose} size="lg">
<div className="tbl-wrap">
<table className="tbl">
<thead>
<tr>
<th>Started</th>
<th>Finished</th>
<th>Trigger</th>
<th>Status</th>
<th>Copied</th>
<th>Skipped</th>
<th>Errors</th>
</tr>
</thead>
<tbody>
{runs === null ? (
<tr className="empty-row"><td colSpan={7}>loading</td></tr>
) : runs.length === 0 ? (
<tr className="empty-row"><td colSpan={7}>no runs yet</td></tr>
) : (
runs.map((r) => (
<tr key={r.id}>
<td>{fmt(r.started_at)}</td>
<td>{fmt(r.finished_at)}</td>
<td>{r.trigger}</td>
<td><StatusBadge status={r.status} /></td>
<td className="num-cell">{r.total_copied}</td>
<td className="num-cell">{r.total_skipped}</td>
<td className="num-cell">{r.total_errors}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</Modal>
)
}