2025-12-26 07:09:27 +00:00
|
|
|
'use strict';
|
|
|
|
|
'require view';
|
|
|
|
|
'require rpc';
|
release: v0.1.1 - Unified Theme System with Dark/Light Mode Support
Major Features:
• Centralized theme system across SecuBox and System Hub
• Three theme modes: dark (default), light, and system (auto-detect)
• Single theme setting in SecuBox controls both plugins
• Real-time theme switching with OS preference detection
SecuBox Changes:
• Added theme.js manager for centralized theme control
• Implemented CSS variables for dark/light mode (secubox.css)
• Fixed hardcoded colors in dashboard.css, alerts.css, monitoring.css
• Integrated theme.js in all 7 views (dashboard, modules, alerts, monitoring, settings, etc.)
• Added get_theme RPC method to luci.secubox backend
• Updated ACL permissions to include get_theme (read access)
• Version updated to 0.1.1
System Hub Changes:
• Added theme.js manager using SecuBox theme API
• Implemented CSS variables for dark/light mode (dashboard.css)
• Integrated theme.js in all 9 views (overview, health, services, logs, backup, components, remote, settings, diagnostics)
• Version updated to 0.1.1
• README updated with maintainer info
Theme System Architecture:
• Configuration: /etc/config/secubox (option theme: dark|light|system)
• RPCD Backend: luci.secubox/get_theme method
• Frontend: theme.js modules (secubox/theme.js, system-hub/theme.js)
• CSS Variables: --sb-bg, --sb-bg-card, --sb-border, --sb-text, --sb-text-muted, --sb-shadow
• Auto-detection: prefers-color-scheme media query for system mode
Documentation:
• Added LUCI_DEVELOPMENT_REFERENCE.md with comprehensive LuCI development patterns
• Documented ubus/RPC types, baseclass.extend() patterns, ACL structure
• Common errors and solutions from implementation experience
Bug Fixes:
• Fixed SecuBox theme not applying visually (CSS variables now used)
• Fixed missing secubox.css in view imports
• Fixed ACL access denied for get_theme method
• Fixed hardcoded colors preventing theme switching
Testing:
• Verified theme switching works in all SecuBox tabs
• Verified theme switching works in all System Hub tabs
• Verified dark/light/system modes function correctly
• Verified single setting controls both plugins
🤖 Generated with Claude Code (https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 15:08:53 +00:00
|
|
|
'require secubox/theme as Theme';
|
2025-12-29 08:03:49 +00:00
|
|
|
'require secubox/api as API';
|
|
|
|
|
'require secubox/nav as SecuNav';
|
release: v0.1.1 - Unified Theme System with Dark/Light Mode Support
Major Features:
• Centralized theme system across SecuBox and System Hub
• Three theme modes: dark (default), light, and system (auto-detect)
• Single theme setting in SecuBox controls both plugins
• Real-time theme switching with OS preference detection
SecuBox Changes:
• Added theme.js manager for centralized theme control
• Implemented CSS variables for dark/light mode (secubox.css)
• Fixed hardcoded colors in dashboard.css, alerts.css, monitoring.css
• Integrated theme.js in all 7 views (dashboard, modules, alerts, monitoring, settings, etc.)
• Added get_theme RPC method to luci.secubox backend
• Updated ACL permissions to include get_theme (read access)
• Version updated to 0.1.1
System Hub Changes:
• Added theme.js manager using SecuBox theme API
• Implemented CSS variables for dark/light mode (dashboard.css)
• Integrated theme.js in all 9 views (overview, health, services, logs, backup, components, remote, settings, diagnostics)
• Version updated to 0.1.1
• README updated with maintainer info
Theme System Architecture:
• Configuration: /etc/config/secubox (option theme: dark|light|system)
• RPCD Backend: luci.secubox/get_theme method
• Frontend: theme.js modules (secubox/theme.js, system-hub/theme.js)
• CSS Variables: --sb-bg, --sb-bg-card, --sb-border, --sb-text, --sb-text-muted, --sb-shadow
• Auto-detection: prefers-color-scheme media query for system mode
Documentation:
• Added LUCI_DEVELOPMENT_REFERENCE.md with comprehensive LuCI development patterns
• Documented ubus/RPC types, baseclass.extend() patterns, ACL structure
• Common errors and solutions from implementation experience
Bug Fixes:
• Fixed SecuBox theme not applying visually (CSS variables now used)
• Fixed missing secubox.css in view imports
• Fixed ACL access denied for get_theme method
• Fixed hardcoded colors preventing theme switching
Testing:
• Verified theme switching works in all SecuBox tabs
• Verified theme switching works in all System Hub tabs
• Verified dark/light/system modes function correctly
• Verified single setting controls both plugins
🤖 Generated with Claude Code (https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 15:08:53 +00:00
|
|
|
|
|
|
|
|
Theme.init();
|
2025-12-26 07:09:27 +00:00
|
|
|
|
|
|
|
|
var callModules = rpc.declare({
|
|
|
|
|
object: 'luci.secubox',
|
|
|
|
|
method: 'modules',
|
|
|
|
|
expect: { modules: [] }
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return view.extend({
|
2025-12-29 08:03:49 +00:00
|
|
|
statusData: {},
|
2025-12-26 07:09:27 +00:00
|
|
|
|
2025-12-29 08:03:49 +00:00
|
|
|
load: function() {
|
|
|
|
|
return Promise.all([
|
|
|
|
|
API.getStatus(),
|
|
|
|
|
callModules()
|
|
|
|
|
]).then(L.bind(function(res) {
|
|
|
|
|
this.statusData = res[0] || {};
|
|
|
|
|
return res[1] || [];
|
|
|
|
|
}, this)).catch(function(err) {
|
|
|
|
|
console.error('=== MODULES DEBUG: RPC ERROR ===', err);
|
|
|
|
|
return [];
|
|
|
|
|
});
|
|
|
|
|
},
|
2025-12-26 07:09:27 +00:00
|
|
|
|
2025-12-29 08:03:49 +00:00
|
|
|
render: function(modules) {
|
|
|
|
|
modules = modules || [];
|
|
|
|
|
var running = modules.filter(function(m) { return m.running; }).length;
|
|
|
|
|
var installed = modules.filter(function(m) { return m.installed; }).length;
|
2025-12-26 07:09:27 +00:00
|
|
|
|
2025-12-29 08:03:49 +00:00
|
|
|
return E('div', { 'class': 'secubox-modules-debug' }, [
|
|
|
|
|
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox/common.css') }),
|
|
|
|
|
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox/secubox.css') }),
|
|
|
|
|
SecuNav.renderTabs('modules'),
|
|
|
|
|
this.renderHeader(modules.length, running, installed),
|
|
|
|
|
modules.length ? this.renderModuleGrid(modules) : this.renderEmptyState()
|
|
|
|
|
]);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
renderHeader: function(total, running, installed) {
|
|
|
|
|
var status = this.statusData || {};
|
|
|
|
|
|
|
|
|
|
return E('div', { 'class': 'sh-page-header sh-page-header-lite' }, [
|
|
|
|
|
E('div', {}, [
|
|
|
|
|
E('h2', { 'class': 'sh-page-title' }, [
|
|
|
|
|
E('span', { 'class': 'sh-page-title-icon' }, '🧪'),
|
|
|
|
|
_('Modules Debug Console')
|
|
|
|
|
]),
|
|
|
|
|
E('p', { 'class': 'sh-page-subtitle' },
|
|
|
|
|
_('Inspect raw module data returned by the SecuBox RPC backend.'))
|
|
|
|
|
]),
|
|
|
|
|
E('div', { 'class': 'sh-header-meta' }, [
|
|
|
|
|
this.renderHeaderChip('🏷️', _('Version'), status.version || _('Unknown')),
|
|
|
|
|
this.renderHeaderChip('📦', _('Total'), total),
|
|
|
|
|
this.renderHeaderChip('🟢', _('Running'), running, running ? 'success' : ''),
|
|
|
|
|
this.renderHeaderChip('💾', _('Installed'), installed)
|
|
|
|
|
])
|
|
|
|
|
]);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
renderModuleGrid: function(modules) {
|
|
|
|
|
return E('div', { 'class': 'cbi-map' }, [
|
|
|
|
|
E('div', { 'class': 'secubox-debug-grid' }, modules.map(function(m) {
|
|
|
|
|
return E('div', { 'class': 'secubox-debug-card' }, [
|
|
|
|
|
E('div', { 'class': 'secubox-debug-card-title' }, m.name || _('Unnamed module')),
|
|
|
|
|
E('div', { 'class': 'secubox-debug-card-desc' }, m.description || _('No description provided.')),
|
|
|
|
|
E('div', { 'class': 'secubox-debug-card-meta' }, [
|
|
|
|
|
E('span', { 'class': 'secubox-debug-pill ' + (m.running ? 'running' : m.installed ? 'installed' : 'missing') },
|
|
|
|
|
m.running ? _('Running') : m.installed ? _('Installed') : _('Not Installed')),
|
|
|
|
|
m.category ? E('span', { 'class': 'secubox-debug-pill neutral' }, m.category) : ''
|
|
|
|
|
]),
|
|
|
|
|
E('pre', { 'class': 'secubox-debug-json' }, JSON.stringify(m, null, 2))
|
|
|
|
|
]);
|
|
|
|
|
}))
|
|
|
|
|
]);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
renderEmptyState: function() {
|
|
|
|
|
return E('div', { 'class': 'cbi-map' }, [
|
|
|
|
|
E('div', { 'class': 'secubox-empty-state' }, [
|
|
|
|
|
E('div', { 'class': 'secubox-empty-icon' }, '📭'),
|
|
|
|
|
E('div', { 'class': 'secubox-empty-title' }, _('No modules found')),
|
|
|
|
|
E('p', { 'class': 'secubox-empty-text' }, _('RPC returned an empty list. Verify luci.secubox modules API.'))
|
|
|
|
|
])
|
|
|
|
|
]);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
renderHeaderChip: function(icon, label, value, tone) {
|
|
|
|
|
return E('div', { 'class': 'sh-header-chip' + (tone ? ' ' + tone : '') }, [
|
|
|
|
|
E('span', { 'class': 'sh-chip-icon' }, icon),
|
|
|
|
|
E('div', { 'class': 'sh-chip-text' }, [
|
|
|
|
|
E('span', { 'class': 'sh-chip-label' }, label),
|
|
|
|
|
E('strong', {}, value.toString())
|
|
|
|
|
])
|
|
|
|
|
]);
|
|
|
|
|
}
|
2025-12-26 07:09:27 +00:00
|
|
|
});
|