feat(jobs): T22 complété - Page détail jobs avec timeline et stats
- Page /jobs/[id] avec affichage complet des détails - Timeline visuelle (Created → Started → Finished) - Barre de progression avec stats (processed/total/remaining) - Stats: scanned, indexed, removed, errors - Vitesse de traitement (fichiers/sec) - Liste des erreurs avec fichier et message - Navigation retour vers la liste - Bouton 'View' sur chaque ligne de job - Lien cliquable sur l'ID du job - Styles CSS pour timeline, progress bar, statistiques DoD: Page job détaillée avec timeline, stats et navigation complète
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { JobProgress } from "./JobProgress";
|
||||
|
||||
interface JobRowProps {
|
||||
@@ -32,14 +33,16 @@ export function JobRow({ job, libraryName, highlighted, onCancel }: JobRowProps)
|
||||
<>
|
||||
<tr className={highlighted ? "job-highlighted" : undefined}>
|
||||
<td>
|
||||
<code>{job.id.slice(0, 8)}</code>
|
||||
<Link href={`/jobs/${job.id}`} className="job-id-link">
|
||||
<code>{job.id.slice(0, 8)}</code>
|
||||
</Link>
|
||||
</td>
|
||||
<td>{job.library_id ? libraryName || job.library_id.slice(0, 8) : "—"}</td>
|
||||
<td>{job.type}</td>
|
||||
<td>
|
||||
<span className={`status-${job.status}`}>{job.status}</span>
|
||||
{job.error_opt && <span className="error-hint" title={job.error_opt}>!</span>}
|
||||
{job.status === "running" && (
|
||||
{(job.status === "running" || job.status === "pending") && (
|
||||
<button
|
||||
className="toggle-progress-btn"
|
||||
onClick={() => setShowProgress(!showProgress)}
|
||||
@@ -50,14 +53,19 @@ export function JobRow({ job, libraryName, highlighted, onCancel }: JobRowProps)
|
||||
</td>
|
||||
<td>{new Date(job.created_at).toLocaleString()}</td>
|
||||
<td>
|
||||
{job.status === "pending" || job.status === "running" ? (
|
||||
<button
|
||||
className="cancel-btn"
|
||||
onClick={() => onCancel(job.id)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
) : null}
|
||||
<div style={{ display: "flex", gap: "8px" }}>
|
||||
<Link href={`/jobs/${job.id}`} className="view-btn">
|
||||
View
|
||||
</Link>
|
||||
{(job.status === "pending" || job.status === "running") && (
|
||||
<button
|
||||
className="cancel-btn"
|
||||
onClick={() => onCancel(job.id)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{showProgress && (job.status === "running" || job.status === "pending") && (
|
||||
|
||||
Reference in New Issue
Block a user