feat: Implement light/dark theme toggle and enhance UI components

- Added theme.js for managing light/dark mode with user preference persistence.
- Updated lab.php to include theme toggle button and adjust styles for light mode.
- Enhanced CSS styles in style.css for light theme support, including background and text colors.
- Introduced DNS record lookup functionality in tools.php with user input for domain queries.
- Improved UI for DNS lookup and outbound connectivity tests in tools.php.
- Added historical benchmark trend chart in lab.php to visualize previous benchmark scores.
- Refactored various UI elements for better spacing and alignment across components.
This commit is contained in:
2026-09-07 13:16:56 +02:00
parent 4400bc2640
commit 61af688ff3
5 changed files with 611 additions and 78 deletions
+168 -10
View File
@@ -68,11 +68,10 @@ function benchmarkDiskIO() {
return ['status' => 'error', 'message' => 'Kan tijdelijk bestand niet aanmaken'];
}
$chunkSize = 64 * 1024; // 64 KB
$chunks = 48; // ~3 MB totaal
$chunkSize = 64 * 1024;
$chunks = 48; // ~3 MB
$dummyData = str_repeat('WPCStudio2026_TEST_STRING_ABCD!', 2048);
// Write test
$writeStart = microtime(true);
$fp = fopen($tempFile, 'wb');
if (!$fp) {
@@ -86,7 +85,6 @@ function benchmarkDiskIO() {
fclose($fp);
$writeTime = max(0.0005, microtime(true) - $writeStart);
// Read test
$readStart = microtime(true);
$fp = fopen($tempFile, 'rb');
if ($fp) {
@@ -284,6 +282,7 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web &amp; PC Studio - Webserver Benchmark</title>
<link rel="stylesheet" href="style.css">
<script src="theme.js"></script>
<style>
.bench-master {
background: linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(11, 15, 25, 0.95));
@@ -299,6 +298,11 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
flex-wrap: wrap;
}
[data-theme="light"] .bench-master {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.95), rgba(241, 245, 249, 0.95));
box-shadow: 0 15px 35px -10px rgba(0, 0, 0, 0.08);
}
.score-box {
display: flex;
align-items: center;
@@ -309,6 +313,10 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
border-radius: var(--radius-lg);
}
[data-theme="light"] .score-box {
background: rgba(241, 245, 249, 0.85);
}
.score-circle {
width: 76px;
height: 76px;
@@ -350,6 +358,12 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
.conc-pill.success { border-color: #10b981; color: #34d399; }
.conc-pill.slow { border-color: #f59e0b; color: #fbbf24; }
.conc-pill.error { border-color: #ef4444; color: #f87171; }
@media print {
.navbar, .btn, .nav-status, .sound-toggle, footer { display: none !important; }
body { background: #fff !important; color: #000 !important; }
.card, .bench-master { box-shadow: none !important; border: 1px solid #ccc !important; }
}
</style>
</head>
<body>
@@ -369,6 +383,7 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
<a href="tools.php" class="nav-item">🛠️ Dev Tools</a>
</div>
<div class="nav-status">
<button class="btn btn-secondary btn-sm theme-btn" onclick="toggleTheme()">🌙 Thema</button>
<button class="btn btn-secondary btn-sm" id="sound-btn" onclick="toggleAudio()" title="Schakel geluid in/uit">
<span id="sound-icon">🔈</span> Geluid: <span id="sound-status">Uit</span>
</button>
@@ -386,16 +401,22 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
<!-- Master Benchmark Banner -->
<div class="bench-master">
<div style="flex: 1; min-width: 280px;">
<h2 style="font-size: 1.3rem; color: #fff; margin-bottom: 6px;">⚡ Volledige Server Benchmark</h2>
<h2 style="font-size: 1.3rem; color: var(--text-main); margin-bottom: 6px;">⚡ Volledige Server Benchmark</h2>
<p style="font-size: 0.88rem; color: var(--text-muted); margin-bottom: 18px;">
Voert in één geautomatiseerde cyclus alle 5 hardware- &amp; softwaretests uit op www.webenpcstudio.nl.
</p>
<div style="display: flex; gap: 10px; align-items: center; flex-wrap: wrap;">
<div style="display: flex; gap: 8px; align-items: center; flex-wrap: wrap;">
<button class="btn btn-primary" id="btn-run-all" onclick="runFullBenchmark()">
▶ Start Volledige Benchmark
</button>
<button class="btn btn-secondary" onclick="copyReport()">
📋 Kopieer Rapport
<button class="btn btn-secondary btn-sm" onclick="copyReport()">
📋 Kopieer
</button>
<button class="btn btn-secondary btn-sm" onclick="downloadJSONReport()">
📥 Download JSON
</button>
<button class="btn btn-secondary btn-sm" onclick="printReport()">
🖨️ PDF / Print
</button>
</div>
<div class="progress-bar-wrap" id="p-bar-wrap">
@@ -406,7 +427,7 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
<!-- Score Display -->
<div class="score-box">
<div class="score-circle" id="score-circle">
<span style="font-size: 1.45rem; color: #fff; line-height: 1;" id="score-num">--</span>
<span style="font-size: 1.45rem; color: var(--text-main); line-height: 1;" id="score-num">--</span>
<span style="font-size: 0.65rem; color: var(--text-muted);">/ 100</span>
</div>
<div>
@@ -416,6 +437,25 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
</div>
</div>
<!-- Historische Vergelijking & Trend Grafiek -->
<div class="card" style="margin-bottom: 24px;">
<div class="card-header">
<div>
<div class="card-title"><span>📈</span> Historische Benchmark Trend (Opeenvolgende Runs)</div>
<p class="card-desc" style="margin-bottom: 0;">Vergelijk eerdere benchmark scores over tijd om server-stabiliteit te monitoren.</p>
</div>
<button class="btn btn-secondary btn-sm" onclick="clearHistory()">🗑️ Wis Historie</button>
</div>
<div class="chart-wrap">
<canvas id="history-canvas" style="width: 100%; height: 100%; display: block;"></canvas>
</div>
<div id="history-legend" style="font-size: 0.78rem; color: var(--text-muted); display: flex; justify-content: space-between;">
<span>Eerste meting</span>
<span id="history-count">0 eerdere benchmarks opgeslagen</span>
<span>Laatste meting</span>
</div>
</div>
<!-- 6 Test Cards -->
<div class="grid-3">
<!-- CPU -->
@@ -554,7 +594,7 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
</div>
<div style="display: flex; gap: 8px; align-items: center;">
<button class="btn btn-secondary btn-sm" onclick="setConc(5, this)">5 Calls</button>
<button class="btn btn-secondary btn-sm" style="border-color: var(--primary); color: #fff;" onclick="setConc(12, this)">12 Calls</button>
<button class="btn btn-secondary btn-sm" style="border-color: var(--primary);" onclick="setConc(12, this)">12 Calls</button>
<button class="btn btn-secondary btn-sm" onclick="setConc(24, this)">24 Calls</button>
<button class="btn btn-primary btn-sm" id="btn-conc" onclick="runConcurrencyTest()">⚡ Start Burst</button>
</div>
@@ -626,6 +666,94 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
let lastReport = null;
// Historie beheer
function getHistory() {
try {
return JSON.parse(localStorage.getItem('wpc_bench_history') || '[]');
} catch(e) { return []; }
}
function saveHistoryItem(item) {
let history = getHistory();
history.push(item);
if (history.length > 20) history.shift();
localStorage.setItem('wpc_bench_history', JSON.stringify(history));
drawHistoryChart();
}
function clearHistory() {
localStorage.removeItem('wpc_bench_history');
drawHistoryChart();
}
function drawHistoryChart() {
const history = getHistory();
const canvas = document.getElementById('history-canvas');
const ctx = canvas.getContext('2d');
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
ctx.clearRect(0, 0, canvas.width, canvas.height);
document.getElementById('history-count').textContent = `${history.length} benchmark runs opgeslagen`;
if (history.length === 0) {
ctx.fillStyle = '#94a3b8';
ctx.font = '12px var(--font-sans)';
ctx.textAlign = 'center';
ctx.fillText('Nog geen eerdere benchmarks opgeslagen. Voer een test uit!', canvas.width / 2, canvas.height / 2);
return;
}
const stepX = canvas.width / Math.max(1, history.length - 1);
// Gradient fill
const grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
grad.addColorStop(0, 'rgba(14, 165, 233, 0.4)');
grad.addColorStop(1, 'rgba(14, 165, 233, 0.0)');
ctx.beginPath();
history.forEach((h, i) => {
const x = history.length === 1 ? canvas.width / 2 : i * stepX;
const y = canvas.height - ((h.score / 100) * (canvas.height - 30)) - 15;
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
if (history.length > 1) {
ctx.lineTo((history.length - 1) * stepX, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.fillStyle = grad;
ctx.fill();
}
// Stroke
ctx.beginPath();
history.forEach((h, i) => {
const x = history.length === 1 ? canvas.width / 2 : i * stepX;
const y = canvas.height - ((h.score / 100) * (canvas.height - 30)) - 15;
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.strokeStyle = '#0ea5e9';
ctx.lineWidth = 2.5;
ctx.stroke();
// Dots & labels
history.forEach((h, i) => {
const x = history.length === 1 ? canvas.width / 2 : i * stepX;
const y = canvas.height - ((h.score / 100) * (canvas.height - 30)) - 15;
ctx.beginPath();
ctx.arc(x, y, 4, 0, Math.PI * 2);
ctx.fillStyle = '#fff';
ctx.fill();
ctx.fillStyle = '#38bdf8';
ctx.font = '10px var(--font-mono)';
ctx.textAlign = 'center';
ctx.fillText(h.score, x, y - 8);
});
}
async function runFullBenchmark() {
const btn = document.getElementById('btn-run-all');
const pWrap = document.getElementById('p-bar-wrap');
@@ -667,6 +795,13 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
document.getElementById('db-time').textContent = data.db.duration_ms + ' ms';
}
// Opslaan in historie
saveHistoryItem({
score: data.score,
grade: data.grade,
time: data.timestamp
});
playTone(880, 'triangle', 0.2);
} catch (err) {
alert('Benchmark fout: ' + err.message);
@@ -785,6 +920,29 @@ $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'Apache / Nginx';
playTone(660, 'sine', 0.1);
});
}
function downloadJSONReport() {
if (!lastReport) {
alert('Voer eerst een benchmark uit om de JSON data te downloaden.');
return;
}
const blob = new Blob([JSON.stringify(lastReport, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `benchmark_webenpcstudio_${Date.now()}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
function printReport() {
window.print();
}
window.addEventListener('resize', drawHistoryChart);
document.addEventListener('DOMContentLoaded', drawHistoryChart);
</script>
</body>
</html>