Skip to content

Commit fd9954b

Browse files
HanSur94claude
andcommitted
feat(dashboard): register all 6 new widget types in engine, serializer, and bridge
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 835d776 commit fd9954b

3 files changed

Lines changed: 138 additions & 0 deletions

File tree

bridge/web/js/widgets.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ var Widgets = (function () {
1717
case "text": return renderText(config, bodyEl);
1818
case "timeline": return renderTimeline(config, bodyEl);
1919
case "rawaxes": return renderRawAxes(config, bodyEl);
20+
case "heatmap": return renderHeatmap(config, bodyEl);
21+
case "barchart": return renderBarChart(config, bodyEl);
22+
case "histogram":return renderHistogram(config, bodyEl);
23+
case "scatter": return renderScatter(config, bodyEl);
24+
case "image": return renderImage(config, bodyEl);
25+
case "multistatus": return renderMultiStatus(config, bodyEl);
2026
default:
2127
bodyEl.textContent = "Unknown widget type: " + type;
2228
}
@@ -229,6 +235,92 @@ var Widgets = (function () {
229235
'</div>';
230236
}
231237

238+
/* --- Heatmap ------------------------------------------- */
239+
function renderHeatmap(cfg, el) {
240+
el.innerHTML = '<div class="placeholder-widget">' +
241+
'<div class="icon">&#x1F7E5;</div>' +
242+
'<div class="label">Heatmap: ' + (cfg.title || '') + '</div>' +
243+
'</div>';
244+
}
245+
246+
/* --- Bar Chart ----------------------------------------- */
247+
function renderBarChart(cfg, el) {
248+
el.innerHTML = '<div class="placeholder-widget">' +
249+
'<div class="icon">&#x1F4CA;</div>' +
250+
'<div class="label">Bar Chart: ' + (cfg.title || '') + '</div>' +
251+
'</div>';
252+
}
253+
254+
/* --- Histogram ----------------------------------------- */
255+
function renderHistogram(cfg, el) {
256+
el.innerHTML = '<div class="placeholder-widget">' +
257+
'<div class="icon">&#x1F4C8;</div>' +
258+
'<div class="label">Histogram: ' + (cfg.title || '') + '</div>' +
259+
'</div>';
260+
}
261+
262+
/* --- Scatter ------------------------------------------- */
263+
function renderScatter(cfg, el) {
264+
el.innerHTML = '<div class="placeholder-widget">' +
265+
'<div class="icon">&#x2022;</div>' +
266+
'<div class="label">Scatter: ' + (cfg.title || '') + '</div>' +
267+
'</div>';
268+
}
269+
270+
/* --- Image --------------------------------------------- */
271+
function renderImage(cfg, el) {
272+
if (cfg.file) {
273+
var img = document.createElement("img");
274+
img.src = cfg.file;
275+
img.alt = cfg.title || "Image";
276+
img.style.maxWidth = "100%";
277+
img.style.maxHeight = "100%";
278+
img.style.objectFit = "contain";
279+
el.appendChild(img);
280+
} else {
281+
el.innerHTML = '<div class="placeholder-widget">' +
282+
'<div class="icon">&#x1F5BC;</div>' +
283+
'<div class="label">Image: ' + (cfg.title || '') + '</div>' +
284+
'</div>';
285+
}
286+
}
287+
288+
/* --- Multi-Status -------------------------------------- */
289+
function renderMultiStatus(cfg, el) {
290+
var items = cfg.items || [];
291+
if (items.length === 0) {
292+
el.innerHTML = '<div class="placeholder-widget">' +
293+
'<div class="label">Multi-Status: ' + (cfg.title || '') + '</div>' +
294+
'</div>';
295+
return;
296+
}
297+
var grid = document.createElement("div");
298+
grid.style.display = "grid";
299+
grid.style.gridTemplateColumns = "repeat(auto-fill, minmax(80px, 1fr))";
300+
grid.style.gap = "6px";
301+
grid.style.padding = "8px";
302+
for (var i = 0; i < items.length; i++) {
303+
var item = items[i];
304+
var cell = document.createElement("div");
305+
cell.style.display = "flex";
306+
cell.style.alignItems = "center";
307+
cell.style.gap = "4px";
308+
var dot = document.createElement("span");
309+
dot.style.width = "10px";
310+
dot.style.height = "10px";
311+
dot.style.borderRadius = "50%";
312+
dot.style.display = "inline-block";
313+
dot.style.backgroundColor = item.color || "#888";
314+
cell.appendChild(dot);
315+
var lbl = document.createElement("span");
316+
lbl.style.fontSize = "0.8em";
317+
lbl.textContent = item.label || "";
318+
cell.appendChild(lbl);
319+
grid.appendChild(cell);
320+
}
321+
el.appendChild(grid);
322+
}
323+
232324
/* --- helpers ------------------------------------------- */
233325
function formatNumber(v) {
234326
if (v == null) return "--";

libs/Dashboard/DashboardEngine.m

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ function addWidget(obj, type, varargin)
9090
'Timeline widget "%s" has no data source. Bind via EventStoreObj.', ...
9191
w.Title);
9292
end
93+
case 'heatmap'
94+
w = HeatmapWidget(varargin{:});
95+
case 'barchart'
96+
w = BarChartWidget(varargin{:});
97+
case 'histogram'
98+
w = HistogramWidget(varargin{:});
99+
case 'scatter'
100+
w = ScatterWidget(varargin{:});
101+
case 'image'
102+
w = ImageWidget(varargin{:});
103+
case 'multistatus'
104+
w = MultiStatusWidget(varargin{:});
93105
otherwise
94106
error('DashboardEngine:unknownType', ...
95107
'Unknown widget type: %s', type);
@@ -563,6 +575,12 @@ function onLiveTick(obj)
563575
'text', 'Static text block (TextWidget)'
564576
'timeline', 'Event timeline display (EventTimelineWidget)'
565577
'rawaxes', 'Raw MATLAB axes for custom plotting (RawAxesWidget)'
578+
'heatmap', 'Heatmap color grid (HeatmapWidget)'
579+
'barchart', 'Bar chart for categories (BarChartWidget)'
580+
'histogram', 'Value distribution histogram (HistogramWidget)'
581+
'scatter', 'X vs Y scatter plot (ScatterWidget)'
582+
'image', 'Static image display (ImageWidget)'
583+
'multistatus', 'Multi-sensor status grid (MultiStatusWidget)'
566584
};
567585
end
568586

libs/Dashboard/DashboardSerializer.m

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,18 @@ function save(config, filepath)
9494
widgets{i} = RawAxesWidget.fromStruct(ws);
9595
case 'timeline'
9696
widgets{i} = EventTimelineWidget.fromStruct(ws);
97+
case 'heatmap'
98+
widgets{i} = HeatmapWidget.fromStruct(ws);
99+
case 'barchart'
100+
widgets{i} = BarChartWidget.fromStruct(ws);
101+
case 'histogram'
102+
widgets{i} = HistogramWidget.fromStruct(ws);
103+
case 'scatter'
104+
widgets{i} = ScatterWidget.fromStruct(ws);
105+
case 'image'
106+
widgets{i} = ImageWidget.fromStruct(ws);
107+
case 'multistatus'
108+
widgets{i} = MultiStatusWidget.fromStruct(ws);
97109
otherwise
98110
warning('DashboardSerializer:unknownType', ...
99111
'Unknown widget type: %s — skipping', ws.type);
@@ -217,6 +229,22 @@ function exportScript(config, filepath)
217229
end
218230
end
219231
lines{end+1} = [line, ');'];
232+
case 'heatmap'
233+
lines{end+1} = sprintf('d.addWidget(''heatmap'', ''Title'', ''%s'', ''Position'', %s);', ws.title, pos);
234+
case 'barchart'
235+
lines{end+1} = sprintf('d.addWidget(''barchart'', ''Title'', ''%s'', ''Position'', %s);', ws.title, pos);
236+
case 'histogram'
237+
lines{end+1} = sprintf('d.addWidget(''histogram'', ''Title'', ''%s'', ''Position'', %s);', ws.title, pos);
238+
case 'scatter'
239+
lines{end+1} = sprintf('d.addWidget(''scatter'', ''Title'', ''%s'', ''Position'', %s);', ws.title, pos);
240+
case 'image'
241+
line = sprintf('d.addWidget(''image'', ''Title'', ''%s'', ''Position'', %s', ws.title, pos);
242+
if isfield(ws, 'file') && ~isempty(ws.file)
243+
line = [line, sprintf(', ...\n ''File'', ''%s''', ws.file)];
244+
end
245+
lines{end+1} = [line, ');'];
246+
case 'multistatus'
247+
lines{end+1} = sprintf('d.addWidget(''multistatus'', ''Title'', ''%s'', ''Position'', %s);', ws.title, pos);
220248
otherwise
221249
lines{end+1} = sprintf('d.addWidget(''%s'', ''Title'', ''%s'', ''Position'', %s);', ws.type, ws.title, pos);
222250
end

0 commit comments

Comments
 (0)