From 04069e080a721b07aa99a9e514c36584314144de Mon Sep 17 00:00:00 2001 From: findthelorax Date: Thu, 16 Apr 2026 10:10:30 -0400 Subject: [PATCH 1/5] feature: double-click on a node to open an edit modal --- frontend/src/App.tsx | 1 + frontend/src/components/canvas/CanvasContainer.tsx | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a36b9d0..c3ff8df 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -400,6 +400,7 @@ export default function App() { handleEditNode(node.id)} onNodeDragStart={snapshotHistory} onOpenPending={(deviceId) => { setHighlightPendingId(undefined) diff --git a/frontend/src/components/canvas/CanvasContainer.tsx b/frontend/src/components/canvas/CanvasContainer.tsx index 3847dc6..cee03e8 100644 --- a/frontend/src/components/canvas/CanvasContainer.tsx +++ b/frontend/src/components/canvas/CanvasContainer.tsx @@ -25,11 +25,12 @@ import type { NodeData, EdgeData } from '@/types' interface CanvasContainerProps { onConnect?: (connection: Connection) => void onEdgeDoubleClick?: (edge: Edge) => void + onNodeDoubleClick?: (node: Node) => void onNodeDragStart?: () => void onOpenPending?: (deviceId: string) => void } -export function CanvasContainer({ onConnect: onConnectProp, onEdgeDoubleClick, onNodeDragStart, onOpenPending }: CanvasContainerProps) { +export function CanvasContainer({ onConnect: onConnectProp, onEdgeDoubleClick, onNodeDoubleClick, onNodeDragStart, onOpenPending }: CanvasContainerProps) { const [lassoMode, setLassoMode] = useState(true) const { nodes, edges, @@ -68,6 +69,10 @@ export function CanvasContainer({ onConnect: onConnectProp, onEdgeDoubleClick, o onEdgeDoubleClick?.(edge) }, [onEdgeDoubleClick]) + const handleNodeDoubleClick = useCallback((_: React.MouseEvent, node: Node) => { + onNodeDoubleClick?.(node) + }, [onNodeDoubleClick]) + return (
Date: Sat, 18 Apr 2026 21:09:49 +0200 Subject: [PATCH 2/5] fix: extract handleNodeDoubleClick into useCallback and add tests Replace inline arrow with named useCallback handler to avoid creating a new fn ref on every render. Add two CanvasContainer tests covering the double-click callback and the no-op path when prop is omitted. --- frontend/src/App.tsx | 6 +++++- .../canvas/__tests__/CanvasContainer.test.tsx | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c3ff8df..fdd1b1c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -343,6 +343,10 @@ export default function App() { setEditEdgeId(edge.id) }, []) + const handleNodeDoubleClick = useCallback((node: Node) => { + handleEditNode(node.id) + }, [handleEditNode]) + const handleEdgeUpdate = useCallback((data: EdgeData) => { if (!editEdgeId) return snapshotHistory() @@ -400,7 +404,7 @@ export default function App() { handleEditNode(node.id)} + onNodeDoubleClick={handleNodeDoubleClick} onNodeDragStart={snapshotHistory} onOpenPending={(deviceId) => { setHighlightPendingId(undefined) diff --git a/frontend/src/components/canvas/__tests__/CanvasContainer.test.tsx b/frontend/src/components/canvas/__tests__/CanvasContainer.test.tsx index a80ced1..332e983 100644 --- a/frontend/src/components/canvas/__tests__/CanvasContainer.test.tsx +++ b/frontend/src/components/canvas/__tests__/CanvasContainer.test.tsx @@ -104,6 +104,24 @@ describe('CanvasContainer', () => { }).not.toThrow() }) + // ── Node double-click ───────────────────────────────────────────────────── + + it('calls onNodeDoubleClick prop when a node is double-clicked', () => { + const onNodeDoubleClick = vi.fn() + const node = makeNode('n1') + render() + ;(rfProps.onNodeDoubleClick as (...args: unknown[]) => unknown)({} as MouseEvent, node) + expect(onNodeDoubleClick).toHaveBeenCalledWith(node) + }) + + it('does not throw when onNodeDoubleClick is not provided', () => { + const node = makeNode('n1') + render() + expect(() => { + ;(rfProps.onNodeDoubleClick as (...args: unknown[]) => unknown)({} as MouseEvent, node) + }).not.toThrow() + }) + // ── Connection validation ───────────────────────────────────────────────── it('isValidConnection returns false for self-connections', () => { From 12f46715c10455692c9da63de5f00c5657ec0d4d Mon Sep 17 00:00:00 2001 From: Pouzor Date: Sat, 18 Apr 2026 21:36:09 +0200 Subject: [PATCH 3/5] fix: bump python-multipart, pytest, pytest-asyncio to fix CVEs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - python-multipart 0.0.22 → 0.0.26 (CVE-2026-40347) - pytest 8.3.3 → 9.0.3 (CVE-2025-71176) - pytest-asyncio 0.24.0 → 0.26.0 (pytest 9 compat) --- backend/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 792a5bc..e30f7bc 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -9,7 +9,7 @@ pydantic-settings==2.5.2 python-jose[cryptography]==3.5.0 passlib[bcrypt]==1.7.4 bcrypt==4.0.1 -python-multipart==0.0.22 +python-multipart==0.0.26 apscheduler==3.10.4 python-nmap==0.7.1 pyyaml==6.0.2 @@ -21,6 +21,6 @@ zeroconf==0.131.0 # Dev ruff==0.6.9 mypy==1.11.2 -pytest==8.3.3 -pytest-asyncio==0.24.0 +pytest==9.0.3 +pytest-asyncio==0.26.0 pytest-cov==5.0.0 From 72d5a51b4464ef28f70ce73f8bbd775636be4415 Mon Sep 17 00:00:00 2001 From: Pouzor Date: Sat, 18 Apr 2026 21:45:10 +0200 Subject: [PATCH 4/5] fix: bump pytest-asyncio to 1.0.0 for pytest 9 compatibility pytest-asyncio 0.26.0 requires pytest<9; 1.0.0 supports pytest 9.x --- backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index e30f7bc..48ec18f 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -22,5 +22,5 @@ zeroconf==0.131.0 ruff==0.6.9 mypy==1.11.2 pytest==9.0.3 -pytest-asyncio==0.26.0 +pytest-asyncio==1.0.0 pytest-cov==5.0.0 From a7b244502e758e8959cdae5bcff61862874bbafb Mon Sep 17 00:00:00 2001 From: Pouzor Date: Sat, 18 Apr 2026 21:52:32 +0200 Subject: [PATCH 5/5] fix: bump pytest-asyncio to 1.3.0 (first version supporting pytest 9) --- backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 48ec18f..3bd01ad 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -22,5 +22,5 @@ zeroconf==0.131.0 ruff==0.6.9 mypy==1.11.2 pytest==9.0.3 -pytest-asyncio==1.0.0 +pytest-asyncio==1.3.0 pytest-cov==5.0.0