feat(ocr): move training cards from system page to OCR overview page

OcrTrainingCard and SegmentationTrainingCard now live on the dedicated
OCR overview page. System page no longer fetches training info.
SegmentationTrainingCard updated to use shared TrainingRun type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-18 10:52:23 +02:00
parent 9ff498a194
commit cea1234400
4 changed files with 10 additions and 36 deletions

View File

@@ -1,23 +1,12 @@
<script lang="ts"> <script lang="ts">
import TrainingHistory from './TrainingHistory.svelte'; import TrainingHistory from './TrainingHistory.svelte';
import { m } from '$lib/paraglide/messages.js'; import { m } from '$lib/paraglide/messages.js';
import type { TrainingRun } from '$lib/types/training.js';
interface Run {
id: string;
status: 'RUNNING' | 'DONE' | 'FAILED';
blockCount: number;
documentCount: number;
modelName: string;
errorMessage?: string;
triggeredBy?: string;
createdAt: string;
completedAt?: string;
}
interface TrainingInfo { interface TrainingInfo {
availableSegBlocks?: number; availableSegBlocks?: number;
ocrServiceAvailable?: boolean; ocrServiceAvailable?: boolean;
runs?: Run[]; runs?: TrainingRun[];
} }
interface Props { interface Props {

View File

@@ -3,6 +3,8 @@ import type { PageData } from './$types';
import OcrHealthBar from './OcrHealthBar.svelte'; import OcrHealthBar from './OcrHealthBar.svelte';
import OcrStatCards from './OcrStatCards.svelte'; import OcrStatCards from './OcrStatCards.svelte';
import OcrModelsTable from './OcrModelsTable.svelte'; import OcrModelsTable from './OcrModelsTable.svelte';
import OcrTrainingCard from '$lib/components/OcrTrainingCard.svelte';
import SegmentationTrainingCard from '$lib/components/SegmentationTrainingCard.svelte';
import * as m from '$lib/paraglide/messages.js'; import * as m from '$lib/paraglide/messages.js';
let { data }: { data: PageData } = $props(); let { data }: { data: PageData } = $props();
@@ -27,6 +29,12 @@ const { trainingInfo } = $derived(data);
availableSegBlocks={trainingInfo.availableSegBlocks ?? 0} availableSegBlocks={trainingInfo.availableSegBlocks ?? 0}
/> />
<!-- Training -->
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
<OcrTrainingCard trainingInfo={trainingInfo} />
<SegmentationTrainingCard trainingInfo={trainingInfo} />
</div>
<!-- Sender models --> <!-- Sender models -->
<div> <div>
<div class="mb-3 flex items-center justify-between"> <div class="mb-3 flex items-center justify-between">

View File

@@ -1,13 +1,6 @@
<script lang="ts"> <script lang="ts">
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
import { m } from '$lib/paraglide/messages.js'; import { m } from '$lib/paraglide/messages.js';
import OcrTrainingCard from '$lib/components/OcrTrainingCard.svelte';
import SegmentationTrainingCard from '$lib/components/SegmentationTrainingCard.svelte';
import type { components } from '$lib/generated/api.js';
type TrainingInfo = components['schemas']['TrainingInfoResponse'];
let trainingInfo: TrainingInfo | null = $state(null);
let backfillResult: number | null = $state(null); let backfillResult: number | null = $state(null);
let backfillLoading = $state(false); let backfillLoading = $state(false);
@@ -58,16 +51,8 @@ async function triggerImport() {
} }
} }
async function fetchTrainingInfo() {
const res = await fetch('/api/ocr/training-info');
if (res.ok) {
trainingInfo = await res.json();
}
}
$effect(() => { $effect(() => {
fetchImportStatus(); fetchImportStatus();
fetchTrainingInfo();
}); });
onDestroy(() => stopPolling()); onDestroy(() => stopPolling());
@@ -103,12 +88,6 @@ async function backfillFileHashes() {
<div class="flex-1 overflow-y-auto p-6"> <div class="flex-1 overflow-y-auto p-6">
<div class="mx-auto max-w-2xl space-y-5"> <div class="mx-auto max-w-2xl space-y-5">
<!-- OCR Recognition Training -->
<OcrTrainingCard trainingInfo={trainingInfo} />
<!-- OCR Segmentation Training -->
<SegmentationTrainingCard trainingInfo={trainingInfo} />
<!-- Backfill versions --> <!-- Backfill versions -->
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm"> <div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-1 font-sans text-sm font-bold text-ink">{m.admin_system_backfill_heading()}</h2> <h2 class="mb-1 font-sans text-sm font-bold text-ink">{m.admin_system_backfill_heading()}</h2>

View File

@@ -78,8 +78,6 @@ describe('Admin system page — mass import card', () => {
startedAt: null startedAt: null
}) })
}) })
// training info fetch → empty
.mockResolvedValueOnce({ ok: true, json: async () => ({}) })
// trigger POST → returns RUNNING immediately // trigger POST → returns RUNNING immediately
.mockResolvedValueOnce({ .mockResolvedValueOnce({
ok: true, ok: true,