diff --git a/apps/app/src/lib/graph/layout.ts b/apps/app/src/lib/graph/layout.ts index 7b9e1b8..54f8a99 100644 --- a/apps/app/src/lib/graph/layout.ts +++ b/apps/app/src/lib/graph/layout.ts @@ -35,6 +35,8 @@ export class FamilyTree extends dagre.graphlib.Graph { if (String(edge.data?.type).toLowerCase() === 'child') { newEdge.sourceHandle = 'child'; newEdge.targetHandle = 'parent'; + }else if (String(edge.data?.type).toLowerCase() === 'parent') { + return } const sourceNode = this.node(edge.source); @@ -43,6 +45,43 @@ export class FamilyTree extends dagre.graphlib.Graph { return; } + if (String(edge.data?.type).toLowerCase() === 'sibling') { + const padding = 50; // distance between sibling and source + const spouseWidth = nodeWidth; + + const existingNodesAtLevel = nodes + .map((n) => ({ id: n.id, pos: this.node(n.id) })) + .filter(({ pos }) => Math.abs(pos.y - sourceNode.y) < nodeHeight / 2); // same horizontal band + + // Collect taken x ranges + const takenXRanges = existingNodesAtLevel.map(({ pos }) => ({ + from: pos.x - spouseWidth / 2, + to: pos.x + spouseWidth / 2 + })); + + // Try placing spouse to the right + let desiredX = sourceNode.x + nodeWidth + padding; + + // Check for collision + const collides = (x: number) => { + return takenXRanges.some(({ from, to }) => x > from && x < to); + }; + + // If right side collides, try left + if (collides(desiredX)) { + desiredX = sourceNode.x - (nodeWidth + padding); + } + + // If both sides collide, push right until free + while (collides(desiredX)) { + desiredX += nodeWidth + padding; + } + + targetNode.x = desiredX; + targetNode.y = sourceNode.y; + + } + if (String(edge.data?.type).toLowerCase() === 'spouse') { const padding = 50; // distance between spouse and source const spouseWidth = nodeWidth; diff --git a/apps/app/src/lib/graph/parse_family_tree.ts b/apps/app/src/lib/graph/parse_family_tree.ts index 737a0d3..0dab057 100644 --- a/apps/app/src/lib/graph/parse_family_tree.ts +++ b/apps/app/src/lib/graph/parse_family_tree.ts @@ -15,8 +15,9 @@ export function parseFamilyTree(data: components['schemas']['FamilyTree']): Layo const nodes: Node[] = data.people.map((person) => { let newNode = { data: { ...person } } as Node; if (person.id !== null && person.id !== undefined) { - newNode.id = "help"+person.id.toString(); + newNode.id = "person"+person.id.toString(); } + newNode.position = { x: 0, y: 0 }; newNode.data.id = person.id; return newNode; }); @@ -25,12 +26,13 @@ export function parseFamilyTree(data: components['schemas']['FamilyTree']): Layo if (data.relationships) { relationships = data.relationships.map((relationship) => { const newEdge = { data: { ...relationship.Props } } as Edge; + newEdge.id = "person"+relationship.ElementId; newEdge.data!.type = relationship.Type?.toLowerCase(); if (relationship.StartElementId !== null && relationship.StartElementId !== undefined) { - newEdge.source = "help"+relationship.StartId!.toString(); + newEdge.source = "person"+relationship.StartId!.toString(); } if (relationship.EndElementId !== null && relationship.EndElementId !== undefined) { - newEdge.target = "help"+relationship.EndId!.toString(); + newEdge.target = "person"+relationship.EndId!.toString(); } return newEdge;