diff --git a/frontend/src/components/modals/ScanConfigModal.tsx b/frontend/src/components/modals/ScanConfigModal.tsx index 4fe101d..46af678 100644 --- a/frontend/src/components/modals/ScanConfigModal.tsx +++ b/frontend/src/components/modals/ScanConfigModal.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react' -import { Plus, Trash2 } from 'lucide-react' +import { Plus, Trash2, Settings } from 'lucide-react' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' @@ -95,18 +95,10 @@ export function ScanConfigModal({ open, onClose, onScanNow }: ScanConfigModalPro - {/* Status check interval */} -
- - setInterval(Number(e.target.value))} - className="font-mono text-sm bg-[#0d1117] border-border w-32" - /> -
+

+ + Status check interval can be configured in the sidebar Settings. +

diff --git a/frontend/src/components/panels/Sidebar.tsx b/frontend/src/components/panels/Sidebar.tsx index 3105bdb..6de1bf4 100644 --- a/frontend/src/components/panels/Sidebar.tsx +++ b/frontend/src/components/panels/Sidebar.tsx @@ -1,5 +1,5 @@ import { useState, useCallback, useEffect, useRef } from 'react' -import { Plus, Save, ScanLine, ChevronLeft, ChevronRight, LayoutDashboard, Clock, EyeOff, Trash2, RefreshCw, Loader2, Square, Eye } from 'lucide-react' +import { Plus, Save, ScanLine, ChevronLeft, ChevronRight, LayoutDashboard, Clock, EyeOff, Trash2, RefreshCw, Loader2, Square, Eye, Settings } from 'lucide-react' import { Logo } from '@/components/ui/Logo' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { useCanvasStore } from '@/stores/canvasStore' @@ -9,7 +9,7 @@ import { PendingDeviceModal, type PendingDevice } from '@/components/modals/Pend const STANDALONE = import.meta.env.VITE_STANDALONE === 'true' -type SidebarView = 'canvas' | 'pending' | 'hidden' | 'history' +type SidebarView = 'canvas' | 'pending' | 'hidden' | 'history' | 'settings' const ALL_VIEWS = [ { id: 'canvas' as SidebarView, icon: LayoutDashboard, label: 'Canvas' }, @@ -95,6 +95,7 @@ export function Sidebar({ onAddNode, onAddGroupRect, onScan, onSave, onNodeAppro {activeView === 'pending' && } {activeView === 'hidden' && } {activeView === 'history' && } + {activeView === 'settings' && } )} @@ -141,6 +142,15 @@ export function Sidebar({ onAddNode, onAddGroupRect, onScan, onSave, onNodeAppro badge={hasUnsavedChanges} accent /> + {!STANDALONE && ( + setActiveView((v) => v === 'settings' ? 'canvas' : 'settings')} + /> + )} ) @@ -417,6 +427,65 @@ function ScanHistoryPanel() { ) } +function SettingsPanel() { + const [interval, setIntervalValue] = useState(60) + const [ranges, setRangesValue] = useState([]) + const [saving, setSaving] = useState(false) + + useEffect(() => { + scanApi.getConfig() + .then((res) => { + setIntervalValue(res.data.interval_seconds) + setRangesValue(res.data.ranges) + }) + .catch(() => {/* use current defaults */}) + }, []) + + const handleSave = async () => { + setSaving(true) + try { + await scanApi.saveConfig({ ranges, interval_seconds: interval }) + toast.success('Settings saved') + } catch { + toast.error('Failed to save settings') + } finally { + setSaving(false) + } + } + + return ( +
+ Settings + +
+ +
+ setIntervalValue(Number(e.target.value))} + className="w-24 px-2 py-1 rounded-md text-xs font-mono bg-[#0d1117] border border-border text-foreground focus:outline-none focus:border-[#00d4ff]" + /> + seconds +
+

+ How often node health is polled (ping, HTTP, SSH…) +

+
+ + +
+ ) +} + const MAC_OUI: Record = { '52:54:00': { label: 'QEMU', title: 'QEMU/KVM Virtual Machine' }, 'bc:24:11': { label: 'PVE', title: 'Proxmox Virtual Machine or LXC' },