feat(admin): add OCR training card to admin/system page
- TrainingHistory.svelte: responsive table with status badges (green/red/animated pulse), keyed iteration, empty-state row - OcrTrainingCard.svelte: shows available blocks/docs, disabled states (< 5 blocks, service down), in-flight "…" state, 5s success message, embeds TrainingHistory - Wired into admin/system/+page.svelte via fetchTrainingInfo() in $effect - Regenerated api.ts with OcrTrainingRun + TrainingInfoResponse types - TRAINING_ALREADY_RUNNING error code in errors.ts + de/en/es translations - 7 OcrTrainingCard Vitest tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -228,6 +228,22 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/ocr/train": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["triggerTraining"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/ocr/batch": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -564,6 +580,22 @@ export interface paths {
|
||||
patch: operations["updateGroup"];
|
||||
trace?: never;
|
||||
};
|
||||
"/api/documents/{id}/training-labels": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch: operations["patchTrainingLabel"];
|
||||
trace?: never;
|
||||
};
|
||||
"/api/documents/{documentId}/comments/{commentId}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -676,6 +708,38 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/ocr/training-info": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getTrainingInfo"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/ocr/training-data/export": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["exportTrainingData"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/ocr/jobs/{jobId}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1106,7 +1170,6 @@ export interface components {
|
||||
receivers?: components["schemas"]["Person"][];
|
||||
sender?: components["schemas"]["Person"];
|
||||
tags?: components["schemas"]["Tag"][];
|
||||
/** @enum {string} */
|
||||
trainingLabels?: ("KURRENT_RECOGNITION" | "KURRENT_SEGMENTATION")[];
|
||||
};
|
||||
UpdateTranscriptionBlockDTO: {
|
||||
@@ -1174,6 +1237,24 @@ export interface components {
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
};
|
||||
OcrTrainingRun: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
/** @enum {string} */
|
||||
status: "RUNNING" | "DONE" | "FAILED";
|
||||
/** Format: int32 */
|
||||
blockCount: number;
|
||||
/** Format: int32 */
|
||||
documentCount: number;
|
||||
modelName: string;
|
||||
errorMessage?: string;
|
||||
/** Format: uuid */
|
||||
triggeredBy?: string;
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
/** Format: date-time */
|
||||
completedAt?: string;
|
||||
};
|
||||
BatchOcrDTO: {
|
||||
documentIds: string[];
|
||||
};
|
||||
@@ -1314,6 +1395,10 @@ export interface components {
|
||||
actorName?: string;
|
||||
documentTitle?: string;
|
||||
};
|
||||
TrainingLabelRequest: {
|
||||
label?: string;
|
||||
enrolled?: boolean;
|
||||
};
|
||||
StatsDTO: {
|
||||
/** Format: int64 */
|
||||
totalPersons?: number;
|
||||
@@ -1325,8 +1410,6 @@ export interface components {
|
||||
/** Format: uuid */
|
||||
id?: string;
|
||||
displayName?: string;
|
||||
/** Format: int64 */
|
||||
documentCount?: number;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
/** Format: int32 */
|
||||
@@ -1335,8 +1418,22 @@ export interface components {
|
||||
deathYear?: number;
|
||||
alias?: string;
|
||||
notes?: string;
|
||||
/** Format: int64 */
|
||||
documentCount?: number;
|
||||
personType?: string;
|
||||
};
|
||||
TrainingInfoResponse: {
|
||||
/** Format: int32 */
|
||||
availableBlocks?: number;
|
||||
/** Format: int32 */
|
||||
totalOcrBlocks?: number;
|
||||
/** Format: int32 */
|
||||
availableDocuments?: number;
|
||||
ocrServiceAvailable?: boolean;
|
||||
lastRun?: components["schemas"]["OcrTrainingRun"];
|
||||
runs?: components["schemas"]["OcrTrainingRun"][];
|
||||
};
|
||||
StreamingResponseBody: unknown;
|
||||
OcrJob: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
@@ -1381,11 +1478,11 @@ export interface components {
|
||||
empty?: boolean;
|
||||
};
|
||||
PageableObject: {
|
||||
paged?: boolean;
|
||||
/** Format: int32 */
|
||||
pageNumber?: number;
|
||||
/** Format: int32 */
|
||||
pageSize?: number;
|
||||
paged?: boolean;
|
||||
/** Format: int64 */
|
||||
offset?: number;
|
||||
sort?: components["schemas"]["SortObject"];
|
||||
@@ -2082,6 +2179,26 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
triggerTraining: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Created */
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["OcrTrainingRun"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
triggerBatch: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -2743,6 +2860,30 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
patchTrainingLabel: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["TrainingLabelRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
deleteComment: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -2923,6 +3064,46 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
getTrainingInfo: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["TrainingInfoResponse"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
exportTrainingData: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["StreamingResponseBody"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
getJobStatus: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
Reference in New Issue
Block a user