fix(dashboard): enhance live activity formatting, add empty state placeholder, and add API unit tests

This commit is contained in:
Riz Ashraf committed 2026-10-05 13:05:08 +01:00
1 parent 19f9c7ace7
commit da3700d1d5
3 files changed
+164 -21

No files matched your search

+64 -10
View File
@@ -344,8 +344,40 @@ function parseActivityPayload(item) {
return parseActivityPayload(item.params);
}
category = (item.category || item.type || "TOOL").toUpperCase();
summary = item.summary || item.message || item.description || item.data || "";
details = item.details || "";
let rawSum = item.summary || item.message || item.description || item.data;
if (rawSum !== undefined && rawSum !== null) {
if (typeof rawSum === "object") {
summary = JSON.stringify(rawSum);
} else {
summary = String(rawSum);
}
}
if (!summary) {
if (item.title)
summary = String(item.title);
else if (item.name)
summary = String(item.name);
else if (item.action)
summary = String(item.action);
else if (item.content)
summary = String(item.content);
else {
const { timestamp: _t, time: _tm, updated_at: _u, category: _c, type: _tp, method: _m, params: _p, jsonrpc: _j, ...rest } = item;
if (Object.keys(rest).length > 0) {
summary = JSON.stringify(rest);
} else {
summary = JSON.stringify(item);
}
}
}
let rawDet = item.details;
if (rawDet !== undefined && rawDet !== null) {
if (typeof rawDet === "object") {
details = JSON.stringify(rawDet);
} else {
details = String(rawDet);
}
}
timestamp = item.timestamp || item.time || item.updated_at || timestamp;
if (typeof timestamp === "number" && timestamp < 10000000000) {
timestamp = timestamp * 1000;
@@ -356,15 +388,23 @@ function parseActivityPayload(item) {
GRAPH: "#2ecc71",
DECISION: "#f39c12",
CODE: "#3498db",
CODE_CHANGE: "#3498db",
TASK: "#1abc9c",
TASK_CREATE: "#1abc9c",
TASK_UPDATE: "#1abc9c",
CLIPBOARD: "#9b59b6",
STICKY_NOTE: "#e67e22",
CHECKPOINT: "#e74c3c",
ERROR_FIX: "#e74c3c",
TECH_DEBT: "#d35400",
SUBAGENT: "#8e44ad",
AGENT_SIGNAL: "#8e44ad",
SNIPPET: "#16a085",
TOOL: "#3498db",
EDITOR: "#9b59b6",
TERMINAL: "#27ae60",
SNAPSHOT: "#f1c40f",
NAMESPACE: "#e67e22",
SYSTEM: "#95a5a6"
};
const badgeColor = colorMap[catUpper] || "#3498db";
@@ -391,6 +431,10 @@ async function loadActivityHistory() {
if (!feed)
return;
feed.innerHTML = "";
if (!history || history.length === 0) {
feed.innerHTML = '<div style="padding:40px 20px; color:#a4b0be; text-align:center; font-family:sans-serif;">No recent activity recorded yet.<br/><span style="font-size:0.85em; opacity:0.8;">Live activity will stream here in real-time as MCP tools and system events execute.</span></div>';
return;
}
const getMillis = (item) => {
if (!item)
return 0;
@@ -427,18 +471,23 @@ async function loadActivityHistory() {
function setupWS() {
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
const ws = new WebSocket(`${protocol}//${location.host}/ws?client=ui`);
const feed = document.getElementById("activity-feed");
ws.onmessage = function(event) {
try {
const data = JSON.parse(event.data);
if (data.type === "activity" || data.method === "notifications/activity" || data.method === "notifications/task/completed" || data.method === "notifications/resources/updated") {
refreshActiveTab();
const isScrolledToTop = feed ? feed.scrollTop <= 20 : true;
const div = document.createElement("div");
div.className = "feed-entry";
const payload = data.params || data.data || data;
div.innerHTML = parseActivityPayload(payload);
if (currentTabId !== "activity-tab") {
refreshActiveTab();
}
const feed = document.getElementById("activity-feed");
if (feed) {
if (feed.querySelector(".feed-entry") === null) {
feed.innerHTML = "";
}
const isScrolledToTop = feed.scrollTop <= 20;
const div = document.createElement("div");
div.className = "feed-entry";
const payload = data.params || data.data || data;
div.innerHTML = parseActivityPayload(payload);
feed.prepend(div);
while (feed.children.length > MAX_ACTIVITY_HISTORY && feed.lastChild) {
feed.removeChild(feed.lastChild);
@@ -619,9 +668,14 @@ function setupSSE() {
sse.onmessage = function(event) {
if (event.data) {
try {
refreshActiveTab();
if (currentTabId !== "activity-tab") {
refreshActiveTab();
}
const feed = document.getElementById("activity-feed");
if (feed) {
if (feed.querySelector(".feed-entry") === null) {
feed.innerHTML = "";
}
const isScrolledToTop = feed.scrollTop <= 20;
const div = document.createElement("div");
div.className = "feed-entry";