@@ -29,7 +29,7 @@ import {
29
29
RUN_STATUS_STOPPED ,
30
30
RUN_STATUS_SUCCEEDED ,
31
31
} from '@opentrons/api-client'
32
- import { useAllCommandsQuery } from '@opentrons/react-api-client'
32
+ import { useAllCommandsQuery , useRunQuery } from '@opentrons/react-api-client'
33
33
34
34
import { NAV_BAR_WIDTH } from '../../../App/constants'
35
35
import { PrimaryButton } from '../../../atoms/buttons'
@@ -48,12 +48,13 @@ import { StepItem } from './StepItem'
48
48
import type { RunCommandSummary } from '@opentrons/api-client'
49
49
import type { RunTimeCommand , CommandStatus } from '@opentrons/shared-data'
50
50
51
- const AVERAGE_ITEM_HEIGHT_PX = 52 // average px height of a command item
51
+ const AVERAGE_ITEM_HEIGHT_PX = 56 // average px height of a command item
52
52
const WINDOW_OVERLAP = 40 // number of command items that fall within two adjacent windows
53
53
const NUM_EAGER_ITEMS = 5 // number of command items away from the end of the current window that will trigger a window transition if scrolled into view
54
54
const COMMANDS_REFETCH_INTERVAL = 3000
55
55
const AVERAGE_WINDOW_HEIGHT_PX =
56
56
( RUN_LOG_WINDOW_SIZE - WINDOW_OVERLAP ) * AVERAGE_ITEM_HEIGHT_PX
57
+ const NON_COMMAND_BUFFER_PX = 118 // px height of a the area below and above the windowed command items, but within the scrolled div
57
58
interface CommandRuntimeInfo {
58
59
analysisCommand : RunTimeCommand | null // analysisCommand will only be null if protocol is nondeterministic
59
60
runCommandSummary : RunCommandSummary | null
@@ -90,6 +91,8 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
90
91
firstPostInitialPlayRunCommandIndex . current != null
91
92
? firstPostInitialPlayRunCommandIndex . current
92
93
: 0
94
+ const isCurrentRun =
95
+ useRunQuery ( runId , { staleTime : Infinity } ) . data ?. data . current ?? false
93
96
const { data : commandsData } = useAllCommandsQuery (
94
97
runId ,
95
98
{
@@ -108,10 +111,9 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
108
111
commandsData ?. links ?. current ?. meta ?. createdAt ?? null
109
112
const runTotalCommandCount = commandsData ?. meta ?. totalLength
110
113
111
- const [
112
- isInitiallyJumpingToCurrent ,
113
- setIsInitiallyJumpingToCurrent ,
114
- ] = React . useState < boolean > ( false )
114
+ const [ isJumpingToCurrent , setIsJumpingToCurrent ] = React . useState < boolean > (
115
+ false
116
+ )
115
117
116
118
const analysisCommandsWithStatus =
117
119
protocolData ?. commands != null
@@ -181,7 +183,7 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
181
183
windowFirstCommandIndex ,
182
184
windowFirstCommandIndex + RUN_LOG_WINDOW_SIZE
183
185
)
184
- const isFirstWindow = windowIndex === 0
186
+
185
187
const isFinalWindow =
186
188
currentCommandList . length <= windowFirstCommandIndex + RUN_LOG_WINDOW_SIZE
187
189
@@ -248,18 +250,23 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
248
250
( RUN_LOG_WINDOW_SIZE - WINDOW_OVERLAP )
249
251
)
250
252
251
- // when we initially mount, if the current item is not in view, jump to it
252
- React . useEffect ( ( ) => {
253
+ const jumpToCurrentCommandWindow = ( ) : void => {
253
254
if (
254
255
indexOfFirstWindowContainingCurrentCommand !== windowIndex &&
255
256
indexOfLastWindowContainingCurrentCommand !== windowIndex
256
257
) {
257
258
const targetWindow = isCurrentCommandInFinalWindow
258
259
? indexOfFirstWindowContainingCurrentCommand
259
260
: indexOfLastWindowContainingCurrentCommand
261
+
260
262
setWindowIndex ( Math . max ( targetWindow , 0 ) )
261
263
}
262
- setIsInitiallyJumpingToCurrent ( true )
264
+ setIsJumpingToCurrent ( true )
265
+ }
266
+
267
+ // when we initially mount, jump to current command window
268
+ React . useEffect ( ( ) => {
269
+ jumpToCurrentCommandWindow ( )
263
270
} , [ ] )
264
271
265
272
const scrollToCurrentItem = ( ) : void => {
@@ -269,14 +276,14 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
269
276
// if jumping to current item and on correct window index, scroll to current item
270
277
React . useEffect ( ( ) => {
271
278
if (
272
- isInitiallyJumpingToCurrent &&
279
+ isJumpingToCurrent &&
273
280
( windowIndex === indexOfFirstWindowContainingCurrentCommand ||
274
281
windowIndex === indexOfLastWindowContainingCurrentCommand )
275
282
) {
276
283
scrollToCurrentItem ( )
277
- setIsInitiallyJumpingToCurrent ( false )
284
+ setIsJumpingToCurrent ( false )
278
285
}
279
- } , [ windowIndex , isInitiallyJumpingToCurrent ] )
286
+ } , [ windowIndex , isJumpingToCurrent ] )
280
287
281
288
if ( protocolData == null || runStatus == null ) return null
282
289
@@ -327,15 +334,17 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
327
334
setShowDownloadRunLogToast ( true )
328
335
}
329
336
330
- const isRunStarted = currentItemRef . current != null
331
-
332
- // check if edges of current step are below or above window
333
337
const isCurrentStepBelow =
334
- currentItemRef . current ?. getBoundingClientRect ( ) . top != null &&
335
- currentItemRef . current ?. getBoundingClientRect ( ) . top > window . innerHeight
338
+ ( currentItemRef . current ?. getBoundingClientRect ( ) . top != null &&
339
+ listInnerRef . current ?. getBoundingClientRect ( ) . bottom != null &&
340
+ currentItemRef . current ?. getBoundingClientRect ( ) . top >
341
+ listInnerRef . current ?. getBoundingClientRect ( ) . bottom ) ||
342
+ windowIndex < indexOfFirstWindowContainingCurrentCommand
336
343
const isCurrentStepAbove =
337
- currentItemRef . current ?. getBoundingClientRect ( ) . bottom != null &&
338
- currentItemRef . current ?. getBoundingClientRect ( ) . bottom < 0
344
+ ( currentItemRef . current ?. getBoundingClientRect ( ) . bottom != null &&
345
+ currentItemRef . current ?. getBoundingClientRect ( ) . bottom <
346
+ NON_COMMAND_BUFFER_PX ) ||
347
+ windowIndex > indexOfLastWindowContainingCurrentCommand
339
348
340
349
const jumpToCurrentStepButton = (
341
350
< PrimaryButton
@@ -345,11 +354,11 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
345
354
transform = "translate(-50%)"
346
355
borderRadius = { SPACING . spacing6 }
347
356
display = {
348
- isRunStarted && ( isCurrentStepBelow || isCurrentStepAbove )
357
+ isCurrentRun && ( isCurrentStepBelow || isCurrentStepAbove )
349
358
? DISPLAY_FLEX
350
359
: DISPLAY_NONE
351
360
}
352
- onClick = { scrollToCurrentItem }
361
+ onClick = { jumpToCurrentCommandWindow }
353
362
id = "RunLog_jumpToCurrentStep"
354
363
>
355
364
< Icon
@@ -377,43 +386,39 @@ export function RunLog({ robotName, runId }: RunLogProps): JSX.Element | null {
377
386
/>
378
387
) : null }
379
388
{ jumpToCurrentStepButton }
380
- { isFirstWindow ? (
381
- < >
382
- < Flex
383
- justifyContent = { JUSTIFY_SPACE_BETWEEN }
384
- alignItems = { ALIGN_CENTER }
385
- borderBottom = { BORDERS . lineBorder }
386
- padding = { SPACING . spacing4 }
389
+ < Flex
390
+ justifyContent = { JUSTIFY_SPACE_BETWEEN }
391
+ alignItems = { ALIGN_CENTER }
392
+ borderBottom = { BORDERS . lineBorder }
393
+ padding = { SPACING . spacing4 }
394
+ >
395
+ < Flex alignItems = { ALIGN_CENTER } >
396
+ < StyledText
397
+ marginRight = { SPACING . spacing3 }
398
+ css = { TYPOGRAPHY . h3SemiBold }
399
+ textTransform = { TEXT_TRANSFORM_CAPITALIZE }
387
400
>
388
- < Flex alignItems = { ALIGN_CENTER } >
389
- < StyledText
390
- marginRight = { SPACING . spacing3 }
391
- css = { TYPOGRAPHY . h3SemiBold }
392
- textTransform = { TEXT_TRANSFORM_CAPITALIZE }
393
- >
394
- { t ( 'run_log' ) }
395
- </ StyledText >
396
- < StyledText
397
- as = "label"
398
- color = { COLORS . darkGreyEnabled }
399
- id = "RunLog_totalStepCount"
400
- >
401
- { isDeterministic
402
- ? t ( 'total_step_count' , { count : currentCommandList . length } )
403
- : t ( 'unable_to_determine_steps' ) }
404
- </ StyledText >
405
- </ Flex >
406
- < Btn
407
- color = { COLORS . darkGreyEnabled }
408
- css = { TYPOGRAPHY . labelSemiBold }
409
- onClick = { onClickDownloadRunLog }
410
- id = "RunLog_downloadRunLog"
411
- >
412
- { t ( 'download_run_log' ) }
413
- </ Btn >
414
- </ Flex >
415
- </ >
416
- ) : null }
401
+ { t ( 'run_log' ) }
402
+ </ StyledText >
403
+ < StyledText
404
+ as = "label"
405
+ color = { COLORS . darkGreyEnabled }
406
+ id = "RunLog_totalStepCount"
407
+ >
408
+ { isDeterministic
409
+ ? t ( 'total_step_count' , { count : currentCommandList . length } )
410
+ : t ( 'unable_to_determine_steps' ) }
411
+ </ StyledText >
412
+ </ Flex >
413
+ < Btn
414
+ color = { COLORS . darkGreyEnabled }
415
+ css = { TYPOGRAPHY . labelSemiBold }
416
+ onClick = { onClickDownloadRunLog }
417
+ id = "RunLog_downloadRunLog"
418
+ >
419
+ { t ( 'download_run_log' ) }
420
+ </ Btn >
421
+ </ Flex >
417
422
< Flex
418
423
flexDirection = { DIRECTION_COLUMN }
419
424
padding = { SPACING . spacing4 }
0 commit comments