secubox-openwrt/luci-app-netdata-dashboard/htdocs/luci-static/resources/view/netdata-dashboard/dashboard.js
CyberMind-FR cf39eb6e1d fix: resolve validation issues across all modules
- Fixed minified RPC declaration in secubox/modules.js that caused false positive in validation
- Added 30 missing menu entries across 10 modules:
  * bandwidth-manager: clients, schedules
  * client-guardian: zones, portal, logs, alerts, parental
  * crowdsec-dashboard: metrics
  * netdata-dashboard: system, processes, realtime, network
  * netifyd-dashboard: talkers, risks, devices
  * network-modes: router, accesspoint, relay, sniffer
  * secubox: settings
  * system-hub: components, diagnostics, health, remote, settings
  * vhost-manager: internal, ssl, redirects
  * wireguard-dashboard: traffic, config
- All modules now pass comprehensive validation (0 errors, 0 warnings)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 09:01:06 +01:00

275 lines
9.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
'require view';
'require dom';
'require ui';
'require poll';
'require netdata-dashboard/api as API';
return view.extend({
load: function() {
return Promise.all([
API.getNetdataStatus(),
API.getNetdataAlarms(),
API.getStats()
]);
},
render: function(data) {
var netdataStatus = data[0] || {};
var alarms = data[1] || {};
var stats = data[2] || {};
var isRunning = netdataStatus.running || false;
var netdataUrl = netdataStatus.url || 'http://127.0.0.1:19999';
// Count active alarms
var alarmCount = 0;
if (alarms.alarms && typeof alarms.alarms === 'object') {
Object.keys(alarms.alarms).forEach(function(key) {
var alarm = alarms.alarms[key];
if (alarm.status && alarm.status !== 'CLEAR') {
alarmCount++;
}
});
}
var view = E('div', { 'class': 'cbi-map' }, [
E('h2', {}, _('Netdata Dashboard')),
E('div', { 'class': 'cbi-map-descr' },
_('Real-time system monitoring and performance metrics powered by Netdata.')),
// Control Panel
E('div', { 'class': 'cbi-section', 'style': 'margin-bottom: 1em;' }, [
E('div', { 'style': 'display: grid; grid-template-columns: 2fr 1fr; gap: 1em;' }, [
// Status Card
E('div', {
'style': 'background: ' + (isRunning ? '#d4edda' : '#f8d7da') + '; border-left: 4px solid ' + (isRunning ? '#28a745' : '#dc3545') + '; padding: 1em; border-radius: 4px;'
}, [
E('div', { 'style': 'display: flex; justify-content: space-between; align-items: center;' }, [
E('div', {}, [
E('div', { 'style': 'font-size: 0.9em; color: #666; margin-bottom: 0.25em;' }, _('Service Status')),
E('div', { 'style': 'font-size: 1.5em; font-weight: bold; color: ' + (isRunning ? '#155724' : '#721c24') + ';' },
isRunning ? _('RUNNING') : _('STOPPED'))
]),
E('div', { 'style': 'text-align: right;' }, [
E('div', { 'style': 'font-size: 0.9em; color: #666; margin-bottom: 0.25em;' }, _('Version')),
E('div', { 'style': 'font-size: 1.1em; font-weight: bold;' }, netdataStatus.version || 'Unknown')
]),
E('div', { 'style': 'text-align: right;' }, [
E('div', { 'style': 'font-size: 0.9em; color: #666; margin-bottom: 0.25em;' }, _('Port')),
E('div', { 'style': 'font-size: 1.1em; font-weight: bold;' }, (netdataStatus.port || 19999).toString())
])
])
]),
// Control Buttons
E('div', { 'style': 'display: flex; flex-direction: column; gap: 0.5em;' }, [
E('button', {
'class': 'cbi-button cbi-button-action',
'click': L.bind(this.handleStart, this),
'disabled': isRunning,
'style': 'flex: 1;'
}, _('Start Netdata')),
E('button', {
'class': 'cbi-button cbi-button-reset',
'click': L.bind(this.handleRestart, this),
'disabled': !isRunning,
'style': 'flex: 1;'
}, _('Restart Netdata')),
E('button', {
'class': 'cbi-button cbi-button-negative',
'click': L.bind(this.handleStop, this),
'disabled': !isRunning,
'style': 'flex: 1;'
}, _('Stop Netdata'))
])
])
]),
// Alarms Card
alarmCount > 0 ? E('div', {
'class': 'cbi-section',
'style': 'background: #fff3cd; border-left: 4px solid #ffc107; padding: 1em; margin-bottom: 1em;'
}, [
E('div', { 'style': 'display: flex; align-items: center; gap: 1em;' }, [
E('div', { 'style': 'font-size: 2em;' }, ''),
E('div', { 'style': 'flex: 1;' }, [
E('strong', {}, _('Active Alarms: %d').format(alarmCount)),
E('p', { 'style': 'margin: 0.25em 0 0 0; color: #666;' },
_('Netdata has detected %d active alarm(s). Check the dashboard for details.').format(alarmCount))
]),
E('a', {
'href': netdataUrl + '#menu_alarms',
'target': '_blank',
'class': 'cbi-button cbi-button-action'
}, _('View Alarms'))
])
]) : null,
// Quick Stats Preview
E('div', { 'class': 'cbi-section', 'style': 'margin-bottom: 1em;' }, [
E('h3', { 'style': 'margin-top: 0;' }, _('Quick Stats')),
E('div', { 'style': 'display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1em;' }, [
this.renderStatCard(_('CPU'), stats.cpu_percent + '%', '#0088cc'),
this.renderStatCard(_('Memory'), stats.memory_percent + '%', '#17a2b8'),
this.renderStatCard(_('Disk'), stats.disk_percent + '%', '#6610f2'),
this.renderStatCard(_('Load'), stats.load || '0.00', '#e83e8c'),
this.renderStatCard(_('Temp'), stats.temperature + '°C', '#fd7e14'),
this.renderStatCard(_('Uptime'), API.formatUptime(stats.uptime || 0), '#28a745')
])
]),
// Netdata Dashboard Iframe
isRunning ? E('div', { 'class': 'cbi-section' }, [
E('h3', { 'style': 'margin-top: 0;' }, _('Netdata Real-Time Dashboard')),
E('div', {
'style': 'position: relative; width: 100%; height: 0; padding-bottom: 75%; background: #f5f5f5; border-radius: 4px; overflow: hidden;'
}, [
E('iframe', {
'src': netdataUrl,
'style': 'position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;',
'frameborder': '0',
'allow': 'fullscreen'
})
]),
E('div', { 'style': 'margin-top: 1em; padding: 0.75em; background: #e8f4f8; border-radius: 4px;' }, [
E('strong', {}, _('Tip:')),
' ',
_('Use the Netdata interface above for detailed real-time monitoring. Click '),
E('a', { 'href': netdataUrl, 'target': '_blank' }, _('here')),
_(' to open in a new window.')
])
]) : E('div', { 'class': 'cbi-section' }, [
E('div', {
'style': 'text-align: center; padding: 3em; background: #f8d7da; border-radius: 4px; border-left: 4px solid #dc3545;'
}, [
E('div', { 'style': 'font-size: 3em; margin-bottom: 0.5em;' }, ''),
E('h3', {}, _('Netdata is not running')),
E('p', { 'style': 'color: #666; margin-bottom: 1.5em;' },
_('Start the Netdata service to access real-time monitoring dashboards.')),
E('button', {
'class': 'cbi-button cbi-button-action',
'style': 'font-size: 1.1em; padding: 0.75em 2em;',
'click': L.bind(this.handleStart, this)
}, _('Start Netdata Now'))
])
])
]);
// Setup auto-refresh
poll.add(L.bind(function() {
return Promise.all([
API.getNetdataStatus(),
API.getStats()
]).then(L.bind(function(refreshData) {
// Could update stats display here
}, this));
}, this), 5);
return view;
},
renderStatCard: function(label, value, color) {
return E('div', {
'style': 'background: white; border-left: 4px solid ' + color + '; padding: 1em; border-radius: 4px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);'
}, [
E('div', { 'style': 'font-size: 0.85em; color: #666; margin-bottom: 0.25em;' }, label),
E('div', { 'style': 'font-size: 1.5em; font-weight: bold; color: ' + color + ';' }, value)
]);
},
handleStart: function(ev) {
var btn = ev.target;
btn.disabled = true;
btn.textContent = _('Starting...');
API.startNetdata().then(function(result) {
if (result.success) {
ui.addNotification(null, E('p', result.message || _('Netdata started successfully')), 'info');
setTimeout(function() {
window.location.reload();
}, 2000);
} else {
ui.addNotification(null, E('p', result.error || _('Failed to start Netdata')), 'error');
btn.disabled = false;
btn.textContent = _('Start Netdata');
}
}).catch(function(err) {
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
btn.disabled = false;
btn.textContent = _('Start Netdata');
});
},
handleStop: function(ev) {
ui.showModal(_('Stop Netdata'), [
E('p', {}, _('Are you sure you want to stop Netdata monitoring?')),
E('p', { 'style': 'color: #856404; background: #fff3cd; padding: 0.75em; border-radius: 4px;' },
_('This will stop all real-time monitoring and data collection.')),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-negative',
'click': L.bind(function() {
ui.hideModal();
this.doStop(ev.target);
}, this)
}, _('Stop Netdata'))
])
]);
},
doStop: function(btn) {
btn.disabled = true;
btn.textContent = _('Stopping...');
API.stopNetdata().then(function(result) {
if (result.success) {
ui.addNotification(null, E('p', result.message || _('Netdata stopped')), 'info');
setTimeout(function() {
window.location.reload();
}, 1500);
} else {
ui.addNotification(null, E('p', result.error || _('Failed to stop Netdata')), 'error');
btn.disabled = false;
btn.textContent = _('Stop Netdata');
}
}).catch(function(err) {
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
btn.disabled = false;
btn.textContent = _('Stop Netdata');
});
},
handleRestart: function(ev) {
var btn = ev.target;
btn.disabled = true;
btn.textContent = _('Restarting...');
API.restartNetdata().then(function(result) {
if (result.success) {
ui.addNotification(null, E('p', result.message || _('Netdata restarted successfully')), 'info');
setTimeout(function() {
window.location.reload();
}, 3000);
} else {
ui.addNotification(null, E('p', result.error || _('Failed to restart Netdata')), 'error');
btn.disabled = false;
btn.textContent = _('Restart Netdata');
}
}).catch(function(err) {
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
btn.disabled = false;
btn.textContent = _('Restart Netdata');
});
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});