diff --git a/html/js/office-render.js b/html/js/office-render.js index a8d690f..f5016c5 100644 --- a/html/js/office-render.js +++ b/html/js/office-render.js @@ -379,17 +379,34 @@ function renderKpiMonitor(frame, kpis) { return g; } - const rowH = (frame.h - 30) / tiles.length; - tiles.forEach((tile, index) => { - const rowY = frame.y + 20 + index * rowH; + // Die Zeilen stehen direkt untereinander, statt die Monitorhoehe gleichmaessig unter den + // Kacheln aufzuteilen: Zaehler-Kacheln wie "Agenten"/"Online" (Issue #39) und "Hooks" + // (Issue #38) haben history: [] und damit keine Sparkline - verteilt man die Hoehe trotzdem, + // klaffen zwischen den Werten grosse leere Sparkline-Kaesten. Ein Verlauf bekommt seinen + // Platz deshalb nur, wenn es ihn wirklich gibt. + const LABEL_HEIGHT = 20; + // Passt zur Punkteberechnung in buildKpiSparklinePoints() (Default-Hoehe 32) - so fuellt die + // Linie den Kasten genau aus. + const SPARKLINE_HEIGHT = 32; + const ROW_GAP = 4; + + let rowTop = frame.y + 20; + tiles.forEach((tile) => { g.appendChild( text(`${tile.label}: ${tile.currentValue ?? "–"} ${tile.unit}`.trim(), { x: frame.x + 16, - y: rowY + 14, + y: rowTop + 14, class: "kpi-tile-label", }) ); - g.appendChild(renderSparkline(tile.sparklinePoints, frame.w - 32, rowH - 26, frame.x + 16, rowY + 20)); + rowTop += LABEL_HEIGHT; + + if (tile.sparklinePoints) { + g.appendChild(renderSparkline(tile.sparklinePoints, frame.w - 32, SPARKLINE_HEIGHT, frame.x + 16, rowTop)); + rowTop += SPARKLINE_HEIGHT; + } + + rowTop += ROW_GAP; }); return g;