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:
@@ -60,7 +60,7 @@ import (
|
|||||||
usersvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/users"
|
usersvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "1.1.110"
|
var version = "1.1.111"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
addr := os.Getenv("EDGEGUARD_API_ADDR")
|
addr := os.Getenv("EDGEGUARD_API_ADDR")
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
|
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "1.1.110"
|
var version = "1.1.111"
|
||||||
|
|
||||||
const usage = `edgeguard-ctl — EdgeGuard CLI
|
const usage = `edgeguard-ctl — EdgeGuard CLI
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import (
|
|||||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
|
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "1.1.110"
|
var version = "1.1.111"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// renewTickInterval — how often we re-evaluate expiring certs.
|
// renewTickInterval — how often we re-evaluate expiring certs.
|
||||||
|
|||||||
@@ -734,7 +734,8 @@
|
|||||||
},
|
},
|
||||||
"wgCard": {
|
"wgCard": {
|
||||||
"title": "WireGuard",
|
"title": "WireGuard",
|
||||||
"empty": "Noch kein WG-Tunnel angelegt."
|
"empty": "Noch kein WG-Tunnel angelegt.",
|
||||||
|
"peersOnline": "{{online}} / {{total}} Peers verbunden"
|
||||||
},
|
},
|
||||||
"firewallCard": {
|
"firewallCard": {
|
||||||
"title": "Firewall",
|
"title": "Firewall",
|
||||||
|
|||||||
@@ -734,7 +734,8 @@
|
|||||||
},
|
},
|
||||||
"wgCard": {
|
"wgCard": {
|
||||||
"title": "WireGuard",
|
"title": "WireGuard",
|
||||||
"empty": "No WG tunnel configured yet."
|
"empty": "No WG tunnel configured yet.",
|
||||||
|
"peersOnline": "{{online}} / {{total}} peers online"
|
||||||
},
|
},
|
||||||
"firewallCard": {
|
"firewallCard": {
|
||||||
"title": "Firewall",
|
"title": "Firewall",
|
||||||
|
|||||||
@@ -518,6 +518,10 @@ export default function DashboardPage() {
|
|||||||
<Space direction="vertical" style={{ width: '100%' }} size={4}>
|
<Space direction="vertical" style={{ width: '100%' }} size={4}>
|
||||||
{(wgIfaces.data ?? []).map(ifc => {
|
{(wgIfaces.data ?? []).map(ifc => {
|
||||||
const status = (wgStatus.data ?? []).filter(s => s.interface === ifc.name)
|
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 (
|
return (
|
||||||
<div key={ifc.id} style={{ borderBottom: '1px solid #F1F5F9', padding: '4px 0' }}>
|
<div key={ifc.id} style={{ borderBottom: '1px solid #F1F5F9', padding: '4px 0' }}>
|
||||||
<Space>
|
<Space>
|
||||||
@@ -525,13 +529,22 @@ export default function DashboardPage() {
|
|||||||
<Tag color={ifc.mode === 'server' ? 'blue' : 'purple'}>{ifc.mode}</Tag>
|
<Tag color={ifc.mode === 'server' ? 'blue' : 'purple'}>{ifc.mode}</Tag>
|
||||||
<StatusDot active={ifc.active} />
|
<StatusDot active={ifc.active} />
|
||||||
</Space>
|
</Space>
|
||||||
{status.map(s => (
|
{ifc.mode === 'server' ? (
|
||||||
<div key={s.peer_public_key} style={{ fontSize: 12, color: '#64748B', marginTop: 2 }}>
|
status.length > 0 && (
|
||||||
{s.endpoint && <span>{s.endpoint} · </span>}
|
<div style={{ fontSize: 12, color: '#64748B', marginTop: 2 }}>
|
||||||
<span>{relativeTime(s.last_handshake_unix, t)}</span>
|
{t('dashboard.wgCard.peersOnline', { online: onlineCount, total: status.length })}
|
||||||
{' · ▼'}{formatBytes(s.transfer_rx)}{' · ▲'}{formatBytes(s.transfer_tx)}
|
{' · ▼'}{formatBytes(totalRx)}{' ▲'}{formatBytes(totalTx)}
|
||||||
</div>
|
</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>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
Reference in New Issue
Block a user