Skip to content

Commit

Permalink
feat(app): Delete quick transfer run on ODD (#15831)
Browse files Browse the repository at this point in the history
  • Loading branch information
smb2268 authored Jul 31, 2024
1 parent 8739d72 commit a25a964
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 13 deletions.
1 change: 1 addition & 0 deletions app/src/assets/localization/en/run_details.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"protocol_title": "Protocol - {{protocol_name}}",
"resume_run": "Resume run",
"return_to_dashboard": "Return to dashboard",
"return_to_quick_transfer": "Return to quick transfer",
"right": "Right",
"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.",
"robot_was_recalibrated": "This robot was recalibrated after this Labware Offset data was stored.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@opentrons/components'
import {
useStopRunMutation,
useDeleteRunMutation,
useDismissCurrentRunMutation,
} from '@opentrons/react-api-client'

Expand All @@ -31,21 +32,35 @@ interface ConfirmCancelRunModalProps {
runId: string
setShowConfirmCancelRunModal: (showConfirmCancelRunModal: boolean) => void
isActiveRun: boolean
isQuickTransfer: boolean
protocolId?: string | null
}

export function ConfirmCancelRunModal({
runId,
setShowConfirmCancelRunModal,
isActiveRun,
isQuickTransfer,
protocolId,
}: ConfirmCancelRunModalProps): JSX.Element {
const { t } = useTranslation(['run_details', 'shared'])
const { stopRun } = useStopRunMutation()
const { deleteRun } = useDeleteRunMutation({
onError: error => {
setIsCanceling(false)
console.error('Error deleting quick transfer run', error)
},
})
const {
dismissCurrentRun,
isLoading: isDismissing,
} = useDismissCurrentRunMutation()
} = useDismissCurrentRunMutation({
onSuccess: () => {
if (isQuickTransfer && !isActiveRun) {
deleteRun(runId)
}
},
})
const runStatus = useRunStatus(runId)
const localRobot = useSelector(getLocalRobot)
const robotName = localRobot?.name ?? ''
Expand Down Expand Up @@ -74,7 +89,11 @@ export function ConfirmCancelRunModal({
trackProtocolRunEvent({ name: ANALYTICS_PROTOCOL_RUN_ACTION.CANCEL })
dismissCurrentRun(runId)
if (!isActiveRun) {
if (protocolId != null) {
if (isQuickTransfer && protocolId != null) {
navigate(`/quick-transfer/${protocolId}`)
} else if (isQuickTransfer) {
navigate('/quick-transfer')
} else if (protocolId != null) {
navigate(`/protocols/${protocolId}`)
} else {
navigate('/protocols')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { RUN_STATUS_IDLE, RUN_STATUS_STOPPED } from '@opentrons/api-client'
import {
useStopRunMutation,
useDeleteRunMutation,
useDismissCurrentRunMutation,
} from '@opentrons/react-api-client'

Expand All @@ -31,6 +32,7 @@ vi.mock('../CancelingRunModal')
vi.mock('../../../../redux/discovery')
const mockNavigate = vi.fn()
const mockStopRun = vi.fn()
const mockDeleteRun = vi.fn()
const mockDismissCurrentRun = vi.fn()
const mockTrackEvent = vi.fn()
const mockTrackProtocolRunEvent = vi.fn(
Expand Down Expand Up @@ -69,11 +71,15 @@ describe('ConfirmCancelRunModal', () => {
isActiveRun: true,
runId: RUN_ID,
setShowConfirmCancelRunModal: mockFn,
isQuickTransfer: false,
}

vi.mocked(useStopRunMutation).mockReturnValue({
stopRun: mockStopRun,
} as any)
vi.mocked(useDeleteRunMutation).mockReturnValue({
deleteRun: mockDeleteRun,
} as any)
vi.mocked(useDismissCurrentRunMutation).mockReturnValue({
dismissCurrentRun: mockDismissCurrentRun,
isLoading: false,
Expand Down Expand Up @@ -152,4 +158,16 @@ describe('ConfirmCancelRunModal', () => {
expect(mockTrackProtocolRunEvent).toHaveBeenCalled()
expect(mockNavigate).toHaveBeenCalledWith('/protocols')
})
it('when quick transfer run is stopped, the run is dismissed and you return to quick transfer', () => {
props = {
...props,
isActiveRun: false,
isQuickTransfer: true,
}
when(useRunStatus).calledWith(RUN_ID).thenReturn(RUN_STATUS_STOPPED)
render(props)

expect(mockDismissCurrentRun).toHaveBeenCalled()
expect(mockNavigate).toHaveBeenCalledWith('/quick-transfer')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ export function AirGap(props: AirGapProps): JSX.Element {
// after each aspirate action, so we need to halve the available capacity for single path
// to get the amount available, assuming a min of 2 aspirates per dispense
maxAvailableCapacity =
(Math.min(maxPipetteVolume, tipVolume) - state.volume) / 2
(Math.min(maxPipetteVolume, tipVolume) - 2 * state.volume) / 2
} else {
// aspirate air gap for multi dispense occurs once per asprirate and
// available volume is max capacity - volume*3 assuming a min of 2 dispenses
// per aspirate plus 1x the volume for disposal
maxAvailableCapacity =
Math.min(maxPipetteVolume, tipVolume) - state.volume / 3
Math.min(maxPipetteVolume, tipVolume) - state.volume * 3
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@ export function QuickTransferAdvancedSettings(
reps: state.mixOnAspirate?.repititions,
})
: '',
enabled: state.transferType === 'transfer',
enabled:
state.transferType === 'transfer' ||
state.transferType === 'distribute',
onClick: () => {
if (state.transferType === 'transfer') {
setSelectedSetting('aspirate_mix')
Expand Down Expand Up @@ -234,7 +236,9 @@ export function QuickTransferAdvancedSettings(
reps: state.mixOnDispense?.repititions,
})
: '',
enabled: state.transferType === 'transfer',
enabled:
state.transferType === 'transfer' ||
state.transferType === 'consolidate',
onClick: () => {
if (state.transferType === 'transfer') {
setSelectedSetting('dispense_mix')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ export function ChangeTip(props: ChangeTipProps): JSX.Element {
) {
allowedChangeTipOptions.push('always')
}
if (state.path === 'single' && state.transferType === 'distribute') {
if (
state.path === 'single' &&
state.transferType === 'distribute' &&
state.destinationWells.length <= 96
) {
allowedChangeTipOptions.push('perDest')
} else if (state.path === 'single') {
} else if (state.path === 'single' && state.sourceWells.length <= 96) {
allowedChangeTipOptions.push('perSource')
}

Expand Down
3 changes: 3 additions & 0 deletions app/src/pages/ProtocolSetup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,9 @@ function PrepareToRun({
{showConfirmCancelModal ? (
<ConfirmCancelRunModal
runId={runId}
isQuickTransfer={
protocolRecord?.data.protocolKind === 'quick-transfer'
}
setShowConfirmCancelRunModal={setShowConfirmCancelModal}
isActiveRun={false}
protocolId={protocolId}
Expand Down
35 changes: 32 additions & 3 deletions app/src/pages/RunSummary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
useHost,
useProtocolQuery,
useInstrumentsQuery,
useDeleteRunMutation,
} from '@opentrons/react-api-client'

import { LargeButton } from '../../atoms/buttons'
Expand Down Expand Up @@ -78,6 +79,7 @@ export function RunSummary(): JSX.Element {
const isRunCurrent = Boolean(runRecord?.data?.current)
const mostRecentRunId = useMostRecentRunId()
const { data: attachedInstruments } = useInstrumentsQuery()
const { deleteRun } = useDeleteRunMutation()
const runStatus = runRecord?.data.status ?? null
const didRunSucceed = runStatus === RUN_STATUS_SUCCEEDED
const protocolId = runRecord?.data.protocolId ?? null
Expand All @@ -87,6 +89,8 @@ export function RunSummary(): JSX.Element {
const protocolName =
protocolRecord?.data.metadata.protocolName ??
protocolRecord?.data.files[0].name
const isQuickTransfer = protocolRecord?.data.protocolKind === 'quick-transfer'

const { startedAt, stoppedAt, completedAt } = useRunTimestamps(runId)
const createdAtTimestamp = useRunCreatedAtTimestamp(runId)
const startedAtTimestamp =
Expand All @@ -105,7 +109,14 @@ export function RunSummary(): JSX.Element {
const localRobot = useSelector(getLocalRobot)
const robotName = localRobot?.name ?? 'no name'
const { trackProtocolRunEvent } = useTrackProtocolRunEvent(runId, robotName)
const { reset, isResetRunLoading } = useRunControls(runId)

const onCloneRunSuccess = (): void => {
if (isQuickTransfer) {
deleteRun(runId)
}
}

const { reset, isResetRunLoading } = useRunControls(runId, onCloneRunSuccess)
const trackEvent = useTrackEvent()
const { closeCurrentRun, isClosingCurrentRun } = useCloseCurrentRun()
const robotAnalyticsData = useRobotAnalyticsData(robotName)
Expand Down Expand Up @@ -148,9 +159,21 @@ export function RunSummary(): JSX.Element {
closeCurrentRun()
navigate('/')
}

// TODO(jh, 07-24-24): After EXEC-504, add reportRecoveredRunResult here.

const returnToQuickTransfer = (): void => {
if (!isRunCurrent) {
deleteRun(runId)
} else {
closeCurrentRun({
onSuccess: () => {
deleteRun(runId)
},
})
}
navigate('/quick-transfer')
}

// TODO(jh, 05-30-24): EXEC-487. Refactor reset() so we can redirect to the setup page, showing the shimmer skeleton instead.
const runAgain = (): void => {
setShowRunAgainSpinner(true)
Expand Down Expand Up @@ -179,6 +202,8 @@ export function RunSummary(): JSX.Element {
host,
pipettesWithTip,
})
} else if (isQuickTransfer) {
returnToQuickTransfer()
} else {
returnToDash()
}
Expand Down Expand Up @@ -325,7 +350,11 @@ export function RunSummary(): JSX.Element {
onClick={() => {
handleReturnToDash(pipettesWithTip)
}}
buttonText={t('return_to_dashboard')}
buttonText={
isQuickTransfer
? t('return_to_quick_transfer')
: t('return_to_dashboard')
}
height="17rem"
/>
<LargeButton
Expand Down
2 changes: 2 additions & 0 deletions app/src/pages/RunningProtocol/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export function RunningProtocol(): JSX.Element {
const protocolName =
protocolRecord?.data.metadata.protocolName ??
protocolRecord?.data.files[0].name
const isQuickTransfer = protocolRecord?.data.protocolKind === 'quick-transfer'
const { playRun, pauseRun } = useRunActionMutations(runId)
const localRobot = useSelector(getLocalRobot)
const robotName = localRobot != null ? localRobot.name : 'no name'
Expand Down Expand Up @@ -196,6 +197,7 @@ export function RunningProtocol(): JSX.Element {
{showConfirmCancelRunModal ? (
<ConfirmCancelRunModal
runId={runId}
isQuickTransfer={isQuickTransfer}
setShowConfirmCancelRunModal={setShowConfirmCancelRunModal}
isActiveRun={true}
/>
Expand Down
7 changes: 5 additions & 2 deletions react-api-client/src/runs/useDismissCurrentRunMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ export type UseDismissCurrentRunMutationOptions = UseMutationOptions<
string
>

export function useDismissCurrentRunMutation(): UseDismissCurrentRunMutationResult {
export function useDismissCurrentRunMutation(
options: UseDismissCurrentRunMutationOptions = {}
): UseDismissCurrentRunMutationResult {
const host = useHost()
const queryClient = useQueryClient()

Expand All @@ -34,7 +36,8 @@ export function useDismissCurrentRunMutation(): UseDismissCurrentRunMutationResu
console.error(`error invalidating runs query: ${e.message}`)
})
return response.data
})
}),
options
)

return {
Expand Down

0 comments on commit a25a964

Please sign in to comment.