fix: don't trap new child nodes under a non-container parent

Adding an LXC/VM with a parent_id pointed at a Proxmox node that is
NOT in container_mode set extent:'parent' anyway, confining the node
to the parent's ~140px bounding box with no way to drag it out.

Nesting is now gated on the parent's container_mode in both places:
App.handleAddNode no longer sets parentId/extent itself (it seeds an
absolute position and lets addNode decide), and addNode strips any
stray parentId/extent when it isn't nesting. New children of a real
container still land at the container's top-left.

ha-relevant: yes
This commit is contained in:
Pouzor
2026-06-17 14:23:49 +02:00
parent 2a4d109ee6
commit 6fba0cdec4
3 changed files with 30 additions and 5 deletions
@@ -150,6 +150,23 @@ describe('canvasStore', () => {
expect(nested?.extent).toBe('parent')
})
it('addNode strips parentId/extent when the parent is not a container', () => {
// Regression: a stray extent:'parent' on a non-container parent traps the
// node in the parent's tiny box with no way to drag it out (issue #205).
const parent = { ...makeNode('p1', { container_mode: false }), position: { x: 100, y: 100 } }
useCanvasStore.getState().addNode(parent)
const trapped: Node<NodeData> = {
...makeNode('c1', { parent_id: 'p1' }),
position: { x: 150, y: 180 },
parentId: 'p1',
extent: 'parent',
}
useCanvasStore.getState().addNode(trapped)
const child = useCanvasStore.getState().nodes.find((n) => n.id === 'c1')
expect(child?.parentId).toBeUndefined()
expect(child?.extent).toBeUndefined()
})
it('docker_container nests under docker_host with container_mode on', () => {
const host = { ...makeNode('dh1', { type: 'docker_host', container_mode: true }), position: { x: 100, y: 100 } }
const container = { ...makeNode('dc1', { type: 'docker_container' }), position: { x: 160, y: 180 } }
+3 -1
View File
@@ -289,7 +289,9 @@ export const useCanvasStore = create<CanvasState>((set) => ({
y: Math.max(10, node.position.y - parent.position.y),
},
}
: node
// Not nesting: strip any parentId/extent a caller may have set so a
// non-container parent can't trap the node in its bounding box.
: { ...node, parentId: undefined, extent: undefined }
// Parents must come before children in the array (React Flow requirement)
const withoutNew = state.nodes.filter((n) => n.id !== node.id)
if (enriched.parentId) {