Skip to content

Commit 32d97af

Browse files
committed
fix(webapp): use stable chart bucket timestamps
1 parent beba646 commit 32d97af

3 files changed

Lines changed: 16 additions & 12 deletions

File tree

apps/webapp/app/components/metrics/MiniLineChart.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export type MiniLineChartProps = {
4444
throttled?: number[];
4545
/** Tooltip wording for the overlay buckets. Null omits the overlay line. */
4646
overlayLabel?: string | null;
47-
/** Epoch ms of the first bucket's start. When omitted, the last bucket is anchored to now. */
47+
/** Epoch ms of the first bucket's start. */
4848
bucketStartMs?: number;
4949
/** Width of each bucket in ms. Defaults to one hour. */
5050
bucketIntervalMs?: number;
@@ -92,7 +92,12 @@ export function MiniLineChart({
9292
showPeak = true,
9393
}: MiniLineChartProps) {
9494
const hasPeakOverride = peakOverride !== undefined;
95-
if (!data || data.length === 0 || (data.every((v) => v === 0) && !hasPeakOverride)) {
95+
if (
96+
!data ||
97+
data.length === 0 ||
98+
bucketStartMs === undefined ||
99+
(data.every((v) => v === 0) && !hasPeakOverride)
100+
) {
96101
return <span className="text-text-dimmed"></span>;
97102
}
98103

@@ -103,11 +108,9 @@ export function MiniLineChart({
103108
const max = Math.max(...data);
104109
const peak = peakOverride ?? max;
105110

106-
// Map each bucket to a dated point so the tooltip can show the window it represents. Buckets are
107-
// `intervalMs` wide; if the caller didn't pass the first bucket's start, anchor the last bucket to
108-
// now (hourly default).
111+
// Map each bucket to a dated point so the tooltip can show the window it represents.
109112
const intervalMs = bucketIntervalMs ?? 3600_000;
110-
const startMs = bucketStartMs ?? Date.now() - (data.length - 1) * intervalMs;
113+
const startMs = bucketStartMs;
111114
const chartData: MiniLineChartDatum[] = data.map((count, i) => {
112115
const t = throttled?.[i] ?? 0;
113116
// Extend the mask one bucket forward (a segment needs both endpoints non-null), so even a

apps/webapp/app/components/primitives/UsageSparkline.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ type UnitLabel = { singular: string; plural: string };
1919
export type UsageSparklineProps = {
2020
/** Equal-width time buckets, oldest first. */
2121
data?: number[];
22-
/** Epoch ms of the first bucket's start. When omitted, the last bucket is anchored to now. */
23-
bucketStartMs?: number;
22+
/** Epoch ms of the first bucket's start. */
23+
bucketStartMs: number;
2424
/** Width of each bucket in ms. Defaults to one hour. */
2525
bucketIntervalMs?: number;
2626
/** Bar colour. Defaults to blue. */
@@ -64,11 +64,9 @@ export function UsageSparkline({
6464
const total = totalOverride ?? data.reduce((a, b) => a + b, 0);
6565
const max = Math.max(...data);
6666

67-
// Map each bucket to a dated point so the tooltip can show the window it
68-
// represents. Buckets are `intervalMs` wide; if the caller didn't pass the
69-
// first bucket's start, anchor the last bucket to now (hourly default).
67+
// Map each bucket to a dated point so the tooltip can show the window it represents.
7068
const intervalMs = bucketIntervalMs ?? 3600_000;
71-
const startMs = bucketStartMs ?? Date.now() - (data.length - 1) * intervalMs;
69+
const startMs = bucketStartMs;
7270
const chartData: UsageDatum[] = data.map((count, i) => ({
7371
date: new Date(startMs + i * intervalMs),
7472
count,

apps/webapp/app/routes/storybook.charts/route.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import SegmentedControl from "~/components/primitives/SegmentedControl";
2121
// Date formatters for chart display
2222
const xAxisTickFormatter = (value: string) => formatISODate(value);
2323
const tooltipLabelFormatter = (label: string) => formatISODateLong(label);
24+
const MINI_LINE_BUCKET_START_MS = Date.UTC(2025, 0, 1);
2425

2526
/**
2627
* Helper function to filter chart data by date range.
@@ -361,6 +362,7 @@ function ChartsDashboard() {
361362
<td className="py-1.5">
362363
<MiniLineChart
363364
data={API_DATA.miniLineData}
365+
bucketStartMs={MINI_LINE_BUCKET_START_MS}
364366
peak={Math.max(...API_DATA.miniLineData)}
365367
unitLabel={{ singular: "queued", plural: "queued" }}
366368
color="var(--color-tasks)"
@@ -372,6 +374,7 @@ function ChartsDashboard() {
372374
<td className="py-1.5">
373375
<MiniLineChart
374376
data={API_DATA.miniLineThrottledData}
377+
bucketStartMs={MINI_LINE_BUCKET_START_MS}
375378
throttled={API_DATA.miniLineThrottledBuckets}
376379
peak={Math.max(...API_DATA.miniLineThrottledData)}
377380
unitLabel={{ singular: "queued", plural: "queued" }}

0 commit comments

Comments
 (0)