secubox-openwrt/package/secubox/luci-app-secubox-admin/htdocs/luci-static/resources/view/secubox-admin/cyber-dashboard.js
CyberMind-FR 3315d61f78 feat(luci-app-secubox-admin): add cyberpunk dual console theme with stats and quick actions
Added a complete cyberpunk-themed admin interface with:

Features:
- 🔮 Dual console layout (left: stats/actions, right: content)
- 📊 Live system stats with emojis
-  Quick action buttons with hover effects
- 💻 Real-time resource monitoring (CPU, RAM, Disk)
- 🌐 Catalog sources status display
- 🎮 Active applications list view
- ⚠️ System alerts panel
- 🔃 Auto-refresh every 10 seconds

Cyberpunk Styling:
- Neon color scheme (cyan #00ffff, magenta #ff00ff, green #00ff41)
- ASCII art header with SecuBox logo
- Terminal/console aesthetic with monospace fonts
- Glitch and pulse animations
- Scanline effects for authentic CRT look
- Progress bars with shimmer effects
- Glowing text shadows and borders
- Responsive grid layouts

Components:
- cyberpunk.css: Complete theme with 600+ lines of styles
- cyber-dashboard.js: Full-featured cyberpunk dashboard view
- Menu entry: '🔮 Cyber Console' between Control Panel and Apps Manager

Access: Admin Control → 🔮 Cyber Console

Incremented PKG_RELEASE: 8 → 9

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-04 16:31:48 +01:00

419 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 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 = data[0].apps || [];
var modules = data[1].modules || {};
var health = data[2] || {};
var alerts = data[3].alerts || [];
var sources = data[4].sources || [];
var updates = data[5] || {};
var self = this;
// Calculate stats
var installedCount = 0;
var runningCount = 0;
apps.forEach(function(app) {
var status = API.getAppStatus(app, modules);
if (status.installed) installedCount++;
if (status.running) runningCount++;
});
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(apps.length, installedCount, runningCount, alerts.length, 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
});