@@ -12,6 +12,7 @@ import {
12
12
DISPLAY_FLEX ,
13
13
DISPLAY_NONE ,
14
14
Flex ,
15
+ InfoScreen ,
15
16
POSITION_FIXED ,
16
17
PrimaryButton ,
17
18
SPACING ,
@@ -58,17 +59,19 @@ export const RunPreviewComponent = (
58
59
? ( RUN_STATUSES_TERMINAL as RunStatus [ ] ) . includes ( runStatus )
59
60
: false
60
61
// 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 (
62
66
runId ,
63
67
{ cursor : 0 , pageLength : MAX_COMMANDS } ,
64
68
{
65
69
staleTime : Infinity ,
66
70
cacheTime : Infinity ,
67
71
enabled : isRunTerminal ,
68
72
}
69
- ) . data ?. data
70
- const nullCheckedCommandsFromQuery =
71
- commandsFromQuery == null ? robotSideAnalysis ?. commands : commandsFromQuery
73
+ )
74
+ const commandsFromQuery = commandsFromQueryResponse ?. data
72
75
const viewPortRef = React . useRef < HTMLDivElement | null > ( null )
73
76
const currentRunCommandKey = useNotifyLastRunCommand ( runId , {
74
77
refetchInterval : LIVE_RUN_COMMANDS_POLL_MS ,
@@ -78,10 +81,9 @@ export const RunPreviewComponent = (
78
81
setIsCurrentCommandVisible ,
79
82
] = React . useState < boolean > ( true )
80
83
if ( robotSideAnalysis == null ) return null
81
- const commands =
82
- ( isRunTerminal
83
- ? nullCheckedCommandsFromQuery
84
- : robotSideAnalysis . commands ) ?? [ ]
84
+ const commands = isRunTerminal
85
+ ? commandsFromQuery
86
+ : robotSideAnalysis . commands
85
87
// pass relevant data from run rather than analysis so that CommandText utilities can properly hash the entities' IDs
86
88
// TODO (nd:05/02/2024, AUTH-380): update name and types for CommandText (and children/utilities) use of analysis.
87
89
// We should ideally pass only subset of analysis/run data required by these children and utilities
@@ -93,14 +95,28 @@ export const RunPreviewComponent = (
93
95
modules : runRecord . data . modules ?? [ ] ,
94
96
pipettes : runRecord . data . pipettes ?? [ ] ,
95
97
liquids : runRecord . data . liquids ?? [ ] ,
96
- commands : commands ,
98
+ commands : commands ?? [ ] ,
97
99
}
98
100
: 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
102
105
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
+ ) : (
104
120
< Flex
105
121
ref = { viewPortRef }
106
122
flexDirection = { DIRECTION_COLUMN }
@@ -110,99 +126,101 @@ export const RunPreviewComponent = (
110
126
gridGap = { SPACING . spacing8 }
111
127
padding = { SPACING . spacing16 }
112
128
>
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' ) }
119
140
</ 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 (
158
164
< 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 }
172
168
>
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 >
181
199
</ Flex >
182
200
</ 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
+ </ >
206
224
</ Flex >
207
225
)
208
226
}
0 commit comments