feat(backoffice): améliorer les détails de job avec historique des phases

- Ajoute migration 0015 : colonne phase2_started_at sur index_jobs
- Indexer : renseigne phase2_started_at lors du passage à generating_thumbnails
- API : expose phase2_started_at et book_id dans IndexJobDetailResponse
- Page détail : timeline avec durée de chaque phase (Discovery / Thumbnails)
- Page détail : banners contextuels (success/failed/cancelled) avec résumé en une ligne
- Page détail : description textuelle du type de job, durée dans l'overview
- Page détail : stats normalisées selon le type (index vs thumbnail-only)
- JobRow : affiche le type via JobTypeBadge (cohérence visuelle)
- Badge : labels lisibles pour tous les types de jobs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 16:40:01 +01:00
parent ff59ac1eff
commit 278f422206
6 changed files with 325 additions and 88 deletions

View File

@@ -157,7 +157,7 @@ pub async fn process_job(
// Thumbnail rebuild: generate thumbnails for books missing them
if job_type == "thumbnail_rebuild" {
sqlx::query(
"UPDATE index_jobs SET status = 'generating_thumbnails', started_at = NOW() WHERE id = $1",
"UPDATE index_jobs SET status = 'generating_thumbnails', started_at = NOW(), phase2_started_at = NOW() WHERE id = $1",
)
.bind(job_id)
.execute(&state.pool)
@@ -178,7 +178,7 @@ pub async fn process_job(
// Thumbnail regenerate: clear all thumbnails then re-generate
if job_type == "thumbnail_regenerate" {
sqlx::query(
"UPDATE index_jobs SET status = 'generating_thumbnails', started_at = NOW() WHERE id = $1",
"UPDATE index_jobs SET status = 'generating_thumbnails', started_at = NOW(), phase2_started_at = NOW() WHERE id = $1",
)
.bind(job_id)
.execute(&state.pool)
@@ -320,7 +320,7 @@ pub async fn process_job(
// Phase 2: Analysis (extract page_count + thumbnails for new/updated books)
sqlx::query(
"UPDATE index_jobs SET status = 'generating_thumbnails', stats_json = $2, current_file = NULL, processed_files = $3 WHERE id = $1",
"UPDATE index_jobs SET status = 'generating_thumbnails', phase2_started_at = NOW(), stats_json = $2, current_file = NULL, processed_files = $3 WHERE id = $1",
)
.bind(job_id)
.bind(serde_json::to_value(&stats)?)