mirror of
https://github.com/IliesAllali/parenthese.git
synced 2026-11-09 23:50:58 +00:00
- Champ de date de la fiche et du formulaire « Ajouter quelqu'un » : une annee seule (1950) ou une date complete (12/03/1950), une aide si le texte n'en est pas une. L'annee seule s'affiche « 1950 » et non plus « 1 janvier 1950 ». - Statut « Decede(e) » sans date : persons.isDeceased (migration additive), « 1908–? » sous le portrait, « Date inconnue » dans la fiche, en bas de la frise. Import de « 1 DEAT Y », export en « 1 DEAT Y ». Une date de deces retire le drapeau. - Parents : plus de « (null) » quand l'union n'a pas de type. Closes #77 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
139 lines
3.9 KiB
TypeScript
139 lines
3.9 KiB
TypeScript
import type { Annotation, MediaItem, ParentChildLink, Person, Union } from '@prisma/client'
|
|
|
|
import { sanitizeAnnotationContentForRead } from '../lib/annotation-content.js'
|
|
import { isImmichAvatarPath } from '../lib/media-files.js'
|
|
|
|
export type GraphPayload = {
|
|
persons: Array<{
|
|
id: string
|
|
firstName: string
|
|
lastName: string
|
|
birthName: string | null
|
|
birthDate: string | null
|
|
deathDate: string | null
|
|
isDeceased: boolean
|
|
birthPlace: string | null
|
|
profession: string | null
|
|
region: string | null
|
|
nationality: string | null
|
|
avatarUrlPath: string | null
|
|
sex: string | null
|
|
notes: string | null
|
|
avatarFromImmich: boolean
|
|
}>
|
|
unions: Array<{
|
|
id: string
|
|
partner1PersonId: string
|
|
partner2PersonId: string | null
|
|
unionType: string | null
|
|
startDate: string | null
|
|
endDate: string | null
|
|
displayOrder: number
|
|
}>
|
|
filiations: Array<{
|
|
id: string
|
|
parentPersonId: string
|
|
childPersonId: string
|
|
viaUnionId: string | null
|
|
parentageType: string | null
|
|
displayOrder: number
|
|
}>
|
|
medias: Array<{
|
|
id: string
|
|
personId: string
|
|
type: string
|
|
mimeType: string
|
|
urlPath: string
|
|
caption: string | null
|
|
source: string | null
|
|
displayOrder: number
|
|
isFeatured: boolean
|
|
}>
|
|
annotations: Array<{
|
|
id: string
|
|
type: string
|
|
x: number
|
|
y: number
|
|
content: string
|
|
style: unknown
|
|
zIndex: number
|
|
createdBy: string | null
|
|
}>
|
|
}
|
|
|
|
function formatDate(value: Date | null): string | null {
|
|
if (!value) {
|
|
return null
|
|
}
|
|
|
|
return value.toISOString().split('T')[0]
|
|
}
|
|
|
|
export function buildGraphPayload(
|
|
treeId: string,
|
|
persons: Person[],
|
|
unions: Union[],
|
|
links: ParentChildLink[],
|
|
medias: MediaItem[] = [],
|
|
annotations: Annotation[] = [],
|
|
): GraphPayload {
|
|
// Keep DB order from route queries to preserve sibling and union ordering semantics.
|
|
return {
|
|
persons: persons.map((person) => ({
|
|
id: person.id,
|
|
firstName: person.firstName,
|
|
lastName: person.lastName,
|
|
birthName: person.birthName,
|
|
birthDate: formatDate(person.birthDate),
|
|
deathDate: formatDate(person.deathDate),
|
|
isDeceased: Boolean(person.isDeceased) && !person.deathDate,
|
|
birthPlace: person.birthPlace,
|
|
profession: person.profession,
|
|
region: person.region,
|
|
nationality: person.nationality,
|
|
avatarUrlPath: person.avatarPath ? `/trees/${treeId}/persons/${person.id}/avatar` : null,
|
|
sex: person.sex,
|
|
notes: person.notes,
|
|
avatarFromImmich: isImmichAvatarPath(person.avatarPath),
|
|
})),
|
|
unions: unions.map((union) => ({
|
|
id: union.id,
|
|
partner1PersonId: union.partner1PersonId,
|
|
partner2PersonId: union.partner2PersonId,
|
|
unionType: union.unionType,
|
|
startDate: formatDate(union.startDate),
|
|
endDate: formatDate(union.endDate),
|
|
displayOrder: union.displayOrder,
|
|
})),
|
|
filiations: links.map((link) => ({
|
|
id: link.id,
|
|
parentPersonId: link.parentPersonId,
|
|
childPersonId: link.childPersonId,
|
|
viaUnionId: link.viaUnionId,
|
|
parentageType: link.parentageType,
|
|
displayOrder: link.displayOrder,
|
|
})),
|
|
medias: medias.map((media) => ({
|
|
id: media.id,
|
|
personId: media.personId,
|
|
type: media.type,
|
|
mimeType: media.mimeType,
|
|
urlPath: media.mimeType === 'video/youtube' ? media.filePath : `/trees/${treeId}/media/${media.id}`,
|
|
caption: media.caption,
|
|
source: media.source,
|
|
displayOrder: media.displayOrder,
|
|
isFeatured: media.isFeatured,
|
|
})),
|
|
annotations: annotations.map((ann) => ({
|
|
id: ann.id,
|
|
type: ann.type,
|
|
x: ann.x,
|
|
y: ann.y,
|
|
content: sanitizeAnnotationContentForRead(ann.content),
|
|
style: ann.style,
|
|
zIndex: ann.zIndex,
|
|
createdBy: ann.createdBy,
|
|
})),
|
|
}
|
|
}
|