feat: add batch metadata jobs, series filters, and translate backoffice to French
- Add metadata_batch job type with background processing via tokio::spawn - Auto-apply metadata only when single result at 100% confidence - Support primary + fallback provider per library, "none" to opt out - Add batch report/results API endpoints and job detail UI - Add series_status and has_missing filters to both series listing pages - Add GET /series/statuses endpoint for dynamic filter options - Normalize series_metadata status values (migration 0036) - Hide ComicVine provider tab when no API key configured - Translate entire backoffice UI from English to French Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -55,13 +55,13 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
body: JSON.stringify({ value })
|
||||
});
|
||||
if (response.ok) {
|
||||
setSaveMessage("Settings saved successfully");
|
||||
setSaveMessage("Paramètres enregistrés avec succès");
|
||||
setTimeout(() => setSaveMessage(null), 3000);
|
||||
} else {
|
||||
setSaveMessage("Failed to save settings");
|
||||
setSaveMessage("Échec de l'enregistrement des paramètres");
|
||||
}
|
||||
} catch (error) {
|
||||
setSaveMessage("Error saving settings");
|
||||
setSaveMessage("Erreur lors de l'enregistrement des paramètres");
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
setCacheStats(stats);
|
||||
}
|
||||
} catch (error) {
|
||||
setClearResult({ success: false, message: "Failed to clear cache" });
|
||||
setClearResult({ success: false, message: "Échec du vidage du cache" });
|
||||
} finally {
|
||||
setIsClearing(false);
|
||||
}
|
||||
@@ -150,8 +150,8 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
const [activeTab, setActiveTab] = useState<"general" | "integrations">("general");
|
||||
|
||||
const tabs = [
|
||||
{ id: "general" as const, label: "General", icon: "settings" as const },
|
||||
{ id: "integrations" as const, label: "Integrations", icon: "refresh" as const },
|
||||
{ id: "general" as const, label: "Général", icon: "settings" as const },
|
||||
{ id: "integrations" as const, label: "Intégrations", icon: "refresh" as const },
|
||||
];
|
||||
|
||||
return (
|
||||
@@ -159,7 +159,7 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
<div className="mb-6">
|
||||
<h1 className="text-3xl font-bold text-foreground flex items-center gap-3">
|
||||
<Icon name="settings" size="xl" />
|
||||
Settings
|
||||
Paramètres
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@@ -195,15 +195,15 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Icon name="image" size="md" />
|
||||
Image Processing
|
||||
Traitement d'images
|
||||
</CardTitle>
|
||||
<CardDescription>These settings only apply when a client explicitly requests format conversion via the API (e.g. <code className="text-xs bg-muted px-1 rounded">?format=webp&width=800</code>). Pages served without parameters are delivered as-is from the archive, with no processing.</CardDescription>
|
||||
<CardDescription>Ces paramètres s'appliquent uniquement lorsqu'un client demande explicitement une conversion de format via l'API (ex. <code className="text-xs bg-muted px-1 rounded">?format=webp&width=800</code>). Les pages servies sans paramètres sont livrées telles quelles depuis l'archive, sans traitement.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<FormRow>
|
||||
<FormField className="flex-1">
|
||||
<label className="text-sm font-medium text-muted-foreground mb-1 block">Default Output Format</label>
|
||||
<label className="text-sm font-medium text-muted-foreground mb-1 block">Format de sortie par défaut</label>
|
||||
<FormSelect
|
||||
value={settings.image_processing.format}
|
||||
onChange={(e) => {
|
||||
@@ -218,7 +218,7 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
</FormSelect>
|
||||
</FormField>
|
||||
<FormField className="flex-1">
|
||||
<label className="text-sm font-medium text-muted-foreground mb-1 block">Default Quality (1-100)</label>
|
||||
<label className="text-sm font-medium text-muted-foreground mb-1 block">Qualité par défaut (1-100)</label>
|
||||
<FormInput
|
||||
type="number"
|
||||
min={1}
|
||||
@@ -235,7 +235,7 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
</FormRow>
|
||||
<FormRow>
|
||||
<FormField className="flex-1">
|
||||
<label className="text-sm font-medium text-muted-foreground mb-1 block">Default Resize Filter</label>
|
||||
<label className="text-sm font-medium text-muted-foreground mb-1 block">Filtre de redimensionnement par défaut</label>
|
||||
<FormSelect
|
||||
value={settings.image_processing.filter}
|
||||
onChange={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user