Skip to content

Commit 26929a2

Browse files
authored
fix(app): clone run with RTPs from HistoricalProtocolRun (#14959)
closes RQA-2601
1 parent daa51dd commit 26929a2

File tree

19 files changed

+201
-65
lines changed

19 files changed

+201
-65
lines changed

api-client/src/runs/constants.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {
2+
RUN_STATUS_FAILED,
3+
RUN_STATUS_STOPPED,
4+
RUN_STATUS_SUCCEEDED,
5+
} from './types'
6+
7+
export const RUN_STATUSES_TERMINAL = [
8+
RUN_STATUS_SUCCEEDED,
9+
RUN_STATUS_FAILED,
10+
RUN_STATUS_STOPPED,
11+
]

api-client/src/runs/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ export { getCommands } from './commands/getCommands'
1010
export { createRunAction } from './createRunAction'
1111
export * from './createLabwareOffset'
1212
export * from './createLabwareDefinition'
13-
13+
export * from './constants'
1414
export * from './types'
1515
export type { CreateRunData } from './createRun'

api-client/src/runs/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {
44
LoadedPipette,
55
ModuleModel,
66
RunTimeCommand,
7+
RunTimeParameter,
78
} from '@opentrons/shared-data'
89
import type { ResourceLink, ErrorDetails } from '../types'
910
export * from './commands/types'
@@ -47,7 +48,7 @@ export interface LegacyGoodRunData {
4748
modules: LoadedModule[]
4849
protocolId?: string
4950
labwareOffsets?: LabwareOffset[]
50-
runTimeParameterValues?: RunTimeParameterCreateData
51+
runTimeParameters: RunTimeParameter[]
5152
}
5253

5354
export interface KnownGoodRunData extends LegacyGoodRunData {

app/src/assets/localization/en/protocol_setup.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"confirm_values": "Confirm values",
4949
"connect_all_hardware": "Connect and calibrate all hardware first",
5050
"connect_all_mod": "Connect all modules first",
51+
"connect_modules_for_controls": "Connect modules to see controls",
5152
"connection_info_not_available": "Connection info not available once run has started",
5253
"connection_status": "Connection Status",
5354
"currently_configured": "Currently configured",
@@ -236,6 +237,7 @@
236237
"run_disabled_modules_and_calibration_not_complete": "Make sure robot calibration is complete and all modules are connected before proceeding to run",
237238
"run_disabled_modules_not_connected": "Make sure all modules are connected before proceeding to run",
238239
"run_labware_position_check": "run labware position check",
240+
"run_never_started": "Run was never started",
239241
"run": "Run",
240242
"secure_labware_instructions": "Secure labware instructions",
241243
"secure_labware_modal": "Securing labware to the {{name}}",

app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
RUN_STATUS_SUCCEEDED,
1616
RUN_STATUS_BLOCKED_BY_OPEN_DOOR,
1717
RUN_STATUS_AWAITING_RECOVERY,
18+
RUN_STATUSES_TERMINAL,
1819
} from '@opentrons/api-client'
1920
import {
2021
useModulesQuery,
@@ -128,11 +129,6 @@ const CANCELLABLE_STATUSES = [
128129
RUN_STATUS_IDLE,
129130
RUN_STATUS_AWAITING_RECOVERY,
130131
]
131-
const RUN_OVER_STATUSES: RunStatus[] = [
132-
RUN_STATUS_FAILED,
133-
RUN_STATUS_STOPPED,
134-
RUN_STATUS_SUCCEEDED,
135-
]
136132

137133
interface ProtocolRunHeaderProps {
138134
protocolRunHeaderRef: React.RefObject<HTMLDivElement> | null
@@ -214,7 +210,11 @@ export function ProtocolRunHeader({
214210
if (runStatus === RUN_STATUS_IDLE) {
215211
setShowDropTipBanner(true)
216212
setPipettesWithTip([])
217-
} else if (runStatus != null && RUN_OVER_STATUSES.includes(runStatus)) {
213+
} else if (
214+
runStatus != null &&
215+
// @ts-expect-error runStatus expected to possibly not be terminal
216+
RUN_STATUSES_TERMINAL.includes(runStatus)
217+
) {
218218
getPipettesWithTipAttached({
219219
host,
220220
runId,

app/src/organisms/Devices/ProtocolRun/ProtocolRunRunTimeParameters.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import * as React from 'react'
22
import { useTranslation } from 'react-i18next'
33
import styled, { css } from 'styled-components'
4+
import {
5+
RUN_ACTION_TYPE_PLAY,
6+
RUN_STATUS_STOPPED,
7+
RUN_STATUSES_TERMINAL,
8+
} from '@opentrons/api-client'
49
import { formatRunTimeParameterValue } from '@opentrons/shared-data'
510
import {
611
ALIGN_CENTER,
@@ -23,8 +28,11 @@ import { Banner } from '../../../atoms/Banner'
2328
import { Divider } from '../../../atoms/structure'
2429
import { Tooltip } from '../../../atoms/Tooltip'
2530
import { useMostRecentCompletedAnalysis } from '../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
31+
import { useRunStatus } from '../../RunTimeControl/hooks'
32+
import { useNotifyRunQuery } from '../../../resources/runs'
2633

2734
import type { RunTimeParameter } from '@opentrons/shared-data'
35+
import type { RunStatus } from '@opentrons/api-client'
2836

2937
interface ProtocolRunRuntimeParametersProps {
3038
runId: string
@@ -34,13 +42,31 @@ export function ProtocolRunRuntimeParameters({
3442
}: ProtocolRunRuntimeParametersProps): JSX.Element {
3543
const { t } = useTranslation('protocol_setup')
3644
const mostRecentAnalysis = useMostRecentCompletedAnalysis(runId)
37-
const runTimeParameters = mostRecentAnalysis?.runTimeParameters ?? []
38-
const hasParameter = runTimeParameters.length > 0
39-
40-
const hasCustomValues = runTimeParameters.some(
45+
const runStatus = useRunStatus(runId)
46+
const isRunTerminal =
47+
runStatus == null
48+
? false
49+
: (RUN_STATUSES_TERMINAL as RunStatus[]).includes(runStatus)
50+
// we access runTimeParameters from the run record rather than the most recent analysis
51+
// because the most recent analysis may not reflect the selected run (e.g. cloning a run
52+
// from a historical protocol run from the device details page)
53+
const run = useNotifyRunQuery(runId).data
54+
const runTimeParameters =
55+
(isRunTerminal
56+
? run?.data?.runTimeParameters
57+
: mostRecentAnalysis?.runTimeParameters) ?? []
58+
const hasRunTimeParameters = runTimeParameters.length > 0
59+
const hasCustomRunTimeParameterValues = runTimeParameters.some(
4160
parameter => parameter.value !== parameter.default
4261
)
4362

63+
const runActions = run?.data.actions
64+
const hasRunStarted = runActions?.some(
65+
action => action.actionType === RUN_ACTION_TYPE_PLAY
66+
)
67+
const isRunCancelledWithoutStarting =
68+
!hasRunStarted && runStatus === RUN_STATUS_STOPPED
69+
4470
return (
4571
<>
4672
<Flex
@@ -56,13 +82,15 @@ export function ProtocolRunRuntimeParameters({
5682
<StyledText as="h3" fontWeight={TYPOGRAPHY.fontWeightSemiBold}>
5783
{t('parameters')}
5884
</StyledText>
59-
{hasParameter ? (
85+
{hasRunTimeParameters ? (
6086
<StyledText as="label" color={COLORS.grey60}>
61-
{hasCustomValues ? t('custom_values') : t('default_values')}
87+
{hasCustomRunTimeParameterValues
88+
? t('custom_values')
89+
: t('default_values')}
6290
</StyledText>
6391
) : null}
6492
</Flex>
65-
{hasParameter ? (
93+
{hasRunTimeParameters ? (
6694
<Banner
6795
type="informing"
6896
width="100%"
@@ -77,9 +105,14 @@ export function ProtocolRunRuntimeParameters({
77105
</Banner>
78106
) : null}
79107
</Flex>
80-
{!hasParameter ? (
108+
{!hasRunTimeParameters ? (
81109
<Flex padding={SPACING.spacing16}>
82-
<InfoScreen contentType="parameters" />
110+
<InfoScreen
111+
contentType={
112+
isRunCancelledWithoutStarting ? 'runNotStarted' : 'parameters'
113+
}
114+
t={t}
115+
/>
83116
</Flex>
84117
) : (
85118
<>

app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import * as React from 'react'
2+
import { UseQueryResult } from 'react-query'
23
import { describe, it, vi, beforeEach, afterEach, expect } from 'vitest'
34
import { screen } from '@testing-library/react'
45
import { when } from 'vitest-when'
56

7+
import { Run } from '@opentrons/api-client'
68
import { InfoScreen } from '@opentrons/components'
79
import { renderWithProviders } from '../../../../__testing-utils__'
810
import { i18n } from '../../../../i18n'
911
import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
12+
import { useRunStatus } from '../../../RunTimeControl/hooks'
13+
import { useNotifyRunQuery } from '../../../../resources/runs'
14+
import { mockSucceededRun } from '../../../RunTimeControl/__fixtures__'
1015

1116
import { ProtocolRunRuntimeParameters } from '../ProtocolRunRunTimeParameters'
1217

@@ -23,6 +28,8 @@ vi.mock('@opentrons/components', async importOriginal => {
2328
}
2429
})
2530
vi.mock('../../../LabwarePositionCheck/useMostRecentCompletedAnalysis')
31+
vi.mock('../../../RunTimeControl/hooks')
32+
vi.mock('../../../../resources/runs')
2633

2734
const RUN_ID = 'mockId'
2835

@@ -100,13 +107,17 @@ describe('ProtocolRunRuntimeParameters', () => {
100107
.thenReturn({
101108
runTimeParameters: mockRunTimeParameterData,
102109
} as CompletedProtocolAnalysis)
110+
vi.mocked(useRunStatus).mockReturnValue('running')
111+
vi.mocked(useNotifyRunQuery).mockReturnValue(({
112+
data: { data: mockSucceededRun },
113+
} as unknown) as UseQueryResult<Run>)
103114
})
104115

105116
afterEach(() => {
106117
vi.resetAllMocks()
107118
})
108119

109-
it('should render title, and banner when RunTimeParameters are note empty and all values are default', () => {
120+
it('should render title, and banner when RunTimeParameters are not empty and all values are default', () => {
110121
render(props)
111122
screen.getByText('Parameters')
112123
screen.getByText('Default values')
@@ -116,7 +127,7 @@ describe('ProtocolRunRuntimeParameters', () => {
116127
screen.getByText('Value')
117128
})
118129

119-
it('should render title, and banner when RunTimeParameters are note empty and some value is changed', () => {
130+
it('should render title, and banner when RunTimeParameters are not empty and some value is changed', () => {
120131
vi.mocked(useMostRecentCompletedAnalysis).mockReturnValue({
121132
runTimeParameters: [
122133
...mockRunTimeParameterData,
@@ -139,7 +150,7 @@ describe('ProtocolRunRuntimeParameters', () => {
139150
screen.getByText('Value')
140151
})
141152

142-
it('should render RunTimeParameters when RunTimeParameters are note empty', () => {
153+
it('should render RunTimeParameters when RunTimeParameters are not empty', () => {
143154
render(props)
144155
screen.getByText('Dry Run')
145156
screen.getByText('Off')

app/src/organisms/Devices/hooks/useRunStatuses.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import {
2+
RUN_STATUSES_TERMINAL,
23
RUN_STATUS_AWAITING_RECOVERY,
3-
RUN_STATUS_FAILED,
44
RUN_STATUS_IDLE,
55
RUN_STATUS_PAUSED,
66
RUN_STATUS_RUNNING,
7-
RUN_STATUS_STOPPED,
8-
RUN_STATUS_SUCCEEDED,
97
} from '@opentrons/api-client'
108
import { useCurrentRunId } from '../../ProtocolUpload/hooks'
119
import { useRunStatus } from '../../RunTimeControl/hooks'
1210

11+
import type { RunStatus } from '@opentrons/api-client'
12+
1313
interface RunStatusesInfo {
1414
isRunStill: boolean
1515
isRunTerminal: boolean
@@ -29,9 +29,9 @@ export function useRunStatuses(): RunStatusesInfo {
2929
runStatus === RUN_STATUS_RUNNING ||
3030
runStatus === RUN_STATUS_AWAITING_RECOVERY
3131
const isRunTerminal =
32-
runStatus === RUN_STATUS_SUCCEEDED ||
33-
runStatus === RUN_STATUS_STOPPED ||
34-
runStatus === RUN_STATUS_FAILED
32+
runStatus != null
33+
? (RUN_STATUSES_TERMINAL as RunStatus[]).includes(runStatus)
34+
: false
3535
const isRunStill = isRunTerminal || isRunIdle
3636

3737
return { isRunStill, isRunTerminal, isRunIdle, isRunRunning }

app/src/organisms/InterventionModal/__fixtures__/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ export const mockRunData: RunData = {
188188
pipettes: [],
189189
labware: [mockLabwareOnModule, mockLabwareOnSlot, mockLabwareOffDeck],
190190
modules: [mockModule],
191+
runTimeParameters: [],
191192
}
192193

193194
export const mockLabwareRenderInfo = [

app/src/organisms/OnDeviceDisplay/RobotDashboard/__tests__/RecentRunProtocolCarousel.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const mockRun = {
2626
pipettes: [],
2727
protocolId: 'mockSortedProtocolID',
2828
status: 'stopped',
29+
runTimeParameters: [],
2930
}
3031

3132
const render = (

0 commit comments

Comments
 (0)