Skip to content

Commit ed9d9d4

Browse files
committed
feat(time-pivot): limit the overlay to the N most recent periods
A long daily history pivoted weekly overlays a hundred-plus series at once; the new Number of periods control keeps only the N most recent, clamped between 1 and the periods present in the data, with empty keeping them all. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f373e98 commit ed9d9d4

5 files changed

Lines changed: 49 additions & 4 deletions

File tree

superset-frontend/plugins/plugin-chart-echarts/src/TimePivot/controlPanel.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ const config: ControlPanelConfig = {
7171
},
7272
},
7373
],
74+
[
75+
{
76+
name: 'period_limit',
77+
config: {
78+
type: 'TextControl',
79+
isInt: true,
80+
label: t('Number of periods'),
81+
renderTrigger: true,
82+
default: '',
83+
description: t(
84+
'Show only the N most recent periods, from 1 up to the number ' +
85+
'of periods in the data. Leave empty to overlay them all.',
86+
),
87+
},
88+
},
89+
],
7490
],
7591
},
7692
{

superset-frontend/plugins/plugin-chart-echarts/src/TimePivot/transformData.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export default function transformData(
109109
records: Record<string, unknown>[],
110110
metricLabel: string,
111111
freq: string,
112+
periodLimit?: number,
112113
): TimePivotSeries[] {
113114
const rows = records
114115
.filter(record => record[DTTM_ALIAS] != null)
@@ -124,9 +125,13 @@ export default function transformData(
124125
return [];
125126
}
126127

127-
const periods = Array.from(new Set(rows.map(row => row.period))).sort(
128-
(a, b) => b - a,
129-
);
128+
const periods = Array.from(new Set(rows.map(row => row.period)))
129+
.sort((a, b) => b - a)
130+
.slice(
131+
0,
132+
// clamp to [1, available periods]; undefined keeps them all
133+
periodLimit && periodLimit > 0 ? Math.floor(periodLimit) : undefined,
134+
);
130135
const maxPeriod = periods[0];
131136
const rankOf = new Map(periods.map((period, index) => [period, index]));
132137
const maxRank = periods.length - 1;
@@ -137,6 +142,9 @@ export default function transformData(
137142
const values = new Map<string, Map<number, number | null>>();
138143
const shiftedTimestamps = new Set<number>();
139144
rows.forEach(({ timestamp, period, value }) => {
145+
if (!rankOf.has(period)) {
146+
return; // period dropped by the limit
147+
}
140148
const series = seriesOf(rankOf.get(period)!);
141149
const shifted = timestamp + (maxPeriod - period);
142150
shiftedTimestamps.add(shifted);

superset-frontend/plugins/plugin-chart-echarts/src/TimePivot/transformProps.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export default function transformProps(
4141
const {
4242
metric,
4343
freq,
44+
periodLimit,
4445
colorPicker,
4546
showLegend,
4647
lineInterpolation,
@@ -57,7 +58,12 @@ export default function transformProps(
5758
const metricLabel = getMetricLabel(metric ?? '');
5859
const records = (queriesData[0]?.data ?? []) as Record<string, unknown>[];
5960
const series: TimePivotSeries[] = Array.isArray(records)
60-
? transformData(records, metricLabel, (freq as string) || 'W-MON')
61+
? transformData(
62+
records,
63+
metricLabel,
64+
(freq as string) || 'W-MON',
65+
periodLimit ? Number(periodLimit) : undefined,
66+
)
6167
: [];
6268

6369
const { r, g, b } = colorPicker ?? DEFAULT_COLOR;

superset-frontend/plugins/plugin-chart-echarts/src/TimePivot/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export type EchartsTimePivotFormData = QueryFormData & {
2727
metric?: QueryFormMetric;
2828
/** pandas-style period offset, e.g. W-MON, D, AS */
2929
freq?: string;
30+
/** keep only the N most recent periods; empty keeps all */
31+
periodLimit?: number | string;
3032
colorPicker?: { r: number; g: number; b: number; a: number };
3133
showLegend?: boolean;
3234
lineInterpolation?: string;

superset-frontend/plugins/plugin-chart-echarts/test/TimePivot/transformData.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,16 @@ describe('TimePivot transformData', () => {
9393
expect(transformData([], 'sum__num', 'W-MON')).toEqual([]);
9494
});
9595
});
96+
97+
test('limits to the N most recent periods, clamped to what exists', () => {
98+
const WEEK = 7 * 24 * 3600 * 1000;
99+
const M1 = 1578268800000;
100+
const records = [0, 1, 2, 3].map(i => ({
101+
__timestamp: M1 + i * WEEK,
102+
m: 10 + i,
103+
}));
104+
const limited = transformData(records, 'm', 'W-MON', 2);
105+
expect(limited.map(s => s.key).sort()).toEqual(['-1', 'current']);
106+
// clamped: asking for more than available keeps them all
107+
expect(transformData(records, 'm', 'W-MON', 99)).toHaveLength(4);
108+
});

0 commit comments

Comments
 (0)