From 5b8aa412fa5a8a15a1d547c4a00007538ee3cb5c Mon Sep 17 00:00:00 2001 From: Atharva Sawant Date: Fri, 12 Apr 2024 09:31:52 +0530 Subject: [PATCH] Improved interface for map view --- src/components/OrgTree/OrgNodeComponent.vue | 18 ++--- src/components/OrgTree/OrgTreeView.vue | 10 +++ src/utils/nodeLayoutGenerator.ts | 75 +++++++++++++-------- 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/components/OrgTree/OrgNodeComponent.vue b/src/components/OrgTree/OrgNodeComponent.vue index 335c0467..80c1a2e5 100644 --- a/src/components/OrgTree/OrgNodeComponent.vue +++ b/src/components/OrgTree/OrgNodeComponent.vue @@ -77,8 +77,9 @@ - - + + + @@ -190,11 +191,12 @@ function cancelContentEdit() { box-shadow: 0 0 0 2px #3b82f6; } -.handle-left, -.handle-right { - width: 8px; - height: 8px; - border: 2px solid #3b82f6; - background: white; +.handle-center { + opacity: 0; + pointer-events: none; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } \ No newline at end of file diff --git a/src/components/OrgTree/OrgTreeView.vue b/src/components/OrgTree/OrgTreeView.vue index ced097f7..9da05b48 100644 --- a/src/components/OrgTree/OrgTreeView.vue +++ b/src/components/OrgTree/OrgTreeView.vue @@ -134,6 +134,16 @@ function exportFile() { border: none; } +.vue-flow__edge.vue-flow__edge-straight { + stroke: #64748b; + stroke-width: 2; +} + +.vue-flow__edge.vue-flow__edge-straight:hover { + stroke: #3b82f6; + stroke-width: 3; +} + .vue-flow__edge.vue-flow__edge-smoothstep { stroke: #64748b; stroke-width: 2; diff --git a/src/utils/nodeLayoutGenerator.ts b/src/utils/nodeLayoutGenerator.ts index 99c4a260..96fef129 100644 --- a/src/utils/nodeLayoutGenerator.ts +++ b/src/utils/nodeLayoutGenerator.ts @@ -14,7 +14,9 @@ export interface FlowEdge { id: string source: string target: string - type: 'smoothstep' + sourceHandle?: string + targetHandle?: string + type: 'straight' | 'smoothstep' } export function generateNodeLayout(nodes: OrgNode[]): { nodes: FlowNode[]; edges: FlowEdge[] } { @@ -22,63 +24,80 @@ export function generateNodeLayout(nodes: OrgNode[]): { nodes: FlowNode[]; edges const flowEdges: FlowEdge[] = [] let nodeCounter = 0 + const levelPositions: Map = new Map() // Track position within each level function processNode( node: OrgNode, level: number, parentId: string | null, - angle: number, - distance: number, - centerX: number = 400, - centerY: number = 300 - ) { + parentX: number = 400, + parentY: number = 100 + ): string { const nodeId = `node-${nodeCounter++}` - // Calculate position in a radial/organic layout - const x = centerX + Math.cos(angle) * distance - const y = centerY + Math.sin(angle) * distance + // Hierarchical positioning: levels go top to bottom + const yPosition = 100 + (level - 1) * 200 // 200px between levels + + // Get current position for this level + let xPosition: number + if (level === 1) { + // Root nodes: center them horizontally + const rootIndex = flowNodes.filter(n => n.data.level === 1).length + const rootSpacing = 350 + const totalRootWidth = (nodes.length - 1) * rootSpacing + xPosition = 400 + rootIndex * rootSpacing - totalRootWidth / 2 + } else { + // Child nodes: position relative to parent + const currentLevelCount = levelPositions.get(level) || 0 + levelPositions.set(level, currentLevelCount + 1) + + // Calculate children positions spread around parent + const parentNode = flowNodes.find(n => n.id === parentId) + if (parentNode) { + const siblingCount = node.children?.length || 1 + const parentChildren = flowNodes.filter(n => + flowEdges.some(e => e.source === parentId && e.target === n.id) + ).length + + const childSpacing = Math.max(250, 400 / Math.max(siblingCount, 1)) + const totalWidth = (siblingCount - 1) * childSpacing + xPosition = parentX + (parentChildren * childSpacing) - (totalWidth / 2) + } else { + xPosition = parentX + (currentLevelCount * 300) + } + } flowNodes.push({ id: nodeId, type: 'orgNode', - position: { x, y }, + position: { x: xPosition, y: yPosition }, data: { node, level } }) - // Add edge from parent + // Add edge from parent - center to center diagonal if (parentId) { flowEdges.push({ id: `edge-${parentId}-${nodeId}`, source: parentId, target: nodeId, - type: 'smoothstep' + type: 'straight' }) } - // Process children in a radial pattern around this node - const childCount = node.children.length - if (childCount > 0) { - const angleStep = (2 * Math.PI) / Math.max(childCount, 3) - const childDistance = Math.max(150, distance * 0.7) - - node.children.forEach((child, index) => { - const childAngle = angle + (index - (childCount - 1) / 2) * angleStep * 0.8 - processNode(child, level + 1, nodeId, childAngle, childDistance, x, y) - }) - } + // Process children + node.children.forEach((child, index) => { + processNode(child, level + 1, nodeId, xPosition, yPosition) + }) return nodeId } - // Start with root nodes in a circular pattern - const rootCount = nodes.length + // Process all root nodes nodes.forEach((node, index) => { - const angle = (2 * Math.PI * index) / rootCount - const distance = rootCount > 1 ? 200 : 0 - processNode(node, 1, null, angle, distance) + processNode(node, 1, null) }) return { nodes: flowNodes, edges: flowEdges }