Skip to content

Commit a25a964

Browse files
authored
feat(app): Delete quick transfer run on ODD (#15831)
fix PLAT-258, PLAT-259
1 parent 8739d72 commit a25a964

File tree

10 files changed

+96
-13
lines changed

10 files changed

+96
-13
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"protocol_title": "Protocol - {{protocol_name}}",
8888
"resume_run": "Resume run",
8989
"return_to_dashboard": "Return to dashboard",
90+
"return_to_quick_transfer": "Return to quick transfer",
9091
"right": "Right",
9192
"robot_has_previous_offsets": "This robot has stored Labware Offset data from previous protocol runs. Do you want to apply that data to this protocol run? You can still adjust any offsets with Labware Position Check.",
9293
"robot_was_recalibrated": "This robot was recalibrated after this Labware Offset data was stored.",

app/src/organisms/OnDeviceDisplay/RunningProtocol/ConfirmCancelRunModal.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from '@opentrons/components'
1515
import {
1616
useStopRunMutation,
17+
useDeleteRunMutation,
1718
useDismissCurrentRunMutation,
1819
} from '@opentrons/react-api-client'
1920

@@ -31,21 +32,35 @@ interface ConfirmCancelRunModalProps {
3132
runId: string
3233
setShowConfirmCancelRunModal: (showConfirmCancelRunModal: boolean) => void
3334
isActiveRun: boolean
35+
isQuickTransfer: boolean
3436
protocolId?: string | null
3537
}
3638

3739
export function ConfirmCancelRunModal({
3840
runId,
3941
setShowConfirmCancelRunModal,
4042
isActiveRun,
43+
isQuickTransfer,
4144
protocolId,
4245
}: ConfirmCancelRunModalProps): JSX.Element {
4346
const { t } = useTranslation(['run_details', 'shared'])
4447
const { stopRun } = useStopRunMutation()
48+
const { deleteRun } = useDeleteRunMutation({
49+
onError: error => {
50+
setIsCanceling(false)
51+
console.error('Error deleting quick transfer run', error)
52+
},
53+
})
4554
const {
4655
dismissCurrentRun,
4756
isLoading: isDismissing,
48-
} = useDismissCurrentRunMutation()
57+
} = useDismissCurrentRunMutation({
58+
onSuccess: () => {
59+
if (isQuickTransfer && !isActiveRun) {
60+
deleteRun(runId)
61+
}
62+
},
63+
})
4964
const runStatus = useRunStatus(runId)
5065
const localRobot = useSelector(getLocalRobot)
5166
const robotName = localRobot?.name ?? ''
@@ -74,7 +89,11 @@ export function ConfirmCancelRunModal({
7489
trackProtocolRunEvent({ name: ANALYTICS_PROTOCOL_RUN_ACTION.CANCEL })
7590
dismissCurrentRun(runId)
7691
if (!isActiveRun) {
77-
if (protocolId != null) {
92+
if (isQuickTransfer && protocolId != null) {
93+
navigate(`/quick-transfer/${protocolId}`)
94+
} else if (isQuickTransfer) {
95+
navigate('/quick-transfer')
96+
} else if (protocolId != null) {
7897
navigate(`/protocols/${protocolId}`)
7998
} else {
8099
navigate('/protocols')

app/src/organisms/OnDeviceDisplay/RunningProtocol/__tests__/ConfirmCancelRunModal.test.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
77
import { RUN_STATUS_IDLE, RUN_STATUS_STOPPED } from '@opentrons/api-client'
88
import {
99
useStopRunMutation,
10+
useDeleteRunMutation,
1011
useDismissCurrentRunMutation,
1112
} from '@opentrons/react-api-client'
1213

@@ -31,6 +32,7 @@ vi.mock('../CancelingRunModal')
3132
vi.mock('../../../../redux/discovery')
3233
const mockNavigate = vi.fn()
3334
const mockStopRun = vi.fn()
35+
const mockDeleteRun = vi.fn()
3436
const mockDismissCurrentRun = vi.fn()
3537
const mockTrackEvent = vi.fn()
3638
const mockTrackProtocolRunEvent = vi.fn(
@@ -69,11 +71,15 @@ describe('ConfirmCancelRunModal', () => {
6971
isActiveRun: true,
7072
runId: RUN_ID,
7173
setShowConfirmCancelRunModal: mockFn,
74+
isQuickTransfer: false,
7275
}
7376

7477
vi.mocked(useStopRunMutation).mockReturnValue({
7578
stopRun: mockStopRun,
7679
} as any)
80+
vi.mocked(useDeleteRunMutation).mockReturnValue({
81+
deleteRun: mockDeleteRun,
82+
} as any)
7783
vi.mocked(useDismissCurrentRunMutation).mockReturnValue({
7884
dismissCurrentRun: mockDismissCurrentRun,
7985
isLoading: false,
@@ -152,4 +158,16 @@ describe('ConfirmCancelRunModal', () => {
152158
expect(mockTrackProtocolRunEvent).toHaveBeenCalled()
153159
expect(mockNavigate).toHaveBeenCalledWith('/protocols')
154160
})
161+
it('when quick transfer run is stopped, the run is dismissed and you return to quick transfer', () => {
162+
props = {
163+
...props,
164+
isActiveRun: false,
165+
isQuickTransfer: true,
166+
}
167+
when(useRunStatus).calledWith(RUN_ID).thenReturn(RUN_STATUS_STOPPED)
168+
render(props)
169+
170+
expect(mockDismissCurrentRun).toHaveBeenCalled()
171+
expect(mockNavigate).toHaveBeenCalledWith('/quick-transfer')
172+
})
155173
})

app/src/organisms/QuickTransferFlow/QuickTransferAdvancedSettings/AirGap.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,13 @@ export function AirGap(props: AirGapProps): JSX.Element {
109109
// after each aspirate action, so we need to halve the available capacity for single path
110110
// to get the amount available, assuming a min of 2 aspirates per dispense
111111
maxAvailableCapacity =
112-
(Math.min(maxPipetteVolume, tipVolume) - state.volume) / 2
112+
(Math.min(maxPipetteVolume, tipVolume) - 2 * state.volume) / 2
113113
} else {
114114
// aspirate air gap for multi dispense occurs once per asprirate and
115115
// available volume is max capacity - volume*3 assuming a min of 2 dispenses
116116
// per aspirate plus 1x the volume for disposal
117117
maxAvailableCapacity =
118-
Math.min(maxPipetteVolume, tipVolume) - state.volume / 3
118+
Math.min(maxPipetteVolume, tipVolume) - state.volume * 3
119119
}
120120
}
121121

app/src/organisms/QuickTransferFlow/QuickTransferAdvancedSettings/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,9 @@ export function QuickTransferAdvancedSettings(
156156
reps: state.mixOnAspirate?.repititions,
157157
})
158158
: '',
159-
enabled: state.transferType === 'transfer',
159+
enabled:
160+
state.transferType === 'transfer' ||
161+
state.transferType === 'distribute',
160162
onClick: () => {
161163
if (state.transferType === 'transfer') {
162164
setSelectedSetting('aspirate_mix')
@@ -234,7 +236,9 @@ export function QuickTransferAdvancedSettings(
234236
reps: state.mixOnDispense?.repititions,
235237
})
236238
: '',
237-
enabled: state.transferType === 'transfer',
239+
enabled:
240+
state.transferType === 'transfer' ||
241+
state.transferType === 'consolidate',
238242
onClick: () => {
239243
if (state.transferType === 'transfer') {
240244
setSelectedSetting('dispense_mix')

app/src/organisms/QuickTransferFlow/TipManagement/ChangeTip.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ export function ChangeTip(props: ChangeTipProps): JSX.Element {
3535
) {
3636
allowedChangeTipOptions.push('always')
3737
}
38-
if (state.path === 'single' && state.transferType === 'distribute') {
38+
if (
39+
state.path === 'single' &&
40+
state.transferType === 'distribute' &&
41+
state.destinationWells.length <= 96
42+
) {
3943
allowedChangeTipOptions.push('perDest')
40-
} else if (state.path === 'single') {
44+
} else if (state.path === 'single' && state.sourceWells.length <= 96) {
4145
allowedChangeTipOptions.push('perSource')
4246
}
4347

app/src/pages/ProtocolSetup/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,9 @@ function PrepareToRun({
813813
{showConfirmCancelModal ? (
814814
<ConfirmCancelRunModal
815815
runId={runId}
816+
isQuickTransfer={
817+
protocolRecord?.data.protocolKind === 'quick-transfer'
818+
}
816819
setShowConfirmCancelRunModal={setShowConfirmCancelModal}
817820
isActiveRun={false}
818821
protocolId={protocolId}

app/src/pages/RunSummary/index.tsx

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
useHost,
3737
useProtocolQuery,
3838
useInstrumentsQuery,
39+
useDeleteRunMutation,
3940
} from '@opentrons/react-api-client'
4041

4142
import { LargeButton } from '../../atoms/buttons'
@@ -78,6 +79,7 @@ export function RunSummary(): JSX.Element {
7879
const isRunCurrent = Boolean(runRecord?.data?.current)
7980
const mostRecentRunId = useMostRecentRunId()
8081
const { data: attachedInstruments } = useInstrumentsQuery()
82+
const { deleteRun } = useDeleteRunMutation()
8183
const runStatus = runRecord?.data.status ?? null
8284
const didRunSucceed = runStatus === RUN_STATUS_SUCCEEDED
8385
const protocolId = runRecord?.data.protocolId ?? null
@@ -87,6 +89,8 @@ export function RunSummary(): JSX.Element {
8789
const protocolName =
8890
protocolRecord?.data.metadata.protocolName ??
8991
protocolRecord?.data.files[0].name
92+
const isQuickTransfer = protocolRecord?.data.protocolKind === 'quick-transfer'
93+
9094
const { startedAt, stoppedAt, completedAt } = useRunTimestamps(runId)
9195
const createdAtTimestamp = useRunCreatedAtTimestamp(runId)
9296
const startedAtTimestamp =
@@ -105,7 +109,14 @@ export function RunSummary(): JSX.Element {
105109
const localRobot = useSelector(getLocalRobot)
106110
const robotName = localRobot?.name ?? 'no name'
107111
const { trackProtocolRunEvent } = useTrackProtocolRunEvent(runId, robotName)
108-
const { reset, isResetRunLoading } = useRunControls(runId)
112+
113+
const onCloneRunSuccess = (): void => {
114+
if (isQuickTransfer) {
115+
deleteRun(runId)
116+
}
117+
}
118+
119+
const { reset, isResetRunLoading } = useRunControls(runId, onCloneRunSuccess)
109120
const trackEvent = useTrackEvent()
110121
const { closeCurrentRun, isClosingCurrentRun } = useCloseCurrentRun()
111122
const robotAnalyticsData = useRobotAnalyticsData(robotName)
@@ -148,9 +159,21 @@ export function RunSummary(): JSX.Element {
148159
closeCurrentRun()
149160
navigate('/')
150161
}
151-
152162
// TODO(jh, 07-24-24): After EXEC-504, add reportRecoveredRunResult here.
153163

164+
const returnToQuickTransfer = (): void => {
165+
if (!isRunCurrent) {
166+
deleteRun(runId)
167+
} else {
168+
closeCurrentRun({
169+
onSuccess: () => {
170+
deleteRun(runId)
171+
},
172+
})
173+
}
174+
navigate('/quick-transfer')
175+
}
176+
154177
// TODO(jh, 05-30-24): EXEC-487. Refactor reset() so we can redirect to the setup page, showing the shimmer skeleton instead.
155178
const runAgain = (): void => {
156179
setShowRunAgainSpinner(true)
@@ -179,6 +202,8 @@ export function RunSummary(): JSX.Element {
179202
host,
180203
pipettesWithTip,
181204
})
205+
} else if (isQuickTransfer) {
206+
returnToQuickTransfer()
182207
} else {
183208
returnToDash()
184209
}
@@ -325,7 +350,11 @@ export function RunSummary(): JSX.Element {
325350
onClick={() => {
326351
handleReturnToDash(pipettesWithTip)
327352
}}
328-
buttonText={t('return_to_dashboard')}
353+
buttonText={
354+
isQuickTransfer
355+
? t('return_to_quick_transfer')
356+
: t('return_to_dashboard')
357+
}
329358
height="17rem"
330359
/>
331360
<LargeButton

app/src/pages/RunningProtocol/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ export function RunningProtocol(): JSX.Element {
116116
const protocolName =
117117
protocolRecord?.data.metadata.protocolName ??
118118
protocolRecord?.data.files[0].name
119+
const isQuickTransfer = protocolRecord?.data.protocolKind === 'quick-transfer'
119120
const { playRun, pauseRun } = useRunActionMutations(runId)
120121
const localRobot = useSelector(getLocalRobot)
121122
const robotName = localRobot != null ? localRobot.name : 'no name'
@@ -196,6 +197,7 @@ export function RunningProtocol(): JSX.Element {
196197
{showConfirmCancelRunModal ? (
197198
<ConfirmCancelRunModal
198199
runId={runId}
200+
isQuickTransfer={isQuickTransfer}
199201
setShowConfirmCancelRunModal={setShowConfirmCancelRunModal}
200202
isActiveRun={true}
201203
/>

react-api-client/src/runs/useDismissCurrentRunMutation.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export type UseDismissCurrentRunMutationOptions = UseMutationOptions<
2222
string
2323
>
2424

25-
export function useDismissCurrentRunMutation(): UseDismissCurrentRunMutationResult {
25+
export function useDismissCurrentRunMutation(
26+
options: UseDismissCurrentRunMutationOptions = {}
27+
): UseDismissCurrentRunMutationResult {
2628
const host = useHost()
2729
const queryClient = useQueryClient()
2830

@@ -34,7 +36,8 @@ export function useDismissCurrentRunMutation(): UseDismissCurrentRunMutationResu
3436
console.error(`error invalidating runs query: ${e.message}`)
3537
})
3638
return response.data
37-
})
39+
}),
40+
options
3841
)
3942

4043
return {

0 commit comments

Comments
 (0)