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 }