@@ -15,6 +15,7 @@ import { aggregateValues } from "../primitives/charts/aggregation";
1515import { MAX_SERIES } from "~/components/primitives/charts/seriesFromRows" ;
1616import { getRunStatusChartColor } from "~/components/runs/v3/TaskRunStatus" ;
1717import { getSeriesColor } from "./chartColors" ;
18+ import { safeChartColor } from "../primitives/charts/chartColors" ;
1819
1920const MAX_SVG_ELEMENT_BUDGET = 6_000 ;
2021const MIN_DATA_POINTS = 100 ;
@@ -287,10 +288,10 @@ function fillTimeGaps(
287288 __rawDate : bucket . rawDate ,
288289 __granularity : granularity ,
289290 __originalX : bucket . originalX ,
291+ ...Object . fromEntries (
292+ series . map ( ( s ) => [ s , aggregateValues ( bucket . values [ s ] , aggregation ) ] )
293+ ) ,
290294 } ;
291- for ( const s of series ) {
292- point [ s ] = aggregateValues ( bucket . values [ s ] , aggregation ) ;
293- }
294295 filledData . push ( point ) ;
295296 } else {
296297 // Create a null-filled data point so gaps appear in line/bar charts
@@ -300,10 +301,8 @@ function fillTimeGaps(
300301 __rawDate : new Date ( t ) ,
301302 __granularity : granularity ,
302303 __originalX : new Date ( t ) . toISOString ( ) ,
304+ ...Object . fromEntries ( series . map ( ( s ) => [ s , null ] ) ) ,
303305 } ;
304- for ( const s of series ) {
305- gapPoint [ s ] = null ;
306- }
307306 filledData . push ( gapPoint ) ;
308307 }
309308 }
@@ -591,10 +590,10 @@ function transformDataForChart(
591590 __rawDate : rawDate ,
592591 __granularity : granularity ,
593592 __originalX : originalX ,
593+ ...Object . fromEntries (
594+ yAxisColumns . map ( ( col ) => [ col , aggregateValues ( yValues [ col ] , aggregation ) ] )
595+ ) ,
594596 } ;
595- for ( const yCol of yAxisColumns ) {
596- point [ yCol ] = aggregateValues ( yValues [ yCol ] , aggregation ) ;
597- }
598597 return point ;
599598 } ) ;
600599
@@ -652,7 +651,7 @@ function transformDataForChart(
652651 const groupTotals = new Map < string , number > ( ) ;
653652 const groupedByX = new Map <
654653 string | number ,
655- { values : Record < string , number [ ] > ; rawDate : Date | null ; originalX : unknown }
654+ { values : Map < string , number [ ] > ; rawDate : Date | null ; originalX : unknown }
656655 > ( ) ;
657656
658657 for ( const row of rows ) {
@@ -667,14 +666,14 @@ function transformDataForChart(
667666 groupTotals . set ( groupValue , ( groupTotals . get ( groupValue ) ?? 0 ) + Math . abs ( yValue ) ) ;
668667
669668 if ( ! groupedByX . has ( xKey ) ) {
670- groupedByX . set ( xKey , { values : { } , rawDate, originalX : row [ xAxisColumn ] } ) ;
669+ groupedByX . set ( xKey , { values : new Map ( ) , rawDate, originalX : row [ xAxisColumn ] } ) ;
671670 }
672671
673672 const existing = groupedByX . get ( xKey ) ! ;
674- if ( ! existing . values [ groupValue ] ) {
675- existing . values [ groupValue ] = [ ] ;
673+ if ( ! existing . values . has ( groupValue ) ) {
674+ existing . values . set ( groupValue , [ ] ) ;
676675 }
677- existing . values [ groupValue ] . push ( yValue ) ;
676+ existing . values . get ( groupValue ) ! . push ( yValue ) ;
678677 }
679678
680679 // Keep only the top MAX_SERIES groups by absolute total to avoid O(n) processing
@@ -697,10 +696,13 @@ function transformDataForChart(
697696 __rawDate : rawDate ,
698697 __granularity : granularity ,
699698 __originalX : originalX ,
699+ ...Object . fromEntries (
700+ series . map ( ( group ) => {
701+ const groupValues = values . get ( group ) ;
702+ return [ group , groupValues ? aggregateValues ( groupValues , aggregation ) : 0 ] ;
703+ } )
704+ ) ,
700705 } ;
701- for ( const group of series ) {
702- point [ group ] = values [ group ] ? aggregateValues ( values [ group ] , aggregation ) : 0 ;
703- }
704706 return point ;
705707 } ) ;
706708
@@ -936,20 +938,34 @@ export const QueryResultsChart = memo(function QueryResultsChart({
936938 return col ?. customRenderType === "runStatus" ;
937939 } , [ groupByColumn , columns ] ) ;
938940
939- // Build chart config for colors/labels
940- const chartConfig = useMemo ( ( ) => {
941- const cfg : ChartConfig = { } ;
942- sortedSeries . forEach ( ( s , i ) => {
943- const statusColor = groupByIsRunStatus ? getRunStatusChartColor ( s ) : undefined ;
944- const originalIndex = config . yAxisColumns . indexOf ( s ) ;
945- const colorIndex = originalIndex >= 0 ? originalIndex : i ;
946- cfg [ s ] = {
947- label : s ,
948- color : statusColor ?? config . seriesColors ?. [ s ] ?? getSeriesColor ( colorIndex ) ,
949- } ;
950- } ) ;
951- return cfg ;
952- } , [ sortedSeries , groupByIsRunStatus , config . seriesColors , config . yAxisColumns ] ) ;
941+ // Keep data-derived names in labels, never in chart identifiers or CSS variable names.
942+ const { chartConfig, chartData, chartSeries } = useMemo ( ( ) => {
943+ const chartSeries = sortedSeries . map ( ( _ , i ) => `series-${ i } ` ) ;
944+ const chartConfig : ChartConfig = Object . fromEntries (
945+ sortedSeries . map ( ( s , i ) => {
946+ const statusColor = groupByIsRunStatus ? getRunStatusChartColor ( s ) : undefined ;
947+ const originalIndex = config . yAxisColumns . indexOf ( s ) ;
948+ const colorIndex = originalIndex >= 0 ? originalIndex : i ;
949+ return [
950+ chartSeries [ i ] ,
951+ {
952+ label : s ,
953+ color :
954+ statusColor ?? safeChartColor ( config . seriesColors ?. [ s ] ) ?? getSeriesColor ( colorIndex ) ,
955+ } ,
956+ ] ;
957+ } )
958+ ) ;
959+ const chartData = data . map ( ( point ) => ( {
960+ ...Object . fromEntries ( sortedSeries . map ( ( s , i ) => [ chartSeries [ i ] , point [ s ] ] ) ) ,
961+ __chartX : point [ xDataKey ] ,
962+ __rawDate : point . __rawDate ,
963+ __granularity : point . __granularity ,
964+ __originalX : point . __originalX ,
965+ } ) ) ;
966+ return { chartConfig, chartData, chartSeries } ;
967+ } , [ sortedSeries , data , xDataKey , groupByIsRunStatus , config . seriesColors , config . yAxisColumns ] ) ;
968+ const chartVisibleSeries = chartSeries . slice ( 0 , visibleSeries . length ) ;
953969
954970 // Custom tooltip label formatter for better date display
955971 const tooltipLabelFormatter = useMemo ( ( ) => {
@@ -1182,10 +1198,10 @@ export const QueryResultsChart = memo(function QueryResultsChart({
11821198 < div ref = { chartMeasureRef } className = "h-full w-full" >
11831199 < Chart . Root
11841200 config = { chartConfig }
1185- data = { data }
1186- dataKey = { xDataKey }
1187- series = { sortedSeries }
1188- visibleSeries = { visibleSeries }
1201+ data = { chartData }
1202+ dataKey = "__chartX"
1203+ series = { chartSeries }
1204+ visibleSeries = { chartVisibleSeries }
11891205 labelFormatter = { legendLabelFormatter }
11901206 showLegend = { showLegend }
11911207 maxLegendItems = { fullLegend ? Infinity : 5 }
@@ -1215,10 +1231,10 @@ export const QueryResultsChart = memo(function QueryResultsChart({
12151231 < div ref = { chartMeasureRef } className = "h-full w-full" >
12161232 < Chart . Root
12171233 config = { chartConfig }
1218- data = { data }
1219- dataKey = { xDataKey }
1220- series = { sortedSeries }
1221- visibleSeries = { visibleSeries }
1234+ data = { chartData }
1235+ dataKey = "__chartX"
1236+ series = { chartSeries }
1237+ visibleSeries = { chartVisibleSeries }
12221238 labelFormatter = { legendLabelFormatter }
12231239 showLegend = { showLegend }
12241240 maxLegendItems = { fullLegend ? Infinity : 5 }
0 commit comments