diff --git a/Overlord-Server/public/assets/logs.js b/Overlord-Server/public/assets/logs.js index fc0e36c..49594c2 100644 --- a/Overlord-Server/public/assets/logs.js +++ b/Overlord-Server/public/assets/logs.js @@ -8,26 +8,28 @@ const refreshBtn = document.getElementById("refresh-btn"); const prevPageBtn = document.getElementById("prev-page"); const nextPageBtn = document.getElementById("next-page"); const pageInfo = document.getElementById("page-info"); +const logsCount = document.getElementById("logs-count"); +const clearFiltersBtn = document.getElementById("clear-filters-btn"); const actionLabels = { client_first_connect: { label: "First Connect", - className: "bg-emerald-900/40 text-emerald-200 border border-emerald-800", + className: "bg-emerald-500/10 text-emerald-300 border-emerald-500/30", icon: "fa-plug-circle-bolt", }, client_reconnect: { label: "Reconnect", - className: "bg-blue-900/40 text-blue-200 border border-blue-800", + className: "bg-blue-500/10 text-blue-300 border-blue-500/30", icon: "fa-rotate", }, client_disconnect: { label: "Disconnect", - className: "bg-orange-900/40 text-orange-200 border border-orange-800", + className: "bg-orange-500/10 text-orange-300 border-orange-500/30", icon: "fa-plug-circle-xmark", }, uninstall: { label: "Uninstall", - className: "bg-rose-900/40 text-rose-200 border border-rose-800", + className: "bg-rose-500/10 text-rose-300 border-rose-500/30", icon: "fa-trash", }, }; @@ -98,15 +100,21 @@ function renderLogs(logs) { logsContainer.innerHTML = ""; if (!logs || logs.length === 0) { logsEmpty.classList.remove("hidden"); + if (logsCount) logsCount.textContent = "0 matching events"; return; } logsEmpty.classList.add("hidden"); + if (logsCount) { + const first = (page - 1) * pageSize + 1; + const last = Math.min(first + logs.length - 1, total); + logsCount.textContent = `${total.toLocaleString()} events · showing ${first}–${last}`; + } logsContainer.innerHTML = logs .map((log) => { const meta = actionLabels[log.action] || { label: log.action, - className: "bg-slate-800/60 text-slate-200 border border-slate-700", + className: "bg-slate-800 text-slate-300 border-slate-700", icon: "fa-circle-info", }; const clientId = log.targetClientId || "-"; @@ -114,25 +122,26 @@ function renderLogs(logs) { const detailText = parseDetails(log.details); return ` -
-
-
- - - ${meta.label} - - - Client: ${escapeHtml(shortId)} - +
+
+ +
+
+
+
+ ${escapeHtml(meta.label || "Event")} + Client + ${escapeHtml(shortId)} +
+
-
${formatTimestamp(log.timestamp)}
+
+ ${escapeHtml(log.ip || "-")} + ${escapeHtml(log.username || "-")} +
+ ${detailText ? `
${detailText}
` : ""}
-
- IP: ${escapeHtml(log.ip || "-")} - User: ${escapeHtml(log.username || "-")} -
- ${detailText ? `
Details: ${detailText}
` : ""} -
+ `; }) .join(""); @@ -140,6 +149,18 @@ function renderLogs(logs) { async function loadLogs() { try { + if (refreshBtn) refreshBtn.disabled = true; + if (logsCount) logsCount.textContent = "Loading events…"; + if (getSelectedActions().length === 0) { + total = 0; + page = 1; + renderLogs([]); + pageInfo.textContent = "Page 1 of 1"; + prevPageBtn.disabled = true; + nextPageBtn.disabled = true; + lastUpdate.textContent = new Date().toLocaleTimeString(); + return; + } const params = buildQuery(); const res = await fetch(`/api/audit-logs?${params.toString()}`); if (!res.ok) { @@ -160,9 +181,12 @@ async function loadLogs() { console.error("Failed to load logs", err); if (logsContainer) { logsContainer.innerHTML = ` -
Failed to load logs. Please try again.
+
Failed to load logs. Please try again.
`; } + if (logsCount) logsCount.textContent = "Unable to load events"; + } finally { + if (refreshBtn) refreshBtn.disabled = false; } } @@ -181,6 +205,15 @@ clientFilter?.addEventListener("input", debounceLoad); startDateInput?.addEventListener("change", resetAndLoad); endDateInput?.addEventListener("change", resetAndLoad); refreshBtn?.addEventListener("click", resetAndLoad); +clearFiltersBtn?.addEventListener("click", () => { + if (clientFilter) clientFilter.value = ""; + if (startDateInput) startDateInput.value = ""; + if (endDateInput) endDateInput.value = ""; + document.querySelectorAll(".action-checkbox").forEach((checkbox) => { + checkbox.checked = true; + }); + resetAndLoad(); +}); Array.from(document.querySelectorAll(".action-checkbox")).forEach((cb) => { cb.addEventListener("change", resetAndLoad); diff --git a/Overlord-Server/public/assets/processes.js b/Overlord-Server/public/assets/processes.js index 9a573ec..f593cb2 100644 --- a/Overlord-Server/public/assets/processes.js +++ b/Overlord-Server/public/assets/processes.js @@ -28,7 +28,7 @@ const searchInput = document.getElementById("search-input"); const clientIdHeader = document.getElementById("client-id-header"); if (clientIdHeader) { - clientIdHeader.textContent = `${clientId} - Process Manager`; + clientIdHeader.innerHTML = `${escapeHtml(clientId)}`; } function connect() { @@ -76,10 +76,13 @@ function updateStatus(state, text) { }; statusEl.innerHTML = `${icons[state] || icons.disconnected} ${text}`; - statusEl.className = - state === "connected" - ? "inline-flex items-center gap-2 px-3 py-2 rounded-full bg-green-900/40 text-green-100 border border-green-700/60" - : "inline-flex items-center gap-2 px-3 py-2 rounded-full bg-slate-800 text-slate-300"; + const stateClasses = { + connected: "bg-emerald-500/10 text-emerald-300 border-emerald-500/30", + error: "bg-red-500/10 text-red-300 border-red-500/30", + disconnected: "bg-slate-800 text-slate-300 border-slate-700", + connecting: "bg-sky-500/10 text-sky-300 border-sky-500/30", + }; + statusEl.className = `inline-flex self-start sm:self-auto items-center gap-2 px-3 py-1.5 rounded-full border text-xs font-medium ${stateClasses[state] || stateClasses.disconnected}`; } function enableControls(enabled) { @@ -280,7 +283,7 @@ function renderProcesses() { function rowClassName(proc) { let cls = - "process-row grid grid-cols-12 gap-3 px-4 py-3 border border-transparent cursor-pointer transition-colors"; + "process-row grid grid-cols-12 gap-3 px-4 py-3 border-l-2 border-transparent cursor-pointer transition-colors"; if (selectedPid === proc.pid) cls += " selected"; if (proc.self) cls += " self-process"; return cls; @@ -356,14 +359,14 @@ function rowInnerHtml(proc, depth) { : ""; return ` -
${proc.pid}
-
+
${proc.pid}
+
${indent}${treeIcon}${procIcon} ${escapeHtml(proc.name)}${selfBadge}
-
${displayCpu.toFixed(1)}%
-
${memoryStr}
-
${escapeHtml(proc.username || "-")}
+
${displayCpu.toFixed(1)}%
+
${memoryStr}
+
${escapeHtml(proc.username || "-")}
`; } diff --git a/Overlord-Server/public/logs.html b/Overlord-Server/public/logs.html index e8a5eee..f3aff03 100644 --- a/Overlord-Server/public/logs.html +++ b/Overlord-Server/public/logs.html @@ -9,7 +9,7 @@ - + @@ -20,109 +20,112 @@
-
-
-
-
-

Client Connection Logs

-

- Track first connects, reconnects, uninstalls, and disconnects. -

+
+
+
+

Client Connection Logs

+

Review connection lifecycle activity across enrolled clients.

+
+
+ + Updated Never +
+
+ +
+
+
+
-
- Updated: Never +
+

Filter activity

+

Narrow results by client, time range, or event type.

-
-
-
- - -
-
- - -
-
- - -
-
- +
+
+ +
+ +
+
+ + +
+
+ + +
+
-
-
- -
-
- -
- -
Page 1
-
-
-
+
+ + +
+
+
+
+ +
+
+

Activity timeline

+

Loading events…

+
+
+
+ +
+ + +
+ +
Page 1
+ +
+
diff --git a/Overlord-Server/public/processes.html b/Overlord-Server/public/processes.html index 1b3e5a6..9edd5d3 100644 --- a/Overlord-Server/public/processes.html +++ b/Overlord-Server/public/processes.html @@ -9,22 +9,19 @@ - +
-
-
- -
-
- - Connecting... - - - - Loading client... - - - 0 processes - +
+
+
+

Process Manager

+

Loading client...

+
+ + Connecting... + +
+ +
+
+
+
+
+ +
+
+

Running processes

+

0 processes

+
+
+
+ + +
-
- - + +
+
+ + +
+
+ Types + System + Service + Own + Other + Agent +
- -
- - -
- - -
- Process Types: -
- - System -
-
- - Service -
-
- - Own -
-
- - Other -
-
- - Overlord Agent -
-
- - -
+
-
+