diff --git a/frontend/src/components/AgentPanel.jsx b/frontend/src/components/AgentPanel.jsx index b417a0e..51f241b 100644 --- a/frontend/src/components/AgentPanel.jsx +++ b/frontend/src/components/AgentPanel.jsx @@ -6,33 +6,52 @@ import { useSettingsStore } from '../stores/settings' import { X, Cpu, MemoryStick, HardDrive, Clock, Network, Shield, Route, Globe, Key, Download, Terminal, Wifi, Search, Plus, Trash2, Copy, Check, ExternalLink, Unplug, Plug, MonitorSmartphone, Ban, + FileKey, UserCheck, Database, CalendarClock, Cable, Settings, Server, GitBranch, } from 'lucide-react' -const allTabs = [ - { id: 'overview', label: 'Uebersicht' }, - { id: 'interfaces', label: 'Interfaces' }, - { id: 'services', label: 'Dienste' }, - { id: 'tunnels', label: 'Tunnel' }, - { id: 'vpn', label: 'VPN', platforms: ['freebsd'] }, - { id: 'wireguard', label: 'WireGuard', platforms: ['freebsd'] }, - { id: 'routes', label: 'Routen' }, - { id: 'dhcp', label: 'DHCP', platforms: ['freebsd'] }, - { id: 'certs', label: 'Zertifikate', platforms: ['freebsd'] }, - { id: 'updates', label: 'Updates', platforms: ['freebsd'] }, - { id: 'security', label: 'Sicherheit', platforms: ['freebsd'] }, - { id: 'tasks', label: 'Aufgaben', platforms: ['freebsd', 'linux'] }, - { id: 'backups', label: 'Backups' }, - { id: 'agent', label: 'Agent' }, +// Two-level navigation structure (DATAZONE style) +const mainCategories = [ + { id: 'uebersicht', label: 'Uebersicht' }, + { id: 'netzwerk', label: 'Netzwerk' }, + { id: 'sicherheit', label: 'Sicherheit' }, + { id: 'daten', label: 'Daten' }, + { id: 'system', label: 'System' }, ] +const subItems = { + netzwerk: [ + { id: 'interfaces', label: 'Interfaces', icon: Network }, + { id: 'vpn', label: 'VPN (WireGuard)', icon: Shield, platforms: ['freebsd'] }, + { id: 'routes', label: 'Routen', icon: GitBranch }, + { id: 'dhcp', label: 'DHCP', icon: Server, platforms: ['freebsd'] }, + { id: 'gateways', label: 'Gateways', icon: Globe }, + ], + sicherheit: [ + { id: 'certs', label: 'Zertifikate', icon: FileKey, platforms: ['freebsd'] }, + { id: 'security', label: 'Logins', icon: UserCheck, platforms: ['freebsd'] }, + ], + daten: [ + { id: 'backups', label: 'Backups', icon: Database }, + { id: 'tasks', label: 'Aufgaben', icon: CalendarClock, platforms: ['freebsd', 'linux'] }, + { id: 'tunnels', label: 'Tunnel', icon: Cable }, + ], + system: [ + { id: 'services', label: 'Dienste', icon: Settings }, + { id: 'updates', label: 'Updates', icon: Download, platforms: ['freebsd'] }, + { id: 'agent', label: 'Agent', icon: Cpu }, + ], +} + export default function AgentPanel({ agentId, customers, onClose, onReload }) { const [data, setData] = useState(null) - const [tab, setTab] = useState('overview') + const [mainTab, setMainTab] = useState('uebersicht') + const [subTab, setSubTab] = useState('overview') const [loading, setLoading] = useState(true) useEffect(() => { setLoading(true) - setTab('overview') + setMainTab('uebersicht') + setSubTab('overview') api.getAgent(agentId).then(setData).finally(() => setLoading(false)) }, [agentId]) @@ -50,7 +69,50 @@ export default function AgentPanel({ agentId, customers, onClose, onReload }) { const { agent, system_data: sys, status } = data const cust = agent.customer_id ? customers.find((c) => c.id === agent.customer_id) : null const platform = agent.platform || 'freebsd' - const tabs = allTabs.filter(t => !t.platforms || t.platforms.includes(platform)) + + // Filter sub-items by platform and determine visible main categories + const getVisibleSubs = (catId) => { + const items = subItems[catId] || [] + return items.filter(s => !s.platforms || s.platforms.includes(platform)) + } + + const visibleMainTabs = mainCategories.filter(cat => { + if (cat.id === 'uebersicht') return true + return getVisibleSubs(cat.id).length > 0 + }) + + const handleMainTabChange = (catId) => { + setMainTab(catId) + if (catId === 'uebersicht') { + setSubTab('overview') + } else { + const subs = getVisibleSubs(catId) + if (subs.length > 0) setSubTab(subs[0].id) + } + } + + // For "gateways" sub-tab, we render the OverviewTab's gateway section standalone + const currentSubs = mainTab !== 'uebersicht' ? getVisibleSubs(mainTab) : [] + + const renderContent = () => { + if (!sys) return
Keine Systemdaten
+ const tab = subTab + if (tab === 'overview') return + if (tab === 'interfaces') return + if (tab === 'services') return + if (tab === 'tunnels') return + if (tab === 'vpn') return <>
+ if (tab === 'routes') return + if (tab === 'dhcp') return + if (tab === 'gateways') return + if (tab === 'certs') return + if (tab === 'updates') return + if (tab === 'security') return + if (tab === 'tasks') return + if (tab === 'backups') return platform === 'linux' ? : + if (tab === 'agent') return + return null + } return ( @@ -86,57 +148,59 @@ export default function AgentPanel({ agentId, customers, onClose, onReload }) { - {/* Tabs */} + {/* Main Category Tabs */}
- {tabs.map((t) => ( + {visibleMainTabs.map((cat) => ( ))}
- {/* Content */} -
- {!sys ? ( -
Keine Systemdaten
- ) : tab === 'overview' ? ( - - ) : tab === 'interfaces' ? ( - - ) : tab === 'services' ? ( - - ) : tab === 'tunnels' ? ( - - ) : tab === 'vpn' ? ( - - ) : tab === 'wireguard' ? ( - - ) : tab === 'routes' ? ( - - ) : tab === 'dhcp' ? ( - - ) : tab === 'certs' ? ( - - ) : tab === 'updates' ? ( - - ) : tab === 'security' ? ( - - ) : tab === 'tasks' ? ( - - ) : tab === 'backups' ? ( - platform === 'linux' ? : - ) : tab === 'agent' ? ( - - ) : null} + {/* Content area with optional sub-nav */} +
+ {/* Sub-Navigation (left sidebar) — hidden for Uebersicht */} + {mainTab !== 'uebersicht' && currentSubs.length > 0 && ( +
+
+ + {mainCategories.find(c => c.id === mainTab)?.label} + +
+ {currentSubs.map((item) => { + const Icon = item.icon + const isActive = subTab === item.id + return ( + + ) + })} +
+ )} + + {/* Main content */} +
+ {renderContent()} +
) @@ -204,7 +268,7 @@ function Panel({ onClose, children }) { return ( <>
-
+
{children}