Skip to content

Commit caa200d

Browse files
authored
Merge pull request #4259 from yancat160/feat/persist-hidden-events-across-range
fix: keep hidden events hidden across date-range changes
2 parents 1dda7bd + 84fe25a commit caa200d

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

src/components/charts/Chart.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export interface ChartProps extends BoxProps {
1818
updateMode?: UpdateMode;
1919
animationDuration?: number;
2020
onTooltip?: (model: any) => void;
21+
hiddenLabels?: Set<string>;
22+
onLegendClick?: (label: string, willBeHidden: boolean) => void;
2123
}
2224

2325
export function Chart({
@@ -27,6 +29,8 @@ export function Chart({
2729
updateMode,
2830
onTooltip,
2931
chartOptions,
32+
hiddenLabels,
33+
onLegendClick,
3034
...props
3135
}: ChartProps) {
3236
const canvas = useRef(null);
@@ -61,6 +65,15 @@ export function Chart({
6165
}, [chartOptions]);
6266

6367
const handleLegendClick = (item: LegendItem) => {
68+
if (onLegendClick && type === 'bar') {
69+
// Controlled mode: caller owns the hidden state. We report the click
70+
// and let the parent push a new hiddenLabels set on the next render.
71+
const { datasetIndex } = item;
72+
const ds = chart.current.data.datasets[datasetIndex];
73+
onLegendClick(ds.label, !hiddenLabels?.has(ds.label));
74+
return;
75+
}
76+
6477
if (type === 'bar') {
6578
const { datasetIndex } = item;
6679
const meta = chart.current.getDatasetMeta(datasetIndex);
@@ -111,13 +124,28 @@ export function Chart({
111124
});
112125
}
113126

127+
// Re-apply caller-driven hidden flags after focusLabel handling so a
128+
// dataset stays hidden across data changes (e.g. date-range switches)
129+
// even though Chart.js regenerates dataset meta on every replace.
130+
if (hiddenLabels) {
131+
chart.current.data.datasets.forEach((ds: { hidden: boolean; label: any }) => {
132+
if (hiddenLabels.has(ds.label)) {
133+
ds.hidden = true;
134+
} else if (!chartData.focusLabel) {
135+
// Explicitly reset so un-hiding a label is always reflected,
136+
// regardless of whether the focusLabel pass ran above.
137+
ds.hidden = false;
138+
}
139+
});
140+
}
141+
114142
chart.current.options = options;
115143

116144
chart.current.update(updateMode);
117145

118146
setLegendItems(chart.current.legend.legendItems);
119147
}
120-
}, [chartData, options, updateMode]);
148+
}, [chartData, options, updateMode, hiddenLabels]);
121149

122150
return (
123151
<Column gap="6">

src/components/metrics/EventsChart.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ export function EventsChart({ websiteId, focusLabel, limit }: EventsChartProps)
2727
const { locale, dateLocale } = useLocale();
2828
const { data, isLoading, error } = useWebsiteEventsSeriesQuery(websiteId, { limit });
2929
const [label, setLabel] = useState<string>(focusLabel);
30+
const [hiddenLabels, setHiddenLabels] = useState<Set<string>>(() => new Set());
31+
32+
const handleLegendClick = useCallback((legendLabel: string, willBeHidden: boolean) => {
33+
setHiddenLabels(prev => {
34+
const next = new Set(prev);
35+
if (willBeHidden) next.add(legendLabel);
36+
else next.delete(legendLabel);
37+
return next;
38+
});
39+
}, []);
3040

3141
const chartData: any = useMemo(() => {
3242
if (!data) return;
@@ -115,6 +125,8 @@ export function EventsChart({ websiteId, focusLabel, limit }: EventsChartProps)
115125
stacked={true}
116126
renderXLabel={renderXLabel}
117127
height="400px"
128+
hiddenLabels={hiddenLabels}
129+
onLegendClick={handleLegendClick}
118130
/>
119131
)}
120132
</LoadingPanel>

0 commit comments

Comments
 (0)