feat: expansion of web dashboard with live activity feed and metrics

This commit is contained in:
syntaxbullet
2026-01-07 13:34:29 +01:00
parent 63f55b6dfd
commit 618d973863
3 changed files with 49 additions and 0 deletions

View File

@@ -1,3 +1,5 @@
import { WebServer } from "@/web/server";
/**
* Centralized logging utility with consistent formatting
*/
@@ -7,6 +9,7 @@ export const logger = {
*/
info: (message: string, ...args: any[]) => {
console.log(` ${message}`, ...args);
try { WebServer.broadcastLog("info", message); } catch { }
},
/**
@@ -14,6 +17,7 @@ export const logger = {
*/
success: (message: string, ...args: any[]) => {
console.log(`${message}`, ...args);
try { WebServer.broadcastLog("success", message); } catch { }
},
/**
@@ -21,6 +25,7 @@ export const logger = {
*/
warn: (message: string, ...args: any[]) => {
console.warn(`⚠️ ${message}`, ...args);
try { WebServer.broadcastLog("warning", message); } catch { }
},
/**
@@ -28,6 +33,7 @@ export const logger = {
*/
error: (message: string, ...args: any[]) => {
console.error(`${message}`, ...args);
try { WebServer.broadcastLog("error", message); } catch { }
},
/**
@@ -35,5 +41,6 @@ export const logger = {
*/
debug: (message: string, ...args: any[]) => {
console.log(`🔍 ${message}`, ...args);
try { WebServer.broadcastLog("debug", message); } catch { }
},
};

View File

@@ -56,12 +56,41 @@ document.addEventListener("DOMContentLoaded", () => {
// We can optionally verify if client clock is drifting, but let's keep it simple.
} else if (msg.type === "WELCOME") {
console.log(msg.message);
} else if (msg.type === "LOG") {
appendToActivityFeed(msg.data);
}
} catch (e) {
console.error("WS Parse Error", e);
}
};
function appendToActivityFeed(log) {
const list = document.querySelector(".activity-feed");
if (!list) return;
const item = document.createElement("li");
item.className = `activity-item ${log.type}`;
const timeSpan = document.createElement("span");
timeSpan.className = "time";
timeSpan.textContent = log.timestamp;
const messageSpan = document.createElement("span");
messageSpan.className = "message";
messageSpan.textContent = log.message;
item.appendChild(timeSpan);
item.appendChild(messageSpan);
// Prepend to top
list.insertBefore(item, list.firstChild);
// Limit history
if (list.children.length > 50) {
list.removeChild(list.lastChild);
}
}
ws.onclose = () => {
console.log("WS Disconnected");
if (statusIndicator) statusIndicator.classList.remove("online");

View File

@@ -65,4 +65,17 @@ export class WebServer {
this.server = null;
}
}
public static broadcastLog(type: string, message: string) {
if (this.server) {
this.server.publish("status-updates", JSON.stringify({
type: "LOG",
data: {
timestamp: new Date().toLocaleTimeString(),
type,
message
}
}));
}
}
}