From b9826e39753b9a2de64cbf0114760feeb6eb968b Mon Sep 17 00:00:00 2001 From: Jeremy Anderson Date: Wed, 25 Mar 2026 18:49:41 -0400 Subject: [PATCH] added LiveDAG --- cockpit/fester-module/targets.js | 144 +++++++++++++++---------------- cockpit/fester-module/ui.html | 143 ++++++++++++++++++++---------- 2 files changed, 171 insertions(+), 116 deletions(-) diff --git a/cockpit/fester-module/targets.js b/cockpit/fester-module/targets.js index ed49d7e..91be4ca 100644 --- a/cockpit/fester-module/targets.js +++ b/cockpit/fester-module/targets.js @@ -1,84 +1,84 @@ // cockpit/fester-module/targets.js -/** - * Fester Targets Module - * Handles nodes, edges, metrics, heatmaps, and live updates for cockpit UI. - */ +// State for available targets +let targets = []; -(function(global) { +// Fetch current targets from backend +async function fetchTargets() { + try { + const res = await fetch("/api/targets"); + targets = await res.json(); + renderTargets(); + } catch (err) { + console.error("Failed to fetch targets:", err); + } +} - const targetsModule = { - nodes: {}, - edges: [], - metrics: {}, - heatmaps: {}, - callbacks: [], +// Render target list in the sidebar +function renderTargets() { + let sidebar = document.getElementById("sidebar"); + let panel = document.getElementById("targets-panel"); + + if(!panel) { + panel = document.createElement("div"); + panel.id = "targets-panel"; + panel.className = "panel"; + sidebar.appendChild(panel); + } - /** - * Register a callback to receive updated DAG data - */ - onUpdate(callback) { - if (typeof callback === 'function') { - this.callbacks.push(callback); - } - }, + panel.innerHTML = "

Targets

"; - /** - * Update the internal state from WS or iframe message - */ - update(data) { - if (!data) return; + targets.forEach(target => { + const container = document.createElement("div"); + container.style.marginBottom = "5px"; - if (data.nodes) { - data.nodes.forEach(node => this.nodes[node.id] = node); - } - if (data.edges) { - this.edges = data.edges; - } - if (data.metrics) { - Object.assign(this.metrics, data.metrics); - } - if (data.heatmaps) { - Object.assign(this.heatmaps, data.heatmaps); - } + const checkbox = document.createElement("input"); + checkbox.type = "checkbox"; + checkbox.id = `target-${target.name}`; + checkbox.checked = target.enabled; + checkbox.addEventListener("change", () => toggleTarget(target.name, checkbox.checked)); - this.dispatch(); - }, + const label = document.createElement("label"); + label.htmlFor = checkbox.id; + label.innerText = target.name; - /** - * Notify all registered callbacks with the updated data - */ - dispatch() { - const snapshot = { - nodes: Object.values(this.nodes), - edges: this.edges, - metrics: this.metrics, - heatmaps: this.heatmaps - }; - this.callbacks.forEach(cb => cb(snapshot)); - }, - - /** - * Clear all stored DAG state - */ - clear() { - this.nodes = {}; - this.edges = []; - this.metrics = {}; - this.heatmaps = {}; - this.dispatch(); - } - }; - - // Listen for iframe messages from cockpit.html - window.addEventListener('message', (event) => { - const data = event.data; - if (data && typeof data === 'object') { - targetsModule.update(data); - } + container.appendChild(checkbox); + container.appendChild(label); + panel.appendChild(container); }); +} - // Expose module globally - global.FesterTargets = targetsModule; +// Enable/disable target via backend +async function toggleTarget(targetName, enabled) { + try { + const res = await fetch(`/api/targets/${targetName}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ enabled }) + }); + if (!res.ok) { + console.error("Failed to update target", targetName); + } else { + console.log(`Target ${targetName} set to ${enabled}`); + } + } catch (err) { + console.error("Error toggling target:", err); + } +} -})(window); +// WebSocket for live target state updates +const wsTargets = new WebSocket("ws://localhost:8080/ws-targets"); + +wsTargets.onmessage = (msg) => { + const event = JSON.parse(msg.data); + if (event.type === "target-update") { + const t = targets.find(t => t.name === event.data.name); + if (t) { + t.enabled = event.data.enabled; + renderTargets(); + } + } +}; + +// Initial fetch +fetchTargets(); diff --git a/cockpit/fester-module/ui.html b/cockpit/fester-module/ui.html index 2fbb02a..3fa2243 100644 --- a/cockpit/fester-module/ui.html +++ b/cockpit/fester-module/ui.html @@ -1,58 +1,113 @@ + + - - Fester Cockpit - - + +Fester Cockpit + + + + - -
-

Fester Cockpit

-
- -
-
Live DAG
-
Replay / Debugger
+ - +
+
+
+

Debugger

+
+ + + +
+
+

+    
+
- -