From 5b92953241f5ba3f737531827d0333ad3ba29084 Mon Sep 17 00:00:00 2001 From: "Valeriano A.R." Date: Wed, 6 Aug 2025 14:04:21 +0200 Subject: [PATCH] Nethogs-Monitor: Dashboard with terminal style --- .../nethogs-monitor-dashboard-template.html | 471 ++++++++++++++---- 1 file changed, 380 insertions(+), 91 deletions(-) diff --git a/monitor-service/nethogs-monitor-dashboard-template.html b/monitor-service/nethogs-monitor-dashboard-template.html index 3040493..707d414 100644 --- a/monitor-service/nethogs-monitor-dashboard-template.html +++ b/monitor-service/nethogs-monitor-dashboard-template.html @@ -13,170 +13,297 @@ } body { - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + font-family: 'Consolas', 'Monaco', 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace; + background: radial-gradient(ellipse at center, #0d1421 0%, #0a0f1a 100%); min-height: 100vh; - color: #333; + color: #00ff41; + position: relative; + overflow-x: hidden; + } + + /* Matrix-like background effect */ + body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: + linear-gradient(90deg, rgba(0, 255, 65, 0.03) 50%, transparent 50%), + linear-gradient(rgba(0, 255, 65, 0.03) 50%, transparent 50%); + background-size: 20px 20px; + pointer-events: none; + z-index: -1; } .container { max-width: 1400px; margin: 0 auto; padding: 20px; + position: relative; + z-index: 1; } .header { - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); - padding: 20px; + background: linear-gradient(145deg, rgba(13, 20, 33, 0.95), rgba(10, 15, 26, 0.95)); + backdrop-filter: blur(20px); + padding: 25px; border-radius: 15px; margin-bottom: 30px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + box-shadow: + 0 0 30px rgba(0, 255, 65, 0.2), + inset 0 1px 0 rgba(0, 255, 65, 0.1), + 0 8px 32px rgba(0, 0, 0, 0.4); + border: 1px solid rgba(0, 255, 65, 0.2); + position: relative; + } + + .header::before { + content: ''; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + background: linear-gradient(45deg, #00ff41, #00cc33, #009926, #00ff41); + border-radius: 17px; + z-index: -1; + opacity: 0.1; } .header h1 { - color: #4a5568; - font-size: 2.5rem; + color: #00ff41; + font-size: 2.8rem; margin-bottom: 10px; text-align: center; + text-shadow: 0 0 20px rgba(0, 255, 65, 0.5); + font-weight: 700; } .generation-info { text-align: center; - color: #718096; - margin-top: 10px; - font-size: 0.9rem; + color: #66ff82; + margin-top: 15px; + font-size: 1rem; + text-shadow: 0 0 10px rgba(102, 255, 130, 0.3); } .stats-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - gap: 20px; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 25px; margin-bottom: 30px; } .stat-card { - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); - padding: 20px; + background: linear-gradient(145deg, rgba(13, 20, 33, 0.9), rgba(10, 15, 26, 0.9)); + backdrop-filter: blur(20px); + padding: 25px; border-radius: 15px; text-align: center; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); - transition: transform 0.3s ease; + box-shadow: + 0 0 25px rgba(0, 255, 65, 0.15), + inset 0 1px 0 rgba(0, 255, 65, 0.1), + 0 8px 32px rgba(0, 0, 0, 0.3); + border: 1px solid rgba(0, 255, 65, 0.15); + transition: all 0.4s ease; + position: relative; + overflow: hidden; + } + + .stat-card::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(0, 255, 65, 0.1), transparent); + transition: left 0.6s ease; + } + + .stat-card:hover::before { + left: 100%; } .stat-card:hover { - transform: translateY(-5px); + transform: translateY(-8px) scale(1.02); + box-shadow: + 0 0 40px rgba(0, 255, 65, 0.3), + inset 0 1px 0 rgba(0, 255, 65, 0.2), + 0 15px 45px rgba(0, 0, 0, 0.4); + border-color: rgba(0, 255, 65, 0.4); } .stat-value { - font-size: 2rem; + font-size: 2.5rem; font-weight: bold; - color: #667eea; - margin-bottom: 5px; + color: #00ff41; + margin-bottom: 8px; + text-shadow: 0 0 15px rgba(0, 255, 65, 0.4); } .stat-label { - color: #718096; - font-size: 0.9rem; + color: #66ff82; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + opacity: 0.9; } .controls { - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); - padding: 20px; + background: linear-gradient(145deg, rgba(13, 20, 33, 0.9), rgba(10, 15, 26, 0.9)); + backdrop-filter: blur(20px); + padding: 25px; border-radius: 15px; margin-bottom: 30px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + box-shadow: + 0 0 25px rgba(0, 255, 65, 0.15), + inset 0 1px 0 rgba(0, 255, 65, 0.1), + 0 8px 32px rgba(0, 0, 0, 0.3); + border: 1px solid rgba(0, 255, 65, 0.15); } .controls-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 15px; - align-items: center; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 20px; + align-items: end; } .control-group { display: flex; flex-direction: column; - gap: 5px; + gap: 8px; } .control-group label { font-weight: 600; - color: #4a5568; + color: #00ff41; + text-transform: uppercase; + font-size: 0.9rem; + letter-spacing: 0.5px; + text-shadow: 0 0 10px rgba(0, 255, 65, 0.3); } .control-group select { - padding: 10px; - border: 2px solid #e2e8f0; + padding: 12px 15px; + border: 2px solid rgba(0, 255, 65, 0.3); border-radius: 8px; font-size: 14px; - transition: border-color 0.3s ease; + background: rgba(13, 20, 33, 0.8); + color: #00ff41; + transition: all 0.3s ease; + font-family: inherit; } .control-group select:focus { outline: none; - border-color: #667eea; + border-color: #00ff41; + box-shadow: 0 0 15px rgba(0, 255, 65, 0.3); + background: rgba(13, 20, 33, 1); + } + + .control-group select option { + background: rgba(13, 20, 33, 0.95); + color: #00ff41; + padding: 8px; } .refresh-btn { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; - border: none; + background: linear-gradient(145deg, rgba(0, 255, 65, 0.2), rgba(0, 204, 51, 0.2)); + color: #00ff41; + border: 2px solid rgba(0, 255, 65, 0.4); padding: 12px 25px; border-radius: 8px; cursor: pointer; font-weight: 600; - transition: transform 0.3s ease; - align-self: end; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 1px; + transition: all 0.3s ease; + position: relative; + overflow: hidden; + } + + .refresh-btn::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(0, 255, 65, 0.2), transparent); + transition: left 0.5s ease; + } + + .refresh-btn:hover::before { + left: 100%; } .refresh-btn:hover { transform: scale(1.05); + box-shadow: 0 0 20px rgba(0, 255, 65, 0.4); + background: linear-gradient(145deg, rgba(0, 255, 65, 0.3), rgba(0, 204, 51, 0.3)); + border-color: #00ff41; } .charts-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(600px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(650px, 1fr)); gap: 30px; margin-bottom: 30px; } .chart-card { - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); - padding: 25px; + background: linear-gradient(145deg, rgba(13, 20, 33, 0.9), rgba(10, 15, 26, 0.9)); + backdrop-filter: blur(20px); + padding: 30px; border-radius: 15px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + box-shadow: + 0 0 25px rgba(0, 255, 65, 0.15), + inset 0 1px 0 rgba(0, 255, 65, 0.1), + 0 8px 32px rgba(0, 0, 0, 0.3); + border: 1px solid rgba(0, 255, 65, 0.15); } .chart-title { - font-size: 1.3rem; + font-size: 1.4rem; font-weight: 600; - color: #4a5568; - margin-bottom: 20px; + color: #00ff41; + margin-bottom: 25px; text-align: center; + text-transform: uppercase; + letter-spacing: 1px; + text-shadow: 0 0 15px rgba(0, 255, 65, 0.3); } .table-container { - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); + background: linear-gradient(145deg, rgba(13, 20, 33, 0.9), rgba(10, 15, 26, 0.9)); + backdrop-filter: blur(20px); border-radius: 15px; overflow: hidden; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + box-shadow: + 0 0 30px rgba(0, 255, 65, 0.2), + inset 0 1px 0 rgba(0, 255, 65, 0.1), + 0 8px 32px rgba(0, 0, 0, 0.3); + border: 1px solid rgba(0, 255, 65, 0.2); } .table-header { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; - padding: 20px; - font-size: 1.2rem; + background: linear-gradient(135deg, rgba(0, 255, 65, 0.2) 0%, rgba(0, 204, 51, 0.2) 100%); + color: #00ff41; + padding: 25px; + font-size: 1.3rem; font-weight: 600; display: flex; justify-content: space-between; align-items: center; + text-transform: uppercase; + letter-spacing: 1px; + text-shadow: 0 0 10px rgba(0, 255, 65, 0.3); + border-bottom: 1px solid rgba(0, 255, 65, 0.3); } .table-wrapper { @@ -190,29 +317,69 @@ } th, td { - padding: 12px 15px; + padding: 15px 18px; text-align: left; - border-bottom: 1px solid #e2e8f0; + border-bottom: 1px solid rgba(0, 255, 65, 0.1); } th { - background: #f7fafc; + background: rgba(13, 20, 33, 0.8); font-weight: 600; - color: #4a5568; + color: #00ff41; position: sticky; top: 0; + text-transform: uppercase; + font-size: 0.9rem; + letter-spacing: 0.5px; + text-shadow: 0 0 8px rgba(0, 255, 65, 0.3); + border-bottom: 2px solid rgba(0, 255, 65, 0.3); + } + + td { + color: #66ff82; + font-size: 0.95rem; } tr:hover { - background: rgba(102, 126, 234, 0.05); + background: rgba(0, 255, 65, 0.05); + transform: scale(1.001); + transition: all 0.2s ease; + } + + tr:hover td { + color: #00ff41; + text-shadow: 0 0 5px rgba(0, 255, 65, 0.2); } .error { - background: #fed7d7; - color: #c53030; - padding: 15px; - border-radius: 8px; + background: linear-gradient(145deg, rgba(255, 0, 0, 0.1), rgba(200, 0, 0, 0.1)); + color: #ff4444; + padding: 20px; + border-radius: 10px; margin: 20px 0; + border: 1px solid rgba(255, 68, 68, 0.3); + text-shadow: 0 0 10px rgba(255, 68, 68, 0.3); + } + + /* Scrollbar styling */ + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + ::-webkit-scrollbar-track { + background: rgba(13, 20, 33, 0.8); + border-radius: 4px; + } + + ::-webkit-scrollbar-thumb { + background: linear-gradient(145deg, rgba(0, 255, 65, 0.3), rgba(0, 204, 51, 0.3)); + border-radius: 4px; + border: 1px solid rgba(0, 255, 65, 0.2); + } + + ::-webkit-scrollbar-thumb:hover { + background: linear-gradient(145deg, rgba(0, 255, 65, 0.5), rgba(0, 204, 51, 0.5)); } @media (max-width: 768px) { @@ -225,8 +392,37 @@ } .header h1 { - font-size: 2rem; + font-size: 2.2rem; } + + .stats-grid { + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + } + } + + /* Animation for loading */ + @keyframes pulse { + 0% { opacity: 0.6; } + 50% { opacity: 1; } + 100% { opacity: 0.6; } + } + + .loading { + animation: pulse 1.5s ease-in-out infinite; + } + + /* Glitch effect for title */ + @keyframes glitch { + 0% { transform: translate(0); } + 20% { transform: translate(-1px, 1px); } + 40% { transform: translate(-1px, -1px); } + 60% { transform: translate(1px, 1px); } + 80% { transform: translate(1px, -1px); } + 100% { transform: translate(0); } + } + + .header h1:hover { + animation: glitch 0.5s ease-in-out; } @@ -234,8 +430,8 @@

🌐 Network Monitor Dashboard

-

- System network traffic monitoring +

+ >>> SYSTEM NETWORK TRAFFIC MONITORING <<<

Generated on: GENERATION_TIME_PLACEHOLDER @@ -321,7 +517,7 @@ - Processing data... + Processing data... @@ -339,6 +535,16 @@ JSON_DATA_PLACEHOLDER let rawData = []; let charts = {}; + // Terminal green color palette + const terminalColors = { + primary: '#00ff41', // Matrix green + secondary: '#00cc33', // Darker green + tertiary: '#66ff82', // Lighter green + accent: '#009926', // Medium green + background: '#0d1421', // Dark blue-black + surface: 'rgba(13, 20, 33, 0.9)' + }; + function formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes'; const k = 1024; @@ -352,11 +558,11 @@ JSON_DATA_PLACEHOLDER return new Date(timestamp * 1000).toLocaleString('es-ES'); } - function generateColor(index) { + function generateTerminalColor(index) { const colors = [ - '#667eea', '#764ba2', '#f093fb', '#f5576c', - '#4facfe', '#00f2fe', '#43e97b', '#38f9d7', - '#ffecd2', '#fcb69f', '#a8edea', '#fed6e3' + '#00ff41', '#00cc33', '#66ff82', '#009926', + '#00ff66', '#33ff66', '#00e639', '#00b32d', + '#80ff80', '#40ff40', '#00d932', '#00a028' ]; return colors[index % colors.length]; } @@ -477,21 +683,34 @@ JSON_DATA_PLACEHOLDER datasets: [{ label: 'Descarga', data: downloadData, - backgroundColor: 'rgba(102, 126, 234, 0.8)', - borderColor: 'rgba(102, 126, 234, 1)', - borderWidth: 1 + backgroundColor: 'rgba(0, 255, 65, 0.7)', + borderColor: '#00ff41', + borderWidth: 2 }, { label: 'Subida', data: uploadData, - backgroundColor: 'rgba(118, 75, 162, 0.8)', - borderColor: 'rgba(118, 75, 162, 1)', - borderWidth: 1 + backgroundColor: 'rgba(0, 204, 51, 0.7)', + borderColor: '#00cc33', + borderWidth: 2 }] }, options: { responsive: true, plugins: { + legend: { + labels: { + color: '#00ff41', + font: { + family: 'Consolas, monospace' + } + } + }, tooltip: { + backgroundColor: 'rgba(13, 20, 33, 0.95)', + titleColor: '#00ff41', + bodyColor: '#66ff82', + borderColor: '#00ff41', + borderWidth: 1, callbacks: { label: function(context) { return context.dataset.label + ': ' + formatBytes(context.parsed.y); @@ -500,12 +719,30 @@ JSON_DATA_PLACEHOLDER } }, scales: { + x: { + ticks: { + color: '#66ff82', + font: { + family: 'Consolas, monospace' + } + }, + grid: { + color: 'rgba(0, 255, 65, 0.1)' + } + }, y: { beginAtZero: true, ticks: { + color: '#66ff82', + font: { + family: 'Consolas, monospace' + }, callback: function(value) { return formatBytes(value); } + }, + grid: { + color: 'rgba(0, 255, 65, 0.1)' } } } @@ -528,7 +765,7 @@ JSON_DATA_PLACEHOLDER const labels = Object.keys(interfaceData); const data = labels.map(label => interfaceData[label]); - const colors = labels.map((_, index) => generateColor(index)); + const colors = labels.map((_, index) => generateTerminalColor(index)); if (charts.interface) charts.interface.destroy(); @@ -539,14 +776,27 @@ JSON_DATA_PLACEHOLDER datasets: [{ data: data, backgroundColor: colors, - borderWidth: 2, - borderColor: '#fff' + borderWidth: 3, + borderColor: '#0d1421' }] }, options: { responsive: true, plugins: { + legend: { + labels: { + color: '#00ff41', + font: { + family: 'Consolas, monospace' + } + } + }, tooltip: { + backgroundColor: 'rgba(13, 20, 33, 0.95)', + titleColor: '#00ff41', + bodyColor: '#66ff82', + borderColor: '#00ff41', + borderWidth: 1, callbacks: { label: function(context) { return context.label + ': ' + formatBytes(context.parsed); @@ -594,23 +844,44 @@ JSON_DATA_PLACEHOLDER datasets: [{ label: 'Descarga', data: downloadData, - borderColor: 'rgba(102, 126, 234, 1)', - backgroundColor: 'rgba(102, 126, 234, 0.1)', + borderColor: '#00ff41', + backgroundColor: 'rgba(0, 255, 65, 0.1)', fill: true, - tension: 0.4 + tension: 0.4, + pointBackgroundColor: '#00ff41', + pointBorderColor: '#00cc33', + pointRadius: 4, + pointHoverRadius: 6 }, { label: 'Subida', data: uploadData, - borderColor: 'rgba(118, 75, 162, 1)', - backgroundColor: 'rgba(118, 75, 162, 0.1)', + borderColor: '#00cc33', + backgroundColor: 'rgba(0, 204, 51, 0.1)', fill: true, - tension: 0.4 + tension: 0.4, + pointBackgroundColor: '#00cc33', + pointBorderColor: '#009926', + pointRadius: 4, + pointHoverRadius: 6 }] }, options: { responsive: true, plugins: { + legend: { + labels: { + color: '#00ff41', + font: { + family: 'Consolas, monospace' + } + } + }, tooltip: { + backgroundColor: 'rgba(13, 20, 33, 0.95)', + titleColor: '#00ff41', + bodyColor: '#66ff82', + borderColor: '#00ff41', + borderWidth: 1, callbacks: { label: function(context) { return context.dataset.label + ': ' + formatBytes(context.parsed.y); @@ -619,12 +890,30 @@ JSON_DATA_PLACEHOLDER } }, scales: { + x: { + ticks: { + color: '#66ff82', + font: { + family: 'Consolas, monospace' + } + }, + grid: { + color: 'rgba(0, 255, 65, 0.1)' + } + }, y: { beginAtZero: true, ticks: { + color: '#66ff82', + font: { + family: 'Consolas, monospace' + }, callback: function(value) { return formatBytes(value); } + }, + grid: { + color: 'rgba(0, 255, 65, 0.1)' } } } @@ -638,7 +927,7 @@ JSON_DATA_PLACEHOLDER const tableCount = document.getElementById('tableCount'); if (filteredData.length === 0) { - tbody.innerHTML = 'No hay datos que mostrar'; + tbody.innerHTML = 'No hay datos que mostrar'; tableCount.textContent = '0 records'; return; }