diff --git a/frontend/src/lib/components/PersonMultiSelect.svelte.spec.ts b/frontend/src/lib/components/PersonMultiSelect.svelte.spec.ts index 08c2ba28..9166c1a4 100644 --- a/frontend/src/lib/components/PersonMultiSelect.svelte.spec.ts +++ b/frontend/src/lib/components/PersonMultiSelect.svelte.spec.ts @@ -12,16 +12,25 @@ const PERSONS = [ firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false }, { id: '2', firstName: 'Anna', lastName: 'Musterfrau', displayName: 'Anna Musterfrau', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false }, - { id: '3', firstName: 'Karl', lastName: 'König', displayName: 'Karl König', personType: 'PERSON' } + { + id: '3', + firstName: 'Karl', + lastName: 'König', + displayName: 'Karl König', + personType: 'PERSON', + familyMember: false + } ]; function mockFetch(persons = PERSONS) { @@ -62,14 +71,16 @@ describe('PersonMultiSelect – rendering', () => { firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false }, { id: '2', firstName: 'Anna', lastName: 'Musterfrau', displayName: 'Anna Musterfrau', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } ] }); @@ -86,14 +97,16 @@ describe('PersonMultiSelect – rendering', () => { firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false }, { id: '2', firstName: 'Anna', lastName: 'Musterfrau', displayName: 'Anna Musterfrau', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } ] }); @@ -112,7 +125,8 @@ describe('PersonMultiSelect – rendering', () => { firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } ] }); @@ -166,7 +180,8 @@ describe('PersonMultiSelect – selecting persons', () => { firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } ] }); @@ -187,7 +202,8 @@ describe('PersonMultiSelect – selecting persons', () => { firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } ]); render(PersonMultiSelect, { selectedPersons: [] }); @@ -210,14 +226,16 @@ describe('PersonMultiSelect – removing persons', () => { firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false }, { id: '2', firstName: 'Anna', lastName: 'Musterfrau', displayName: 'Anna Musterfrau', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } ] }); @@ -236,14 +254,16 @@ describe('PersonMultiSelect – removing persons', () => { firstName: 'Max', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false }, { id: '2', firstName: 'Anna', lastName: 'Musterfrau', displayName: 'Anna Musterfrau', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } ] }); diff --git a/frontend/src/lib/generated/api.ts b/frontend/src/lib/generated/api.ts index 81925006..30cec4fb 100644 --- a/frontend/src/lib/generated/api.ts +++ b/frontend/src/lib/generated/api.ts @@ -212,6 +212,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/persons/{id}/relationships": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getRelationships"]; + put?: never; + post: operations["addRelationship"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/persons/{id}/merge": { parameters: { query?: never; @@ -612,6 +628,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/persons/{id}/family-member": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch: operations["patchFamilyMember"]; + trace?: never; + }; "/api/notifications/{id}/read": { parameters: { query?: never; @@ -852,6 +884,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/persons/{id}/inferred-relationships": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getInferredRelationships"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/persons/{id}/documents": { parameters: { query?: never; @@ -884,6 +932,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/persons/{aId}/relationship-to/{bId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getRelationshipBetween"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/ocr/training-info": { parameters: { query?: never; @@ -1044,6 +1108,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/network": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getNetwork"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/documents/{id}/versions": { parameters: { query?: never; @@ -1332,6 +1412,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/persons/{id}/relationships/{relId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["deleteRelationship"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/persons/{id}/aliases/{aliasId}": { parameters: { query?: never; @@ -1430,6 +1526,8 @@ export interface components { color?: string; }; PersonUpdateDTO: { + /** @enum {string} */ + personType: "PERSON" | "INSTITUTION" | "GROUP" | "UNKNOWN" | "SKIP"; title?: string; firstName?: string; lastName?: string; @@ -1454,6 +1552,7 @@ export interface components { birthYear?: number; /** Format: int32 */ deathYear?: number; + familyMember: boolean; readonly displayName: string; }; DocumentUpdateDTO: { @@ -1462,6 +1561,8 @@ export interface components { documentDate?: string; location?: string; documentLocation?: string; + archiveBox?: string; + archiveFolder?: string; transcription?: string; summary?: string; /** Format: uuid */ @@ -1561,6 +1662,41 @@ export interface components { /** Format: uuid */ targetId: string; }; + CreateRelationshipRequest: { + /** Format: uuid */ + relatedPersonId: string; + relationType: string; + /** Format: int32 */ + fromYear?: number; + /** Format: int32 */ + toYear?: number; + notes?: string; + }; + RelationshipDTO: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + personId: string; + /** Format: uuid */ + relatedPersonId: string; + personDisplayName: string; + /** Format: int32 */ + personBirthYear?: number; + /** Format: int32 */ + personDeathYear?: number; + relatedPersonDisplayName: string; + /** Format: int32 */ + relatedPersonBirthYear?: number; + /** Format: int32 */ + relatedPersonDeathYear?: number; + /** @enum {string} */ + relationType: "PARENT_OF" | "SPOUSE_OF" | "SIBLING_OF" | "FRIEND" | "COLLEAGUE" | "EMPLOYER" | "DOCTOR" | "NEIGHBOR" | "OTHER"; + /** Format: int32 */ + fromYear?: number; + /** Format: int32 */ + toYear?: number; + notes?: string; + }; PersonNameAliasDTO: { lastName: string; firstName?: string; @@ -1808,6 +1944,9 @@ export interface components { /** Format: int32 */ count: number; }; + FamilyMemberPatchDTO: { + familyMember?: boolean; + }; NotificationDTO: { /** Format: uuid */ id: string; @@ -1912,15 +2051,38 @@ export interface components { displayName?: string; firstName?: string; lastName?: string; - /** Format: int64 */ - documentCount?: number; + personType?: string; /** Format: int32 */ birthYear?: number; /** Format: int32 */ deathYear?: number; - alias?: string; + familyMember?: boolean; notes?: string; - personType?: string; + /** Format: int64 */ + documentCount?: number; + alias?: string; + }; + InferredRelationshipWithPersonDTO: { + person: components["schemas"]["PersonNodeDTO"]; + label: string; + /** Format: int32 */ + hops: number; + }; + PersonNodeDTO: { + /** Format: uuid */ + id: string; + displayName: string; + /** Format: int32 */ + birthYear?: number; + /** Format: int32 */ + deathYear?: number; + familyMember: boolean; + }; + InferredRelationshipDTO: { + labelFromA: string; + labelFromB: string; + /** Format: int32 */ + hops: number; }; SenderModel: { /** Format: uuid */ @@ -2021,6 +2183,10 @@ export interface components { empty?: boolean; unsorted?: boolean; }; + NetworkDTO: { + nodes: components["schemas"]["PersonNodeDTO"][]; + edges: components["schemas"]["RelationshipDTO"][]; + }; DocumentVersionSummary: { /** Format: uuid */ id: string; @@ -2131,7 +2297,7 @@ export interface components { }; ActivityFeedItemDTO: { /** @enum {string} */ - kind: "FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED"; + kind: "FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED" | "USER_CREATED" | "USER_DELETED" | "GROUP_MEMBERSHIP_CHANGED"; actor?: components["schemas"]["ActivityActorDTO"]; /** Format: uuid */ documentId: string; @@ -2745,6 +2911,54 @@ export interface operations { }; }; }; + getRelationships: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["RelationshipDTO"][]; + }; + }; + }; + }; + addRelationship: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateRelationshipRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["RelationshipDTO"]; + }; + }; + }; + }; mergePerson: { parameters: { query?: never; @@ -3491,6 +3705,32 @@ export interface operations { }; }; }; + patchFamilyMember: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["FamilyMemberPatchDTO"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Person"]; + }; + }; + }; + }; markOneRead: { parameters: { query?: never; @@ -3889,6 +4129,28 @@ export interface operations { }; }; }; + getInferredRelationships: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["InferredRelationshipWithPersonDTO"][]; + }; + }; + }; + }; getPersonDocuments: { parameters: { query?: never; @@ -3935,6 +4197,29 @@ export interface operations { }; }; }; + getRelationshipBetween: { + parameters: { + query?: never; + header?: never; + path: { + aId: string; + bId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["InferredRelationshipDTO"]; + }; + }; + }; + }; getTrainingInfo: { parameters: { query?: never; @@ -4150,6 +4435,26 @@ export interface operations { }; }; }; + getNetwork: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["NetworkDTO"]; + }; + }; + }; + }; getVersions: { parameters: { query?: never; @@ -4470,7 +4775,7 @@ export interface operations { query?: { limit?: number; /** @description Filter by audit kinds; omit for all rollup-eligible kinds */ - kinds?: ("FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED")[]; + kinds?: ("FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED" | "USER_CREATED" | "USER_DELETED" | "GROUP_MEMBERSHIP_CHANGED")[]; }; header?: never; path?: never; @@ -4571,6 +4876,27 @@ export interface operations { }; }; }; + deleteRelationship: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + relId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description No Content */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; removeAlias: { parameters: { query?: never; diff --git a/frontend/src/routes/DocumentList.svelte.spec.ts b/frontend/src/routes/DocumentList.svelte.spec.ts index a41c92b9..19a11676 100644 --- a/frontend/src/routes/DocumentList.svelte.spec.ts +++ b/frontend/src/routes/DocumentList.svelte.spec.ts @@ -131,7 +131,8 @@ describe('DocumentList – sender grouping', () => { id: 's1', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } } }), @@ -143,7 +144,8 @@ describe('DocumentList – sender grouping', () => { id: 's2', lastName: 'Musterfrau', displayName: 'Anna Musterfrau', - personType: 'PERSON' + personType: 'PERSON', + familyMember: false } } }) @@ -162,7 +164,8 @@ describe('DocumentList – sender grouping', () => { id: 's1', lastName: 'Mustermann', displayName: 'Max Mustermann', - personType: 'PERSON' as const + personType: 'PERSON' as const, + familyMember: false }; const items = [ makeItem({ document: { ...makeItem().document, id: '1', sender } }), @@ -191,7 +194,13 @@ describe('DocumentList – receiver grouping', () => { ...makeItem().document, id: '1', receivers: [ - { id: 'r1', lastName: 'Brandt', displayName: 'Felix Brandt', personType: 'PERSON' } + { + id: 'r1', + lastName: 'Brandt', + displayName: 'Felix Brandt', + personType: 'PERSON', + familyMember: false + } ] } }) @@ -210,8 +219,20 @@ describe('DocumentList – receiver grouping', () => { id: '1', title: 'Rundbriefchen', receivers: [ - { id: 'r1', lastName: 'Brandt', displayName: 'Felix Brandt', personType: 'PERSON' }, - { id: 'r2', lastName: 'Meier', displayName: 'Hans Meier', personType: 'PERSON' } + { + id: 'r1', + lastName: 'Brandt', + displayName: 'Felix Brandt', + personType: 'PERSON', + familyMember: false + }, + { + id: 'r2', + lastName: 'Meier', + displayName: 'Hans Meier', + personType: 'PERSON', + familyMember: false + } ] } }) diff --git a/frontend/src/routes/briefwechsel/page.svelte.spec.ts b/frontend/src/routes/briefwechsel/page.svelte.spec.ts index d861f196..9b4e720f 100644 --- a/frontend/src/routes/briefwechsel/page.svelte.spec.ts +++ b/frontend/src/routes/briefwechsel/page.svelte.spec.ts @@ -35,6 +35,7 @@ const makePerson = (overrides: Record = {}) => ({ firstName: 'Hans', lastName: 'Müller', personType: 'PERSON' as const, + familyMember: false, displayName: 'Hans Müller', ...overrides });