From de597f1d8b42f74b132c55a402148e4435fe8818 Mon Sep 17 00:00:00 2001 From: Carsten Rehfeld Date: Sun, 17 May 2026 01:12:10 +0200 Subject: [PATCH] =?UTF-8?q?fix(admin):=20clip=20rate=20chart=20at=20100%?= =?UTF-8?q?=20=E2=80=94=20SVG=20clipPath=20+=20data=20cap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two-layer fix: - SVG clipPath on plot area: path physically cannot escape chart bounds - Chart flush caps rpm at rateLimit: timing drift (two batches in one 5 s window) no longer causes visual overshoot Live label still shows true req/min and % including values > 100%. Co-Authored-By: Mira Rehfeld --- .../src/main/resources/META-INF/resources/admin.js | 10 ++++++++-- .../resources/templates/DashboardResource/global.html | 2 +- .../resources/templates/DashboardResource/sandbox.html | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apix-admin/src/main/resources/META-INF/resources/admin.js b/apix-admin/src/main/resources/META-INF/resources/admin.js index bc1b514..3ba56ec 100644 --- a/apix-admin/src/main/resources/META-INF/resources/admin.js +++ b/apix-admin/src/main/resources/META-INF/resources/admin.js @@ -185,7 +185,12 @@ var ly = yS(rateLimit); svg.append('line').attr('x1', ML).attr('x2', W).attr('y1', ly).attr('y2', ly).attr('class', 'rate-limit-line'); - var path = svg.append('path').attr('class', 'rate-area'); + // Clip path — area can never escape the plot region regardless of data spikes + var clipId = 'rc-' + sid.slice(0, 8); + svg.append('defs').append('clipPath').attr('id', clipId) + .append('rect').attr('x', ML).attr('y', 0).attr('width', W - ML).attr('height', CH); + + var path = svg.append('path').attr('class', 'rate-area').attr('clip-path', 'url(#' + clipId + ')'); function fmt(n) { return n >= 1e6 ? (n / 1e6).toFixed(1) + 'M' : n >= 1e3 ? (n / 1e3).toFixed(1) + 'k' : String(n); @@ -200,8 +205,9 @@ } // Chart bucket: flush accumulated delta every 5 s regardless of poll rate + // Cap at rateLimit so the area never visually exceeds 100% (live label shows true value) setInterval(function () { - var rpm = Math.round(accDelta * (60000 / CHART_TICK)); + var rpm = Math.min(Math.round(accDelta * (60000 / CHART_TICK)), rateLimit); buf.push(rpm); buf.shift(); path.attr('d', areaFn(buf)); accDelta = 0; diff --git a/apix-admin/src/main/resources/templates/DashboardResource/global.html b/apix-admin/src/main/resources/templates/DashboardResource/global.html index 71877df..85e9c7c 100644 --- a/apix-admin/src/main/resources/templates/DashboardResource/global.html +++ b/apix-admin/src/main/resources/templates/DashboardResource/global.html @@ -106,6 +106,6 @@ nav { - + diff --git a/apix-admin/src/main/resources/templates/DashboardResource/sandbox.html b/apix-admin/src/main/resources/templates/DashboardResource/sandbox.html index 3245ae5..2030b16 100644 --- a/apix-admin/src/main/resources/templates/DashboardResource/sandbox.html +++ b/apix-admin/src/main/resources/templates/DashboardResource/sandbox.html @@ -151,6 +151,6 @@ button.promote:hover { background: #2ea043; } - +