diff --git a/docs/specs/ocr-admin-spec.html b/docs/specs/ocr-admin-spec.html new file mode 100644 index 00000000..f448b9c5 --- /dev/null +++ b/docs/specs/ocr-admin-spec.html @@ -0,0 +1,1101 @@ + + + + + +Admin — OCR: Übersicht & Modell-Detail + + + + +
+ + +
+

Admin — OCR: Übersicht & Modell-Detail

+

Neue Admin-Sektion für das OCR-Pipeline-Monitoring. Zwei Seiten: Die Übersicht zeigt Systemstatus, globale Block-Statistiken und alle Modelle (global + sendergebunden) in einer Tabelle auf einen Blick. Die Modell-Detailseite zeigt die aktuellen Trainingsmetriken und die vollständige Trainingshistorie für ein einzelnes Modell, mit Aktions-Buttons direkt über der Tabelle. Tägliche Nutzung — Statistiken und aktive Läufe sind daher immer sofort sichtbar.

+
+ Route: /admin/ocr + Route: /admin/ocr/global + Route: /admin/ocr/[personId] + Neue EntityNav-Sektion: System → OCR + Breakpoints: 320 / 640 / 1024 / 1440 + API: GET /api/ocr/training-info · POST /api/ocr/train · POST /api/ocr/segtrain +
+ +
+ + +
+

1 — Übersicht: Desktop (≥1024px)

+

Die Übersichtsseite öffnet sich beim Klick auf „OCR" in der EntityNav. Kein Split-Panel — OCR ist kein Entity-Editor. Der volle Bereich rechts der EntityNav gehört dem Dashboard. Vertikaler Fluss: Health-Bar → Statistiken → Modelltabelle → Globale Aktionen. Beim Klick auf eine Tabellenzeile wird die Modell-Detailseite geöffnet.

