@@ -12,6 +12,7 @@ import {
1212 DISPLAY_FLEX ,
1313 DISPLAY_NONE ,
1414 Flex ,
15+ InfoScreen ,
1516 POSITION_FIXED ,
1617 PrimaryButton ,
1718 SPACING ,
@@ -58,17 +59,19 @@ export const RunPreviewComponent = (
5859 ? ( RUN_STATUSES_TERMINAL as RunStatus [ ] ) . includes ( runStatus )
5960 : false
6061 // we only ever want one request done for terminal runs because this is a heavy request
61- const commandsFromQuery = useNotifyAllCommandsAsPreSerializedList (
62+ const {
63+ data : commandsFromQueryResponse ,
64+ isLoading : isRunCommandDataLoading ,
65+ } = useNotifyAllCommandsAsPreSerializedList (
6266 runId ,
6367 { cursor : 0 , pageLength : MAX_COMMANDS } ,
6468 {
6569 staleTime : Infinity ,
6670 cacheTime : Infinity ,
6771 enabled : isRunTerminal ,
6872 }
69- ) . data ?. data
70- const nullCheckedCommandsFromQuery =
71- commandsFromQuery == null ? robotSideAnalysis ?. commands : commandsFromQuery
73+ )
74+ const commandsFromQuery = commandsFromQueryResponse ?. data
7275 const viewPortRef = React . useRef < HTMLDivElement | null > ( null )
7376 const currentRunCommandKey = useNotifyLastRunCommand ( runId , {
7477 refetchInterval : LIVE_RUN_COMMANDS_POLL_MS ,
@@ -78,10 +81,9 @@ export const RunPreviewComponent = (
7881 setIsCurrentCommandVisible ,
7982 ] = React . useState < boolean > ( true )
8083 if ( robotSideAnalysis == null ) return null
81- const commands =
82- ( isRunTerminal
83- ? nullCheckedCommandsFromQuery
84- : robotSideAnalysis . commands ) ?? [ ]
84+ const commands = isRunTerminal
85+ ? commandsFromQuery
86+ : robotSideAnalysis . commands
8587 // pass relevant data from run rather than analysis so that CommandText utilities can properly hash the entities' IDs
8688 // TODO (nd:05/02/2024, AUTH-380): update name and types for CommandText (and children/utilities) use of analysis.
8789 // We should ideally pass only subset of analysis/run data required by these children and utilities
@@ -93,14 +95,28 @@ export const RunPreviewComponent = (
9395 modules : runRecord . data . modules ?? [ ] ,
9496 pipettes : runRecord . data . pipettes ?? [ ] ,
9597 liquids : runRecord . data . liquids ?? [ ] ,
96- commands : commands ,
98+ commands : commands ?? [ ] ,
9799 }
98100 : robotSideAnalysis
99- const currentRunCommandIndex = commands . findIndex (
100- c => c . key === currentRunCommandKey
101- )
101+ const currentRunCommandIndex =
102+ commands != null
103+ ? commands . findIndex ( c => c . key === currentRunCommandKey )
104+ : 0
102105
103- return (
106+ if ( isRunCommandDataLoading || commands == null ) {
107+ return (
108+ < Flex flexDirection = { DIRECTION_COLUMN } padding = { SPACING . spacing16 } >
109+ < StyledText alignSelf = { ALIGN_CENTER } color = { COLORS . grey50 } >
110+ { t ( 'protocol_setup:loading_data' ) }
111+ </ StyledText >
112+ </ Flex >
113+ )
114+ }
115+ return commands . length === 0 ? (
116+ < Flex flexDirection = { DIRECTION_COLUMN } padding = { SPACING . spacing16 } >
117+ < InfoScreen contentType = "runNotStarted" />
118+ </ Flex >
119+ ) : (
104120 < Flex
105121 ref = { viewPortRef }
106122 flexDirection = { DIRECTION_COLUMN }
@@ -110,99 +126,101 @@ export const RunPreviewComponent = (
110126 gridGap = { SPACING . spacing8 }
111127 padding = { SPACING . spacing16 }
112128 >
113- < Flex gridGap = { SPACING . spacing8 } alignItems = { ALIGN_CENTER } >
114- < StyledText as = "h3" fontWeight = { TYPOGRAPHY . fontWeightSemiBold } >
115- { t ( 'run_preview' ) }
116- </ StyledText >
117- < StyledText as = "label" color = { COLORS . grey50 } >
118- { t ( 'steps_total' , { count : commands . length } ) }
129+ < >
130+ < Flex gridGap = { SPACING . spacing8 } alignItems = { ALIGN_CENTER } >
131+ < StyledText as = "h3" fontWeight = { TYPOGRAPHY . fontWeightSemiBold } >
132+ { t ( 'run_preview' ) }
133+ </ StyledText >
134+ < StyledText as = "label" color = { COLORS . grey50 } >
135+ { t ( 'steps_total' , { count : commands . length } ) }
136+ </ StyledText >
137+ </ Flex >
138+ < StyledText as = "p" marginBottom = { SPACING . spacing8 } >
139+ { t ( 'preview_of_protocol_steps' ) }
119140 </ StyledText >
120- </ Flex >
121- < StyledText as = "p" marginBottom = { SPACING . spacing8 } >
122- { t ( 'preview_of_protocol_steps' ) }
123- </ StyledText >
124- < Divider marginX = { `calc(-1 * ${ SPACING . spacing16 } )` } />
125- < ViewportList
126- viewportRef = { viewPortRef }
127- ref = { ref }
128- items = { commands }
129- onViewportIndexesChange = { ( [
130- lowestVisibleIndex ,
131- highestVisibleIndex ,
132- ] ) => {
133- if ( currentRunCommandIndex >= 0 ) {
134- setIsCurrentCommandVisible (
135- currentRunCommandIndex >= lowestVisibleIndex &&
136- currentRunCommandIndex <= highestVisibleIndex
137- )
138- }
139- } }
140- initialIndex = { currentRunCommandIndex }
141- >
142- { ( command , index ) => {
143- const isCurrent = index === currentRunCommandIndex
144- const backgroundColor = isCurrent ? COLORS . blue30 : COLORS . grey20
145- const iconColor = isCurrent ? COLORS . blue60 : COLORS . grey50
146- return (
147- < Flex
148- key = { command . id }
149- alignItems = { ALIGN_CENTER }
150- gridGap = { SPACING . spacing8 }
151- >
152- < StyledText
153- minWidth = { SPACING . spacing16 }
154- fontSize = { TYPOGRAPHY . fontSizeCaption }
155- >
156- { index + 1 }
157- </ StyledText >
141+ < Divider marginX = { `calc(-1 * ${ SPACING . spacing16 } )` } />
142+ < ViewportList
143+ viewportRef = { viewPortRef }
144+ ref = { ref }
145+ items = { commands }
146+ onViewportIndexesChange = { ( [
147+ lowestVisibleIndex ,
148+ highestVisibleIndex ,
149+ ] ) => {
150+ if ( currentRunCommandIndex >= 0 ) {
151+ setIsCurrentCommandVisible (
152+ currentRunCommandIndex >= lowestVisibleIndex &&
153+ currentRunCommandIndex <= highestVisibleIndex
154+ )
155+ }
156+ } }
157+ initialIndex = { currentRunCommandIndex }
158+ >
159+ { ( command , index ) => {
160+ const isCurrent = index === currentRunCommandIndex
161+ const backgroundColor = isCurrent ? COLORS . blue30 : COLORS . grey20
162+ const iconColor = isCurrent ? COLORS . blue60 : COLORS . grey50
163+ return (
158164 < Flex
159- flexDirection = { DIRECTION_COLUMN }
160- gridGap = { SPACING . spacing4 }
161- width = "100%"
162- backgroundColor = {
163- index === jumpedIndex ? '#F5E3FF' : backgroundColor
164- }
165- color = { COLORS . black90 }
166- borderRadius = { BORDERS . borderRadius4 }
167- padding = { SPACING . spacing8 }
168- css = { css `
169- transition : background-color ${ COLOR_FADE_MS } ms ease-out,
170- border-color ${ COLOR_FADE_MS } ms ease-out;
171- ` }
165+ key = { command . id }
166+ alignItems = { ALIGN_CENTER }
167+ gridGap = { SPACING . spacing8 }
172168 >
173- < Flex alignItems = { ALIGN_CENTER } gridGap = { SPACING . spacing8 } >
174- < CommandIcon command = { command } color = { iconColor } />
175- < CommandText
176- command = { command }
177- robotSideAnalysis = { protocolDataFromAnalysisOrRun }
178- robotType = { robotType }
179- color = { COLORS . black90 }
180- />
169+ < StyledText
170+ minWidth = { SPACING . spacing16 }
171+ fontSize = { TYPOGRAPHY . fontSizeCaption }
172+ >
173+ { index + 1 }
174+ </ StyledText >
175+ < Flex
176+ flexDirection = { DIRECTION_COLUMN }
177+ gridGap = { SPACING . spacing4 }
178+ width = "100%"
179+ backgroundColor = {
180+ index === jumpedIndex ? '#F5E3FF' : backgroundColor
181+ }
182+ color = { COLORS . black90 }
183+ borderRadius = { BORDERS . borderRadius4 }
184+ padding = { SPACING . spacing8 }
185+ css = { css `
186+ transition : background-color ${ COLOR_FADE_MS } ms ease-out,
187+ border-color ${ COLOR_FADE_MS } ms ease-out;
188+ ` }
189+ >
190+ < Flex alignItems = { ALIGN_CENTER } gridGap = { SPACING . spacing8 } >
191+ < CommandIcon command = { command } color = { iconColor } />
192+ < CommandText
193+ command = { command }
194+ robotSideAnalysis = { protocolDataFromAnalysisOrRun }
195+ robotType = { robotType }
196+ color = { COLORS . black90 }
197+ />
198+ </ Flex >
181199 </ Flex >
182200 </ Flex >
183- </ Flex >
184- )
185- } }
186- </ ViewportList >
187- { currentRunCommandIndex >= 0 ? (
188- < PrimaryButton
189- position = { POSITION_FIXED }
190- bottom = { SPACING . spacing40 }
191- left = { `calc(calc(100% + ${ NAV_BAR_WIDTH } )/2)` } // add width of half of nav bar to center within run tab
192- transform = "translate(-50%)"
193- borderRadius = { SPACING . spacing32 }
194- display = { isCurrentCommandVisible ? DISPLAY_NONE : DISPLAY_FLEX }
195- onClick = { makeHandleScrollToStep ( currentRunCommandIndex ) }
196- id = "RunLog_jumpToCurrentStep"
197- >
198- { t ( 'view_current_step' ) }
199- </ PrimaryButton >
200- ) : null }
201- { currentRunCommandIndex === commands . length - 1 ? (
202- < StyledText as = "h6" color = { COLORS . grey60 } >
203- { t ( 'end_of_protocol' ) }
204- </ StyledText >
205- ) : null }
201+ )
202+ } }
203+ </ ViewportList >
204+ { currentRunCommandIndex >= 0 ? (
205+ < PrimaryButton
206+ position = { POSITION_FIXED }
207+ bottom = { SPACING . spacing40 }
208+ left = { `calc(calc(100% + ${ NAV_BAR_WIDTH } )/2)` } // add width of half of nav bar to center within run tab
209+ transform = "translate(-50%)"
210+ borderRadius = { SPACING . spacing32 }
211+ display = { isCurrentCommandVisible ? DISPLAY_NONE : DISPLAY_FLEX }
212+ onClick = { makeHandleScrollToStep ( currentRunCommandIndex ) }
213+ id = "RunLog_jumpToCurrentStep"
214+ >
215+ { t ( 'view_current_step' ) }
216+ </ PrimaryButton >
217+ ) : null }
218+ { currentRunCommandIndex === commands . length - 1 ? (
219+ < StyledText as = "h6" color = { COLORS . grey60 } >
220+ { t ( 'end_of_protocol' ) }
221+ </ StyledText >
222+ ) : null }
223+ </ >
206224 </ Flex >
207225 )
208226}
0 commit comments