Skip to content

Commit 3c5786a

Browse files
authored
Updates
1 parent 5113b81 commit 3c5786a

8 files changed

Lines changed: 642 additions & 16 deletions

File tree

config/var/www/admin/control-panel/api.php

Lines changed: 436 additions & 2 deletions
Large diffs are not rendered by default.

config/var/www/admin/control-panel/dashboard.css

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
}
77

88
:root {
9-
/* Color Scheme */
9+
/* Color Scheme - Dark Theme (Default) */
1010
--primary-bg: #1a1a1a;
1111
--secondary-bg: #2d2d2d;
1212
--card-bg: #333;
@@ -20,6 +20,10 @@
2020
--warning-color: #ffb800;
2121
--error-color: #f44;
2222
--info-color: #00a8ff;
23+
--skeleton-base: #333;
24+
--skeleton-highlight: #3e3e3e;
25+
--input-bg: #2d2d2d;
26+
--hover-overlay: rgba(255, 255, 255, 0.05);
2327

2428
/* Layout */
2529
--sidebar-width: 280px;
@@ -29,6 +33,33 @@
2933
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
3034
}
3135

36+
/* Light Theme */
37+
[data-theme="light"] {
38+
--primary-bg: #f5f5f5;
39+
--secondary-bg: #ffffff;
40+
--card-bg: #ffffff;
41+
--accent-color: #00a88a;
42+
--accent-hover: #00937a;
43+
--text-primary: #1a1a1a;
44+
--text-secondary: #555555;
45+
--text-muted: #777777;
46+
--border-color: #e0e0e0;
47+
--success-color: #00a88a;
48+
--warning-color: #e6a700;
49+
--error-color: #d32f2f;
50+
--info-color: #0088cc;
51+
--skeleton-base: #e0e0e0;
52+
--skeleton-highlight: #f0f0f0;
53+
--input-bg: #f5f5f5;
54+
--hover-overlay: rgba(0, 0, 0, 0.05);
55+
--shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
56+
}
57+
58+
/* Light theme body background adjustment */
59+
[data-theme="light"] body {
60+
background: linear-gradient(135deg, var(--primary-bg) 0%, #e8e8e8 100%);
61+
}
62+
3263
body {
3364
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
3465
background: linear-gradient(135deg, var(--primary-bg) 0%, #2a2a2d 100%);
@@ -1223,5 +1254,49 @@ button:focus, select:focus, input:focus {
12231254
color: var(--error-color);
12241255
}
12251256

1257+
/* Theme Toggle Button */
1258+
.theme-toggle {
1259+
display: flex;
1260+
align-items: center;
1261+
justify-content: center;
1262+
width: 40px;
1263+
height: 40px;
1264+
background: var(--card-bg);
1265+
border: 1px solid var(--border-color);
1266+
border-radius: var(--border-radius);
1267+
cursor: pointer;
1268+
color: var(--text-primary);
1269+
font-size: 1.1rem;
1270+
transition: var(--transition);
1271+
}
1272+
1273+
.theme-toggle:hover {
1274+
background: var(--hover-overlay);
1275+
border-color: var(--accent-color);
1276+
color: var(--accent-color);
1277+
}
1278+
1279+
.theme-toggle:focus {
1280+
outline: 2px solid var(--accent-color);
1281+
outline-offset: 2px;
1282+
}
1283+
1284+
/* Theme toggle icon states */
1285+
.theme-toggle .fa-sun {
1286+
display: none;
1287+
}
1288+
1289+
.theme-toggle .fa-moon {
1290+
display: block;
1291+
}
1292+
1293+
[data-theme="light"] .theme-toggle .fa-sun {
1294+
display: block;
1295+
}
1296+
1297+
[data-theme="light"] .theme-toggle .fa-moon {
1298+
display: none;
1299+
}
1300+
12261301
/* External Services styles moved to external-services/external-services.css */
12271302

config/var/www/admin/control-panel/dashboard.js

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// EngineScript Admin Dashboard - Modern JavaScript
22
// Security-hardened version with input validation and XSS prevention
33

4-
import { DashboardAPI } from './modules/api.js?v=2025.11.25.2';
5-
import { DashboardState } from './modules/state.js?v=2025.11.25.2';
6-
import { DashboardUtils } from './modules/utils.js?v=2025.11.25.2';
4+
import { DashboardAPI } from './modules/api.js?v=2025.11.25.3';
5+
import { DashboardState } from './modules/state.js?v=2025.11.25.3';
6+
import { DashboardUtils } from './modules/utils.js?v=2025.11.25.3';
77
// External services loaded dynamically when needed (lazy loading)
88

99
class EngineScriptDashboard {
@@ -25,6 +25,7 @@ class EngineScriptDashboard {
2525
}
2626

2727
init() {
28+
this.initTheme(); // Initialize theme before rendering
2829
this.setupEventListeners();
2930
this.setupNavigation();
3031
this.startClock();
@@ -33,7 +34,38 @@ class EngineScriptDashboard {
3334
this.hideLoadingScreen();
3435
}
3536

37+
/**
38+
* Initialize theme from localStorage or system preference
39+
*/
40+
initTheme() {
41+
const savedTheme = localStorage.getItem('dashboard-theme');
42+
if (savedTheme) {
43+
document.documentElement.setAttribute('data-theme', savedTheme);
44+
} else {
45+
// Check system preference
46+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
47+
document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light');
48+
}
49+
}
50+
51+
/**
52+
* Toggle between dark and light themes
53+
*/
54+
toggleTheme() {
55+
const currentTheme = document.documentElement.getAttribute('data-theme') || 'dark';
56+
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
57+
58+
document.documentElement.setAttribute('data-theme', newTheme);
59+
localStorage.setItem('dashboard-theme', newTheme);
60+
}
61+
3662
setupEventListeners() {
63+
// Theme toggle button
64+
const themeToggle = document.getElementById("theme-toggle");
65+
if (themeToggle) {
66+
themeToggle.addEventListener("click", () => this.toggleTheme());
67+
}
68+
3769
// Mobile menu toggle
3870
const mobileMenuToggle = document.getElementById("mobile-menu-toggle");
3971
if (mobileMenuToggle) {
@@ -183,7 +215,7 @@ class EngineScriptDashboard {
183215

184216
console.log('[Dashboard] Importing external services module...');
185217
// Dynamic import - only loads when needed
186-
const { ExternalServicesManager } = await import('./external-services/external-services.js?v=2025.11.25.2');
218+
const { ExternalServicesManager } = await import('./external-services/external-services.js?v=2025.11.25.3');
187219

188220
console.log('[Dashboard] Creating ExternalServicesManager instance...');
189221
// Create instance and initialize
@@ -676,7 +708,7 @@ class EngineScriptDashboard {
676708
}
677709

678710
/**
679-
* Task 70: Show skeleton loading state for system info using DocumentFragment
711+
* Show skeleton loading state for system info using DocumentFragment
680712
* Avoids forced DOM reparse from innerHTML
681713
*/
682714
showSkeletonSystemInfo() {

config/var/www/admin/control-panel/external-services/external-services.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// EngineScript External Services Manager - ES6 Module
22
// Handles external service status monitoring with drag-drop ordering and preferences
33

4-
import { DashboardUtils } from '../modules/utils.js?v=2025.11.25.2';
5-
import { SERVICE_DEFINITIONS } from './services-config.js?v=2025.11.25.2';
4+
import { DashboardUtils } from '../modules/utils.js?v=2025.11.25.3';
5+
import { SERVICE_DEFINITIONS } from './services-config.js?v=2025.11.25.3';
66

77
export class ExternalServicesManager {
88
constructor(containerSelector, settingsContainerSelector) {

config/var/www/admin/control-panel/index.html

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/{FONTAWESOME_VER}/css/all.min.css" rel="stylesheet" crossorigin="anonymous">
1212

1313
<!-- Custom Styles -->
14-
<link rel="stylesheet" href="dashboard.css?v=2025.11.25.2">
15-
<link rel="stylesheet" href="external-services/external-services.css?v=2025.11.25.2">
14+
<link rel="stylesheet" href="dashboard.css?v=2025.11.25.3">
15+
<link rel="stylesheet" href="external-services/external-services.css?v=2025.11.25.3">
1616

1717
<!-- Preload Critical Resources -->
18-
<link rel="modulepreload" href="dashboard.js?v=2025.11.25.2" crossorigin="use-credentials">
19-
<link rel="modulepreload" href="modules/api.js?v=2025.11.25.2" crossorigin="use-credentials">
18+
<link rel="modulepreload" href="dashboard.js?v=2025.11.25.3" crossorigin="use-credentials">
19+
<link rel="modulepreload" href="modules/api.js?v=2025.11.25.3" crossorigin="use-credentials">
2020
</head>
2121
<body>
2222
<!-- Loading Screen -->
@@ -75,6 +75,10 @@ <h1 id="page-title">Overview</h1>
7575
<span id="last-updated">Last updated: <span id="update-time">--</span></span>
7676
</div>
7777
<div class="header-right">
78+
<button class="theme-toggle" id="theme-toggle" title="Toggle dark/light theme" aria-label="Toggle dark/light theme">
79+
<i class="fas fa-moon"></i>
80+
<i class="fas fa-sun"></i>
81+
</button>
7882
<button class="btn btn-primary" id="refresh-btn">
7983
<i class="fas fa-sync-alt"></i> Refresh
8084
</button>
@@ -369,10 +373,10 @@ <h3>Uptime Robot</h3>
369373

370374
<!-- Dashboard Version -->
371375
<div style="text-align: center; padding: 20px; color: #666; font-size: 0.85rem; border-top: 1px solid #444;">
372-
EngineScript Dashboard v2025.11.25.2
376+
EngineScript Dashboard v2025.11.25.3
373377
</div>
374378

375379
<!-- Scripts -->
376-
<script type="module" src="dashboard.js?v=2025.11.25.2" data-cfasync="false"></script>
380+
<script type="module" src="dashboard.js?v=2025.11.25.3" data-cfasync="false"></script>
377381
</body>
378382
</html>

config/var/www/admin/control-panel/modules/api.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,59 @@ export class DashboardAPI {
138138
}
139139
}
140140

141+
/**
142+
* Batch multiple API requests into a single call
143+
* Reduces network round-trips and improves performance
144+
*
145+
* @param {string[]} endpoints - Array of API endpoints to fetch
146+
* @returns {Promise<Object>} - Object with results keyed by endpoint
147+
*
148+
* @example
149+
* const data = await api.batchRequest(['/system/info', '/services/status']);
150+
* console.log(data.results['/system/info']);
151+
*/
152+
async batchRequest(endpoints) {
153+
try {
154+
if (typeof fetch === "undefined" || this.isOperaMini()) {
155+
return { error: 'Fetch not supported', results: {}, errors: {} };
156+
}
157+
158+
if (!Array.isArray(endpoints) || endpoints.length === 0) {
159+
return { error: 'No endpoints provided', results: {}, errors: {} };
160+
}
161+
162+
// Limit batch size client-side to match server limit
163+
const maxBatchSize = 10;
164+
if (endpoints.length > maxBatchSize) {
165+
console.warn(`Batch size ${endpoints.length} exceeds max ${maxBatchSize}, truncating`);
166+
endpoints = endpoints.slice(0, maxBatchSize);
167+
}
168+
169+
const headers = {
170+
'Content-Type': 'application/json'
171+
};
172+
if (this.csrfToken) {
173+
headers['X-CSRF-Token'] = this.csrfToken;
174+
}
175+
176+
const response = await fetch('/api/batch', {
177+
method: 'POST',
178+
headers: headers,
179+
credentials: 'include',
180+
body: JSON.stringify({ requests: endpoints })
181+
});
182+
183+
if (!response.ok) {
184+
throw new Error(`Batch API returned ${response.status}: ${response.statusText}`);
185+
}
186+
187+
return await response.json();
188+
} catch (error) {
189+
console.error('Batch API request failed:', error);
190+
return { error: error.message, results: {}, errors: {} };
191+
}
192+
}
193+
141194
async getServiceStatus(service) {
142195
try {
143196
if (typeof fetch === "undefined" || this.isOperaMini()) {

scripts/functions/shared/enginescript-common.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,26 @@ function purge_nginx_helper_cache() {
141141
}
142142

143143

144+
145+
# ----------------------------------------------------------------
146+
# Clear EngineScript API cache directory (/var/cache/enginescript/api)
147+
function clear_api_cache() {
148+
echo "Clearing EngineScript API cache"
149+
local cache_dir="/var/cache/enginescript/api"
150+
151+
if [ -d "${cache_dir}" ]; then
152+
find "${cache_dir}" -type f -name '*.json' -delete 2>/dev/null || {
153+
echo "Error: Failed to clear API cache at ${cache_dir}."
154+
return 1
155+
}
156+
echo "API cache cleared successfully"
157+
else
158+
echo "Warning: API cache directory not found at ${cache_dir}"
159+
return 1
160+
fi
161+
}
162+
163+
144164
# ----------------------------------------------------------------
145165
# Clear all WordPress caches for a single site (cache + rewrites)
146166
function clear_wordpress_caches() {
@@ -214,6 +234,7 @@ function clear_all_wordpress_caches() {
214234
# ----------------------------------------------------------------
215235
# Clear all system caches (Nginx, OpCache, Redis)
216236
function clear_all_system_caches() {
237+
clear_api_cache
217238
clear_nginx_cache
218239
clear_opcache
219240
clear_redis_cache

setup.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@ if [[ ! -d "/var/www/admin/enginescript/" ]]; then
124124
echo "✓ EngineScript admin directory created"
125125
fi
126126

127+
# Create /var/cache/enginescript/api if it doesn't exist
128+
if [[ ! -d "/var/cache/enginescript/api" ]]; then
129+
echo "Creating EngineScript dashboard API cache directory..."
130+
mkdir -p "/var/cache/enginescript/api"
131+
echo "✓ EngineScript dashboard API cache directory created"
132+
fi
133+
127134
# EngineScript Logs
128135
# Create EngineScript logs
129136
mkdir -p "/var/log/EngineScript"

0 commit comments

Comments
 (0)