+
+ +
+
+
Desktop lg (1280px) — kein aktiver Lauf
+
+
+
+ + Dokumente + Personen + Admin +
M
+
+
+ +
+
Admin
+
5
Benutzer
+
3
Gruppen
+
142
Schlagwörter
+
+
+
System
+
7
OCR
+
+
+ +
+
+ OCR-Administration +
+
+ +
+ ● Service online +
+ Kein aktiver Trainingsauftrag +
+ Letzter Lauf: sender_anna_raddatz · vor 2 Std. +
+ +
+
+
1.842
+
Eligible Blocks
+
Kurrent-Erkennung
+
+
+
23
+
Dokumente
+
mit annotierten Blöcken
+
+
+
310
+
Seg. Blocks
+
Segmentierungstraining
+
+
+ +
+
+ Alle Modelle +
+
+ Modell / Absender + Genauigkeit + ZFR ① + Blöcke + Letzter Lauf + Status +
+ +
+
global_kurrent
Globales Erkennungsmodell
+ 95,1 % + 2,3 % + 1.842 + vor 1 Tag + ✓ Fertig +
+ +
+
Anna Raddatz
sender_anna_raddatz
+ 98,3 % + 1,7 % + 128 + vor 2 Std. + ✓ Fertig +
+
+
Franz Kaufmann
sender_franz_kaufmann
+ + + 45 + vor 3 Tagen + ✕ Fehler +
+
+
Marie Schulz
sender_marie_schulz
+ 96,7 % + 1,9 % + 203 + vor 3 Tagen + ✓ Fertig +
+
+
Johann Raddatz
sender_johann_raddatz
+ 94,2 % + 2,9 % + 87 + vor 1 Woche + ✓ Fertig +
+
+
+ 3 weitere Modelle
+ +
+
+ +
+
Globale Aktionen
+
+ Training Erkennung + Training Segmentierung + Erkennungsdaten exportieren + Segmentierungsdaten exportieren +
+
+
+
+
+
+ + +
Desktop lg — mit aktivem Lauf (Health-Bar + Tabellenzeile)
+
+
+
+ + Dokumente + Personen + Admin +
M
+
+
+
+
Admin
+
5
Benutzer
+
3
Gruppen
+
142
Schlagwörter
+
+
System
+
7
OCR
+
+
+
+
OCR-Administration
+
+ +
+ ● Service online +
+ ⟳ sender_anna_raddatz · läuft seit 4 Min. +
+ ⏳ 1 in Warteschlange +
+
+ +
+
Alle Modelle
+
+ Modell / AbsenderGenauigkeitZFRBlöckeLetzter LaufStatus +
+
+
global_kurrent
Globales Erkennungsmodell
+ 95,1 %2,3 %1.842 + vor 1 Tag✓ Fertig +
+
+
Anna Raddatz
sender_anna_raddatz
+ 98,3 %1,7 %128 + gerade jetzt⟳ Läuft +
+
+
Marie Schulz
sender_marie_schulz
+ 203 + ⏳ Warteschlange +
+
+
+
+
+
+
+
+ +
+
1
+
Globales Modell immer an Position 0. Die global_kurrent-Zeile hat einen leicht bläulichen Hintergrund (bg-[#F8F8FC]) und ist unabhängig von Sortierung immer die erste Zeile. Sie wird anhand personId === null identifiziert.
+
+
+
2
+
Health-Bar als Echtzeit-Primärindikator. Der Status (RUNNING, QUEUED, idle) wird via SSE aktualisiert — derselbe /api/ocr/jobs/{jobId}/progress-Kanal wie in der Dokumentenansicht. RUNNING-Tabellenzeilen erhalten zusätzlich bg-amber-50. Die Buttons „Training Erkennung" und „Training Segmentierung" werden disabled + opacity-50 wenn ein Lauf aktiv ist.
+
+
+
3
+
① ZFR = Zeichenfehlerrate (CER). Abkürzung im <th> mit title="Zeichenfehlerrate (Character Error Rate)" und aria-label für Screenreader. Kleinere Werte sind besser — ein Pfeil in der Implementierung ist optional.
+
+ + + +
+

2 — Übersicht: Mobile (320px)

+

Auf kleinen Bildschirmen stapeln sich die drei Stat-Karten einspaltig. Die Modelltabelle zeigt nur Name und Status-Pill (keine Metriken-Spalten — zu schmal). Aktions-Buttons werden vollbreit und vertikal gestapelt.

+
+ +
+
+
320px
+
+
09:41●●●●
+
+ +
+ +
+
+
+
+
+
+ +
+ OCR-Administration +
+ +
+ ● Online + Kein aktiver Lauf +
+
+ +
+
1.842
+
Eligible Blocks
+
+
+
23
+
Dokumente
+
+
+
310
+
Seg. Blocks
+
+ +
+
Alle Modelle
+
+
global_kurrent
95,1 % · 1.842 Bl.
+ +
+
+
Anna Raddatz
98,3 % · 128 Bl.
+ +
+
+
Franz Kaufmann
Fehler · 45 Bl.
+ +
+
+
Marie Schulz
96,7 % · 203 Bl.
+ +
+
+ 4 weitere…
+
+ + Training Erkennung + Training Segmentierung + Erkennungsdaten exportieren +
+
+
+
+
+ + + +
+

3 — Modell-Detail: Desktop (≥1024px)

+

Die Detailseite öffnet sich beim Klick auf eine Zeile der Übersichtstabelle. Sie folgt demselben vertikalen Muster: Metric-Cards oben, darunter die vollständige Trainingshistorie nur für dieses Modell. Für Sender-Modelle gibt es einen Link zur Personen-Detailseite. Zwei Varianten: Sender-Modell (mit Personen-Link) und globales Modell (ohne).

+
+ +
+
+
Desktop lg — sender_anna_raddatz (Lauf aktiv)
+
+
+
+ + Dokumente + Personen + Admin +
M
+
+
+
+
Admin
+
5
Benutzer
+
3
Gruppen
+
142
Schlagwörter
+
+
System
+
7
OCR
+
+
+
+ +
+ ← OCR + sender_anna_raddatz + · Anna Raddatz + ⟳ Läuft +
+
+ +
+
+
98,3 %
+
Genauigkeit
+
↑ von 97,1 % (vorher)
+
+
+
1,7 %
+
Zeichenfehlerrate
+
↓ von 2,2 % (vorher)
+
+
+
128
+
Training-Blöcke
+
beim letzten Lauf
+
+
+
50
+
Epochs
+
letztes Training
+
+
+ +
+ Trainingshistorie + Jetzt neu trainieren + Training-Daten exportieren + → Anna Raddatz +
+ +
+
+ Status + Zeitpunkt + Genauigkeit + ZFR + Blöcke + Epochs +
+
+ ⟳ Läuft + gerade jetzt + + + 128 + +
+
+ ✓ Fertig + vor 2 Std. + 98,3 % + 1,7 % + 128 + 50 +
+
+ ✓ Fertig + vor 3 Tagen + 97,1 % + 2,2 % + 92 + 50 +
+
+ ✓ Fertig + vor 1 Woche + 96,4 % + 2,8 % + 74 + 40 +
+
+ ✕ Fehler + vor 3 Wochen + + + 60 + +
+ +
+ Fehler: Connection timeout nach 120 s — OCR-Service nicht erreichbar +
+
+
+
+
+
+ + +
Desktop lg — global_kurrent (kein Personen-Link)
+
+
+
+ + Dokumente + Personen + Admin +
M
+
+
+
+
Admin
+
5
Benutzer
+
3
Gruppen
+
142
Schlagwörter
+
+
System
+
7
OCR
+
+
+
+
+ ← OCR + global_kurrent + · Globales Erkennungsmodell + ✓ Fertig +
+
+
+
+
95,1 %
+
Genauigkeit
+
↑ von 94,8 % (vorher)
+
+
+
2,3 %
+
Zeichenfehlerrate
+
↓ von 2,7 % (vorher)
+
+
+
1.842
+
Training-Blöcke
+
beim letzten Lauf
+
+
+
100
+
Epochs
+
letztes Training
+
+
+
+ Trainingshistorie + Jetzt neu trainieren + Training-Daten exportieren + +
+
+
+ StatusZeitpunktGenauigkeitZFRBlöckeEpochs +
+
+ ✓ Fertig + vor 1 Tag + 95,1 %2,3 %1.842100 +
+
+ ✓ Fertig + vor 5 Tagen + 94,8 %2,7 %1.650100 +
+
+ ✓ Fertig + vor 2 Wochen + 93,2 %3,1 %1.420100 +
+
+
+
+
+
+
+
+ +
+
4
+
Delta-Zeile in Metric-Cards. Unter jedem Metrikwert erscheint ein Vergleich zum vorherigen erfolgreichen Lauf (↑ / ↓ von X % (vorher)). Grün für Verbesserung, rot für Verschlechterung. Berechnung: letzter DONE-Lauf vs. vorletzter DONE-Lauf im nach completedAt sortierten Array. Entfällt wenn weniger als zwei DONE-Läufe vorhanden.
+
+
+
5
+
FAILED-Fehlertext inline. Bei einer FAILED-Zeile erscheint direkt darunter eine zweite Zeile mit dem errorMessage-Feld — leicht rosa hinterlegt, kein Modal nötig. Ist errorMessage null oder leer, entfällt die zweite Zeile.
+
+
+
6
+
Keine Danger-Zone. Sender-Modelle werden programmatisch durch SenderModelService angelegt und gelöscht. Die Detailseite bietet bewusst keinen manuellen Lösch-Button. Beim globalen Modell fehlt der „→ Person"-Link, da personId === null.
+
+ + + +
+

4 — Modell-Detail: Mobile (320px)

+

Die vier Metric-Cards arrangieren sich auf Mobile in einem 2×2-Raster. Aktions-Buttons nehmen die volle Breite ein. Die Trainingshistorie zeigt auf kleinen Bildschirmen nur Status, Datum und Genauigkeit — ZFR, Blöcke und Epochs entfallen.

+
+ +
+
+
320px — sender_anna_raddatz
+
+
09:41●●●●
+
+
+ +
+
+
+
+
+
+ +
+ ← OCR +
+
sender_anna_raddatz
+
Anna Raddatz
+
+ +
+
+ +
+
+
98,3 %
+
Genauigkeit
+
↑ von 97,1 %
+
+
+
1,7 %
+
ZFR
+
↓ von 2,2 %
+
+
+
128
+
Blöcke
+
letzter Lauf
+
+
+
50
+
Epochs
+
letzter Lauf
+
+
+ + Jetzt neu trainieren + Training-Daten exportieren + → Anna Raddatz + +
+
+ Trainingshistorie +
+
+ + gerade jetzt · 128 Bl. +
+
+ + vor 2 Std. + 98,3 % +
+
+ + vor 3 Tagen + 97,1 % +
+
+ + vor 1 Woche + 96,4 % +
+
+ + vor 3 Wochen · Timeout +
+
+
+
+
+
+
+ + + +
+

5 — Implementation Reference

+

Exakte Tailwind-Klassen und Pixelwerte für beide Seiten. Neue Dateien sind mit Neu markiert.

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ElementTailwind-KlassenReal px / WertHinweis
Routen & Dateien
Übersichtsrc/routes/admin/ocr/+page.svelte
src/routes/admin/ocr/+page.server.ts
GET /api/ocr/training-infoNeu
Global-Detailsrc/routes/admin/ocr/global/+page.svelteGET /api/ocr/training-info (gefiltert: personId === null)Neu
Sender-Detailsrc/routes/admin/ocr/[personId]/+page.svelteGET /api/ocr/training-info (gefiltert nach personId)Neu
EntityNav-EintragVorhandene EntityNav-Komponente um OCR-Eintrag ergänzenNeue Sektion „System" mit Separator davorBestehende Datei ändern
Seitenstruktur (beide Seiten)
OCR Content Areaflex-1 flex flex-col overflow-hidden min-w-0 bg-surfaceKein Tree-Panel, kein Edit-Panel — volle Breite nach EntityNavOCR ist kein Entity-Editor; enthält kein Split-Layout
Page Header Barflex items-center gap-2 px-4 py-2.5 border-b border-line bg-white shrink-0 h-10h: 40pxEnthält Back-Link (nur Detail), Titel, optionale Status-Pill
Scrollbarer Seiteninhaltflex-1 overflow-y-auto p-4 flex flex-col gap-3gap: 12px zwischen Sektionen
Back-Link (Detail)text-[11px] text-gray-400 hover:text-ink transition-colors shrink-0goto('/admin/ocr') oder <a href="/admin/ocr">
Health Bar (Übersicht)
Health Bar Containerflex items-center gap-3 px-4 py-2 bg-white border border-line rounded-smh: 36pxNeu
Service-Pill (online)inline-flex items-center gap-1 px-2 py-0.5 rounded-sm text-[10px] font-bold uppercase tracking-wide bg-green-50 text-green-700 border border-green-200Offline: bg-red-50 text-red-700 border-red-200
Running-Pillbg-amber-50 text-amber-700 border border-amber-200 (gleiche Basis)Nur sichtbar wenn status === 'RUNNING'. Icon ⟳ via animate-spin
Queued-Badgetext-[10px] text-amber-800 bg-amber-100 border border-amber-200 px-2 py-0.5 rounded-sm font-boldNur sichtbar wenn mind. 1 Lauf QUEUED. Text: „⏳ N in Warteschlange"
Stat Cards (Übersicht)
Grid (Desktop)grid grid-cols-1 sm:grid-cols-3 gap-3Mobile: 1 Spalte; ab 640px: 3 SpaltenNeu
Stat Cardbg-white border border-line rounded-sm px-4 py-3padding: 12px 16px · kein Hover (nicht klickbar)
Stat-Zahlfont-serif text-3xl font-bold text-ink leading-none30px, Merriweather · deutsche Tausend-Trennung via n.toLocaleString('de-DE')
Stat-Labeltext-[10px] font-bold uppercase tracking-widest text-gray-400 mt-110px
Stat-Subtexttext-[9px] text-gray-300 mt-0.59px · optional
Modell-Tabelle (Übersicht)
Tabellen-Containerbg-white border border-line rounded-sm overflow-hiddenNeu — kein <table>, sondern CSS-Grid-Rows
Tabellenkopfbg-ink grid px-4 py-2 grid-cols-[2fr_80px_80px_80px_80px_100px]Kopfzellen: text-[9px] font-bold uppercase tracking-wide text-brand-mint
Tabellenzeilegrid px-4 py-2.5 border-b border-line items-center cursor-pointer hover:bg-surface transition-colors grid-cols-[2fr_80px_80px_80px_80px_100px]Klick → goto('/admin/ocr/{id}')Mobile: Tabelle horizontal scrollbar (overflow-x-auto) oder vereinfachte 2-Spalten-Liste
Global-ZeileZusätzlich bg-[#F8F8FC]Immer erste Zeile (personId === null)
Sender-Nametext-sm font-medium text-gray-70014px · darunter modelName: text-[10px] text-gray-400 mt-0.5Name aus personNames[run.personId] des training-info-Endpoints
Metrik-Wert (gut)text-green-700 font-semiboldAccuracy ≥ 95 % oder niedrigste CER
Metrik-Wert (Fehler)text-red-600 font-semiboldZeigt „—" bei fehlenden Werten (FAILED/RUNNING)
Status Pills (alle Seiten)
Basis-Klasseninline-flex items-center gap-1 px-2 py-0.5 rounded-sm text-[10px] font-bold uppercase tracking-wide borderIcon als Textzeichen vor Label (✓ ⟳ ✕ ⏳)
DONEbg-green-50 text-green-700 border-green-200
RUNNINGbg-amber-50 text-amber-700 border-amber-200Icon ⟳ in eigenem <span class="animate-spin">
FAILEDbg-red-50 text-red-700 border-red-200
QUEUEDbg-yellow-50 text-yellow-800 border-yellow-200
Metric Cards (Detail)
Gridgrid grid-cols-2 sm:grid-cols-4 gap-3Mobile: 2×2 · Desktop: 4×1Neu
Metric Cardbg-white border border-line rounded-sm px-4 py-3 text-center
Zahl (positiv)font-serif text-3xl font-bold leading-none text-green-700Accuracy ≥ 95 %
Zahl (neutral)font-serif text-3xl font-bold leading-none text-inkStandard
Delta-Zeiletext-[10px] mt-1 + text-green-600 / text-red-600 / text-gray-40010pxFormat: „↑ von 94,8 % (vorher)". Entfällt bei < 2 DONE-Läufen.
Trainingshistorie (Detail)
Tabellen-Containerbg-white border border-line rounded-sm overflow-hidden
Tabellenkopfbg-ink grid px-4 py-2 grid-cols-[100px_1fr_80px_80px_80px_80px]Mobile: grid-cols-[80px_1fr_80px] (Status · Datum · Genauigkeit)
RUNNING-Zeilebg-amber-50 zusätzlichLeere Metrik-Zellen zeigen „—"
FAILED-Zeilebg-red-50 (sehr hell, ~#fff8f8)Fehlertext folgt als zweite Sub-Zeile: text-[11px] text-red-600 px-4 pb-2 col-span-full
Buttons & Aktionen
Primär-Buttoninline-flex items-center h-9 px-4 bg-ink text-white rounded-sm text-xs font-bold uppercase tracking-wide hover:opacity-90 transition-opacityh: 36px (44px auf Mobile)Disabled wenn Lauf aktiv: opacity-50 cursor-not-allowed pointer-events-none
Outline-Buttoninline-flex items-center h-9 px-4 border border-ink text-ink rounded-sm text-xs font-bold uppercase tracking-wide hover:bg-surface transition-colorsExport: window.location.href = '/api/ocr/training-data/export'
Personen-Linktext-sm text-ink underline underline-offset-2 hover:text-brand-mint transition-colorsNur auf Sender-Detailseite. Ziel: /persons/{personId}. Entfällt bei personId === null.
API-Aufrufe
Übersicht ladenGET /api/ocr/training-infoFelder: availableBlocks · totalOcrBlocks · availableDocuments · availableSegBlocks · ocrServiceAvailable · runs · personNamesIm +page.server.ts laden; SenderModel-Liste zusätzlich via eigenem Endpunkt oder aus runs aggregieren
Training startenPOST /api/ocr/train / POST /api/ocr/segtrainResponse: OcrTrainingRunSofort in Health-Bar und Tabelle anzeigen; SSE-Kanal öffnen
Live-UpdatesEventSource('/api/ocr/jobs/{jobId}/progress')Server-Sent EventsHealth-Bar + Status-Pills live aktualisieren; onDestroy schließen
+
+ +
+ + diff --git a/frontend/src/lib/generated/api.ts b/frontend/src/lib/generated/api.ts index 884212dc..4631e759 100644 --- a/frontend/src/lib/generated/api.ts +++ b/frontend/src/lib/generated/api.ts @@ -1756,8 +1756,6 @@ export interface components { /** Format: int64 */ totalElements?: number; pageable?: components["schemas"]["PageableObject"]; - first?: boolean; - last?: boolean; /** Format: int32 */ size?: number; content?: components["schemas"]["NotificationDTO"][]; @@ -1766,6 +1764,8 @@ export interface components { sort?: components["schemas"]["SortObject"]; /** Format: int32 */ numberOfElements?: number; + first?: boolean; + last?: boolean; empty?: boolean; }; PageableObject: { @@ -3605,7 +3605,9 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["TrainingInfoResponse"]; + "*/*": { + [key: string]: unknown; + }; }; }; };