fix(group): preserve children + size on edit, fix status WS proxy
- Skip NodeModal on double-click for 'group'/'groupRect' (use inline rename) - Exempt 'group' from properties-clears-height rule in updateNode (was collapsing group + hiding children with extent: 'parent') - Enable ws: true on Vite /api proxy so /api/v1/status/ws/status upgrades (status bubbles stayed grey because WS handshake failed) - Add regression tests for group/groupRect height preservation
This commit is contained in:
@@ -465,6 +465,11 @@ export default function App() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleNodeDoubleClick = useCallback((node: Node<NodeData>) => {
|
const handleNodeDoubleClick = useCallback((node: Node<NodeData>) => {
|
||||||
|
// 'group' uses inline rename (pencil button in header). Opening the
|
||||||
|
// generic NodeModal would clobber the group's height (via the
|
||||||
|
// properties-clears-height rule in updateNode) and lose its children.
|
||||||
|
// 'groupRect' has its own onDoubleClick that already routes to GroupRectModal.
|
||||||
|
if (node.data.type === 'group' || node.data.type === 'groupRect') return
|
||||||
handleEditNode(node.id)
|
handleEditNode(node.id)
|
||||||
}, [handleEditNode])
|
}, [handleEditNode])
|
||||||
|
|
||||||
|
|||||||
@@ -724,6 +724,36 @@ describe('canvasStore', () => {
|
|||||||
expect(stored?.height).toBeUndefined()
|
expect(stored?.height).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('updateNode preserves height for group type when properties change (children must not vanish)', () => {
|
||||||
|
const group: Node<NodeData> = {
|
||||||
|
id: 'g1',
|
||||||
|
type: 'group',
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
width: 360,
|
||||||
|
height: 240,
|
||||||
|
data: { label: 'Zone', type: 'group', status: 'unknown', services: [] },
|
||||||
|
}
|
||||||
|
useCanvasStore.setState({ nodes: [group], edges: [] })
|
||||||
|
useCanvasStore.getState().updateNode('g1', { properties: [] })
|
||||||
|
const stored = useCanvasStore.getState().nodes.find((n) => n.id === 'g1')
|
||||||
|
expect(stored?.height).toBe(240)
|
||||||
|
expect(stored?.width).toBe(360)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('updateNode preserves height for groupRect when properties change', () => {
|
||||||
|
const rect: Node<NodeData> = {
|
||||||
|
id: 'r1',
|
||||||
|
type: 'groupRect',
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
width: 360,
|
||||||
|
height: 240,
|
||||||
|
data: { label: 'Rect', type: 'groupRect', status: 'unknown', services: [] },
|
||||||
|
}
|
||||||
|
useCanvasStore.setState({ nodes: [rect], edges: [] })
|
||||||
|
useCanvasStore.getState().updateNode('r1', { properties: [] })
|
||||||
|
expect(useCanvasStore.getState().nodes.find((n) => n.id === 'r1')?.height).toBe(240)
|
||||||
|
})
|
||||||
|
|
||||||
// ── bottom_handles edge remapping ──────────────────────────────────────────
|
// ── bottom_handles edge remapping ──────────────────────────────────────────
|
||||||
|
|
||||||
it('remaps source edges to "bottom" when bottom_handles is reduced', () => {
|
it('remaps source edges to "bottom" when bottom_handles is reduced', () => {
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ export const useCanvasStore = create<CanvasState>((set) => ({
|
|||||||
if (n.id !== id) return n
|
if (n.id !== id) return n
|
||||||
const updated: Node<NodeData> = { ...n, data: { ...n.data, ...data } }
|
const updated: Node<NodeData> = { ...n, data: { ...n.data, ...data } }
|
||||||
// When properties change, clear stored height so the node auto-sizes to fit new content
|
// When properties change, clear stored height so the node auto-sizes to fit new content
|
||||||
if ('properties' in data && n.data.type !== 'proxmox' && n.data.type !== 'groupRect') {
|
if ('properties' in data && n.data.type !== 'proxmox' && n.data.type !== 'groupRect' && n.data.type !== 'group') {
|
||||||
updated.height = undefined
|
updated.height = undefined
|
||||||
}
|
}
|
||||||
if ('parent_id' in data) {
|
if ('parent_id' in data) {
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': 'http://localhost:8000',
|
'/api': {
|
||||||
|
target: 'http://localhost:8000',
|
||||||
|
changeOrigin: true,
|
||||||
|
ws: true,
|
||||||
|
},
|
||||||
'/ws': {
|
'/ws': {
|
||||||
target: 'ws://localhost:8000',
|
target: 'ws://localhost:8000',
|
||||||
ws: true,
|
ws: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user