fix: set correct edge handles on YAML import
Edges created by parseYamlToCanvas had no sourceHandle/targetHandle, causing React Flow to connect everything at the top of nodes. - Regular links: bottom → top-t - Parent edges: bottom → top-t - clusterR/clusterL: cluster-right → cluster-left
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { parseYamlToCanvas } from '../importYaml'
|
||||
import type { Node, Edge } from '@xyflow/react'
|
||||
import type { NodeData, EdgeData } from '@/types'
|
||||
@@ -73,6 +73,38 @@ describe('parseYamlToCanvas', () => {
|
||||
expect(nodes[0].data.show_hardware).toBeUndefined()
|
||||
})
|
||||
|
||||
it('links edges have bottom→top-t handles', () => {
|
||||
const yaml = `
|
||||
- nodeType: switch
|
||||
label: "SW"
|
||||
links:
|
||||
- label: "SRV"
|
||||
linkType: ethernet
|
||||
- nodeType: server
|
||||
label: "SRV"
|
||||
`
|
||||
const { edges } = parseYamlToCanvas(yaml, empty, emptyEdges)
|
||||
expect(edges).toHaveLength(1)
|
||||
expect(edges[0].sourceHandle).toBe('bottom')
|
||||
expect(edges[0].targetHandle).toBe('top-t')
|
||||
})
|
||||
|
||||
it('cluster edges have cluster-right→cluster-left handles', () => {
|
||||
const yaml = `
|
||||
- nodeType: proxmox
|
||||
label: "PVE1"
|
||||
clusterR:
|
||||
label: "PVE2"
|
||||
linkType: ethernet
|
||||
- nodeType: proxmox
|
||||
label: "PVE2"
|
||||
`
|
||||
const { edges } = parseYamlToCanvas(yaml, empty, emptyEdges)
|
||||
expect(edges).toHaveLength(1)
|
||||
expect(edges[0].sourceHandle).toBe('cluster-right')
|
||||
expect(edges[0].targetHandle).toBe('cluster-left')
|
||||
})
|
||||
|
||||
it('parent relationship sets parentId and creates an edge', () => {
|
||||
const yaml = `
|
||||
- nodeType: proxmox
|
||||
|
||||
@@ -34,16 +34,16 @@ export function parseYamlToCanvas(
|
||||
const yamlNodes: YamlNode[] = []
|
||||
|
||||
for (const entry of entries) {
|
||||
const raw = entry as Record<string, unknown>
|
||||
const entryRecord = entry as Record<string, unknown>
|
||||
|
||||
if (!raw.nodeType || typeof raw.nodeType !== 'string') {
|
||||
if (!entryRecord.nodeType || typeof entryRecord.nodeType !== 'string') {
|
||||
throw new Error(`Each YAML entry must have a "nodeType" string field`)
|
||||
}
|
||||
if (!raw.label || typeof raw.label !== 'string') {
|
||||
if (!entryRecord.label || typeof entryRecord.label !== 'string') {
|
||||
throw new Error(`Each YAML entry must have a "label" string field`)
|
||||
}
|
||||
|
||||
const yn = raw as unknown as YamlNode
|
||||
const yn = entryRecord as unknown as YamlNode
|
||||
|
||||
// Skip if a node with this label already exists on the canvas
|
||||
if (labelToId.has(yn.label)) {
|
||||
@@ -95,6 +95,8 @@ export function parseYamlToCanvas(
|
||||
sourceId: string,
|
||||
targetId: string,
|
||||
conn: YamlNodeConnection,
|
||||
sourceHandle = 'bottom',
|
||||
targetHandle = 'top-t',
|
||||
) {
|
||||
const key = `${sourceId}|${targetId}`
|
||||
const reverseKey = `${targetId}|${sourceId}`
|
||||
@@ -105,6 +107,8 @@ export function parseYamlToCanvas(
|
||||
id: generateUUID(),
|
||||
source: sourceId,
|
||||
target: targetId,
|
||||
sourceHandle,
|
||||
targetHandle,
|
||||
type: edgeType,
|
||||
data: {
|
||||
type: edgeType,
|
||||
@@ -126,8 +130,8 @@ export function parseYamlToCanvas(
|
||||
node.data = { ...node.data, parent_id: parentId }
|
||||
node.parentId = parentId
|
||||
node.extent = 'parent'
|
||||
// Also create an edge
|
||||
addEdgeIfNew(parentId, node.id, yn.parent)
|
||||
// Also create an edge (parent bottom → child top)
|
||||
addEdgeIfNew(parentId, node.id, yn.parent, 'bottom', 'top-t')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +141,7 @@ export function parseYamlToCanvas(
|
||||
if (!targetId) {
|
||||
console.warn(`[importYaml] links label not found: "${link.label}" — skipping`)
|
||||
} else {
|
||||
addEdgeIfNew(node.id, targetId, link)
|
||||
addEdgeIfNew(node.id, targetId, link, 'bottom', 'top-t')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,7 +151,7 @@ export function parseYamlToCanvas(
|
||||
if (!targetId) {
|
||||
console.warn(`[importYaml] clusterR label not found: "${yn.clusterR.label}" — skipping`)
|
||||
} else {
|
||||
addEdgeIfNew(node.id, targetId, yn.clusterR)
|
||||
addEdgeIfNew(node.id, targetId, yn.clusterR, 'cluster-right', 'cluster-left')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +160,7 @@ export function parseYamlToCanvas(
|
||||
if (!sourceId) {
|
||||
console.warn(`[importYaml] clusterL label not found: "${yn.clusterL.label}" — skipping`)
|
||||
} else {
|
||||
addEdgeIfNew(sourceId, node.id, yn.clusterL)
|
||||
addEdgeIfNew(sourceId, node.id, yn.clusterL, 'cluster-right', 'cluster-left')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user