diff --git a/frontend/src/components/modals/PendingDeviceModal.tsx b/frontend/src/components/modals/PendingDeviceModal.tsx index fe90281..cbad9c7 100644 --- a/frontend/src/components/modals/PendingDeviceModal.tsx +++ b/frontend/src/components/modals/PendingDeviceModal.tsx @@ -78,7 +78,7 @@ export function PendingDeviceModal({ device, onClose, onApprove, onHide, onIgnor const TypeIcon = TYPE_ICONS[device.suggested_type ?? 'generic'] ?? Circle - const handleApprove = () => { onApprove(device); onClose() } + const handleApprove = () => { onApprove(device) } const handleHide = () => { onHide(device); onClose() } const handleIgnore = () => { onIgnore(device); onClose() } diff --git a/frontend/src/components/modals/__tests__/PendingDeviceModal.test.tsx b/frontend/src/components/modals/__tests__/PendingDeviceModal.test.tsx index 3ec4211..c100651 100644 --- a/frontend/src/components/modals/__tests__/PendingDeviceModal.test.tsx +++ b/frontend/src/components/modals/__tests__/PendingDeviceModal.test.tsx @@ -126,7 +126,7 @@ describe('PendingDeviceModal', () => { // ── Actions ─────────────────────────────────────────────────────────────── - it('calls onApprove with the device and onClose when Approve is clicked', () => { + it('calls onApprove with the device when Approve is clicked (parent controls close on success)', () => { const device = makeDevice() const onApprove = vi.fn() const onClose = vi.fn() @@ -135,7 +135,7 @@ describe('PendingDeviceModal', () => { ) fireEvent.click(screen.getByRole('button', { name: 'Approve' })) expect(onApprove).toHaveBeenCalledWith(device) - expect(onClose).toHaveBeenCalledOnce() + expect(onClose).not.toHaveBeenCalled() }) it('calls onHide with the device and onClose when Hide is clicked', () => { diff --git a/frontend/src/components/panels/DetailPanel.tsx b/frontend/src/components/panels/DetailPanel.tsx index 2714c5b..690860f 100644 --- a/frontend/src/components/panels/DetailPanel.tsx +++ b/frontend/src/components/panels/DetailPanel.tsx @@ -85,6 +85,7 @@ export function DetailPanel({ onEdit }: DetailPanelProps) { const handleAddService = () => { const port = parseInt(newSvc.port, 10) if (!newSvc.service_name.trim() || isNaN(port) || port < 1 || port > 65535) return + snapshotHistory() const svc: ServiceInfo = { port, protocol: newSvc.protocol, service_name: newSvc.service_name.trim() } updateNode(node.id, { services: [...services, svc] }) setNewSvc(EMPTY_FORM) @@ -92,6 +93,7 @@ export function DetailPanel({ onEdit }: DetailPanelProps) { } const handleRemoveService = (index: number) => { + snapshotHistory() const updated = services.filter((_, i) => i !== index) updateNode(node.id, { services: updated }) if (editingIndex === index) setEditingFor(null) @@ -109,6 +111,7 @@ export function DetailPanel({ onEdit }: DetailPanelProps) { if (editingIndex === null) return const port = parseInt(editSvc.port, 10) if (!editSvc.service_name.trim() || isNaN(port) || port < 1 || port > 65535) return + snapshotHistory() const updated = services.map((svc, i) => i === editingIndex ? { ...svc, port, protocol: editSvc.protocol, service_name: editSvc.service_name.trim() } : svc ) diff --git a/frontend/src/components/panels/Sidebar.tsx b/frontend/src/components/panels/Sidebar.tsx index 941f63d..e0f2b9c 100644 --- a/frontend/src/components/panels/Sidebar.tsx +++ b/frontend/src/components/panels/Sidebar.tsx @@ -163,6 +163,8 @@ export function Sidebar({ onAddNode, onAddGroupRect, onScan, onSave, onNodeAppro ) } +const COMMON_PORTS = new Set([22, 80, 443]) + function PendingDevicesPanel({ onNodeApproved, highlightId }: { onNodeApproved: (nodeId: string) => void; highlightId?: string }) { const [devices, setDevices] = useState([]) const [loading, setLoading] = useState(false) @@ -223,6 +225,7 @@ function PendingDevicesPanel({ onNodeApproved, highlightId }: { onNodeApproved: }) toast.success(`Approved ${nodeData.label}`) setDevices((prev) => prev.filter((d) => d.id !== device.id)) + setSelected(null) onNodeApproved(nodeId) } catch { toast.error('Failed to approve device') @@ -269,7 +272,6 @@ function PendingDevicesPanel({ onNodeApproved, highlightId }: { onNodeApproved:

No pending devices

)} {devices.map((d) => { - const COMMON_PORTS = new Set([22, 80, 443]) const namedService = d.services.find((s) => s.category != null && !COMMON_PORTS.has(s.port)) const titleService = namedService ?? d.services.find((s) => s.port === 80)