Skip to content

Commit

Permalink
refactor(app): promise chain commands
Browse files Browse the repository at this point in the history
Doing so gives us more granular control over when to show robot in motion views.
  • Loading branch information
mjhuff committed Jan 15, 2025
1 parent 8be24d9 commit da584ad
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 88 deletions.
12 changes: 9 additions & 3 deletions app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ export function ExitConfirmation({
state,
}: LPCWizardContentProps): JSX.Element {
const { i18n, t } = useTranslation(['labware_position_check', 'shared'])
const { confirmExitLPC, cancelExitLPC } = commandUtils
const { confirmExitLPC, cancelExitLPC, toggleRobotMoving } = commandUtils

const handleConfirmExit = (): void => {
toggleRobotMoving(true).then(() => {
confirmExitLPC()
})
}

return (
<Flex css={CONTAINER_STYLE}>
Expand Down Expand Up @@ -64,7 +70,7 @@ export function ExitConfirmation({
buttonType="secondary"
/>
<SmallButton
onClick={confirmExitLPC}
onClick={handleConfirmExit}
buttonText={t('remove_calibration_probe')}
buttonType="alert"
/>
Expand All @@ -76,7 +82,7 @@ export function ExitConfirmation({
{t('shared:go_back')}
</SecondaryButton>
<AlertPrimaryButton
onClick={confirmExitLPC}
onClick={handleConfirmExit}
textTransform={TYPOGRAPHY.textTransformCapitalize}
>
{t('remove_calibration_probe')}
Expand Down
10 changes: 8 additions & 2 deletions app/src/organisms/LabwarePositionCheck/LPCErrorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ export function LPCErrorModal({
onCloseClick,
}: LPCWizardContentProps): JSX.Element {
const { t } = useTranslation(['labware_position_check', 'shared', 'branded'])
const { errorMessage } = commandUtils
const { errorMessage, toggleRobotMoving } = commandUtils

const handleClose = (): void => {
void toggleRobotMoving(true).then(() => {
onCloseClick()
})
}

return (
<Flex
Expand Down Expand Up @@ -65,7 +71,7 @@ export function LPCErrorModal({
<PrimaryButton
textTransform={TEXT_TRANSFORM_CAPITALIZE}
alignSelf={ALIGN_FLEX_END}
onClick={onCloseClick}
onClick={handleClose}
>
{t('shared:exit')}
</PrimaryButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,6 @@ export function useLPCFlows({
maintenanceRunId != null &&
protocolName != null &&
mostRecentAnalysis != null
console.log('=>(useLPCFlows.ts:119) mostRecentAnalysis', mostRecentAnalysis)
console.log('=>(useLPCFlows.ts:119) protocolName', protocolName)
console.log('=>(useLPCFlows.ts:119) maintenanceRunId', maintenanceRunId)
console.log('=>(useLPCFlows.ts:119) hasCreatedLPCRun', hasCreatedLPCRun)
console.log('=>(useLPCFlows.ts:119) showLPC', showLPC)

return showLPC
? {
Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/LabwarePositionCheck/LPCWizardFlex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ function LPCWizardHeader({
confirmExitLPC,
} = commandUtils

// TODO(jh 01-15-24): Revisit the onExit conditions. Can we simplify?
return (
<WizardHeader
title={t('labware_position_check_title')}
Expand All @@ -99,7 +100,6 @@ function LPCWizardContent(props: LPCWizardContentProps): JSX.Element {
const { t } = useTranslation('shared')
const { current: currentStep } = props.state.steps
const {
isExiting,
isRobotMoving,
errorMessage,
showExitConfirmation,
Expand All @@ -108,7 +108,7 @@ function LPCWizardContent(props: LPCWizardContentProps): JSX.Element {
// TODO(jh, 01-14-25): Handle open door behavior.

// Handle special cases that are shared by multiple steps first.
if (isExiting || isRobotMoving) {
if (isRobotMoving) {
return <RobotMotionLoader header={t('stand_back_robot_is_in_motion')} />
}
if (errorMessage != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,17 @@ export type UseLPCCommandsResult = UseApplyLPCOffsetsResult &
UseHandleValidMoveToMaintenancePositionResult & {
errorMessage: string | null
isRobotMoving: boolean
toggleRobotMoving: (isMoving: boolean) => Promise<void>
}

// Consolidates all command handlers and handler state for injection into LPC.
export function useLPCCommands(
props: UseLPCCommandsProps
): UseLPCCommandsResult {
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const [isRobotMoving, setIsRobotMoving] = useState(false)

const {
chainRunCommands,
isCommandMutationLoading: isRobotMoving,
} = useChainMaintenanceCommands()
const { chainRunCommands } = useChainMaintenanceCommands()

const chainLPCCommands = (
commands: CreateCommand[],
Expand Down Expand Up @@ -108,6 +107,11 @@ export function useLPCCommands(
return {
errorMessage,
isRobotMoving,
toggleRobotMoving: (isMoving: boolean) =>
new Promise<void>(resolve => {
setIsRobotMoving(isMoving)
resolve()
}),
...applyLPCOffsetsUtils,
...buildLPCOffsets,
...handleJogUtils,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export interface UseApplyLPCOffsetsProps extends UseLPCCommandChildProps {
}

export interface UseApplyLPCOffsetsResult {
handleApplyOffsets: (offsets: LabwareOffsetCreateData[]) => void
handleApplyOffsetsAndClose: (
offsets: LabwareOffsetCreateData[]
) => Promise<void>
isApplyingOffsets: boolean
}

Expand All @@ -23,17 +25,22 @@ export function useApplyLPCOffsets({

const { createLabwareOffset } = useCreateLabwareOffsetMutation()

const handleApplyOffsets = (offsets: LabwareOffsetCreateData[]): void => {
const handleApplyOffsetsAndClose = (
offsets: LabwareOffsetCreateData[]
): Promise<void> => {
setIsApplyingOffsets(true)
Promise.all(offsets.map(data => createLabwareOffset({ runId, data })))
return Promise.all(
offsets.map(data => createLabwareOffset({ runId, data }))
)
.then(() => {
onCloseClick()
setIsApplyingOffsets(false)
})
.catch((e: Error) => {
setErrorMessage(`Error applying labware offsets: ${e.message}`)
return Promise.reject(new Error('Could not apply offsets.'))
})
}

return { isApplyingOffsets, handleApplyOffsets }
return { isApplyingOffsets, handleApplyOffsetsAndClose }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import { selectActiveLwInitialPosition } from '/app/organisms/LabwarePositionChe
import type { CreateCommand } from '@opentrons/shared-data'
import type { UseLPCCommandWithChainRunChildProps } from './types'
import type { LabwarePositionCheckStep } from '/app/organisms/LabwarePositionCheck/types'
import type { CommandData } from '@opentrons/api-client'

export interface UseHandlePrepModulesResult {
handleCheckItemsPrepModules: (step: LabwarePositionCheckStep | null) => void
handleCheckItemsPrepModules: (
step: LabwarePositionCheckStep | null
) => Promise<CommandData[]>
}

// Prep module(s) before LPCing a specific labware involving module(s).
Expand All @@ -17,7 +20,7 @@ export function useHandlePrepModules({
}: UseLPCCommandWithChainRunChildProps): UseHandlePrepModulesResult {
const handleCheckItemsPrepModules = (
step: LabwarePositionCheckStep | null
): void => {
): Promise<CommandData[]> => {
const initialPosition = selectActiveLwInitialPosition(step, state)

if (step?.section === NAV_STEPS.CHECK_POSITIONS) {
Expand All @@ -31,11 +34,13 @@ export function useHandlePrepModules({
step.section === NAV_STEPS.CHECK_POSITIONS &&
prepCommands.length > 0
) {
void chainLPCCommands(prepCommands, false)
return chainLPCCommands(prepCommands, false)
}
} else {
console.warn('Cannot prep modules during unsupported step.')
}

return Promise.reject(
new Error('Cannot prep modules during unsupported step.')
)
}

return { handleCheckItemsPrepModules }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,28 @@ import type {
import type { UseLPCCommandWithChainRunChildProps } from './types'

export interface UseHandleStartLPCResult {
createStartLPCHandler: (onSuccess: () => void) => () => void
createStartLPCHandler: (onSuccess: () => void) => () => Promise<void>
}

export function useHandleStartLPC({
chainLPCCommands,
mostRecentAnalysis,
state,
}: UseLPCCommandWithChainRunChildProps): UseHandleStartLPCResult {
const createStartLPCHandler = (onSuccess: () => void): (() => void) => {
const createStartLPCHandler = (
onSuccess: () => void
): (() => Promise<void>) => {
const startCommands: CreateCommand[] = [
...buildInstrumentLabwarePrepCommands(mostRecentAnalysis),
...moduleInitBeforeAnyLPCCommands(mostRecentAnalysis),
...fullHomeCommands(),
...moveToMaintenancePosition(state.steps.current, state),
]

return (): void => {
void chainLPCCommands(startCommands, false).then(() => {
return () =>
chainLPCCommands(startCommands, false).then(() => {
onSuccess()
})
}
}

return { createStartLPCHandler }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { moveToMaintenancePosition } from '/app/organisms/LabwarePositionCheck/hooks/useLPCCommands/commands'
import { NAV_STEPS } from '/app/organisms/LabwarePositionCheck/constants'

import type { CommandData } from '@opentrons/api-client'
import type { LabwarePositionCheckStep } from '/app/organisms/LabwarePositionCheck/types'
import type { UseLPCCommandWithChainRunChildProps } from '/app/organisms/LabwarePositionCheck/hooks/useLPCCommands/types'

export interface UseHandleValidMoveToMaintenancePositionResult {
/* Only move to maintenance position during probe steps. */
handleValidMoveToMaintenancePosition: (
step: LabwarePositionCheckStep | null
) => void
) => Promise<CommandData[]>
}

export function useHandleValidMoveToMaintenancePosition({
Expand All @@ -18,12 +19,18 @@ export function useHandleValidMoveToMaintenancePosition({
return {
handleValidMoveToMaintenancePosition: (
step: LabwarePositionCheckStep | null
) => {
): Promise<CommandData[]> => {
if (
step?.section === NAV_STEPS.ATTACH_PROBE ||
step?.section === NAV_STEPS.DETACH_PROBE
) {
void chainLPCCommands(moveToMaintenancePosition(step, state), false)
return chainLPCCommands(moveToMaintenancePosition(step, state), false)
} else {
return Promise.reject(
new Error(
'Does not move to maintenance position if step is not a probe step.'
)
)
}
},
}
Expand Down
12 changes: 7 additions & 5 deletions app/src/organisms/LabwarePositionCheck/steps/AttachProbe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function AttachProbe({
unableToDetect,
createProbeAttachmentHandler,
handleCheckItemsPrepModules,
toggleRobotMoving,
} = commandUtils
const pipette = selectActivePipette(step, state)
const handleProbeAttached = createProbeAttachmentHandler(
Expand Down Expand Up @@ -62,10 +63,11 @@ export function AttachProbe({
}
})()

const handleConfirmProbeAttached = (): void => {
void handleProbeAttached().then(() => {
handleCheckItemsPrepModules(steps.next)
})
const handleProceed = (): void => {
void toggleRobotMoving(true)
.then(() => handleProbeAttached())
.then(() => handleCheckItemsPrepModules(steps.next))
.finally(() => toggleRobotMoving(false))
}

if (unableToDetect) {
Expand Down Expand Up @@ -98,7 +100,7 @@ export function AttachProbe({
</LegacyStyledText>
}
proceedButtonText={i18n.format(t('shared:continue'), 'capitalize')}
proceed={handleConfirmProbeAttached}
proceed={handleProceed}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function BeforeBeginning({
}: LPCStepProps<BeforeBeginningStep>): JSX.Element {
const { t, i18n } = useTranslation(['labware_position_check', 'shared'])
const { isOnDevice, protocolName, labwareDefs, existingOffsets } = state
const { createStartLPCHandler } = commandUtils
const { createStartLPCHandler, toggleRobotMoving } = commandUtils

const handleStartLPC = createStartLPCHandler(proceed)

Expand All @@ -43,6 +43,12 @@ export function BeforeBeginning({
},
]

const handleProceed = (): void => {
void toggleRobotMoving(true)
.then(() => handleStartLPC())
.finally(() => toggleRobotMoving(false))
}

return (
<TwoUpTileLayout
title={t('shared:before_you_begin')}
Expand All @@ -69,10 +75,10 @@ export function BeforeBeginning({
{isOnDevice ? (
<SmallButton
buttonText={t('shared:get_started')}
onClick={handleStartLPC}
onClick={handleProceed}
/>
) : (
<PrimaryButton onClick={handleStartLPC}>
<PrimaryButton onClick={handleProceed}>
{i18n.format(t('shared:get_started'), 'capitalize')}
</PrimaryButton>
)}
Expand Down
Loading

0 comments on commit da584ad

Please sign in to comment.