Identified by automated analysis of ARTESCA-17128
Confidence: high
What needs to change
File: @artesca/ui/src/components/system-health-monitoring/overview/long-term-metrics/LongTermCapacityChart.tsx
Fix 1 — Blinking Legend (in scality/artesca):
Add keepPreviousData: true (React Query v3) or placeholderData: keepPreviousData (React Query v5) to both useGetPrometheusQueryRange and useGetPrometheusQuery hooks. This ensures that when the query key changes (e.g., endTimestamp updates), the previous data remains available during the refetch, preventing isSuccess from transitioning to false and series from becoming [].
In useGetPrometheusQueryRange.ts:
return useQuery<PrometheusQueryResult>({
queryKey: [query, startTimestamp, endTimestamp, step],
queryFn: async () => { ... },
keepPreviousData: true, // ADD THIS
...
});
In useGetPrometheusQuery.ts:
return useQuery<PrometheusQueryResult>({
queryKey: ['prometheus-instant', query, timestamp],
queryFn: async () => { ... },
keepPreviousData: true, // ADD THIS
...
});
Additionally, in LongTermCapacityChart.tsx, the series useMemo guard should be relaxed to also keep the previous series data while loading:
const series = useMemo(() => {
if (!isSuccessAggregatedData && !aggregatedData.length) { // Change || to &&
return [];
}
// ... rest of the series building logic
}, [...]);
Fix 2 — Tooltip Cursor (in scality/core-ui):
In src/lib/components/iconhelper/IconHelper.tsx, change cursor: pointer to cursor: default in the HelpButton styled component:
const HelpButton = styled.button`
...
cursor: default; // Was: cursor: pointer
...
`;
Root Cause
Two related bugs exist in the long-term metrics chart:
Bug 1 — Blinking Legend: In LongTermCapacityChart.tsx, the series useMemo (line 96-98) returns an empty array [] when !isSuccessAggregatedData || !aggregatedData.length. When the component remounts (e.g., navigating away and back, or any parent re-render causing remount), a new endTimestamp is computed via Math.floor(new Date().getTime() / 1000) (line 47). This creates a new React Query cache key [query, startTimestamp, endTimestamp, step] in useGetPrometheusQueryRange, causing React Query to treat it as a fresh query — transitioning isSuccess from true to false momentarily. During this transition, series becomes [], which causes the useChartData hook in core-ui to switch from real data lines (key: "Net capacity-0") to empty placeholder lines (key: "empty-Net capacity"), forcing Recharts to unmount/remount <Line> components — producing the visible blink. The root issue is that keepPreviousData is not used in the React Query hooks, so stale data is discarded during refetches.
Bug 2 — Wrong cursor on tooltip icon: The helpText prop on LineTimeSerieChart renders an IconHelp component from @scality/core-ui. The HelpButton styled component in IconHelper.tsx (line 26) sets cursor: pointer, giving the informational tooltip icon an "action" cursor. Since this icon only shows a tooltip and is not clickable/actionable, it should use cursor: default or cursor: help.
Evidence
@artesca/ui/src/components/system-health-monitoring/overview/long-term-metrics/LongTermCapacityChart.tsx
├── L96: const series = useMemo(() => { ... — When isSuccessAggregatedData transitions to false during a refetch (new query key), series becomes []. This empties the chart legend and forces Recharts to unmount/remount Line components, causing the visible blink.
└── L46: const timestamps = useMemo(() => { ... — endTimestamp is computed from Date.now() inside useMemo. On component remount, a new endTimestamp value is generated, which changes the React Query cache key and triggers a fresh fetch (losing cached data).
@artesca/ui/src/hooks/prometheus/useGetPrometheusQueryRange.ts
└── L22: return useQuery<PrometheusQueryResult>({ ... — The queryKey includes endTimestamp. A new endTimestamp creates a new cache key, causing React Query to start a fresh fetch. Without keepPreviousData, the previous data is discarded and isSuccess becomes false during the fetch.
@artesca/ui/src/hooks/long-terms-metrics/useAggregatedPrometheusData.ts
└── L101: return { ... — isSuccess is directly tied to the range query's success state. When a new query key triggers a fresh fetch, isSuccessRange becomes false, propagating up to LongTermCapacityChart where it causes series to return [].
@artesca/ui/src/hooks/prometheus/useGetPrometheusQuery.ts
└── L15: return useQuery<PrometheusQueryResult>({ ... — The instant query also includes the timestamp (endTimestamp) in its query key, so it also triggers a fresh fetch when endTimestamp changes, contributing to the loading state flash.
Upstream Impact
Medium severity. The blinking chart legend is a visual regression that affects the user experience on the main overview/dashboard page. Every time a user navigates to or revisits the System Health Monitoring overview, the chart legend may flash/blink momentarily. The incorrect cursor on the tooltip icon is a minor UI polish issue but contributes to a perception of inconsistency. Both bugs affect all users viewing the long-term metrics chart.
What needs to change
File:
@artesca/ui/src/components/system-health-monitoring/overview/long-term-metrics/LongTermCapacityChart.tsxFix 1 — Blinking Legend (in scality/artesca):
Add
keepPreviousData: true(React Query v3) orplaceholderData: keepPreviousData(React Query v5) to bothuseGetPrometheusQueryRangeanduseGetPrometheusQueryhooks. This ensures that when the query key changes (e.g., endTimestamp updates), the previous data remains available during the refetch, preventingisSuccessfrom transitioning tofalseandseriesfrom becoming[].In
useGetPrometheusQueryRange.ts:In
useGetPrometheusQuery.ts:Additionally, in
LongTermCapacityChart.tsx, theseriesuseMemo guard should be relaxed to also keep the previous series data while loading:Fix 2 — Tooltip Cursor (in scality/core-ui):
In
src/lib/components/iconhelper/IconHelper.tsx, changecursor: pointertocursor: defaultin theHelpButtonstyled component:Root Cause
Two related bugs exist in the long-term metrics chart:
Bug 1 — Blinking Legend: In
LongTermCapacityChart.tsx, theseriesuseMemo (line 96-98) returns an empty array[]when!isSuccessAggregatedData || !aggregatedData.length. When the component remounts (e.g., navigating away and back, or any parent re-render causing remount), a newendTimestampis computed viaMath.floor(new Date().getTime() / 1000)(line 47). This creates a new React Query cache key[query, startTimestamp, endTimestamp, step]inuseGetPrometheusQueryRange, causing React Query to treat it as a fresh query — transitioningisSuccessfromtruetofalsemomentarily. During this transition,seriesbecomes[], which causes theuseChartDatahook in core-ui to switch from real data lines (key: "Net capacity-0") to empty placeholder lines (key: "empty-Net capacity"), forcing Recharts to unmount/remount<Line>components — producing the visible blink. The root issue is thatkeepPreviousDatais not used in the React Query hooks, so stale data is discarded during refetches.Bug 2 — Wrong cursor on tooltip icon: The
helpTextprop onLineTimeSerieChartrenders anIconHelpcomponent from@scality/core-ui. TheHelpButtonstyled component inIconHelper.tsx(line 26) setscursor: pointer, giving the informational tooltip icon an "action" cursor. Since this icon only shows a tooltip and is not clickable/actionable, it should usecursor: defaultorcursor: help.Evidence
Upstream Impact
Medium severity. The blinking chart legend is a visual regression that affects the user experience on the main overview/dashboard page. Every time a user navigates to or revisits the System Health Monitoring overview, the chart legend may flash/blink momentarily. The incorrect cursor on the tooltip icon is a minor UI polish issue but contributes to a perception of inconsistency. Both bugs affect all users viewing the long-term metrics chart.