From 14a5aca9767f729394cbb5982f333444b02e86e9 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sun, 28 Dec 2025 03:14:10 +0100 Subject: [PATCH] feat(system-hub): add Network and Services widgets to Real-Time Metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added 2 new performance widgets: 🌐 Network Stats: - Online/Offline status with badge - Total download (RX) in GB - Total upload (TX) in GB - Network status indicator - Cyan → Blue gradient ⚙️ Services Monitor: - Running/Total services count - Failed services count - Health percentage (running/total) - Status badges: healthy/issues/critical - Green → Emerald gradient All widgets now visible by default (6 total): 1. CPU Performance (with load histogram) 2. Memory Usage (with swap visualization) 3. Disk Space 4. Temperature 5. Network Stats (NEW) 6. Services Monitor (NEW) Grid layout auto-adapts: 280px min per widget --- .../resources/view/system-hub/overview.js | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/luci-app-system-hub/htdocs/luci-static/resources/view/system-hub/overview.js b/luci-app-system-hub/htdocs/luci-static/resources/view/system-hub/overview.js index 6c435184..caf5225f 100644 --- a/luci-app-system-hub/htdocs/luci-static/resources/view/system-hub/overview.js +++ b/luci-app-system-hub/htdocs/luci-static/resources/view/system-hub/overview.js @@ -328,6 +328,8 @@ return view.extend({ var memory = this.healthData.memory || {}; var disk = this.healthData.disk || {}; var temp = this.healthData.temperature || {}; + var network = this.healthData.network || {}; + var services = this.healthData.services || {}; return E('div', { 'class': 'sh-realtime-metrics' }, [ // CPU with load trend bars @@ -478,6 +480,84 @@ return view.extend({ E('span', { 'class': 'sh-rt-detail-value' }, '85°C') ]) ]) + ]), + + // Network Stats (v0.3.2 - NEW) + E('div', { 'class': 'sh-rt-metric sh-rt-metric-network' }, [ + E('div', { 'class': 'sh-rt-header' }, [ + E('div', { 'class': 'sh-rt-title-group' }, [ + E('span', { 'class': 'sh-rt-icon' }, '🌐'), + E('span', { 'class': 'sh-rt-title' }, 'Network Stats') + ]), + E('div', { 'class': 'sh-rt-value-group' }, [ + E('span', { 'class': 'sh-rt-value' }, network.wan_up ? 'Online' : 'Offline'), + E('span', { 'class': 'sh-rt-badge sh-rt-badge-' + (network.wan_up ? 'ok' : 'critical') }, + network.wan_up ? 'connected' : 'disconnected') + ]) + ]), + E('div', { 'class': 'sh-rt-progress-modern' }, [ + E('div', { + 'class': 'sh-rt-progress-fill sh-rt-gradient-network', + 'style': 'width: ' + (network.wan_up ? 100 : 0) + '%' + }) + ]), + E('div', { 'class': 'sh-rt-details-grid' }, [ + E('div', { 'class': 'sh-rt-detail' }, [ + E('span', { 'class': 'sh-rt-detail-label' }, 'Download'), + E('span', { 'class': 'sh-rt-detail-value' }, + '↓ ' + ((network.rx_bytes || 0) / 1024 / 1024 / 1024).toFixed(2) + ' GB') + ]), + E('div', { 'class': 'sh-rt-detail' }, [ + E('span', { 'class': 'sh-rt-detail-label' }, 'Upload'), + E('span', { 'class': 'sh-rt-detail-value' }, + '↑ ' + ((network.tx_bytes || 0) / 1024 / 1024 / 1024).toFixed(2) + ' GB') + ]), + E('div', { 'class': 'sh-rt-detail' }, [ + E('span', { 'class': 'sh-rt-detail-label' }, 'Status'), + E('span', { 'class': 'sh-rt-detail-value' }, network.status || 'unknown') + ]) + ]) + ]), + + // Services Monitor (v0.3.2 - NEW) + E('div', { 'class': 'sh-rt-metric sh-rt-metric-services' }, [ + E('div', { 'class': 'sh-rt-header' }, [ + E('div', { 'class': 'sh-rt-title-group' }, [ + E('span', { 'class': 'sh-rt-icon' }, '⚙️'), + E('span', { 'class': 'sh-rt-title' }, 'Services Monitor') + ]), + E('div', { 'class': 'sh-rt-value-group' }, [ + E('span', { 'class': 'sh-rt-value' }, (services.running || 0) + '/' + ((services.running || 0) + (services.failed || 0))), + E('span', { + 'class': 'sh-rt-badge sh-rt-badge-' + ((services.failed || 0) === 0 ? 'ok' : (services.failed || 0) > 3 ? 'critical' : 'warning') + }, (services.failed || 0) === 0 ? 'healthy' : 'issues') + ]) + ]), + E('div', { 'class': 'sh-rt-progress-modern' }, [ + E('div', { + 'class': 'sh-rt-progress-fill sh-rt-gradient-services', + 'style': 'width: ' + (((services.running || 0) + (services.failed || 0)) > 0 + ? Math.round(((services.running || 0) / ((services.running || 0) + (services.failed || 0))) * 100) + : 100) + '%' + }) + ]), + E('div', { 'class': 'sh-rt-details-grid' }, [ + E('div', { 'class': 'sh-rt-detail' }, [ + E('span', { 'class': 'sh-rt-detail-label' }, 'Running'), + E('span', { 'class': 'sh-rt-detail-value' }, (services.running || 0) + ' services') + ]), + E('div', { 'class': 'sh-rt-detail' }, [ + E('span', { 'class': 'sh-rt-detail-label' }, 'Failed'), + E('span', { 'class': 'sh-rt-detail-value' }, (services.failed || 0) + ' services') + ]), + E('div', { 'class': 'sh-rt-detail' }, [ + E('span', { 'class': 'sh-rt-detail-label' }, 'Health'), + E('span', { 'class': 'sh-rt-detail-value' }, + (((services.running || 0) + (services.failed || 0)) > 0 + ? Math.round(((services.running || 0) / ((services.running || 0) + (services.failed || 0))) * 100) + : 100) + '%') + ]) + ]) ]) ]); },