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:
@@ -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 & 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- & 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>
|
||||
|
||||
Reference in New Issue
Block a user