Skip to content

Commit

Permalink
feat(app): wire up module calibration to backend (#13449)
Browse files Browse the repository at this point in the history
RAUT-655

Co-authored-by: Brian Cooper <[email protected]>
Co-authored-by: smb2268 <[email protected]>
  • Loading branch information
3 people authored and TamarZanzouri committed Sep 13, 2023
1 parent 3ddcb13 commit 6a824c8
Show file tree
Hide file tree
Showing 24 changed files with 327 additions and 132 deletions.
1 change: 0 additions & 1 deletion app/src/assets/localization/en/app_settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"__dev_internal__enableExtendedHardware": "Enable Extended Hardware",
"__dev_internal__enableModuleCalibration": "Enable Module Calibration",
"__dev_internal__lpcWithProbe": "Golden Tip LPC",
"add_folder_button": "Add labware source folder",
"add_ip_button": "Add",
Expand Down
9 changes: 8 additions & 1 deletion app/src/assets/localization/en/module_wizard_flows.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
"calibration_adapter_temperature": "Calibration Adapter",
"calibration_adapter_thermocycler": "Calibration Adapter",
"checking_firmware": "Checking {{module}} firmware",
"complete_calibration": "Complete calibration",
"confirm_location": "Confirm location",
"confirm_placement": "Confirm placement",
"detach_probe": "Remove pipette probe",
"detach_probe_description": "Unlock the pipette calibration probe, remove it from the nozzle, and return it to its storage location.",
"error_during_calibration": "Error during calibration",
"exit": "Exit",
"firmware_updated": "{{module}} firmware updated!",
"get_started": "<block>To get started, remove labware from the deck and clean up the working area to make the calibration easier. Also gather the needed equipment shown to the right.</block><block>The calibration adapter came with your module. The pipette probe came with your Flex pipette.</block>",
Expand All @@ -20,14 +24,17 @@
"install_probe": "Take the calibration probe from its storage location. Ensure its collar is unlocked. Push the pipette ejector up and press the probe firmly onto the pipette nozzle. Twist the collar to lock the probe. Test that the probe is secure by gently pulling it back and forth.",
"module_calibration": "Module calibration",
"module_calibrating": "Stand back, {{moduleName}} is calibrating",
"module_calibration_failed": "The module calibration could not be completed. Contact customer support for assistance.",
"module_secured": "The module must be fully secured in its caddy and secured in the deck slot.",
"move_gantry_to_front": "Move gantry to front",
"next": "Next",
"pipette_probe": "Pipette Probe",
"place_adapter": "Place calibration adapter in {{module}}",
"place_flush": "Place the adapter flush on top of the module.",
"recalibrate": "Recalibrate",
"stand_back": "Stand back, calibration in progress",
"successfully_calibrated": "{{module}} successfully calibrated",
"select_location": "Select module location",
"select_the_slot": "Select the slot where you installed the {{module}} on the deck map to the right. The location must be correct for successful calibration."
"select_the_slot": "Select the slot where you installed the {{module}} on the deck map to the right. The location must be correct for successful calibration.",
"start_setup": "Start setup"
}
2 changes: 1 addition & 1 deletion app/src/assets/localization/en/run_details.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
"start_time": "Start Time",
"start": "Start",
"status_blocked-by-open-door": "Paused - door open",
"status_failed": "Completed",
"status_failed": "Failed",
"status_finishing": "Finishing",
"status_idle": "Not started",
"status_pause-requested": "Pause requested",
Expand Down
2 changes: 1 addition & 1 deletion app/src/molecules/WizardHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { StepMeter } from '../../atoms/StepMeter'

