refactor(luci): Convert iot-guard and magicmirror2 to KissTheme CSS variables

Replace hardcoded hex colors with KissTheme CSS variables:
- iot-guard: RISK_COLORS, status colors, table styling
- magicmirror2: :root variable definitions, nav bar, buttons, status badges

Files updated:
- iot-guard/devices.js, policies.js
- magicmirror2/dashboard.js, modules.js, overview.js, settings.js, webui.js

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-03-12 11:39:54 +01:00
parent 1bbd345cee
commit 65a82f7fdd
7 changed files with 83 additions and 83 deletions

View File

@ -44,12 +44,12 @@ var callScan = rpc.declare({
expect: {}
});
// Risk level colors
// Risk level colors - use CSS variable names for inline styles
var RISK_COLORS = {
high: '#ff4444',
medium: '#ffaa00',
low: '#44cc44',
unknown: '#888888'
high: 'var(--kiss-red)',
medium: 'var(--kiss-orange)',
low: 'var(--kiss-green)',
unknown: 'var(--kiss-muted)'
};
return view.extend({
@ -96,12 +96,12 @@ return view.extend({
var cloudList = (device.cloud_deps || []).map(function(c) {
return E('li', { 'style': 'margin: 5px 0;' }, [
E('span', {}, c.domain),
E('span', { 'style': 'color: #888; margin-left: 10px;' }, '(' + c.query_count + ' queries)')
E('span', { 'style': 'color: var(--kiss-muted); margin-left: 10px;' }, '(' + c.query_count + ' queries)')
]);
});
var anomalyList = (device.anomalies || []).map(function(a) {
var sevColor = a.severity === 'high' ? '#ff4444' : (a.severity === 'medium' ? '#ffaa00' : '#888');
var sevColor = a.severity === 'high' ? 'var(--kiss-red)' : (a.severity === 'medium' ? 'var(--kiss-orange)' : 'var(--kiss-muted)');
return E('li', { 'style': 'margin: 5px 0;' }, [
E('span', { 'style': 'color: ' + sevColor + ';' }, '[' + a.severity + '] '),
E('span', {}, a.type + ': ' + a.description)
@ -203,19 +203,19 @@ return view.extend({
var rows = devices.map(function(d) {
var riskColor = RISK_COLORS[d.risk_level] || RISK_COLORS.unknown;
var status = d.blocked ? 'Blocked' : (d.isolated ? 'Isolated' : (d.trusted ? 'Trusted' : 'Active'));
var statusColor = d.blocked ? '#ff4444' : (d.isolated ? '#ffaa00' : (d.trusted ? '#44cc44' : '#888'));
var statusColor = d.blocked ? 'var(--kiss-red)' : (d.isolated ? 'var(--kiss-orange)' : (d.trusted ? 'var(--kiss-green)' : 'var(--kiss-muted)'));
return E('tr', { 'style': 'cursor: pointer;', 'click': function() { self.handleShowDetail(d.mac); } }, [
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, d.mac),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, d.ip || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, d.hostname || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, d.vendor ? (d.vendor.length > 25 ? d.vendor.substring(0, 22) + '...' : d.vendor) : '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, d.device_class),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333; color: ' + riskColor + ';' }, d.risk_level),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333; text-align: center;' }, d.risk_score),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, d.zone),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333; color: ' + statusColor + ';' }, status),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, [
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, d.mac),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, d.ip || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, d.hostname || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, d.vendor ? (d.vendor.length > 25 ? d.vendor.substring(0, 22) + '...' : d.vendor) : '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, d.device_class),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line); color: ' + riskColor + ';' }, d.risk_level),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line); text-align: center;' }, d.risk_score),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, d.zone),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line); color: ' + statusColor + ';' }, status),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, [
!d.isolated && !d.blocked ? E('button', {
'class': 'kiss-btn kiss-btn-blue btn-sm',
'style': 'padding: 2px 8px; font-size: 12px; margin-right: 5px;',
@ -237,14 +237,14 @@ return view.extend({
'class': 'kiss-btn kiss-btn-blue',
'click': L.bind(this.handleScan, this)
}, 'Scan Network'),
E('span', { 'style': 'margin-left: 15px; color: #888;' }, devices.length + ' devices')
E('span', { 'style': 'margin-left: 15px; color: var(--kiss-muted);' }, devices.length + ' devices')
]),
devices.length === 0 ?
E('div', { 'style': 'padding: 30px; text-align: center; color: #888;' },
E('div', { 'style': 'padding: 30px; text-align: center; color: var(--kiss-muted);' },
'No devices found. Click "Scan Network" to discover IoT devices.') :
E('table', { 'style': 'width: 100%; border-collapse: collapse;' }, [
E('thead', {}, E('tr', { 'style': 'background: #222;' }, [
E('thead', {}, E('tr', { 'style': 'background: var(--kiss-bg2);' }, [
E('th', { 'style': 'padding: 10px; text-align: left;' }, 'MAC'),
E('th', { 'style': 'padding: 10px; text-align: left;' }, 'IP'),
E('th', { 'style': 'padding: 10px; text-align: left;' }, 'Hostname'),

View File

@ -25,9 +25,9 @@ var callDeleteVendorRule = rpc.declare({
});
var RISK_COLORS = {
high: '#ff4444',
medium: '#ffaa00',
low: '#44cc44'
high: 'var(--kiss-red)',
medium: 'var(--kiss-orange)',
low: 'var(--kiss-green)'
};
var DEVICE_CLASSES = ['camera', 'thermostat', 'lighting', 'plug', 'assistant', 'media', 'lock', 'sensor', 'diy', 'mixed'];
@ -118,15 +118,15 @@ return view.extend({
var self = this;
var rows = rules.map(function(r) {
var riskColor = RISK_COLORS[r.risk_level] || '#888';
var riskColor = RISK_COLORS[r.risk_level] || 'var(--kiss-muted)';
return E('tr', {}, [
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, r.name),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333; font-family: monospace;' }, r.pattern || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333; font-family: monospace;' }, r.oui_prefix || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, r.device_class),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333; color: ' + riskColor + ';' }, r.risk_level),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, r.auto_isolate ? 'Yes' : 'No'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid #333;' }, [
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, r.name),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line); font-family: monospace;' }, r.pattern || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line); font-family: monospace;' }, r.oui_prefix || '-'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, r.device_class),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line); color: ' + riskColor + ';' }, r.risk_level),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, r.auto_isolate ? 'Yes' : 'No'),
E('td', { 'style': 'padding: 10px; border-bottom: 1px solid var(--kiss-line);' }, [
E('button', {
'class': 'kiss-btn kiss-btn-red btn-sm',
'style': 'padding: 2px 8px; font-size: 12px;',
@ -138,7 +138,7 @@ return view.extend({
var content = E('div', { 'class': 'cbi-map', 'style': 'padding: 20px;' }, [
E('h2', {}, 'IoT Guard Policies'),
E('p', { 'style': 'color: #888; margin-bottom: 20px;' },
E('p', { 'style': 'color: var(--kiss-muted); margin-bottom: 20px;' },
'Vendor classification rules determine how devices are identified and their default risk level.'),
E('div', { 'style': 'margin-bottom: 20px;' }, [
@ -151,10 +151,10 @@ return view.extend({
E('h3', { 'style': 'margin-top: 25px;' }, 'Vendor Classification Rules'),
rules.length === 0 ?
E('div', { 'style': 'padding: 20px; color: #888; text-align: center;' },
E('div', { 'style': 'padding: 20px; color: var(--kiss-muted); text-align: center;' },
'No custom vendor rules defined. Using built-in classification.') :
E('table', { 'style': 'width: 100%; border-collapse: collapse;' }, [
E('thead', {}, E('tr', { 'style': 'background: #222;' }, [
E('thead', {}, E('tr', { 'style': 'background: var(--kiss-bg2);' }, [
E('th', { 'style': 'padding: 10px; text-align: left;' }, 'Name'),
E('th', { 'style': 'padding: 10px; text-align: left;' }, 'Vendor Pattern'),
E('th', { 'style': 'padding: 10px; text-align: left;' }, 'OUI Prefix'),
@ -168,7 +168,7 @@ return view.extend({
E('h3', { 'style': 'margin-top: 30px;' }, 'Device Classes'),
E('table', { 'style': 'width: 100%; border-collapse: collapse; margin-top: 10px;' }, [
E('thead', {}, E('tr', { 'style': 'background: #222;' }, [
E('thead', {}, E('tr', { 'style': 'background: var(--kiss-bg2);' }, [
E('th', { 'style': 'padding: 8px; text-align: left;' }, 'Class'),
E('th', { 'style': 'padding: 8px; text-align: left;' }, 'Description'),
E('th', { 'style': 'padding: 8px; text-align: left;' }, 'Default Risk')
@ -192,11 +192,11 @@ return view.extend({
},
renderClassRow: function(name, desc, risk) {
var color = RISK_COLORS[risk] || '#888';
var color = RISK_COLORS[risk] || 'var(--kiss-muted)';
return E('tr', {}, [
E('td', { 'style': 'padding: 8px; border-bottom: 1px solid #333;' }, name),
E('td', { 'style': 'padding: 8px; border-bottom: 1px solid #333; color: #888;' }, desc),
E('td', { 'style': 'padding: 8px; border-bottom: 1px solid #333; color: ' + color + ';' }, risk)
E('td', { 'style': 'padding: 8px; border-bottom: 1px solid var(--kiss-line);' }, name),
E('td', { 'style': 'padding: 8px; border-bottom: 1px solid var(--kiss-line); color: var(--kiss-muted);' }, desc),
E('td', { 'style': 'padding: 8px; border-bottom: 1px solid var(--kiss-line); color: ' + color + ';' }, risk)
]);
},

View File

@ -23,13 +23,13 @@ var MM2_NAV = [
function renderMM2Nav(activeId) {
return E('div', {
'class': 'mm2-app-nav',
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:#141419;border:1px solid rgba(255,255,255,0.08);border-radius:12px;'
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:var(--kiss-bg);border:1px solid var(--kiss-line);border-radius:12px;'
}, MM2_NAV.map(function(item) {
var isActive = activeId === item.id;
return E('a', {
'href': L.url('admin', 'secubox', 'services', 'magicmirror2', item.id),
'style': 'display:flex;align-items:center;gap:8px;padding:10px 16px;border-radius:8px;text-decoration:none;font-size:14px;font-weight:500;transition:all 0.2s;' +
(isActive ? 'background:linear-gradient(135deg,#9b59b6,#8e44ad);color:white;' : 'color:#a0a0b0;background:transparent;')
(isActive ? 'background:var(--kiss-purple);color:white;' : 'color:var(--kiss-muted);background:transparent;')
}, [
E('span', {}, item.icon),
E('span', {}, _(item.label))
@ -63,16 +63,16 @@ return view.extend({
var view = E('div', { 'class': 'mm2-dashboard' }, [
E('style', {}, [
':root { --mm2-primary: #9b59b6; --mm2-success: #27ae60; --mm2-warning: #f39c12; --mm2-danger: #e74c3c; --mm2-bg-card: #141419; --mm2-text: #fff; --mm2-text-muted: #a0a0b0; }',
':root { --mm2-primary: var(--kiss-purple); --mm2-success: var(--kiss-green); --mm2-warning: var(--kiss-orange); --mm2-danger: var(--kiss-red); --mm2-bg-card: var(--kiss-bg); --mm2-text: var(--kiss-text); --mm2-text-muted: var(--kiss-muted); }',
'.mm2-dashboard { color: var(--mm2-text); }',
'.mm2-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; padding: 20px 24px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 16px; }',
'.mm2-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; padding: 20px 24px; background: var(--kiss-purple); border-radius: 16px; }',
'.mm2-logo { display: flex; align-items: center; gap: 16px; }',
'.mm2-logo-icon { font-size: 48px; }',
'.mm2-logo-text { font-size: 28px; font-weight: 700; }',
'.mm2-logo-sub { font-size: 14px; opacity: 0.8; }',
'.mm2-status-badge { display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border-radius: 20px; font-weight: 500; }',
'.mm2-status-badge.running { background: rgba(39, 174, 96, 0.2); color: #27ae60; }',
'.mm2-status-badge.stopped { background: rgba(231, 76, 60, 0.2); color: #e74c3c; }',
'.mm2-status-badge.running { background: rgba(39, 174, 96, 0.2); color: var(--kiss-green); }',
'.mm2-status-badge.stopped { background: rgba(231, 76, 60, 0.2); color: var(--kiss-red); }',
'.mm2-status-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }',
'.mm2-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 24px; }',
'.mm2-card { background: var(--mm2-bg-card); border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; padding: 20px; }',
@ -83,9 +83,9 @@ return view.extend({
'.mm2-stat-value { font-size: 36px; font-weight: 700; color: var(--mm2-primary); }',
'.mm2-stat-label { font-size: 14px; color: var(--mm2-text-muted); margin-top: 4px; }',
'.mm2-btn { display: inline-flex; align-items: center; gap: 8px; padding: 10px 20px; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s; }',
'.mm2-btn-primary { background: linear-gradient(135deg, #9b59b6, #8e44ad); color: white; }',
'.mm2-btn-success { background: linear-gradient(135deg, #27ae60, #229954); color: white; }',
'.mm2-btn-danger { background: linear-gradient(135deg, #e74c3c, #c0392b); color: white; }',
'.mm2-btn-primary { background: var(--kiss-purple); color: white; }',
'.mm2-btn-success { background: var(--kiss-green); color: white; }',
'.mm2-btn-danger { background: var(--kiss-red); color: white; }',
'.mm2-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.3); }',
'.mm2-actions { display: flex; gap: 12px; flex-wrap: wrap; }',
'.mm2-module-list { max-height: 300px; overflow-y: auto; }',

View File

@ -22,13 +22,13 @@ var MM2_NAV = [
function renderMM2Nav(activeId) {
return E('div', {
'class': 'mm2-app-nav',
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:#141419;border:1px solid rgba(255,255,255,0.08);border-radius:12px;'
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:var(--kiss-bg);border:1px solid var(--kiss-line);border-radius:12px;'
}, MM2_NAV.map(function(item) {
var isActive = activeId === item.id;
return E('a', {
'href': L.url('admin', 'secubox', 'services', 'magicmirror2', item.id),
'style': 'display:flex;align-items:center;gap:8px;padding:10px 16px;border-radius:8px;text-decoration:none;font-size:14px;font-weight:500;transition:all 0.2s;' +
(isActive ? 'background:linear-gradient(135deg,#9b59b6,#8e44ad);color:white;' : 'color:#a0a0b0;background:transparent;')
(isActive ? 'background:var(--kiss-purple);color:white;' : 'color:var(--kiss-muted);background:transparent;')
}, [
E('span', {}, item.icon),
E('span', {}, _(item.label))
@ -72,7 +72,7 @@ return view.extend({
var view = E('div', { 'class': 'mm2-modules' }, [
E('style', {}, [
':root { --mm2-primary: #9b59b6; --mm2-success: #27ae60; --mm2-warning: #f39c12; --mm2-danger: #e74c3c; --mm2-bg-card: #141419; --mm2-text: #fff; --mm2-text-muted: #a0a0b0; }',
':root { --mm2-primary: var(--kiss-purple); --mm2-success: var(--kiss-green); --mm2-warning: var(--kiss-orange); --mm2-danger: var(--kiss-red); --mm2-bg-card: var(--kiss-bg); --mm2-text: var(--kiss-text); --mm2-text-muted: var(--kiss-muted); }',
'.mm2-modules { color: var(--mm2-text); }',
'.mm2-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; }',
'.mm2-header h2 { margin: 0; display: flex; align-items: center; gap: 12px; }',
@ -80,9 +80,9 @@ return view.extend({
'.mm2-card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid rgba(255,255,255,0.08); }',
'.mm2-card-title { font-size: 18px; font-weight: 600; display: flex; align-items: center; gap: 8px; }',
'.mm2-btn { display: inline-flex; align-items: center; gap: 8px; padding: 10px 20px; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s; }',
'.mm2-btn-primary { background: linear-gradient(135deg, #9b59b6, #8e44ad); color: white; }',
'.mm2-btn-success { background: linear-gradient(135deg, #27ae60, #229954); color: white; }',
'.mm2-btn-danger { background: rgba(231, 76, 60, 0.2); color: #e74c3c; border: 1px solid rgba(231, 76, 60, 0.3); }',
'.mm2-btn-primary { background: var(--kiss-purple); color: white; }',
'.mm2-btn-success { background: var(--kiss-green); color: white; }',
'.mm2-btn-danger { background: rgba(231, 76, 60, 0.2); color: var(--kiss-red); border: 1px solid rgba(231, 76, 60, 0.3); }',
'.mm2-btn-sm { padding: 6px 12px; font-size: 12px; }',
'.mm2-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.3); }',
'.mm2-module-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }',

View File

@ -10,7 +10,7 @@ var callStart = rpc.declare({ object: 'luci.magicmirror2', method: 'start', expe
var callStop = rpc.declare({ object: 'luci.magicmirror2', method: 'stop', expect: {} });
var callRestart = rpc.declare({ object: 'luci.magicmirror2', method: 'restart', expect: {} });
var css = '.mm-container{max-width:900px;margin:0 auto}.mm-header{display:flex;justify-content:space-between;align-items:center;padding:1.5rem;background:linear-gradient(135deg,#1a1a2e 0%,#16213e 100%);border-radius:16px;color:#fff;margin-bottom:1.5rem}.mm-header h2{margin:0;font-size:1.5rem;display:flex;align-items:center;gap:.5rem}.mm-status{display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;border-radius:20px;font-size:.9rem}.mm-status.running{background:rgba(16,185,129,.2)}.mm-status.stopped{background:rgba(239,68,68,.2)}.mm-dot{width:10px;height:10px;border-radius:50%;animation:pulse 2s infinite}.mm-status.running .mm-dot{background:#10b981}.mm-status.stopped .mm-dot{background:#ef4444}@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}.mm-card{background:#fff;border-radius:12px;padding:1.5rem;box-shadow:0 2px 8px rgba(0,0,0,.08);margin-bottom:1rem}.mm-card-title{font-size:1.1rem;font-weight:600;margin-bottom:1rem;display:flex;align-items:center;gap:.5rem}.mm-info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:1rem}.mm-info-item{padding:1rem;background:#f8f9fa;border-radius:8px}.mm-info-label{font-size:.8rem;color:#666;margin-bottom:.25rem}.mm-info-value{font-size:1rem;font-weight:500}.mm-actions{display:flex;gap:.75rem;flex-wrap:wrap}.mm-btn{padding:.6rem 1.2rem;border-radius:8px;border:none;cursor:pointer;font-weight:500;transition:all .2s}.mm-btn-primary{background:linear-gradient(135deg,#1a1a2e,#16213e);color:#fff}.mm-btn-success{background:#10b981;color:#fff}.mm-btn-danger{background:#ef4444;color:#fff}.mm-btn:disabled{opacity:.5;cursor:not-allowed}.mm-not-installed{text-align:center;padding:3rem}.mm-features{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1rem;margin:1.5rem 0}.mm-feature{padding:.75rem;background:#e0e7ff;border-radius:8px;font-size:.9rem}';
var css = '.mm-container{max-width:900px;margin:0 auto}.mm-header{display:flex;justify-content:space-between;align-items:center;padding:1.5rem;background:var(--kiss-purple);border-radius:16px;color:var(--kiss-text);margin-bottom:1.5rem}.mm-header h2{margin:0;font-size:1.5rem;display:flex;align-items:center;gap:.5rem}.mm-status{display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;border-radius:20px;font-size:.9rem}.mm-status.running{background:rgba(16,185,129,.2)}.mm-status.stopped{background:rgba(239,68,68,.2)}.mm-dot{width:10px;height:10px;border-radius:50%;animation:pulse 2s infinite}.mm-status.running .mm-dot{background:var(--kiss-green)}.mm-status.stopped .mm-dot{background:var(--kiss-red)}@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}.mm-card{background:var(--kiss-card);border-radius:12px;padding:1.5rem;box-shadow:0 2px 8px rgba(0,0,0,.08);margin-bottom:1rem}.mm-card-title{font-size:1.1rem;font-weight:600;margin-bottom:1rem;display:flex;align-items:center;gap:.5rem}.mm-info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:1rem}.mm-info-item{padding:1rem;background:var(--kiss-bg2);border-radius:8px}.mm-info-label{font-size:.8rem;color:var(--kiss-muted);margin-bottom:.25rem}.mm-info-value{font-size:1rem;font-weight:500}.mm-actions{display:flex;gap:.75rem;flex-wrap:wrap}.mm-btn{padding:.6rem 1.2rem;border-radius:8px;border:none;cursor:pointer;font-weight:500;transition:all .2s}.mm-btn-primary{background:var(--kiss-purple);color:var(--kiss-text)}.mm-btn-success{background:var(--kiss-green);color:var(--kiss-text)}.mm-btn-danger{background:var(--kiss-red);color:var(--kiss-text)}.mm-btn:disabled{opacity:.5;cursor:not-allowed}.mm-not-installed{text-align:center;padding:3rem}.mm-features{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1rem;margin:1.5rem 0}.mm-feature{padding:.75rem;background:var(--kiss-bg2);border-radius:8px;font-size:.9rem}';
return view.extend({
load: function() { return callStatus(); },
@ -59,7 +59,7 @@ return view.extend({
E('div', { 'class': 'mm-feature' }, '\uD83D\uDDE3 Compliments'),
E('div', { 'class': 'mm-feature' }, '\uD83D\uDD0C Modules')
]),
!status.docker_available ? E('div', { 'style': 'color:#ef4444;margin-bottom:1rem' }, _('Docker required')) : '',
!status.docker_available ? E('div', { 'style': 'color:var(--kiss-red);margin-bottom:1rem' }, _('Docker required')) : '',
E('button', { 'class': 'mm-btn mm-btn-primary', 'click': ui.createHandlerFn(this, 'handleInstall'), 'disabled': !status.docker_available }, _('Install MagicMirror'))
])
])

View File

@ -24,13 +24,13 @@ var MM2_NAV = [
function renderMM2Nav(activeId) {
return E('div', {
'class': 'mm2-app-nav',
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:#141419;border:1px solid rgba(255,255,255,0.08);border-radius:12px;'
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:var(--kiss-bg);border:1px solid var(--kiss-line);border-radius:12px;'
}, MM2_NAV.map(function(item) {
var isActive = activeId === item.id;
return E('a', {
'href': L.url('admin', 'secubox', 'services', 'magicmirror2', item.id),
'style': 'display:flex;align-items:center;gap:8px;padding:10px 16px;border-radius:8px;text-decoration:none;font-size:14px;font-weight:500;transition:all 0.2s;' +
(isActive ? 'background:linear-gradient(135deg,#9b59b6,#8e44ad);color:white;' : 'color:#a0a0b0;background:transparent;')
(isActive ? 'background:var(--kiss-purple);color:white;' : 'color:var(--kiss-muted);background:transparent;')
}, [
E('span', {}, item.icon),
E('span', {}, _(item.label))
@ -260,24 +260,24 @@ return view.extend({
// Add custom styles for form
wrapper.appendChild(E('style', {}, [
'.cbi-map { background: #141419; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; padding: 20px; }',
'.cbi-map { background: var(--kiss-bg); border: 1px solid var(--kiss-line); border-radius: 12px; padding: 20px; }',
'.cbi-section { margin-bottom: 20px; }',
'.cbi-section-node { background: rgba(255,255,255,0.02); border-radius: 8px; padding: 16px; }',
'.cbi-tabmenu { display: flex; gap: 8px; margin-bottom: 20px; flex-wrap: wrap; }',
'.cbi-tabmenu li { list-style: none; }',
'.cbi-tabmenu li a { display: block; padding: 10px 20px; background: rgba(255,255,255,0.05); border-radius: 8px; color: #a0a0b0; text-decoration: none; font-weight: 500; }',
'.cbi-tabmenu li.cbi-tab a { background: linear-gradient(135deg, #9b59b6, #8e44ad); color: white; }',
'.cbi-tabmenu li a { display: block; padding: 10px 20px; background: var(--kiss-bg2); border-radius: 8px; color: var(--kiss-muted); text-decoration: none; font-weight: 500; }',
'.cbi-tabmenu li.cbi-tab a { background: var(--kiss-purple); color: white; }',
'.cbi-value { display: flex; align-items: center; padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,0.05); }',
'.cbi-value:last-child { border-bottom: none; }',
'.cbi-value-title { flex: 0 0 200px; font-weight: 500; color: #fff; }',
'.cbi-value-title { flex: 0 0 200px; font-weight: 500; color: var(--kiss-text); }',
'.cbi-value-field { flex: 1; }',
'.cbi-value-description { font-size: 12px; color: #a0a0b0; margin-top: 4px; }',
'.cbi-input-text, .cbi-input-select, .cbi-input-password { width: 100%; padding: 10px 14px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; color: white; font-size: 14px; }',
'.cbi-input-text:focus, .cbi-input-select:focus, .cbi-input-password:focus { outline: none; border-color: #9b59b6; }',
'.cbi-value-description { font-size: 12px; color: var(--kiss-muted); margin-top: 4px; }',
'.cbi-input-text, .cbi-input-select, .cbi-input-password { width: 100%; padding: 10px 14px; background: var(--kiss-bg2); border: 1px solid var(--kiss-line); border-radius: 6px; color: var(--kiss-text); font-size: 14px; }',
'.cbi-input-text:focus, .cbi-input-select:focus, .cbi-input-password:focus { outline: none; border-color: var(--kiss-purple); }',
'.cbi-button { padding: 10px 20px; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s; }',
'.cbi-button-save, .cbi-button-apply { background: linear-gradient(135deg, #27ae60, #229954); color: white; }',
'.cbi-button-reset { background: rgba(255,255,255,0.1); color: white; }',
'.cbi-checkbox { accent-color: #9b59b6; }',
'.cbi-button-save, .cbi-button-apply { background: var(--kiss-green); color: white; }',
'.cbi-button-reset { background: var(--kiss-bg2); color: var(--kiss-text); }',
'.cbi-checkbox { accent-color: var(--kiss-purple); }',
'.cbi-dynlist { display: flex; flex-direction: column; gap: 8px; }',
'.cbi-dynlist > .item { display: flex; gap: 8px; align-items: center; }',
'.cbi-dynlist > .item > input { flex: 1; }'
@ -285,11 +285,11 @@ return view.extend({
// Regenerate config button
var actionBar = E('div', {
'style': 'display: flex; gap: 12px; margin-bottom: 20px; padding: 16px; background: #141419; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px;'
'style': 'display: flex; gap: 12px; margin-bottom: 20px; padding: 16px; background: var(--kiss-bg); border: 1px solid var(--kiss-line); border-radius: 12px;'
}, [
E('button', {
'class': 'kiss-btn',
'style': 'background: linear-gradient(135deg, #9b59b6, #8e44ad); color: white;',
'class': 'kiss-btn kiss-btn-purple',
'click': function() {
ui.showModal(_('Regenerating...'), [
E('p', { 'class': 'spinning' }, _('Regenerating MagicMirror2 config.js...'))
@ -306,7 +306,7 @@ return view.extend({
}, ['🔧 ', _('Regenerate Config')]),
E('button', {
'class': 'kiss-btn',
'style': 'background: linear-gradient(135deg, #3498db, #2980b9); color: white;',
'class': 'kiss-btn kiss-btn-blue',
'click': function() {
if (!status.running) {
ui.addNotification(null, E('p', {}, _('Service is not running')), 'warning');

View File

@ -22,13 +22,13 @@ var MM2_NAV = [
function renderMM2Nav(activeId) {
return E('div', {
'class': 'mm2-app-nav',
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:#141419;border:1px solid rgba(255,255,255,0.08);border-radius:12px;'
'style': 'display:flex;gap:8px;margin-bottom:20px;padding:12px 16px;background:var(--kiss-bg);border:1px solid var(--kiss-line);border-radius:12px;'
}, MM2_NAV.map(function(item) {
var isActive = activeId === item.id;
return E('a', {
'href': L.url('admin', 'secubox', 'services', 'magicmirror2', item.id),
'style': 'display:flex;align-items:center;gap:8px;padding:10px 16px;border-radius:8px;text-decoration:none;font-size:14px;font-weight:500;transition:all 0.2s;' +
(isActive ? 'background:linear-gradient(135deg,#9b59b6,#8e44ad);color:white;' : 'color:#a0a0b0;background:transparent;')
(isActive ? 'background:var(--kiss-purple);color:white;' : 'color:var(--kiss-muted);background:transparent;')
}, [
E('span', {}, item.icon),
E('span', {}, _(item.label))
@ -55,14 +55,14 @@ return view.extend({
if (!status.running) {
content = E('div', {
'class': 'mm2-card',
'style': 'text-align: center; padding: 60px 20px; background: #141419; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px;'
'style': 'text-align: center; padding: 60px 20px; background: var(--kiss-bg); border: 1px solid var(--kiss-line); border-radius: 12px;'
}, [
E('div', { 'style': 'font-size: 64px; margin-bottom: 20px;' }, '⚠️'),
E('h2', { 'style': 'margin: 0 0 10px 0; color: #f39c12;' }, _('MagicMirror2 is not running')),
E('p', { 'style': 'color: #a0a0b0; margin: 0 0 20px 0;' }, _('Start the service to view the display')),
E('h2', { 'style': 'margin: 0 0 10px 0; color: var(--kiss-orange);' }, _('MagicMirror2 is not running')),
E('p', { 'style': 'color: var(--kiss-muted); margin: 0 0 20px 0;' }, _('Start the service to view the display')),
E('button', {
'class': 'mm2-btn mm2-btn-success',
'style': 'display: inline-flex; align-items: center; gap: 8px; padding: 12px 24px; background: linear-gradient(135deg, #27ae60, #229954); color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer;',
'class': 'kiss-btn kiss-btn-green',
'click': function() {
ui.showModal(_('Starting...'), [
E('p', { 'class': 'spinning' }, _('Starting MagicMirror2...'))
@ -80,10 +80,10 @@ return view.extend({
content = E('div', { 'style': 'display: flex; flex-direction: column; height: calc(100vh - 200px); min-height: 600px;' }, [
// Toolbar
E('div', {
'style': 'display: flex; align-items: center; gap: 12px; margin-bottom: 12px; padding: 12px 16px; background: #141419; border-radius: 8px; border: 1px solid rgba(255,255,255,0.08);'
'style': 'display: flex; align-items: center; gap: 12px; margin-bottom: 12px; padding: 12px 16px; background: var(--kiss-bg); border-radius: 8px; border: 1px solid var(--kiss-line);'
}, [
E('span', { 'style': 'color: #27ae60; font-weight: 500;' }, '● ' + _('Live Preview')),
E('span', { 'style': 'color: #a0a0b0; font-size: 13px;' }, iframeSrc),
E('span', { 'style': 'color: var(--kiss-green); font-weight: 500;' }, '● ' + _('Live Preview')),
E('span', { 'style': 'color: var(--kiss-muted); font-size: 13px;' }, iframeSrc),
E('div', { 'style': 'flex: 1;' }),
E('button', {
'style': 'display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; background: rgba(255,255,255,0.1); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 13px;',
@ -93,7 +93,7 @@ return view.extend({
}
}, ['🔄 ', _('Refresh')]),
E('a', {
'style': 'display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; background: linear-gradient(135deg, #9b59b6, #8e44ad); color: white; border: none; border-radius: 6px; text-decoration: none; font-size: 13px;',
'class': 'kiss-btn kiss-btn-purple',
'href': iframeSrc,
'target': '_blank'
}, ['↗ ', _('Fullscreen')])
@ -101,7 +101,7 @@ return view.extend({
// Iframe container
E('div', {
'style': 'flex: 1; border-radius: 12px; overflow: hidden; border: 1px solid rgba(255,255,255,0.1); background: #000;'
'style': 'flex: 1; border-radius: 12px; overflow: hidden; border: 1px solid var(--kiss-line); background: #000;'
}, [
E('iframe', {
'class': 'mm2-iframe',