secubox-openwrt/package/secubox/luci-app-secubox-admin/htdocs/luci-static/resources/view/secubox-admin/cyber-dashboard.js
2026-01-04 19:50:25 +01:00

412 lines
16 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 secubox-admin.api as API';
'require secubox-admin.data-utils as DataUtils';
'require poll';
'require ui';
return view.extend({
load: function() {
return Promise.all([
L.resolveDefault(API.getApps(), { apps: [] }),
L.resolveDefault(API.getModules(), { modules: {} }),
L.resolveDefault(API.getHealth(), {}),
L.resolveDefault(API.getAlerts(), { alerts: [] }),
L.resolveDefault(API.getCatalogSources(), { sources: [] }),
L.resolveDefault(API.checkUpdates(), { updates: [] })
]);
},
render: function(data) {
var apps = DataUtils.normalizeApps(data[0]);
var modules = DataUtils.normalizeModules(data[1]);
var health = data[2] || {};
var alerts = DataUtils.normalizeAlerts(data[3]);
var sources = DataUtils.normalizeSources(data[4]);
var updates = DataUtils.normalizeUpdates(data[5]);
var stats = DataUtils.buildAppStats(apps, modules, alerts, updates, API.getAppStatus);
var self = this;
var container = E('div', { 'class': 'cyberpunk-mode' }, [
E('link', { 'rel': 'stylesheet',
'href': L.resource('secubox-admin/cyberpunk.css') }),
// ASCII Art Header
E('div', { 'class': 'cyber-header cyber-scanlines' }, [
E('pre', { 'class': 'cyber-ascii-art' },
`╔═══════════════════════════════════════════════════════════════╗
║ ███████╗███████╗ ██████╗██╗ ██╗██████╗ ██████╗ ██╗ ██╗ ║
║ ██╔════╝██╔════╝██╔════╝██║ ██║██╔══██╗██╔═══██╗╚██╗██╔╝ ║
║ ███████╗█████╗ ██║ ██║ ██║██████╔╝██║ ██║ ╚███╔╝ ║
║ ╚════██║██╔══╝ ██║ ██║ ██║██╔══██╗██║ ██║ ██╔██╗ ║
║ ███████║███████╗╚██████╗╚██████╔╝██████╔╝╚██████╔╝██╔╝ ██╗ ║
║ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ║
╚═══════════════════════════════════════════════════════════════╝`),
E('div', { 'class': 'cyber-header-title cyber-text-glow' }, 'ADMIN CONTROL CENTER'),
E('div', { 'class': 'cyber-header-subtitle' }, 'System Status: ONLINE • Access Level: ROOT')
]),
// Dual Console Layout
E('div', { 'class': 'cyber-dual-console' }, [
// LEFT CONSOLE - Stats & Quick Actions
E('div', { 'class': 'cyber-console-left' }, [
// System Stats
this.renderStatsPanel(stats.totalApps, stats.installedCount, stats.runningCount, stats.alertCount, updates.total_updates_available || 0),
// System Resources
this.renderSystemPanel(health),
// Quick Actions
this.renderQuickActionsPanel(),
// Catalog Sources Status
this.renderSourcesPanel(sources)
]),
// RIGHT CONSOLE - Main Content
E('div', { 'class': 'cyber-console-right' }, [
// Active Apps List
this.renderAppsPanel(apps, modules),
// System Alerts
this.renderAlertsPanel(alerts)
])
])
]);
// Auto-refresh
poll.add(L.bind(this.pollData, this), 10);
return container;
},
renderStatsPanel: function(totalApps, installed, running, alertCount, updateCount) {
return E('div', { 'class': 'cyber-panel cyber-scanlines' }, [
E('div', { 'class': 'cyber-panel-header' }, [
E('div', { 'class': 'cyber-panel-title' }, '📊 SYSTEM STATS'),
E('span', { 'class': 'cyber-panel-badge' }, 'LIVE')
]),
E('div', { 'class': 'cyber-panel-body' }, [
E('div', { 'class': 'cyber-stats-grid' }, [
E('div', { 'class': 'cyber-stat-card' }, [
E('div', { 'class': 'cyber-stat-icon' }, '📦'),
E('div', { 'class': 'cyber-stat-value' }, totalApps.toString()),
E('div', { 'class': 'cyber-stat-label' }, 'Total Apps')
]),
E('div', { 'class': 'cyber-stat-card accent' }, [
E('div', { 'class': 'cyber-stat-icon' }, '✅'),
E('div', { 'class': 'cyber-stat-value' }, installed.toString()),
E('div', { 'class': 'cyber-stat-label' }, 'Installed')
]),
E('div', { 'class': 'cyber-stat-card' }, [
E('div', { 'class': 'cyber-stat-icon' }, '▶️'),
E('div', { 'class': 'cyber-stat-value' }, running.toString()),
E('div', { 'class': 'cyber-stat-label' }, 'Running')
]),
E('div', { 'class': 'cyber-stat-card ' + (alertCount > 0 ? 'warning' : '') }, [
E('div', { 'class': 'cyber-stat-icon' }, '⚠️'),
E('div', { 'class': 'cyber-stat-value' }, alertCount.toString()),
E('div', { 'class': 'cyber-stat-label' }, 'Alerts')
]),
E('div', { 'class': 'cyber-stat-card ' + (updateCount > 0 ? 'accent' : '') }, [
E('div', { 'class': 'cyber-stat-icon' }, '🔄'),
E('div', { 'class': 'cyber-stat-value' }, updateCount.toString()),
E('div', { 'class': 'cyber-stat-label' }, 'Updates')
]),
E('div', { 'class': 'cyber-stat-card' }, [
E('div', { 'class': 'cyber-stat-icon' }, '🌐'),
E('div', { 'class': 'cyber-stat-value' }, '100%'),
E('div', { 'class': 'cyber-stat-label' }, 'Network')
])
])
])
]);
},
renderSystemPanel: function(health) {
var cpu = health.cpu || 0;
var memory = health.memory || 0;
var disk = health.disk || 0;
return E('div', { 'class': 'cyber-panel cyber-scanlines' }, [
E('div', { 'class': 'cyber-panel-header' }, [
E('div', { 'class': 'cyber-panel-title' }, '💻 SYSTEM RESOURCES')
]),
E('div', { 'class': 'cyber-panel-body' }, [
E('div', { 'class': 'cyber-system-status' }, [
// CPU
E('div', { 'class': 'cyber-metric' }, [
E('div', { 'class': 'cyber-metric-header' }, [
E('div', { 'class': 'cyber-metric-label' }, [
E('span', {}, '⚡'),
E('span', {}, 'CPU Load')
]),
E('div', { 'class': 'cyber-metric-value' }, cpu + '%')
]),
E('div', { 'class': 'cyber-progress-bar' }, [
E('div', {
'class': 'cyber-progress-fill' + (cpu > 80 ? ' danger' : cpu > 60 ? ' warning' : ''),
'style': 'width: ' + cpu + '%'
})
])
]),
// Memory
E('div', { 'class': 'cyber-metric' }, [
E('div', { 'class': 'cyber-metric-header' }, [
E('div', { 'class': 'cyber-metric-label' }, [
E('span', {}, '🧠'),
E('span', {}, 'Memory Usage')
]),
E('div', { 'class': 'cyber-metric-value' }, memory + '%')
]),
E('div', { 'class': 'cyber-progress-bar' }, [
E('div', {
'class': 'cyber-progress-fill' + (memory > 80 ? ' danger' : memory > 60 ? ' warning' : ''),
'style': 'width: ' + memory + '%'
})
])
]),
// Disk
E('div', { 'class': 'cyber-metric' }, [
E('div', { 'class': 'cyber-metric-header' }, [
E('div', { 'class': 'cyber-metric-label' }, [
E('span', {}, '💾'),
E('span', {}, 'Disk Usage')
]),
E('div', { 'class': 'cyber-metric-value' }, disk + '%')
]),
E('div', { 'class': 'cyber-progress-bar' }, [
E('div', {
'class': 'cyber-progress-fill' + (disk > 80 ? ' danger' : disk > 60 ? ' warning' : ''),
'style': 'width: ' + disk + '%'
})
])
])
])
])
]);
},
renderQuickActionsPanel: function() {
var self = this;
return E('div', { 'class': 'cyber-panel cyber-scanlines' }, [
E('div', { 'class': 'cyber-panel-header' }, [
E('div', { 'class': 'cyber-panel-title' }, '⚡ QUICK ACTIONS')
]),
E('div', { 'class': 'cyber-panel-body' }, [
E('div', { 'class': 'cyber-quick-actions' }, [
E('button', {
'class': 'cyber-action-btn',
'click': function() {
window.location = L.url('admin/secubox/admin/apps');
}
}, [
E('span', { 'class': 'cyber-action-icon' }, '📦'),
E('span', { 'class': 'cyber-action-label' }, 'Manage Apps'),
E('span', { 'class': 'cyber-action-arrow' }, '▸')
]),
E('button', {
'class': 'cyber-action-btn',
'click': function() {
window.location = L.url('admin/secubox/admin/updates');
}
}, [
E('span', { 'class': 'cyber-action-icon' }, '🔄'),
E('span', { 'class': 'cyber-action-label' }, 'Check Updates'),
E('span', { 'class': 'cyber-action-arrow' }, '▸')
]),
E('button', {
'class': 'cyber-action-btn',
'click': function() {
window.location = L.url('admin/secubox/admin/catalog-sources');
}
}, [
E('span', { 'class': 'cyber-action-icon' }, '🌐'),
E('span', { 'class': 'cyber-action-label' }, 'Catalog Sources'),
E('span', { 'class': 'cyber-action-arrow' }, '▸')
]),
E('button', {
'class': 'cyber-action-btn',
'click': function() {
window.location = L.url('admin/secubox/admin/health');
}
}, [
E('span', { 'class': 'cyber-action-icon' }, '💊'),
E('span', { 'class': 'cyber-action-label' }, 'System Health'),
E('span', { 'class': 'cyber-action-arrow' }, '▸')
]),
E('button', {
'class': 'cyber-action-btn',
'click': function() {
window.location = L.url('admin/secubox/admin/logs');
}
}, [
E('span', { 'class': 'cyber-action-icon' }, '📋'),
E('span', { 'class': 'cyber-action-label' }, 'View Logs'),
E('span', { 'class': 'cyber-action-arrow' }, '▸')
]),
E('button', {
'class': 'cyber-action-btn',
'click': function() {
self.syncCatalogs();
}
}, [
E('span', { 'class': 'cyber-action-icon' }, '🔃'),
E('span', { 'class': 'cyber-action-label' }, 'Sync Catalogs'),
E('span', { 'class': 'cyber-action-arrow' }, '▸')
])
])
])
]);
},
renderSourcesPanel: function(sources) {
var activeSources = sources.filter(function(s) { return s.enabled; });
var onlineSources = sources.filter(function(s) { return s.status === 'online' || s.status === 'available'; });
return E('div', { 'class': 'cyber-panel cyber-scanlines' }, [
E('div', { 'class': 'cyber-panel-header' }, [
E('div', { 'class': 'cyber-panel-title' }, '🛰️ CATALOG SOURCES'),
E('span', { 'class': 'cyber-panel-badge' }, onlineSources.length + '/' + sources.length)
]),
E('div', { 'class': 'cyber-panel-body' }, [
E('div', { 'style': 'display: flex; flex-direction: column; gap: 8px;' },
sources.length > 0 ?
sources.map(function(source) {
var isOnline = source.status === 'online' || source.status === 'available';
return E('div', {
'style': 'display: flex; justify-content: space-between; align-items: center; padding: 8px; background: rgba(0,255,65,0.05); border-left: 2px solid ' + (isOnline ? 'var(--cyber-primary)' : 'var(--cyber-text-dim)')
}, [
E('div', { 'style': 'display: flex; align-items: center; gap: 8px;' }, [
E('span', { 'class': 'cyber-status-dot ' + (isOnline ? 'online' : 'offline') }),
E('span', { 'style': 'font-size: 12px; font-weight: bold; text-transform: uppercase;' }, source.name)
]),
E('span', {
'class': 'cyber-badge ' + (isOnline ? 'success' : 'warning'),
'style': 'font-size: 9px;'
}, source.status || 'unknown')
]);
}) :
E('div', { 'style': 'text-align: center; color: var(--cyber-text-dim); padding: 20px;' }, 'No sources configured')
)
])
]);
},
renderAppsPanel: function(apps, modules) {
return E('div', { 'class': 'cyber-panel cyber-scanlines' }, [
E('div', { 'class': 'cyber-panel-header' }, [
E('div', { 'class': 'cyber-panel-title' }, '🎮 ACTIVE APPLICATIONS'),
E('span', { 'class': 'cyber-panel-badge' }, apps.length)
]),
E('div', { 'class': 'cyber-panel-body' }, [
E('div', { 'class': 'cyber-list' },
apps.length > 0 ?
apps.slice(0, 6).map(function(app) {
var status = API.getAppStatus(app, modules);
return E('div', {
'class': 'cyber-list-item' + (status.running ? ' active' : status.installed ? '' : ' offline')
}, [
E('div', { 'class': 'cyber-list-icon' }, app.icon || '📦'),
E('div', { 'class': 'cyber-list-content' }, [
E('div', { 'class': 'cyber-list-title' }, [
app.name,
status.running ? E('span', { 'class': 'cyber-badge success' }, [
E('span', { 'class': 'cyber-status-dot online' }),
E('span', {}, 'RUNNING')
]) : status.installed ? E('span', { 'class': 'cyber-badge info' }, 'INSTALLED') : null
]),
E('div', { 'class': 'cyber-list-meta' }, [
E('div', { 'class': 'cyber-list-meta-item' }, [
E('span', {}, '📁'),
E('span', {}, app.category || 'unknown')
]),
E('div', { 'class': 'cyber-list-meta-item' }, [
E('span', {}, '🏷️'),
E('span', {}, app.version || 'N/A')
])
])
]),
E('div', { 'class': 'cyber-list-actions' }, [
status.running ?
E('button', { 'class': 'cyber-btn danger' }, '⏹ Stop') :
status.installed ?
E('button', { 'class': 'cyber-btn primary' }, '▶️ Start') :
E('button', { 'class': 'cyber-btn' }, '⬇️ Install')
])
]);
}) :
E('div', { 'style': 'text-align: center; color: var(--cyber-text-dim); padding: 40px;' }, 'No applications found')
)
])
]);
},
renderAlertsPanel: function(alerts) {
return E('div', { 'class': 'cyber-panel cyber-scanlines' }, [
E('div', { 'class': 'cyber-panel-header' }, [
E('div', { 'class': 'cyber-panel-title' }, '⚠️ SYSTEM ALERTS'),
E('span', { 'class': 'cyber-panel-badge' }, alerts.length)
]),
E('div', { 'class': 'cyber-panel-body' }, [
E('div', { 'class': 'cyber-list' },
alerts.length > 0 ?
alerts.slice(0, 3).map(function(alert) {
var severityClass = alert.severity === 'error' ? 'danger' : alert.severity === 'warning' ? 'warning' : 'info';
return E('div', { 'class': 'cyber-list-item' }, [
E('div', { 'class': 'cyber-list-icon' },
alert.severity === 'error' ? '🚨' : alert.severity === 'warning' ? '⚠️' : ''),
E('div', { 'class': 'cyber-list-content' }, [
E('div', { 'class': 'cyber-list-title' }, [
alert.message,
E('span', { 'class': 'cyber-badge ' + severityClass }, alert.severity.toUpperCase())
])
])
]);
}) :
E('div', { 'style': 'text-align: center; color: var(--cyber-primary); padding: 40px;' }, [
E('div', { 'style': 'font-size: 48px; margin-bottom: 10px;' }, '✅'),
E('div', { 'style': 'font-size: 16px; font-weight: bold; text-transform: uppercase; letter-spacing: 2px;' }, 'ALL SYSTEMS NOMINAL')
])
)
])
]);
},
syncCatalogs: function() {
ui.showModal(_('Syncing'), [
E('p', { 'class': 'spinning' }, _('Synchronizing catalogs...'))
]);
API.syncCatalog(null).then(function(result) {
ui.hideModal();
if (result.success) {
ui.addNotification(null, E('p', _('Catalogs synced successfully')), 'success');
window.location.reload();
} else {
ui.addNotification(null, E('p', _('Sync failed')), 'error');
}
}).catch(function(err) {
ui.hideModal();
ui.addNotification(null, E('p', _('Error: ' + err.message)), 'error');
});
},
pollData: function() {
// Auto-refresh data every 10 seconds
return Promise.all([
API.getHealth(),
API.getModules(),
API.getAlerts()
]).then(function(data) {
// Update UI without full reload
});
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});