Files
edgeguard-native/management-ui/src/components/Layout/Sidebar.tsx
Debian 2fac8f40dd fix(update): Upgrade-Skript ausserhalb /tmp wegen PrivateTmp
edgeguard-api.service hat PrivateTmp=true → schreibt in privates /tmp.
Die per `sudo systemd-run` gestartete Transient-Unit sah das nicht und
brach mit "bash: /tmp/edgeguard-upgrade.sh: No such file or directory"
ab — Modal hing endlos. Pfad jetzt /var/lib/edgeguard/upgrade.sh
(edgeguard-owned, persistent, in beiden Namespaces sichtbar). Sudoers
entsprechend angepasst.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:21:59 +02:00

119 lines
3.5 KiB
TypeScript

import { NavLink } from 'react-router-dom'
import type { ReactNode } from 'react'
import {
ApartmentOutlined,
ClockCircleOutlined,
CloudServerOutlined,
ClusterOutlined,
CrownOutlined,
DashboardOutlined,
DatabaseOutlined,
FireOutlined,
GlobalOutlined,
NodeIndexOutlined,
SafetyCertificateOutlined,
SettingOutlined,
ThunderboltOutlined,
} from '@ant-design/icons'
import { useTranslation } from 'react-i18next'
interface SidebarProps {
isOpen: boolean
onClose?: () => void
}
interface NavItem {
path: string
labelKey: string
icon: ReactNode
}
interface NavSection {
labelKey: string
items: NavItem[]
}
const NAV: NavSection[] = [
{
labelKey: 'nav.section.overview',
items: [
{ path: '/dashboard', labelKey: 'nav.dashboard', icon: <DashboardOutlined /> },
],
},
{
labelKey: 'nav.section.routing',
items: [
{ path: '/domains', labelKey: 'nav.domains', icon: <GlobalOutlined /> },
{ path: '/backends', labelKey: 'nav.backends', icon: <DatabaseOutlined /> },
// /routing-rules erreichbar via Domain-Modal "Pfad-Routing"-Tab —
// kein eigener Nav-Eintrag mehr (war für 90% der Setups overkill).
],
},
{
labelKey: 'nav.section.network',
items: [
{ path: '/networks', labelKey: 'nav.networks', icon: <ClusterOutlined /> },
{ path: '/ip-addresses', labelKey: 'nav.ipAddresses', icon: <NodeIndexOutlined /> },
{ path: '/ssl', labelKey: 'nav.ssl', icon: <SafetyCertificateOutlined /> },
{ path: '/dns', labelKey: 'nav.dns', icon: <GlobalOutlined /> },
{ path: '/ntp', labelKey: 'nav.ntp', icon: <ClockCircleOutlined /> },
],
},
{
labelKey: 'nav.section.security',
items: [
{ path: '/firewall', labelKey: 'nav.firewall', icon: <FireOutlined /> },
{ path: '/vpn/wireguard', labelKey: 'nav.wireguard', icon: <ThunderboltOutlined /> },
{ path: '/forward-proxy', labelKey: 'nav.forwardProxy', icon: <CloudServerOutlined /> },
],
},
{
labelKey: 'nav.section.system',
items: [
{ path: '/cluster', labelKey: 'nav.cluster', icon: <ApartmentOutlined /> },
{ path: '/license', labelKey: 'nav.license', icon: <CrownOutlined /> },
{ path: '/settings', labelKey: 'nav.settings', icon: <SettingOutlined /> },
],
},
]
const VERSION = '1.0.54'
export default function Sidebar({ isOpen, onClose }: SidebarProps) {
const { t } = useTranslation()
return (
<aside className={`sidebar${isOpen ? ' open' : ''}`}>
<div className="sidebar-logo">
<div className="sidebar-logo-icon">EG</div>
<span className="sidebar-logo-text">{t('app.title')}</span>
</div>
{NAV.map((section) => (
<div key={section.labelKey} className="sidebar-section">
<div className="sidebar-section-label">{t(section.labelKey)}</div>
<ul className="sidebar-menu">
{section.items.map((item) => (
<li key={item.path} className="sidebar-menu-item">
<NavLink
to={item.path}
onClick={onClose}
className={({ isActive }) =>
isActive ? 'sidebar-menu-item active' : ''
}
end
>
{item.icon}
<span>{t(item.labelKey)}</span>
</NavLink>
</li>
))}
</ul>
</div>
))}
<div className="sidebar-version">v{VERSION}</div>
</aside>
)
}