Spaces:
Running
Running
Update templates/code_new.html
Browse files- templates/code_new.html +197 -23
templates/code_new.html
CHANGED
|
@@ -675,32 +675,113 @@
|
|
| 675 |
|
| 676 |
<!-- VIEW: DIAGNOSTICS -->
|
| 677 |
<div id="view-diagnostics" class="hidden h-[calc(100vh-6rem)] flex flex-col overflow-hidden">
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
<p class="text-[10px] font-label text-on-surface-variant tracking-widest uppercase mb-1">API Health</p>
|
| 685 |
-
<div class="flex items-end gap-2"><span class="text-xl font-headline font-bold text-on-surface">--</span><span class="text-xs font-label text-outline mb-1">PENDING</span></div>
|
| 686 |
-
</div>
|
| 687 |
-
<div class="p-6 border-r border-outline-variant/10">
|
| 688 |
-
<p class="text-[10px] font-label text-on-surface-variant tracking-widest uppercase mb-1">FastAPI Latency</p>
|
| 689 |
-
<div class="flex items-end gap-2"><span class="text-xl font-headline font-bold text-on-surface">--</span><span class="text-xs font-label text-outline mb-1">PENDING</span></div>
|
| 690 |
</div>
|
| 691 |
-
<div class="
|
| 692 |
-
<
|
| 693 |
-
|
|
|
|
|
|
|
|
|
|
| 694 |
</div>
|
| 695 |
</div>
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
|
| 699 |
-
<
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 704 |
</div>
|
| 705 |
</div>
|
| 706 |
|
|
@@ -901,6 +982,10 @@ function showView(viewId) {
|
|
| 901 |
if (FLEX_VIEWS.includes(viewId)) target.classList.add("flex");
|
| 902 |
}
|
| 903 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 904 |
// Actualizar nav activo
|
| 905 |
const BOTTOM_LINKS = ["diagnostics", "logs"];
|
| 906 |
Object.entries(NAV_ITEMS).forEach(([key, id]) => {
|
|
@@ -1245,5 +1330,94 @@ function exportHistory() {
|
|
| 1245 |
a.click();
|
| 1246 |
}
|
| 1247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1248 |
</script>
|
| 1249 |
</body></html>
|
|
|
|
| 675 |
|
| 676 |
<!-- VIEW: DIAGNOSTICS -->
|
| 677 |
<div id="view-diagnostics" class="hidden h-[calc(100vh-6rem)] flex flex-col overflow-hidden">
|
| 678 |
+
|
| 679 |
+
<!-- Header -->
|
| 680 |
+
<div class="px-8 py-5 flex justify-between items-center bg-surface-container-low/30 border-b border-slate-800/40 shrink-0">
|
| 681 |
+
<div>
|
| 682 |
+
<h1 class="font-headline text-2xl font-bold tracking-tight text-on-surface">System Diagnostics</h1>
|
| 683 |
+
<p class="font-body text-sm text-on-surface-variant">Hardware metrics en tiempo real del contenedor Docker.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 684 |
</div>
|
| 685 |
+
<div class="flex items-center gap-4">
|
| 686 |
+
<div class="flex items-center gap-2">
|
| 687 |
+
<div id="diagDot" class="w-2 h-2 rounded-full bg-outline"></div>
|
| 688 |
+
<span id="diagStatus" class="text-[10px] font-headline tracking-widest uppercase text-outline">Conectando...</span>
|
| 689 |
+
</div>
|
| 690 |
+
<span id="diagTimestamp" class="text-[10px] font-mono text-outline/50"></span>
|
| 691 |
</div>
|
| 692 |
</div>
|
| 693 |
+
|
| 694 |
+
<!-- Cards Grid -->
|
| 695 |
+
<div class="flex-1 overflow-y-auto custom-scrollbar p-8">
|
| 696 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto">
|
| 697 |
+
|
| 698 |
+
<!-- CPU -->
|
| 699 |
+
<div class="glass-card rounded p-6 border-l-4 border-primary">
|
| 700 |
+
<div class="flex items-center justify-between mb-4">
|
| 701 |
+
<div class="flex items-center gap-3">
|
| 702 |
+
<span class="material-symbols-outlined text-primary text-2xl">memory</span>
|
| 703 |
+
<div>
|
| 704 |
+
<h3 class="font-headline text-sm font-bold text-on-surface uppercase tracking-widest">CPU</h3>
|
| 705 |
+
<p id="diagCpuCores" class="text-[10px] text-on-surface-variant font-mono">-- cores</p>
|
| 706 |
+
</div>
|
| 707 |
+
</div>
|
| 708 |
+
<span id="diagCpuPct" class="text-3xl font-headline font-black text-primary">--%</span>
|
| 709 |
+
</div>
|
| 710 |
+
<div class="w-full h-2 bg-surface-container-lowest rounded-full overflow-hidden">
|
| 711 |
+
<div id="diagCpuBar" class="h-full bg-primary transition-all duration-700 rounded-full" style="width:0%"></div>
|
| 712 |
+
</div>
|
| 713 |
+
<div class="flex justify-between mt-2">
|
| 714 |
+
<span class="text-[10px] font-mono text-on-surface-variant">0%</span>
|
| 715 |
+
<span class="text-[10px] font-mono text-on-surface-variant">100%</span>
|
| 716 |
+
</div>
|
| 717 |
+
</div>
|
| 718 |
+
|
| 719 |
+
<!-- RAM -->
|
| 720 |
+
<div class="glass-card rounded p-6 border-l-4 border-secondary">
|
| 721 |
+
<div class="flex items-center justify-between mb-4">
|
| 722 |
+
<div class="flex items-center gap-3">
|
| 723 |
+
<span class="material-symbols-outlined text-secondary text-2xl">storage</span>
|
| 724 |
+
<div>
|
| 725 |
+
<h3 class="font-headline text-sm font-bold text-on-surface uppercase tracking-widest">RAM</h3>
|
| 726 |
+
<p id="diagRamDetail" class="text-[10px] text-on-surface-variant font-mono">-- / -- GB</p>
|
| 727 |
+
</div>
|
| 728 |
+
</div>
|
| 729 |
+
<span id="diagRamPct" class="text-3xl font-headline font-black text-secondary">--%</span>
|
| 730 |
+
</div>
|
| 731 |
+
<div class="w-full h-2 bg-surface-container-lowest rounded-full overflow-hidden">
|
| 732 |
+
<div id="diagRamBar" class="h-full bg-secondary transition-all duration-700 rounded-full" style="width:0%"></div>
|
| 733 |
+
</div>
|
| 734 |
+
<div class="flex justify-between mt-2">
|
| 735 |
+
<span class="text-[10px] font-mono text-on-surface-variant">0%</span>
|
| 736 |
+
<span class="text-[10px] font-mono text-on-surface-variant">100%</span>
|
| 737 |
+
</div>
|
| 738 |
+
</div>
|
| 739 |
+
|
| 740 |
+
<!-- DISCO -->
|
| 741 |
+
<div class="glass-card rounded p-6 border-l-4 border-tertiary">
|
| 742 |
+
<div class="flex items-center justify-between mb-4">
|
| 743 |
+
<div class="flex items-center gap-3">
|
| 744 |
+
<span class="material-symbols-outlined text-tertiary text-2xl">hard_drive</span>
|
| 745 |
+
<div>
|
| 746 |
+
<h3 class="font-headline text-sm font-bold text-on-surface uppercase tracking-widest">Disco</h3>
|
| 747 |
+
<p id="diagDiskDetail" class="text-[10px] text-on-surface-variant font-mono">-- / -- GB</p>
|
| 748 |
+
</div>
|
| 749 |
+
</div>
|
| 750 |
+
<span id="diagDiskPct" class="text-3xl font-headline font-black text-tertiary">--%</span>
|
| 751 |
+
</div>
|
| 752 |
+
<div class="w-full h-2 bg-surface-container-lowest rounded-full overflow-hidden">
|
| 753 |
+
<div id="diagDiskBar" class="h-full bg-tertiary transition-all duration-700 rounded-full" style="width:0%"></div>
|
| 754 |
+
</div>
|
| 755 |
+
<div class="flex justify-between mt-2">
|
| 756 |
+
<span class="text-[10px] font-mono text-on-surface-variant">0 GB</span>
|
| 757 |
+
<span id="diagDiskMax" class="text-[10px] font-mono text-on-surface-variant">-- GB</span>
|
| 758 |
+
</div>
|
| 759 |
+
</div>
|
| 760 |
+
|
| 761 |
+
<!-- RED -->
|
| 762 |
+
<div class="glass-card rounded p-6 border-l-4 border-primary-dim">
|
| 763 |
+
<div class="flex items-center gap-3 mb-4">
|
| 764 |
+
<span class="material-symbols-outlined text-primary-dim text-2xl">network_check</span>
|
| 765 |
+
<h3 class="font-headline text-sm font-bold text-on-surface uppercase tracking-widest">Red</h3>
|
| 766 |
+
</div>
|
| 767 |
+
<div class="grid grid-cols-2 gap-4">
|
| 768 |
+
<div class="bg-surface-container-lowest p-3 rounded border border-outline-variant/20">
|
| 769 |
+
<p class="text-[10px] font-headline tracking-widest text-on-surface-variant uppercase mb-1">β Entrada</p>
|
| 770 |
+
<p id="diagNetIn" class="text-xl font-headline font-black text-primary">-- KB/s</p>
|
| 771 |
+
<p id="diagNetInTotal" class="text-[10px] font-mono text-on-surface-variant mt-1">Total: -- MB</p>
|
| 772 |
+
</div>
|
| 773 |
+
<div class="bg-surface-container-lowest p-3 rounded border border-outline-variant/20">
|
| 774 |
+
<p class="text-[10px] font-headline tracking-widest text-on-surface-variant uppercase mb-1">β Salida</p>
|
| 775 |
+
<p id="diagNetOut" class="text-xl font-headline font-black text-secondary">-- KB/s</p>
|
| 776 |
+
<p id="diagNetOutTotal" class="text-[10px] font-mono text-on-surface-variant mt-1">Total: -- MB</p>
|
| 777 |
+
</div>
|
| 778 |
+
</div>
|
| 779 |
+
</div>
|
| 780 |
+
|
| 781 |
+
</div>
|
| 782 |
+
|
| 783 |
+
<!-- Error banner -->
|
| 784 |
+
<div id="diagError" class="hidden max-w-4xl mx-auto mt-4 p-4 border border-error/30 bg-error/5 text-error text-xs font-mono rounded"></div>
|
| 785 |
</div>
|
| 786 |
</div>
|
| 787 |
|
|
|
|
| 982 |
if (FLEX_VIEWS.includes(viewId)) target.classList.add("flex");
|
| 983 |
}
|
| 984 |
|
| 985 |
+
// Arrancar/parar poller de diagnostics
|
| 986 |
+
if (viewId === "diagnostics") startDiagPoller();
|
| 987 |
+
else stopDiagPoller();
|
| 988 |
+
|
| 989 |
// Actualizar nav activo
|
| 990 |
const BOTTOM_LINKS = ["diagnostics", "logs"];
|
| 991 |
Object.entries(NAV_ITEMS).forEach(([key, id]) => {
|
|
|
|
| 1330 |
a.click();
|
| 1331 |
}
|
| 1332 |
|
| 1333 |
+
|
| 1334 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1335 |
+
// DIAGNOSTICS POLLER
|
| 1336 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1337 |
+
let diagInterval = null;
|
| 1338 |
+
|
| 1339 |
+
function getBarColor(pct) {
|
| 1340 |
+
if (pct >= 90) return "bg-error";
|
| 1341 |
+
if (pct >= 70) return "bg-tertiary";
|
| 1342 |
+
return null; // keep default
|
| 1343 |
+
}
|
| 1344 |
+
|
| 1345 |
+
function updateDiagUI(data) {
|
| 1346 |
+
const el = id => document.getElementById(id);
|
| 1347 |
+
|
| 1348 |
+
// Status dot
|
| 1349 |
+
el("diagDot").className = "w-2 h-2 rounded-full bg-secondary shadow-[0_0_8px_#37ee9b]";
|
| 1350 |
+
el("diagStatus").textContent = "Live";
|
| 1351 |
+
el("diagStatus").className = "text-[10px] font-headline tracking-widest uppercase text-secondary font-bold";
|
| 1352 |
+
el("diagTimestamp").textContent = new Date(data.timestamp).toLocaleTimeString();
|
| 1353 |
+
|
| 1354 |
+
// CPU
|
| 1355 |
+
const cpu = data.cpu;
|
| 1356 |
+
el("diagCpuPct").textContent = cpu.percent + "%";
|
| 1357 |
+
el("diagCpuCores").textContent = cpu.cores + " cores";
|
| 1358 |
+
const cpuBar = el("diagCpuBar");
|
| 1359 |
+
cpuBar.style.width = cpu.percent + "%";
|
| 1360 |
+
if (cpu.percent >= 90) cpuBar.className = "h-full bg-error transition-all duration-700 rounded-full";
|
| 1361 |
+
else if (cpu.percent >= 70) cpuBar.className = "h-full bg-tertiary transition-all duration-700 rounded-full";
|
| 1362 |
+
else cpuBar.className = "h-full bg-primary transition-all duration-700 rounded-full";
|
| 1363 |
+
|
| 1364 |
+
// RAM
|
| 1365 |
+
const ram = data.ram;
|
| 1366 |
+
el("diagRamPct").textContent = ram.percent + "%";
|
| 1367 |
+
el("diagRamDetail").textContent = ram.used_gb + " / " + ram.total_gb + " GB";
|
| 1368 |
+
const ramBar = el("diagRamBar");
|
| 1369 |
+
ramBar.style.width = ram.percent + "%";
|
| 1370 |
+
if (ram.percent >= 90) ramBar.className = "h-full bg-error transition-all duration-700 rounded-full";
|
| 1371 |
+
else if (ram.percent >= 70) ramBar.className = "h-full bg-tertiary transition-all duration-700 rounded-full";
|
| 1372 |
+
else ramBar.className = "h-full bg-secondary transition-all duration-700 rounded-full";
|
| 1373 |
+
|
| 1374 |
+
// Disco
|
| 1375 |
+
const disk = data.disk;
|
| 1376 |
+
el("diagDiskPct").textContent = disk.percent + "%";
|
| 1377 |
+
el("diagDiskDetail").textContent = disk.used_gb + " / " + disk.total_gb + " GB";
|
| 1378 |
+
el("diagDiskMax").textContent = disk.total_gb + " GB";
|
| 1379 |
+
const diskBar = el("diagDiskBar");
|
| 1380 |
+
diskBar.style.width = disk.percent + "%";
|
| 1381 |
+
if (disk.percent >= 90) diskBar.className = "h-full bg-error transition-all duration-700 rounded-full";
|
| 1382 |
+
else if (disk.percent >= 70) diskBar.className = "h-full bg-tertiary transition-all duration-700 rounded-full";
|
| 1383 |
+
else diskBar.className = "h-full bg-tertiary transition-all duration-700 rounded-full";
|
| 1384 |
+
|
| 1385 |
+
// Red
|
| 1386 |
+
const net = data.network;
|
| 1387 |
+
el("diagNetIn").textContent = net.in_kb_s + " KB/s";
|
| 1388 |
+
el("diagNetOut").textContent = net.out_kb_s + " KB/s";
|
| 1389 |
+
el("diagNetInTotal").textContent = "Total: " + net.in_total_mb + " MB";
|
| 1390 |
+
el("diagNetOutTotal").textContent = "Total: " + net.out_total_mb + " MB";
|
| 1391 |
+
|
| 1392 |
+
// Ocultar error
|
| 1393 |
+
el("diagError").classList.add("hidden");
|
| 1394 |
+
}
|
| 1395 |
+
|
| 1396 |
+
async function fetchDiagnostics() {
|
| 1397 |
+
try {
|
| 1398 |
+
const res = await fetch("/api/diagnostics");
|
| 1399 |
+
const data = await res.json();
|
| 1400 |
+
if (data.error) throw new Error(data.error);
|
| 1401 |
+
updateDiagUI(data);
|
| 1402 |
+
} catch(e) {
|
| 1403 |
+
const dot = document.getElementById("diagDot");
|
| 1404 |
+
const status = document.getElementById("diagStatus");
|
| 1405 |
+
const err = document.getElementById("diagError");
|
| 1406 |
+
if (dot) dot.className = "w-2 h-2 rounded-full bg-error";
|
| 1407 |
+
if (status) { status.textContent = "Error"; status.className = "text-[10px] font-headline tracking-widest uppercase text-error font-bold"; }
|
| 1408 |
+
if (err) { err.textContent = "Error: " + e.message; err.classList.remove("hidden"); }
|
| 1409 |
+
}
|
| 1410 |
+
}
|
| 1411 |
+
|
| 1412 |
+
function startDiagPoller() {
|
| 1413 |
+
fetchDiagnostics(); // fetch inmediato
|
| 1414 |
+
if (diagInterval) clearInterval(diagInterval);
|
| 1415 |
+
diagInterval = setInterval(fetchDiagnostics, 4000); // cada 4s
|
| 1416 |
+
}
|
| 1417 |
+
|
| 1418 |
+
function stopDiagPoller() {
|
| 1419 |
+
if (diagInterval) { clearInterval(diagInterval); diagInterval = null; }
|
| 1420 |
+
}
|
| 1421 |
+
|
| 1422 |
</script>
|
| 1423 |
</body></html>
|