feat(dashboard): WG server tunnels show peer summary instead of per-peer rows

Server tunnels with many peers previously flooded the WG card. Now
server mode shows "X/Y peers online · ▼rx ▲tx" (3-min handshake
threshold) while client tunnels retain full per-peer detail.
Adds i18n keys dashboard.wgCard.peersOnline (EN/DE). v1.1.111.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-26 20:01:49 +02:00
parent 4406f9ac5b
commit 326f79cf00
7 changed files with 28 additions and 13 deletions

View File

@@ -734,7 +734,8 @@
},
"wgCard": {
"title": "WireGuard",
"empty": "Noch kein WG-Tunnel angelegt."
"empty": "Noch kein WG-Tunnel angelegt.",
"peersOnline": "{{online}} / {{total}} Peers verbunden"
},
"firewallCard": {
"title": "Firewall",

View File

@@ -734,7 +734,8 @@
},
"wgCard": {
"title": "WireGuard",
"empty": "No WG tunnel configured yet."
"empty": "No WG tunnel configured yet.",
"peersOnline": "{{online}} / {{total}} peers online"
},
"firewallCard": {
"title": "Firewall",

View File

@@ -518,6 +518,10 @@ export default function DashboardPage() {
<Space direction="vertical" style={{ width: '100%' }} size={4}>
{(wgIfaces.data ?? []).map(ifc => {
const status = (wgStatus.data ?? []).filter(s => s.interface === ifc.name)
const nowSec = Date.now() / 1000
const onlineCount = status.filter(s => s.last_handshake_unix > 0 && nowSec - s.last_handshake_unix < 180).length
const totalRx = status.reduce((acc, s) => acc + s.transfer_rx, 0)
const totalTx = status.reduce((acc, s) => acc + s.transfer_tx, 0)
return (
<div key={ifc.id} style={{ borderBottom: '1px solid #F1F5F9', padding: '4px 0' }}>
<Space>
@@ -525,13 +529,22 @@ export default function DashboardPage() {
<Tag color={ifc.mode === 'server' ? 'blue' : 'purple'}>{ifc.mode}</Tag>
<StatusDot active={ifc.active} />
</Space>
{status.map(s => (
<div key={s.peer_public_key} style={{ fontSize: 12, color: '#64748B', marginTop: 2 }}>
{s.endpoint && <span>{s.endpoint} · </span>}
<span>{relativeTime(s.last_handshake_unix, t)}</span>
{' · ▼'}{formatBytes(s.transfer_rx)}{' · ▲'}{formatBytes(s.transfer_tx)}
</div>
))}
{ifc.mode === 'server' ? (
status.length > 0 && (
<div style={{ fontSize: 12, color: '#64748B', marginTop: 2 }}>
{t('dashboard.wgCard.peersOnline', { online: onlineCount, total: status.length })}
{' · ▼'}{formatBytes(totalRx)}{' ▲'}{formatBytes(totalTx)}
</div>
)
) : (
status.map(s => (
<div key={s.peer_public_key} style={{ fontSize: 12, color: '#64748B', marginTop: 2 }}>
{s.endpoint && <span>{s.endpoint} · </span>}
<span>{relativeTime(s.last_handshake_unix, t)}</span>
{' · ▼'}{formatBytes(s.transfer_rx)}{' ▲'}{formatBytes(s.transfer_tx)}
</div>
))
)}
</div>
)
})}