diff --git a/apps/api/src/index_jobs.rs b/apps/api/src/index_jobs.rs index c761114..eddb1b1 100644 --- a/apps/api/src/index_jobs.rs +++ b/apps/api/src/index_jobs.rs @@ -65,6 +65,8 @@ pub struct IndexJobDetailResponse { pub finished_at: Option>, #[schema(value_type = Option)] pub phase2_started_at: Option>, + #[schema(value_type = Option)] + pub generating_thumbnails_started_at: Option>, pub stats_json: Option, pub error_opt: Option, #[schema(value_type = String)] @@ -324,6 +326,7 @@ fn map_row_detail(row: sqlx::postgres::PgRow) -> IndexJobDetailResponse { started_at: row.get("started_at"), finished_at: row.get("finished_at"), phase2_started_at: row.try_get("phase2_started_at").ok().flatten(), + generating_thumbnails_started_at: row.try_get("generating_thumbnails_started_at").ok().flatten(), stats_json: row.get("stats_json"), error_opt: row.get("error_opt"), created_at: row.get("created_at"), @@ -350,7 +353,7 @@ pub async fn get_active_jobs(State(state): State) -> Result, ) -> Result, ApiError> { let row = sqlx::query( - "SELECT id, library_id, book_id, type, status, started_at, finished_at, phase2_started_at, + "SELECT id, library_id, book_id, type, status, started_at, finished_at, phase2_started_at, generating_thumbnails_started_at, stats_json, error_opt, created_at, current_file, progress_percent, total_files, processed_files FROM index_jobs WHERE id = $1" ) diff --git a/apps/backoffice/app/components/JobProgress.tsx b/apps/backoffice/app/components/JobProgress.tsx index c74fc97..d53e6f5 100644 --- a/apps/backoffice/app/components/JobProgress.tsx +++ b/apps/backoffice/app/components/JobProgress.tsx @@ -87,8 +87,8 @@ export function JobProgress({ jobId, onComplete }: JobProgressProps) { const percent = progress.progress_percent ?? 0; const processed = progress.processed_files ?? 0; const total = progress.total_files ?? 0; - const isThumbnailsPhase = progress.status === "generating_thumbnails"; - const unitLabel = isThumbnailsPhase ? "thumbnails" : "files"; + const isPhase2 = progress.status === "extracting_pages" || progress.status === "generating_thumbnails"; + const unitLabel = progress.status === "extracting_pages" ? "pages" : progress.status === "generating_thumbnails" ? "thumbnails" : "files"; return (
@@ -112,7 +112,7 @@ export function JobProgress({ jobId, onComplete }: JobProgressProps) { )}
- {progress.stats_json && !isThumbnailsPhase && ( + {progress.stats_json && !isPhase2 && (
Scanned: {progress.stats_json.scanned_files} Indexed: {progress.stats_json.indexed_files} diff --git a/apps/backoffice/app/components/JobRow.tsx b/apps/backoffice/app/components/JobRow.tsx index c38c8fc..7a44be4 100644 --- a/apps/backoffice/app/components/JobRow.tsx +++ b/apps/backoffice/app/components/JobRow.tsx @@ -33,7 +33,7 @@ interface JobRowProps { } export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, formatDuration }: JobRowProps) { - const isActive = job.status === "running" || job.status === "pending" || job.status === "generating_thumbnails"; + const isActive = job.status === "running" || job.status === "pending" || job.status === "extracting_pages" || job.status === "generating_thumbnails"; const [showProgress, setShowProgress] = useState(highlighted || isActive); const handleComplete = () => { @@ -52,13 +52,14 @@ export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, fo const removed = job.stats_json?.removed_files ?? 0; const errors = job.stats_json?.errors ?? 0; + const isPhase2 = job.status === "extracting_pages" || job.status === "generating_thumbnails"; const isThumbnailPhase = job.status === "generating_thumbnails"; const isThumbnailJob = job.type === "thumbnail_rebuild" || job.type === "thumbnail_regenerate"; - const hasThumbnailPhase = isThumbnailPhase || isThumbnailJob; + const hasThumbnailPhase = isPhase2 || isThumbnailJob; - // Files column: index-phase stats only + // Files column: index-phase stats only (Phase 1 discovery) const filesDisplay = - job.status === "running" && !isThumbnailPhase + job.status === "running" && !isPhase2 ? job.total_files != null ? `${job.processed_files ?? 0}/${job.total_files}` : scanned > 0 @@ -70,8 +71,8 @@ export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, fo ? `${scanned} scanned` : "—"; - // Thumbnails column - const thumbInProgress = hasThumbnailPhase && (job.status === "running" || isThumbnailPhase); + // Thumbnails column (Phase 2: extracting_pages + generating_thumbnails) + const thumbInProgress = hasThumbnailPhase && (job.status === "running" || isPhase2); const thumbDisplay = thumbInProgress && job.total_files != null ? `${job.processed_files ?? 0}/${job.total_files}` @@ -128,7 +129,7 @@ export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, fo {errors > 0 && ⚠ {errors}}
)} - {job.status === "running" && !isThumbnailPhase && job.total_files != null && ( + {job.status === "running" && !isPhase2 && job.total_files != null && ( )} @@ -155,7 +156,7 @@ export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, fo > View - {(job.status === "pending" || job.status === "running" || job.status === "generating_thumbnails") && ( + {(job.status === "pending" || job.status === "running" || job.status === "extracting_pages" || job.status === "generating_thumbnails") && (