feat(web): schedule control, next-run, broken badge, run-log modal
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user