11import type { Interpolation , Theme } from "@emotion/react" ;
22import type { TimingStage } from "api/typesGenerated" ;
3+ import { T } from "lodash/fp" ;
34import { CircleAlertIcon , InfoIcon } from "lucide-react" ;
45import type { FC } from "react" ;
56import { Bar , ClickableBar } from "./Chart/Bar" ;
@@ -52,7 +53,7 @@ export type Stage = {
5253tooltip :Omit < TooltipProps , "children" > ;
5354} ;
5455
55- type StageTiming = {
56+ export type StageTiming = {
5657stage :Stage ;
5758/**
5859 * Represents the number of resources included in this stage that can be
@@ -65,7 +66,7 @@ type StageTiming = {
6566 * duration of the stage and to position the stage within the chart. This can
6667 * be undefined if a stage has no timing data.
6768 */
68- range :TimeRange | undefined ;
69+ ranges :TimeRange [ ] | undefined ;
6970/**
7071 * Display an error icon within the bar to indicate when a stage has failed.
7172 * This is used in the agent scripts stage.
@@ -83,7 +84,10 @@ export const StagesChart: FC<StagesChartProps> = ({
8384onSelectStage,
8485} ) => {
8586const totalRange = mergeTimeRanges (
86- timings . map ( ( t ) => t . range ) . filter ( ( t ) => t !== undefined ) ,
87+ timings
88+ . map ( ( t ) => t . ranges )
89+ . filter ( ( t ) => t !== undefined )
90+ . flat ( ) ,
8791) ;
8892const totalTime = calcDuration ( totalRange ) ;
8993const [ ticks , scale ] = makeTicks ( totalTime ) ;
@@ -129,11 +133,12 @@ export const StagesChart: FC<StagesChartProps> = ({
129133const stageTimings = timings . filter (
130134( t ) => t . stage . section === section ,
131135) ;
136+
132137return (
133138< XAxisSection key = { section } >
134139{ stageTimings . map ( ( t ) => {
135140// If the stage has no timing data, we just want to render an empty row
136- if ( t . range === undefined ) {
141+ if ( t . ranges === undefined ) {
137142return (
138143< XAxisRow
139144key = { t . stage . name }
@@ -142,53 +147,55 @@ export const StagesChart: FC<StagesChartProps> = ({
142147) ;
143148}
144149
145- const value = calcDuration ( t . range ) ;
146- const offset = calcOffset ( t . range , totalRange ) ;
147- const validDuration = value > 0 && ! Number . isNaN ( value ) ;
150+ return t . ranges ?. map ( ( range , index ) => {
151+ const value = calcDuration ( range ) ;
152+ const offset = calcOffset ( range , totalRange ) ;
153+ const validDuration = value > 0 && ! Number . isNaN ( value ) ;
148154
149- return (
150- < XAxisRow
151- key = { t . stage . name }
152- yAxisLabelId = { encodeURIComponent ( t . stage . name ) }
153- >
154- { /** We only want to expand stages with more than one resource */ }
155- { t . visibleResources > 1 ?(
156- < ClickableBar
157- aria-label = { `View${ t . stage . label } details` }
158- scale = { scale }
159- value = { value }
160- offset = { offset }
161- onClick = { ( ) => {
162- onSelectStage ( t . stage ) ;
163- } }
164- >
165- { t . error && (
166- < CircleAlertIcon
167- className = "size-icon-sm"
168- css = { {
169- color :"#F87171" ,
170- marginRight :4 ,
171- } }
172- />
173- ) }
174- < Blocks count = { t . visibleResources } />
175- </ ClickableBar >
176- ) :(
177- < Bar scale = { scale } value = { value } offset = { offset } />
178- ) }
179- { validDuration ?(
180- < span > { formatTime ( value ) } </ span >
181- ) :(
182- < span
183- css = { ( theme ) => ( {
184- color :theme . palette . error . main ,
185- } ) }
186- >
187- Invalid
188- </ span >
189- ) }
190- </ XAxisRow >
191- ) ;
155+ return (
156+ < XAxisRow
157+ key = { t . stage . name + index }
158+ yAxisLabelId = { encodeURIComponent ( t . stage . name ) }
159+ >
160+ { /** We only want to expand stages with more than one resource */ }
161+ { t . visibleResources > 1 ?(
162+ < ClickableBar
163+ aria-label = { `View${ t . stage . label } details` }
164+ scale = { scale }
165+ value = { value }
166+ offset = { offset }
167+ onClick = { ( ) => {
168+ onSelectStage ( t . stage ) ;
169+ } }
170+ >
171+ { t . error && (
172+ < CircleAlertIcon
173+ className = "size-icon-sm"
174+ css = { {
175+ color :"#F87171" ,
176+ marginRight :4 ,
177+ } }
178+ />
179+ ) }
180+ < Blocks count = { t . visibleResources } />
181+ </ ClickableBar >
182+ ) :(
183+ < Bar scale = { scale } value = { value } offset = { offset } />
184+ ) }
185+ { validDuration ?(
186+ < span > { formatTime ( value ) } </ span >
187+ ) :(
188+ < span
189+ css = { ( theme ) => ( {
190+ color :theme . palette . error . main ,
191+ } ) }
192+ >
193+ Invalid
194+ </ span >
195+ ) }
196+ </ XAxisRow >
197+ ) ;
198+ } ) ;
192199} ) }
193200</ XAxisSection >
194201) ;