First dev version v.0.1

This commit is contained in:
2025-10-21 17:53:37 +01:00
parent 8f319f4039
commit a09d4818b5
26 changed files with 1680 additions and 0 deletions

111
src/js/home.js Normal file
View File

@@ -0,0 +1,111 @@
document.addEventListener('page-loaded', e => {
if (e.detail.page !== "home") return;
const stats = ['Cpu','Ram','Zram','Swap','Disk','Disk0','Images'];
const elements = {};
const bars = {};
const prev = {};
const textElements = {
'Ram': document.getElementById('statRamText'),
'Disk': document.getElementById('statDiskText'),
'Disk0': document.getElementById('statDisk0Text')
};
stats.forEach(k => {
elements[k] = document.getElementById('stat'+k);
bars[k] = document.getElementById('bar'+k);
prev[k] = 0;
});
fetchStats();
setInterval(fetchStats, 2000);
async function fetchStats() {
try {
const res = await fetch("includes/stats.php", { cache: "no-store" });
const data = await res.json();
stats.forEach(key => {
let val = data[key.toLowerCase()];
if (val === undefined || val === null) return;
const numVal = Number(val) || 0;
// Animate number
if (key === 'Images') {
// Raw number
animateValue(elements[key], prev[key], numVal, 400, false);
} else {
// Percentage display
animateValue(elements[key], prev[key], numVal, 400, true);
}
prev[key] = numVal;
if (textElements['Ram'] && data.ram_used !== undefined && data.ram_total) {
textElements['Ram'].textContent = `${formatBytes(data.ram_used)} / ${formatBytes(data.ram_total)}`;
}
if (textElements['Disk'] && data.disk_used !== undefined && data.disk_total) {
textElements['Disk'].textContent = `${formatBytes(data.disk_used)} / ${formatBytes(data.disk_total)}`;
}
if (textElements['Disk0'] && data.disk0_used !== undefined && data.disk0_total) {
textElements['Disk0'].textContent = `${formatBytes(data.disk0_used)} / ${formatBytes(data.disk0_total)}`;
}
// Progress bar
if (bars[key]) {
let pct = key === 'Images' ? Math.min(numVal / 100 * 100, 100) : numVal;
bars[key].style.width = pct + '%';
}
// Color thresholds
if (numVal >= 85) {
elements[key].className = 'high';
} else if (numVal >= 75) {
elements[key].className = 'medium';
} else {
elements[key].className = 'low';
}
});
// Add memory and disk text
if (data.ram_total && data.ram_used !== undefined) {
elements['Ram'].textContent += ` (${formatBytes(data.ram_used)} / ${formatBytes(data.ram_total)})`;
}
if (data.disk_total && data.disk_used !== undefined) {
elements['Disk'].textContent += ` (${formatBytes(data.disk_used)} / ${formatBytes(data.disk_total)})`;
}
if (data.disk0_total && data.disk0_used !== undefined) {
elements['Disk0'].textContent += ` (${formatBytes(data.disk0_used)} / ${formatBytes(data.disk0_total)})`;
}
} catch(err) {
console.warn("Failed to fetch stats:", err);
}
}
function animateValue(el, start, end, duration, showPercent = true) {
let startTime = null;
function step(timestamp) {
if (!startTime) startTime = timestamp;
const progress = Math.min((timestamp - startTime) / duration, 1);
const current = start + (end - start) * progress;
el.textContent = Math.round(current) + (showPercent ? '%' : '');
if (progress < 1) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}
function formatBytes(bytes) {
if (bytes === 0) return '0B';
const k = 1024;
const sizes = ['B','KB','MB','GB','TB'];
const i = Math.floor(Math.log(bytes)/Math.log(k));
return parseFloat((bytes / Math.pow(k,i)).toFixed(1)) + sizes[i];
}
});