diff --git a/public_html/admin/index.php b/public_html/admin/index.php
index bd1a80f..2ffaa0a 100644
--- a/public_html/admin/index.php
+++ b/public_html/admin/index.php
@@ -827,53 +827,49 @@ function scanShell(tblWrapId, headers, titleEl, scanLabel) {
}
// ── AGENTS ────────────────────────────────────────────────────────────────────
+const miniBar = (pct, warn=70, crit=85) => {
+ if (pct == null) return '—';
+ const c = pct>=crit?'var(--red)':pct>=warn?'var(--yellow)':'var(--green)';
+ return `${Math.round(pct)}%`;
+};
+
async function loadAgents() {
- const tbl = document.getElementById('agents-tbl');
+ const tbl = document.getElementById('agents-tbl');
const title = document.getElementById('agents-title');
- // Build empty table shell immediately — no waiting
- tbl.innerHTML = `
- | HOSTNAME | STATUS | TYPE | IP | METRICS | LAST SEEN | REGISTERED | |
-
`;
-
+ tbl.innerHTML = `
+ | HOSTNAME | STATUS | TYPE | IP | METRICS | LAST SEEN | REGISTERED | |
+
`;
title.innerHTML = 'AGENTS SCANNING...';
- const agents = await api('agents_list');
- const tbody = document.getElementById('agents-tbody');
+ let agents;
+ try { agents = await api('agents_list'); }
+ catch(e) { tbl.innerHTML='ERROR LOADING AGENTS
'; title.textContent='AGENTS'; return; }
- if (!agents.length) {
+ if (!Array.isArray(agents) || !agents.length) {
tbl.innerHTML = 'NO AGENTS REGISTERED
';
title.textContent = 'AGENTS';
return;
}
- // Reveal each agent row with a staggered delay
agents.forEach((a, i) => {
setTimeout(() => {
+ const tbody = document.getElementById('agents-tbody');
+ if (!tbody) return;
const m = a.metrics;
const online = a.status === 'online';
const lastSeen = a.last_seen ? (Date.now() - new Date(a.last_seen)) / 1000 : null;
const fresh = lastSeen !== null && lastSeen < 30;
-
- // CPU/RAM mini bars
- let meterCell = `no metrics`;
- if (m) {
- function miniBar(pct, warn=70, crit=85) {
- if (pct == null) return '—';
- const c = pct>=crit?'var(--red)':pct>=warn?'var(--yellow)':'var(--green)';
- return `${Math.round(pct)}%`;
- }
- meterCell = `CPU ${miniBar(m.cpu_pct)} · RAM ${miniBar(m.mem_pct)} · DISK ${miniBar(m.disk_pct,80,90)}`;
- }
+ const meterCell = m
+ ? `CPU ${miniBar(m.cpu_pct)} · RAM ${miniBar(m.mem_pct)} · DISK ${miniBar(m.disk_pct,80,90)}`
+ : `no metrics`;
const row = document.createElement('tr');
row.className = 'agent-row';
- row.style.animationDelay = '0s';
row.innerHTML = `
-
-
+ |
${esc(a.hostname)}
- ${fresh && online ? '● LIVE' : ''}
+ ${fresh&&online?'● LIVE':''}
|
${statusBadge(a.status)} |
${esc(a.agent_type||'linux').toUpperCase()} |
@@ -882,15 +878,14 @@ async function loadAgents() {
${ago(a.last_seen)} |
${ts(a.created_at)} |
| `;
- tbody?.appendChild(row);
+ tbody.appendChild(row);
- // Update title counter as agents appear
const found = i + 1;
- const online_count = agents.slice(0, found).filter(x => x.status === 'online').length;
- if (title) title.innerHTML = found < agents.length
+ const onlineCt = agents.slice(0, found).filter(x => x.status === 'online').length;
+ title.innerHTML = found < agents.length
? `AGENTS SCANNING... ${found}/${agents.length}`
- : `AGENTS ${online_count} ONLINE / ${agents.length} TOTAL`;
- }, i * 120); // 120ms stagger per agent
+ : `AGENTS ${onlineCt} ONLINE / ${agents.length} TOTAL`;
+ }, i * 120);
});
}