feat(training): add document-level training enrollment

- V29 migration: document_training_labels join table
- TrainingLabel enum: KURRENT_RECOGNITION, KURRENT_SEGMENTATION
- Document.trainingLabels @ElementCollection
- DocumentService.addTrainingLabel / removeTrainingLabel
- PATCH /api/documents/{id}/training-labels (WRITE_ALL)
- Auto-enroll on Kurrent OCR trigger (OcrService.startOcr)
- TranscriptionEditView: enrollment chips in panel footer
- JPQL queries updated to use MEMBER OF trainingLabels

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-13 14:30:51 +02:00
parent 73229077be
commit fdf1eb92ad
12 changed files with 614 additions and 11 deletions

View File

@@ -129,6 +129,15 @@ async function reviewToggle(blockId: string) {
transcriptionBlocks = transcriptionBlocks.map((b) => (b.id === blockId ? updated : b));
}
async function toggleTrainingLabel(label: string, enrolled: boolean) {
const res = await fetch(`/api/documents/${doc.id}/training-labels`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ label, enrolled })
});
if (!res.ok) throw new Error('Failed to update training label');
}
let ocrRunning = $state(false);
let ocrProgressMessage = $state('');
let ocrErrorMessage = $state('');
@@ -449,11 +458,14 @@ onMount(() => {
activeAnnotationId={activeAnnotationId}
storedScriptType={doc.scriptType ?? ''}
canRunOcr={canWrite && !!doc.filePath}
canWrite={canWrite}
trainingLabels={doc.trainingLabels ?? []}
onBlockFocus={handleBlockFocus}
onSaveBlock={saveBlock}
onDeleteBlock={deleteBlock}
onReviewToggle={reviewToggle}
onTriggerOcr={triggerOcr}
onToggleTrainingLabel={toggleTrainingLabel}
/>
{/if}
</div>