import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { listJobs, fetchLibraries, rebuildIndex, rebuildThumbnails, regenerateThumbnails, startMetadataBatch, IndexJobDto, LibraryDto } from "../../lib/api"; import { JobsList } from "../components/JobsList"; import { Card, CardHeader, CardTitle, CardDescription, CardContent, Button, FormField, FormSelect, FormRow } from "../components/ui"; export const dynamic = "force-dynamic"; export default async function JobsPage({ searchParams }: { searchParams: Promise<{ highlight?: string }> }) { const { highlight } = await searchParams; const [jobs, libraries] = await Promise.all([ listJobs().catch(() => [] as IndexJobDto[]), fetchLibraries().catch(() => [] as LibraryDto[]) ]); const libraryMap = new Map(libraries.map(l => [l.id, l.name])); async function triggerRebuild(formData: FormData) { "use server"; const libraryId = formData.get("library_id") as string; const result = await rebuildIndex(libraryId || undefined); revalidatePath("/jobs"); redirect(`/jobs?highlight=${result.id}`); } async function triggerFullRebuild(formData: FormData) { "use server"; const libraryId = formData.get("library_id") as string; const result = await rebuildIndex(libraryId || undefined, true); revalidatePath("/jobs"); redirect(`/jobs?highlight=${result.id}`); } async function triggerThumbnailsRebuild(formData: FormData) { "use server"; const libraryId = formData.get("library_id") as string; const result = await rebuildThumbnails(libraryId || undefined); revalidatePath("/jobs"); redirect(`/jobs?highlight=${result.id}`); } async function triggerThumbnailsRegenerate(formData: FormData) { "use server"; const libraryId = formData.get("library_id") as string; const result = await regenerateThumbnails(libraryId || undefined); revalidatePath("/jobs"); redirect(`/jobs?highlight=${result.id}`); } async function triggerMetadataBatch(formData: FormData) { "use server"; const libraryId = formData.get("library_id") as string; if (!libraryId) return; const result = await startMetadataBatch(libraryId); revalidatePath("/jobs"); redirect(`/jobs?highlight=${result.id}`); } return ( <>
Scan incrémental : détecte les fichiers ajoutés, modifiés ou supprimés depuis le dernier scan, les indexe et génère les miniatures manquantes. Les données existantes non modifiées sont conservées. C’est l’action la plus courante et la plus rapide.
Supprime toutes les données indexées (livres, séries, miniatures) puis effectue un scan complet depuis zéro. Utile si la base de données est désynchronisée ou corrompue. Opération longue et destructive : les statuts de lecture et les métadonnées manuelles seront perdus.
Génère les miniatures uniquement pour les livres qui n’en ont pas encore. Les miniatures existantes ne sont pas touchées. Utile après un import ou si certaines miniatures sont manquantes.
Regénère toutes les miniatures depuis zéro, en remplaçant les existantes. Utile si la qualité ou la taille des miniatures a changé dans la configuration, ou si des miniatures sont corrompues.
Recherche automatiquement les métadonnées de chaque série de la bibliothèque auprès du provider configuré (avec fallback si configuré). Seuls les résultats avec un match unique à 100% de confiance sont appliqués automatiquement. Les séries déjà liées sont ignorées. Un rapport détaillé par série est disponible à la fin du job. Requiert une bibliothèque spécifique (ne fonctionne pas sur « Toutes les bibliothèques »).