secubox-openwrt/luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/overview.js

196 lines
6.3 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.

This file contains Unicode characters that might be confused with other characters. 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 network-modes.api as api';
return view.extend({
title: _('Network Modes'),
load: function() {
return api.getAllData();
},
handleModeSwitch: function(mode) {
var self = this;
ui.showModal(_('Switch Mode'), [
E('p', {}, _('Are you sure you want to switch to ') + mode + _(' mode?')),
E('p', { 'class': 'nm-alert nm-alert-warning' }, [
E('span', { 'class': 'nm-alert-icon' }, '⚠️'),
E('div', {}, [
E('div', { 'class': 'nm-alert-title' }, _('Warning')),
E('div', { 'class': 'nm-alert-text' }, _('This will change network configuration. A backup will be created.'))
])
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Cancel')),
' ',
E('button', {
'class': 'btn cbi-button-positive',
'click': function() {
ui.hideModal();
return api.applyMode(mode).then(function(result) {
if (result.success) {
ui.addNotification(null, E('p', {}, result.message), 'success');
window.location.reload();
} else {
ui.addNotification(null, E('p', {}, 'Error: ' + result.error), 'error');
}
});
}
}, _('Switch Mode'))
])
]);
},
render: function(data) {
var self = this;
var status = data.status || {};
var modesData = (data.modes || {}).modes || [];
var currentMode = status.current_mode || 'router';
var modeInfos = {
sniffer: api.getModeInfo('sniffer'),
accesspoint: api.getModeInfo('accesspoint'),
relay: api.getModeInfo('relay'),
router: api.getModeInfo('router')
};
var currentModeInfo = modeInfos[currentMode];
var view = E('div', { 'class': 'network-modes-dashboard' }, [
// Header
E('div', { 'class': 'nm-header' }, [
E('div', { 'class': 'nm-logo' }, [
E('div', { 'class': 'nm-logo-icon' }, '⚙️'),
E('div', { 'class': 'nm-logo-text' }, ['Network ', E('span', {}, 'Modes')])
]),
E('div', { 'class': 'nm-mode-badge ' + currentMode }, [
E('span', { 'class': 'nm-mode-dot' }),
currentModeInfo ? currentModeInfo.name : currentMode
])
]),
// Status info
E('div', { 'class': 'nm-alert nm-alert-info' }, [
E('span', { 'class': 'nm-alert-icon' }, ''),
E('div', {}, [
E('div', { 'class': 'nm-alert-title' }, 'Current Mode: ' + (currentModeInfo ? currentModeInfo.name : currentMode)),
E('div', { 'class': 'nm-alert-text' },
'Last changed: ' + (status.last_change || 'Never') + ' • Uptime: ' + api.formatUptime(status.uptime))
])
]),
// Mode Selection Grid
E('div', { 'class': 'nm-modes-grid' },
Object.keys(modeInfos).map(function(modeId) {
var info = modeInfos[modeId];
var isActive = modeId === currentMode;
return E('div', {
'class': 'nm-mode-card ' + modeId + (isActive ? ' active' : ''),
'click': function() {
if (!isActive) {
self.handleModeSwitch(modeId);
}
}
}, [
isActive ? E('div', { 'class': 'nm-mode-active-indicator' }, 'Active') : '',
E('div', { 'class': 'nm-mode-header' }, [
E('div', { 'class': 'nm-mode-icon' }, info.icon),
E('div', { 'class': 'nm-mode-title' }, [
E('h3', {}, info.name),
E('p', {}, modeId.charAt(0).toUpperCase() + modeId.slice(1) + ' Mode')
])
]),
E('div', { 'class': 'nm-mode-description' }, info.description),
E('div', { 'class': 'nm-mode-features' },
info.features.map(function(f) {
return E('span', { 'class': 'nm-mode-feature' }, [
E('span', { 'class': 'nm-mode-feature-icon' }, '✓'),
f
]);
})
)
]);
})
),
// Interfaces Status
E('div', { 'class': 'nm-card' }, [
E('div', { 'class': 'nm-card-header' }, [
E('div', { 'class': 'nm-card-title' }, [
E('span', { 'class': 'nm-card-title-icon' }, '🔌'),
'Network Interfaces'
]),
E('div', { 'class': 'nm-card-badge' }, (status.interfaces || []).length + ' interfaces')
]),
E('div', { 'class': 'nm-card-body' }, [
E('div', { 'class': 'nm-interfaces-grid' },
(status.interfaces || []).map(function(iface) {
var icon = '🔌';
if (iface.name.startsWith('wlan') || iface.name.startsWith('wl')) icon = '📶';
else if (iface.name.startsWith('wg')) icon = '🔐';
else if (iface.name.startsWith('br')) icon = '🌉';
else if (iface.name.startsWith('eth')) icon = '🔗';
return E('div', { 'class': 'nm-interface-card' }, [
E('div', { 'class': 'nm-interface-icon' }, icon),
E('div', { 'class': 'nm-interface-info' }, [
E('div', { 'class': 'nm-interface-name' }, iface.name),
E('div', { 'class': 'nm-interface-ip' }, iface.ip || 'No IP')
]),
E('div', { 'class': 'nm-interface-status ' + iface.state })
]);
})
)
])
]),
// Services Status
E('div', { 'class': 'nm-card' }, [
E('div', { 'class': 'nm-card-header' }, [
E('div', { 'class': 'nm-card-title' }, [
E('span', { 'class': 'nm-card-title-icon' }, '🔧'),
'Services Status'
])
]),
E('div', { 'class': 'nm-card-body' }, [
E('div', { 'class': 'nm-interfaces-grid' },
[
{ name: 'Firewall', key: 'firewall', icon: '🛡️' },
{ name: 'DHCP/DNS', key: 'dnsmasq', icon: '📡' },
{ name: 'Netifyd', key: 'netifyd', icon: '🔍' },
{ name: 'Nginx', key: 'nginx', icon: '🌐' },
{ name: 'Squid', key: 'squid', icon: '🦑' }
].map(function(svc) {
var running = status.services && status.services[svc.key];
return E('div', { 'class': 'nm-interface-card' }, [
E('div', { 'class': 'nm-interface-icon' }, svc.icon),
E('div', { 'class': 'nm-interface-info' }, [
E('div', { 'class': 'nm-interface-name' }, svc.name),
E('div', { 'class': 'nm-interface-ip' }, running ? 'Running' : 'Stopped')
]),
E('div', { 'class': 'nm-interface-status ' + (running ? 'up' : 'down') })
]);
})
)
])
])
]);
// Include CSS
var cssLink = E('link', { 'rel': 'stylesheet', 'href': L.resource('network-modes/dashboard.css') });
document.head.appendChild(cssLink);
return view;
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});