From 4603e335fdebec0a8ea4f380ba07a57841751218 Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 8 Jun 2026 17:04:51 +0200 Subject: [PATCH] feat(frontend): add JOURNEY_ITEM error codes, i18n keys, regen API types Adds JOURNEY_ITEM_NOT_FOUND and JOURNEY_ITEM_POSITION_CONFLICT to the frontend ErrorCode union and getErrorMessage() switch. Adds de/en/es translations. Regenerates api.ts from the current OpenAPI spec (needs a second run once the backend is restarted with the new endpoints compiled in). Co-Authored-By: Claude Sonnet 4.6 --- frontend/messages/de.json | 2 + frontend/messages/en.json | 2 + frontend/messages/es.json | 2 + frontend/src/lib/generated/api.ts | 261 +++++++++++++----------------- frontend/src/lib/shared/errors.ts | 6 + 5 files changed, 126 insertions(+), 147 deletions(-) diff --git a/frontend/messages/de.json b/frontend/messages/de.json index da8b0672..b0e3e054 100644 --- a/frontend/messages/de.json +++ b/frontend/messages/de.json @@ -1023,6 +1023,8 @@ "nav_stammbaum": "Stammbaum", "nav_geschichten": "Geschichten", "error_geschichte_not_found": "Die Geschichte wurde nicht gefunden.", + "error_journey_item_not_found": "Der Reise-Eintrag wurde nicht gefunden.", + "error_journey_item_position_conflict": "Positionskonflikt beim Sortieren der Reise-Einträge.", "geschichten_index_title": "Geschichten", "geschichten_new_button": "Neue Geschichte", "geschichten_filter_all_pill": "Alle", diff --git a/frontend/messages/en.json b/frontend/messages/en.json index ab47f6f9..7bca4db1 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -1023,6 +1023,8 @@ "nav_stammbaum": "Family tree", "nav_geschichten": "Stories", "error_geschichte_not_found": "The story was not found.", + "error_journey_item_not_found": "The journey item was not found.", + "error_journey_item_position_conflict": "Position conflict while reordering journey items.", "geschichten_index_title": "Stories", "geschichten_new_button": "New story", "geschichten_filter_all_pill": "All", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index abe21231..ea5002d9 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -1023,6 +1023,8 @@ "nav_stammbaum": "Árbol genealógico", "nav_geschichten": "Historias", "error_geschichte_not_found": "No se encontró la historia.", + "error_journey_item_not_found": "No se encontró el elemento del viaje.", + "error_journey_item_position_conflict": "Conflicto de posición al reordenar los elementos del viaje.", "geschichten_index_title": "Historias", "geschichten_new_button": "Nueva historia", "geschichten_filter_all_pill": "Todas", diff --git a/frontend/src/lib/generated/api.ts b/frontend/src/lib/generated/api.ts index 526e51aa..d5518fd5 100644 --- a/frontend/src/lib/generated/api.ts +++ b/frontend/src/lib/generated/api.ts @@ -692,22 +692,6 @@ export interface paths { patch?: never; trace?: never; }; - "/api/admin/backfill-titles": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post: operations["backfillTitles"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; "/api/admin/backfill-file-hashes": { parameters: { query?: never; @@ -875,7 +859,7 @@ export interface paths { path?: never; cookie?: never; }; - get: operations["search_1"]; + get: operations["search"]; put?: never; post?: never; delete?: never; @@ -1339,7 +1323,7 @@ export interface paths { path?: never; cookie?: never; }; - get: operations["search_2"]; + get: operations["search_1"]; put?: never; post?: never; delete?: never; @@ -1428,6 +1412,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/documents/conversation": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getConversation"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/dashboard/resume": { parameters: { query?: never; @@ -1758,7 +1758,6 @@ export interface components { sender?: components["schemas"]["Person"]; tags?: components["schemas"]["Tag"][]; trainingLabels?: ("KURRENT_RECOGNITION" | "KURRENT_SEGMENTATION")[]; - hasTranscription: boolean; thumbnailUrl?: string; }; PersonMention: { @@ -1819,75 +1818,6 @@ export interface components { /** Format: uuid */ targetId: string; }; - Pageable: { - /** Format: int32 */ - page?: number; - /** Format: int32 */ - size?: number; - sort?: string[]; - }; - ActivityActorDTO: { - initials: string; - color: string; - name?: string; - }; - DocumentListItem: { - /** Format: uuid */ - id: string; - title: string; - originalFilename: string; - thumbnailUrl?: string; - /** Format: date */ - documentDate?: string; - /** @enum {string} */ - metaDatePrecision: "DAY" | "MONTH" | "SEASON" | "YEAR" | "RANGE" | "APPROX" | "UNKNOWN"; - /** Format: date */ - metaDateEnd?: string; - sender?: components["schemas"]["Person"]; - receivers: components["schemas"]["Person"][]; - tags: components["schemas"]["Tag"][]; - archiveBox?: string; - archiveFolder?: string; - location?: string; - summary?: string; - /** Format: int32 */ - completionPercentage: number; - contributors: components["schemas"]["ActivityActorDTO"][]; - matchData: components["schemas"]["SearchMatchData"]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - }; - DocumentSearchResult: { - items: components["schemas"]["DocumentListItem"][]; - /** Format: int64 */ - totalElements: number; - /** Format: int32 */ - pageNumber: number; - /** Format: int32 */ - pageSize: number; - /** Format: int32 */ - totalPages: number; - /** Format: int64 */ - undatedCount: number; - }; - MatchOffset: { - /** Format: int32 */ - start: number; - /** Format: int32 */ - length: number; - }; - SearchMatchData: { - transcriptionSnippet?: string; - titleOffsets: components["schemas"]["MatchOffset"][]; - senderMatched: boolean; - matchedReceiverIds: string[]; - matchedTagIds: string[]; - snippetOffsets: components["schemas"]["MatchOffset"][]; - summarySnippet?: string; - summaryOffsets: components["schemas"]["MatchOffset"][]; - }; CreateRelationshipRequest: { /** Format: uuid */ relatedPersonId: string; @@ -2016,6 +1946,7 @@ export interface components { /** @enum {string} */ status?: "DRAFT" | "PUBLISHED"; personIds?: string[]; + documentIds?: string[]; }; Geschichte: { /** Format: uuid */ @@ -2024,11 +1955,9 @@ export interface components { body?: string; /** @enum {string} */ status: "DRAFT" | "PUBLISHED"; - /** @enum {string} */ - type: "STORY" | "JOURNEY"; author?: components["schemas"]["AppUser"]; persons?: components["schemas"]["Person"][]; - items?: components["schemas"]["JourneyItem"][]; + documents?: components["schemas"]["Document"][]; /** Format: date-time */ createdAt: string; /** Format: date-time */ @@ -2036,32 +1965,6 @@ export interface components { /** Format: date-time */ publishedAt?: string; }; - JourneyItem: { - /** Format: uuid */ - id: string; - /** Format: int32 */ - position: number; - /** Format: uuid */ - documentId?: string; - note?: string; - }; - GeschichteSummary: { - /** Format: uuid */ - id: string; - title: string; - /** @enum {string} */ - status: "DRAFT" | "PUBLISHED"; - /** @enum {string} */ - type: "STORY" | "JOURNEY"; - author?: { - firstName?: string; - lastName?: string; - email: string; - }; - body?: string; - /** Format: date-time */ - publishedAt?: string; - }; CreateTranscriptionBlockDTO: { /** Format: int32 */ pageNumber?: number; @@ -2300,6 +2203,11 @@ export interface components { /** Format: int64 */ transcriptionCount: number; }; + ActivityActorDTO: { + initials: string; + color: string; + name?: string; + }; TranscriptionQueueItemDTO: { /** Format: uuid */ id: string; @@ -2322,11 +2230,6 @@ export interface components { color?: string; /** Format: int32 */ documentCount: number; - /** - * Format: int32 - * @description Distinct documents tagged with this tag or any descendant tag (subtree rollup) - */ - subtreeDocumentCount: number; children?: components["schemas"]["TagTreeNodeDTO"][]; /** * Format: uuid @@ -2467,6 +2370,8 @@ export interface components { /** Format: int32 */ totalPages?: number; pageable?: components["schemas"]["PageableObject"]; + first?: boolean; + last?: boolean; /** Format: int32 */ size?: number; content?: components["schemas"]["NotificationDTO"][]; @@ -2475,8 +2380,6 @@ export interface components { sort?: components["schemas"]["SortObject"]; /** Format: int32 */ numberOfElements?: number; - first?: boolean; - last?: boolean; empty?: boolean; }; PageableObject: { @@ -2540,6 +2443,63 @@ export interface components { /** Format: int32 */ totalPages?: number; }; + DocumentListItem: { + /** Format: uuid */ + id: string; + title: string; + originalFilename: string; + thumbnailUrl?: string; + /** Format: date */ + documentDate?: string; + /** @enum {string} */ + metaDatePrecision: "DAY" | "MONTH" | "SEASON" | "YEAR" | "RANGE" | "APPROX" | "UNKNOWN"; + /** Format: date */ + metaDateEnd?: string; + sender?: components["schemas"]["Person"]; + receivers: components["schemas"]["Person"][]; + tags: components["schemas"]["Tag"][]; + archiveBox?: string; + archiveFolder?: string; + location?: string; + summary?: string; + /** Format: int32 */ + completionPercentage: number; + contributors: components["schemas"]["ActivityActorDTO"][]; + matchData: components["schemas"]["SearchMatchData"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + DocumentSearchResult: { + items: components["schemas"]["DocumentListItem"][]; + /** Format: int64 */ + totalElements: number; + /** Format: int32 */ + pageNumber: number; + /** Format: int32 */ + pageSize: number; + /** Format: int32 */ + totalPages: number; + /** Format: int64 */ + undatedCount: number; + }; + MatchOffset: { + /** Format: int32 */ + start: number; + /** Format: int32 */ + length: number; + }; + SearchMatchData: { + transcriptionSnippet?: string; + titleOffsets: components["schemas"]["MatchOffset"][]; + senderMatched: boolean; + matchedReceiverIds: string[]; + matchedTagIds: string[]; + snippetOffsets: components["schemas"]["MatchOffset"][]; + summarySnippet?: string; + summaryOffsets: components["schemas"]["MatchOffset"][]; + }; IncompleteDocumentDTO: { /** Format: uuid */ id: string; @@ -3603,6 +3563,7 @@ export interface operations { query?: { status?: "DRAFT" | "PUBLISHED"; personId?: string[]; + documentId?: string; limit?: number; }; header?: never; @@ -3617,7 +3578,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["GeschichteSummary"][]; + "*/*": components["schemas"]["Geschichte"][]; }; }; }; @@ -4144,26 +4105,6 @@ export interface operations { }; }; }; - backfillTitles: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["BackfillResult"]; - }; - }; - }; - }; backfillFileHashes: { parameters: { query?: never; @@ -4512,7 +4453,7 @@ export interface operations { }; }; }; - search_1: { + search: { parameters: { query?: { q?: string; @@ -5136,7 +5077,7 @@ export interface operations { }; }; }; - search_2: { + search_1: { parameters: { query?: { q?: string; @@ -5306,6 +5247,32 @@ export interface operations { }; }; }; + getConversation: { + parameters: { + query: { + senderId: string; + receiverId?: string; + from?: string; + to?: string; + dir?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Document"][]; + }; + }; + }; + }; getResume: { parameters: { query?: never; diff --git a/frontend/src/lib/shared/errors.ts b/frontend/src/lib/shared/errors.ts index 6efec2a7..894d102a 100644 --- a/frontend/src/lib/shared/errors.ts +++ b/frontend/src/lib/shared/errors.ts @@ -46,6 +46,8 @@ export type ErrorCode = | 'CIRCULAR_RELATIONSHIP' | 'DUPLICATE_RELATIONSHIP' | 'GESCHICHTE_NOT_FOUND' + | 'JOURNEY_ITEM_NOT_FOUND' + | 'JOURNEY_ITEM_POSITION_CONFLICT' | 'INVALID_CREDENTIALS' | 'SESSION_EXPIRED' | 'MISSING_CREDENTIALS' @@ -164,6 +166,10 @@ export function getErrorMessage(code: ErrorCode | string | undefined): string { return m.error_duplicate_relationship(); case 'GESCHICHTE_NOT_FOUND': return m.error_geschichte_not_found(); + case 'JOURNEY_ITEM_NOT_FOUND': + return m.error_journey_item_not_found(); + case 'JOURNEY_ITEM_POSITION_CONFLICT': + return m.error_journey_item_position_conflict(); case 'INVALID_CREDENTIALS': return m.error_invalid_credentials(); case 'SESSION_EXPIRED':