interface WizardHeaderProps {
title: string
onExit?: React.MouseEventHandler | null
onExit?: (() => void) | null
totalSteps?: number
currentStep?: number | null
exitDisabled?: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ describe('ProtocolRunHeader', () => {
const [{ getByText }] = render()

const button = getByText('Run again')
getByText('Completed')
getByText('Failed')
getByText(formatTimestamp(COMPLETED_AT))
fireEvent.click(button)
expect(mockTrackProtocolRunEvent).toBeCalledWith({
Expand Down
6 changes: 5 additions & 1 deletion app/src/organisms/GripperWizardFlows/BeforeBeginning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ interface BeforeBeginningProps extends GripperWizardStepProps {
unknown
>
isCreateLoading: boolean
createdMaintenanceRunId: string | null
}

export const BeforeBeginning = (
Expand All @@ -70,10 +71,13 @@ export const BeforeBeginning = (
errorMessage,
maintenanceRunId,
setErrorMessage,
createdMaintenanceRunId,
} = props
const { t } = useTranslation(['gripper_wizard_flows', 'shared'])
React.useEffect(() => {
createMaintenanceRun({})
if (createdMaintenanceRunId == null) {
createMaintenanceRun({})
}
}, [])

const commandsOnProceed: CreateCommand[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ describe('BeforeBeginning', () => {
isRobotMoving: false,
setErrorMessage: jest.fn(),
errorMessage: null,
createdMaintenanceRunId: null,
}
// mockNeedHelpLink.mockReturnValue(<div>mock need help link</div>)
mockInProgressModal.mockReturnValue(<div>mock in progress</div>)
Expand Down
1 change: 1 addition & 0 deletions app/src/organisms/GripperWizardFlows/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ export const GripperWizard = (
{...currentStep}
{...sharedProps}
createMaintenanceRun={createMaintenanceRun}
createdMaintenanceRunId={createdMaintenanceRunId}
/>
)
} else if (currentStep.section === SECTIONS.MOVE_PIN) {
Expand Down
16 changes: 9 additions & 7 deletions app/src/organisms/ModuleCard/ModuleOverflowMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Flex, POSITION_RELATIVE } from '@opentrons/components'

import { MenuList } from '../../atoms/MenuList'
import { MenuItem } from '../../atoms/MenuList/MenuItem'
import { useFeatureFlag } from '../../redux/config'
import { useCurrentRunId } from '../ProtocolUpload/hooks'
import {
useIsOT3,
Expand Down Expand Up @@ -43,7 +42,7 @@ export const ModuleOverflowMenu = (
isLoadedInRun,
} = props

const { t } = useTranslation('module_wizard_flows')
const { t, i18n } = useTranslation('module_wizard_flows')

const currentRunId = useCurrentRunId()
const { isRunTerminal, isRunStill } = useRunStatuses()
Expand All @@ -52,8 +51,6 @@ export const ModuleOverflowMenu = (
const isIncompatibleWithOT3 =
isOT3 && module.moduleModel === 'thermocyclerModuleV1'

const enableModuleCalibration = useFeatureFlag('enableModuleCalibration')

let isDisabled: boolean = false
if (runId != null && isLoadedInRun) {
isDisabled = !isRunStill
Expand All @@ -78,9 +75,14 @@ export const ModuleOverflowMenu = (
return (
<Flex position={POSITION_RELATIVE}>
<MenuList>
{enableModuleCalibration ? (
<MenuItem onClick={handleCalibrateClick}>{t('calibrate')}</MenuItem>
) : null}
<MenuItem onClick={handleCalibrateClick}>
{i18n.format(
module.moduleOffset?.last_modified != null
? t('recalibrate')
: t('calibrate'),
'capitalize'
)}
</MenuItem>
{menuOverflowItemsByModuleType[module.moduleType].map(
(item: any, index: number) => {
return (
Expand Down
72 changes: 46 additions & 26 deletions app/src/organisms/ModuleWizardFlows/AttachProbe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,26 @@ import attachProbe1 from '../../assets/videos/pipette-wizard-flows/Pipette_Attac
import attachProbe8 from '../../assets/videos/pipette-wizard-flows/Pipette_Attach_Probe_8.webm'
import attachProbe96 from '../../assets/videos/pipette-wizard-flows/Pipette_Attach_Probe_96.webm'
import { Trans, useTranslation } from 'react-i18next'
import { THERMOCYCLER_MODULE_MODELS } from '@opentrons/shared-data/js/constants'
import {
LEFT,
THERMOCYCLER_MODULE_MODELS,
} from '@opentrons/shared-data/js/constants'
import { getModuleDisplayName } from '@opentrons/shared-data/js/modules'
import { InProgressModal } from '../../molecules/InProgressModal/InProgressModal'
import {
Flex,
RESPONSIVENESS,
SPACING,
TYPOGRAPHY,
COLORS,
} from '@opentrons/components'

import { StyledText } from '../../atoms/text'
import { GenericWizardTile } from '../../molecules/GenericWizardTile'
import { SimpleWizardBody } from '../../molecules/SimpleWizardBody'

import type { ModuleCalibrationWizardStepProps } from './types'
interface AttachProbeProps extends ModuleCalibrationWizardStepProps {
isExiting: boolean
adapterId: string | null
}

const IN_PROGRESS_STYLE = css`
Expand All @@ -50,10 +52,12 @@ export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => {
const {
proceed,
goBack,
chainRunCommands,
setErrorMessage,
adapterId,
isRobotMoving,
attachedModule,
attachedPipette,
errorMessage,
isExiting,
isOnDevice,
slotName,
Expand Down Expand Up @@ -168,34 +172,50 @@ export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => {
<StyledText css={BODY_STYLE}>{t('install_probe')}</StyledText>
)

const handleBeginCalibration = (): void => {
if (adapterId == null) {
setErrorMessage('calibration adapter has not been loaded yet')
return
}
chainRunCommands?.(
[
{
commandType: 'home' as const,
params: {
axes: attachedPipette.mount === LEFT ? ['leftZ'] : ['rightZ'],
},
},
{
commandType: 'calibration/calibrateModule',
params: {
moduleId: attachedModule.id,
labwareId: adapterId,
mount: attachedPipette.mount,
},
},
{
commandType: 'calibration/moveToMaintenancePosition' as const,
params: {
mount: attachedPipette.mount,
},
},
],
false
)
.then(() => proceed())
.catch((e: Error) =>
setErrorMessage(`error starting module calibration: ${e.message}`)
)
}

// TODO: add calibration loading screen and error screen
return errorMessage != null ? (
<SimpleWizardBody
isSuccess={false}
iconColor={COLORS.errorEnabled}
header={t('shared:error_encountered')}
subHeader={
<Trans
t={t}
i18nKey={'return_probe_error'}
values={{ error: errorMessage }}
components={{
block: <StyledText as="p" />,
bold: (
<StyledText as="p" fontWeight={TYPOGRAPHY.fontWeightSemiBold} />
),
}}
/>
}
/>
) : (
return (
<GenericWizardTile
header={i18n.format(t('attach_probe'), 'capitalize')}
// TODO: make sure this is the right animation
rightHandBody={pipetteAttachProbeVid}
bodyText={bodyText}
proceedButtonText={t('begin_calibration')}
proceed={proceed}
proceed={handleBeginCalibration}
back={goBack}
/>
)
Expand Down
21 changes: 7 additions & 14 deletions app/src/organisms/ModuleWizardFlows/BeforeBeginning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import {
import { getModuleDisplayName } from '@opentrons/shared-data'
import { StyledText } from '../../atoms/text'
import { GenericWizardTile } from '../../molecules/GenericWizardTile'
import { SimpleWizardBody } from '../../molecules/SimpleWizardBody'
import { WizardRequiredEquipmentList } from '../../molecules/WizardRequiredEquipmentList'
import { COLORS } from '@opentrons/components'
import type {
CreateMaintenanceRunData,
MaintenanceRun,
Expand All @@ -27,7 +25,7 @@ interface BeforeBeginningProps extends ModuleCalibrationWizardStepProps {
unknown
>
isCreateLoading: boolean
errorMessage: string | null
createdMaintenanceRunId: string | null
}

export const BeforeBeginning = (
Expand All @@ -39,11 +37,13 @@ export const BeforeBeginning = (
isCreateLoading,
attachedModule,
maintenanceRunId,
errorMessage,
createdMaintenanceRunId,
} = props
const { t } = useTranslation(['module_wizard_flows', 'shared'])
React.useEffect(() => {
createMaintenanceRun({})
if (createdMaintenanceRunId == null) {
createMaintenanceRun({})
}
}, [])
const moduleDisplayName = getModuleDisplayName(attachedModule.moduleModel)

Expand Down Expand Up @@ -82,14 +82,7 @@ export const BeforeBeginning = (
{ loadName: adapterLoadname, displayName: t(adapterDisplaynameKey) },
]

return errorMessage != null ? (
<SimpleWizardBody
isSuccess={false}
iconColor={COLORS.errorEnabled}
header={t('shared:error_encountered')}
subHeader={errorMessage}
/>
) : (
return (
<GenericWizardTile
header={t('calibration', { module: moduleDisplayName })}
rightHandBody={
Expand All @@ -103,7 +96,7 @@ export const BeforeBeginning = (
components={{ block: <StyledText as="p" /> }}
/>
}
proceedButtonText={t('move_gantry_to_front')}
proceedButtonText={t('start_setup')}
proceedIsDisabled={isCreateLoading || maintenanceRunId == null}
proceed={proceed}
/>
Expand Down
Loading

0 comments on commit 6a824c8

Please sign in to comment.