/** Dashboard: workspace controls rendering (buttons, tables, labels, displays, machines). */ import { esc } from './util.js'; import { addTrace } from './trace.js'; import { setDashboard } from './chat.js'; let _ws = null; export function setWs(ws) { _ws = ws; } export function dockControls(controls) { setDashboard(controls); // S3*: remember what's rendered const body = document.getElementById('workspace-body'); if (!body) return; body.innerHTML = ''; const container = document.createElement('div'); container.className = 'controls-container'; for (const ctrl of controls) { if (ctrl.type === 'button') { const btn = document.createElement('button'); btn.className = 'control-btn'; btn.textContent = ctrl.label; btn.onclick = () => { if (_ws && _ws.readyState === 1) { _ws.send(JSON.stringify({ type: 'action', action: ctrl.action, data: ctrl.payload || ctrl.data || {} })); addTrace('runtime', 'action', ctrl.action); } }; container.appendChild(btn); } else if (ctrl.type === 'table') { const table = document.createElement('table'); table.className = 'control-table'; if (ctrl.columns) { const thead = document.createElement('tr'); for (const col of ctrl.columns) { const th = document.createElement('th'); th.textContent = col; thead.appendChild(th); } table.appendChild(thead); } for (const row of (ctrl.data || [])) { const tr = document.createElement('tr'); if (Array.isArray(row)) { for (const cell of row) { const td = document.createElement('td'); td.textContent = cell; tr.appendChild(td); } } else if (typeof row === 'object') { for (const col of (ctrl.columns || Object.keys(row))) { const td = document.createElement('td'); td.textContent = row[col] ?? ''; tr.appendChild(td); } } table.appendChild(tr); } container.appendChild(table); } else if (ctrl.type === 'label') { const lbl = document.createElement('div'); lbl.className = 'control-label'; lbl.innerHTML = '' + esc(ctrl.text || '') + '' + esc(String(ctrl.value ?? '')) + ''; container.appendChild(lbl); } else if (ctrl.type === 'display') { const disp = document.createElement('div'); const dt = ctrl.display_type || 'text'; const style = ctrl.style ? ' display-' + ctrl.style : ''; disp.className = 'control-display display-' + dt + style; if (dt === 'progress') { const pct = Math.min(100, Math.max(0, Number(ctrl.value) || 0)); disp.innerHTML = '' + esc(ctrl.label) + '' + '
' + '' + pct + '%'; } else if (dt === 'status') { disp.innerHTML = '' + (ctrl.style === 'success' ? '\u2713' : ctrl.style === 'error' ? '\u2717' : '\u2139') + '' + '' + esc(ctrl.label) + ''; } else { disp.innerHTML = '' + esc(ctrl.label) + '' + (ctrl.value ? '' + esc(String(ctrl.value)) + '' : ''); } container.appendChild(disp); } } body.appendChild(container); } export function clearDashboard() { const body = document.getElementById('workspace-body'); if (body) body.innerHTML = ''; }