From cbccf7d40e21c4455f7de70783b947e38e8e3bf6 Mon Sep 17 00:00:00 2001 From: Shlok Amin Date: Fri, 1 Sep 2023 17:43:51 -0400 Subject: [PATCH] feat(app): wire up module calibration to backend (#13449) RAUT-655 Co-authored-by: Brian Cooper Co-authored-by: smb2268 --- .../assets/localization/en/app_settings.json | 1 - .../localization/en/module_wizard_flows.json | 9 ++- .../assets/localization/en/run_details.json | 2 +- app/src/molecules/WizardHeader/index.tsx | 2 +- .../__tests__/ProtocolRunHeader.test.tsx | 2 +- .../GripperWizardFlows/BeforeBeginning.tsx | 6 +- .../__tests__/BeforeBeginning.test.tsx | 1 + .../organisms/GripperWizardFlows/index.tsx | 1 + .../ModuleCard/ModuleOverflowMenu.tsx | 16 ++-- .../ModuleWizardFlows/AttachProbe.tsx | 72 ++++++++++------- .../ModuleWizardFlows/BeforeBeginning.tsx | 21 ++--- .../ModuleWizardFlows/DetachProbe.tsx | 78 +++++++++++++++++++ .../ModuleWizardFlows/FirmwareUpdate.tsx | 43 ---------- .../ModuleWizardFlows/PlaceAdapter.tsx | 76 ++++++++++++++++-- app/src/organisms/ModuleWizardFlows/index.tsx | 61 ++++++++++++--- .../PipetteWizardFlows/BeforeBeginning.tsx | 6 +- .../__tests__/BeforeBeginning.test.tsx | 1 + .../organisms/PipetteWizardFlows/index.tsx | 1 + .../RobotSettingsCalibration/index.tsx | 16 ++-- app/src/redux/config/constants.ts | 1 - app/src/redux/config/schema-types.ts | 5 +- .../src/step-forms/reducers/index.ts | 8 +- shared-data/js/helpers/index.ts | 28 ++++++- .../protocol/types/schemaV7/command/setup.ts | 2 +- 24 files changed, 327 insertions(+), 132 deletions(-) create mode 100644 app/src/organisms/ModuleWizardFlows/DetachProbe.tsx delete mode 100644 app/src/organisms/ModuleWizardFlows/FirmwareUpdate.tsx diff --git a/app/src/assets/localization/en/app_settings.json b/app/src/assets/localization/en/app_settings.json index 7dff78befd4..fc9ee2f7269 100644 --- a/app/src/assets/localization/en/app_settings.json +++ b/app/src/assets/localization/en/app_settings.json @@ -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", diff --git a/app/src/assets/localization/en/module_wizard_flows.json b/app/src/assets/localization/en/module_wizard_flows.json index 232fe1da1bc..76b5b96ac84 100644 --- a/app/src/assets/localization/en/module_wizard_flows.json +++ b/app/src/assets/localization/en/module_wizard_flows.json @@ -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": "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.The calibration adapter came with your module. The pipette probe came with your Flex pipette.", @@ -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" } diff --git a/app/src/assets/localization/en/run_details.json b/app/src/assets/localization/en/run_details.json index 4e4baeaeab1..b6f74676a97 100644 --- a/app/src/assets/localization/en/run_details.json +++ b/app/src/assets/localization/en/run_details.json @@ -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", diff --git a/app/src/molecules/WizardHeader/index.tsx b/app/src/molecules/WizardHeader/index.tsx index 00d58e0753a..146b3c85932 100644 --- a/app/src/molecules/WizardHeader/index.tsx +++ b/app/src/molecules/WizardHeader/index.tsx @@ -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 diff --git a/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunHeader.test.tsx b/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunHeader.test.tsx index af1e9455f9c..b657b7889b2 100644 --- a/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunHeader.test.tsx +++ b/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunHeader.test.tsx @@ -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({ diff --git a/app/src/organisms/GripperWizardFlows/BeforeBeginning.tsx b/app/src/organisms/GripperWizardFlows/BeforeBeginning.tsx index 01d1b52195b..60702fc724c 100644 --- a/app/src/organisms/GripperWizardFlows/BeforeBeginning.tsx +++ b/app/src/organisms/GripperWizardFlows/BeforeBeginning.tsx @@ -55,6 +55,7 @@ interface BeforeBeginningProps extends GripperWizardStepProps { unknown > isCreateLoading: boolean + createdMaintenanceRunId: string | null } export const BeforeBeginning = ( @@ -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[] = [ diff --git a/app/src/organisms/GripperWizardFlows/__tests__/BeforeBeginning.test.tsx b/app/src/organisms/GripperWizardFlows/__tests__/BeforeBeginning.test.tsx index 0029b044467..1579e40bd61 100644 --- a/app/src/organisms/GripperWizardFlows/__tests__/BeforeBeginning.test.tsx +++ b/app/src/organisms/GripperWizardFlows/__tests__/BeforeBeginning.test.tsx @@ -39,6 +39,7 @@ describe('BeforeBeginning', () => { isRobotMoving: false, setErrorMessage: jest.fn(), errorMessage: null, + createdMaintenanceRunId: null, } // mockNeedHelpLink.mockReturnValue(
mock need help link
) mockInProgressModal.mockReturnValue(
mock in progress
) diff --git a/app/src/organisms/GripperWizardFlows/index.tsx b/app/src/organisms/GripperWizardFlows/index.tsx index 1efac704334..6fc5cdc9778 100644 --- a/app/src/organisms/GripperWizardFlows/index.tsx +++ b/app/src/organisms/GripperWizardFlows/index.tsx @@ -279,6 +279,7 @@ export const GripperWizard = ( {...currentStep} {...sharedProps} createMaintenanceRun={createMaintenanceRun} + createdMaintenanceRunId={createdMaintenanceRunId} /> ) } else if (currentStep.section === SECTIONS.MOVE_PIN) { diff --git a/app/src/organisms/ModuleCard/ModuleOverflowMenu.tsx b/app/src/organisms/ModuleCard/ModuleOverflowMenu.tsx index 457807d56e5..1458b1dcf06 100644 --- a/app/src/organisms/ModuleCard/ModuleOverflowMenu.tsx +++ b/app/src/organisms/ModuleCard/ModuleOverflowMenu.tsx @@ -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, @@ -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() @@ -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 @@ -78,9 +75,14 @@ export const ModuleOverflowMenu = ( return ( - {enableModuleCalibration ? ( - {t('calibrate')} - ) : null} + + {i18n.format( + module.moduleOffset?.last_modified != null + ? t('recalibrate') + : t('calibrate'), + 'capitalize' + )} + {menuOverflowItemsByModuleType[module.moduleType].map( (item: any, index: number) => { return ( diff --git a/app/src/organisms/ModuleWizardFlows/AttachProbe.tsx b/app/src/organisms/ModuleWizardFlows/AttachProbe.tsx index a0aa2fe4d23..e8f0fcd59e9 100644 --- a/app/src/organisms/ModuleWizardFlows/AttachProbe.tsx +++ b/app/src/organisms/ModuleWizardFlows/AttachProbe.tsx @@ -7,7 +7,10 @@ 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 { @@ -15,16 +18,15 @@ import { 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` @@ -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, @@ -168,34 +172,50 @@ export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => { {t('install_probe')} ) + 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 ? ( - , - bold: ( - - ), - }} - /> - } - /> - ) : ( + return ( ) diff --git a/app/src/organisms/ModuleWizardFlows/BeforeBeginning.tsx b/app/src/organisms/ModuleWizardFlows/BeforeBeginning.tsx index 9b54395d858..a8a360740f8 100644 --- a/app/src/organisms/ModuleWizardFlows/BeforeBeginning.tsx +++ b/app/src/organisms/ModuleWizardFlows/BeforeBeginning.tsx @@ -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, @@ -27,7 +25,7 @@ interface BeforeBeginningProps extends ModuleCalibrationWizardStepProps { unknown > isCreateLoading: boolean - errorMessage: string | null + createdMaintenanceRunId: string | null } export const BeforeBeginning = ( @@ -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) @@ -82,14 +82,7 @@ export const BeforeBeginning = ( { loadName: adapterLoadname, displayName: t(adapterDisplaynameKey) }, ] - return errorMessage != null ? ( - - ) : ( + return ( }} /> } - proceedButtonText={t('move_gantry_to_front')} + proceedButtonText={t('start_setup')} proceedIsDisabled={isCreateLoading || maintenanceRunId == null} proceed={proceed} /> diff --git a/app/src/organisms/ModuleWizardFlows/DetachProbe.tsx b/app/src/organisms/ModuleWizardFlows/DetachProbe.tsx new file mode 100644 index 00000000000..c5bc623692a --- /dev/null +++ b/app/src/organisms/ModuleWizardFlows/DetachProbe.tsx @@ -0,0 +1,78 @@ +import * as React from 'react' +import { css } from 'styled-components' +import detachProbe1 from '../../assets/videos/pipette-wizard-flows/Pipette_Detach_Probe_1.webm' +import detachProbe8 from '../../assets/videos/pipette-wizard-flows/Pipette_Detach_Probe_8.webm' +import detachProbe96 from '../../assets/videos/pipette-wizard-flows/Pipette_Detach_96.webm' +import { useTranslation } from 'react-i18next' +import { + Flex, + RESPONSIVENESS, + SPACING, + TYPOGRAPHY, +} from '@opentrons/components' + +import { StyledText } from '../../atoms/text' +import { GenericWizardTile } from '../../molecules/GenericWizardTile' + +import type { ModuleCalibrationWizardStepProps } from './types' + +const BODY_STYLE = css` + ${TYPOGRAPHY.pRegular}; + + @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { + font-size: 1.275rem; + line-height: 1.75rem; + } +` + +export const DetachProbe = ( + props: ModuleCalibrationWizardStepProps +): JSX.Element | null => { + const { attachedPipette, proceed, goBack } = props + const { t, i18n } = useTranslation('module_wizard_flows') + + const pipetteChannels = attachedPipette.data.channels + let pipetteDetachProbeVideoSource + switch (pipetteChannels) { + case 1: + pipetteDetachProbeVideoSource = detachProbe1 + break + case 8: + pipetteDetachProbeVideoSource = detachProbe8 + break + case 96: + pipetteDetachProbeVideoSource = detachProbe96 + break + } + + const pipetteDetachProbeVid = ( + + + + ) + + const bodyText = ( + {t('detach_probe_description')} + ) + + return ( + + ) +} diff --git a/app/src/organisms/ModuleWizardFlows/FirmwareUpdate.tsx b/app/src/organisms/ModuleWizardFlows/FirmwareUpdate.tsx deleted file mode 100644 index 704c55ed095..00000000000 --- a/app/src/organisms/ModuleWizardFlows/FirmwareUpdate.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from 'react' -import { useTranslation } from 'react-i18next' -import { css } from 'styled-components' - -import { - COLORS, - PrimaryButton, - RESPONSIVENESS, - TYPOGRAPHY, -} from '@opentrons/components' - -import { SimpleWizardBody } from '../../molecules/SimpleWizardBody' - -import type { ModuleCalibrationWizardStepProps } from './types' - -export const BODY_STYLE = css` - ${TYPOGRAPHY.pRegular}; - - @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { - font-size: 1.275rem; - line-height: 1.75rem; - } -` - -export const FirmwareUpdate = ( - props: ModuleCalibrationWizardStepProps -): JSX.Element | null => { - const { proceed } = props - const { t } = useTranslation('module_wizard_flows') - const handleOnClick = (): void => { - proceed() - } - - return ( - - {t('next')} - - ) -} diff --git a/app/src/organisms/ModuleWizardFlows/PlaceAdapter.tsx b/app/src/organisms/ModuleWizardFlows/PlaceAdapter.tsx index 83483934c51..152ada6678f 100644 --- a/app/src/organisms/ModuleWizardFlows/PlaceAdapter.tsx +++ b/app/src/organisms/ModuleWizardFlows/PlaceAdapter.tsx @@ -1,6 +1,7 @@ import * as React from 'react' import { useTranslation } from 'react-i18next' import { css } from 'styled-components' +import { v4 as uuidv4 } from 'uuid' import HeaterShaker_PlaceAdapter_L from '@opentrons/app/src/assets/videos/module_wizard_flows/HeaterShaker_PlaceAdapter_L.webm' import HeaterShaker_PlaceAdapter_R from '@opentrons/app/src/assets/videos/module_wizard_flows/HeaterShaker_PlaceAdapter_R.webm' import TempModule_PlaceAdapter_L from '@opentrons/app/src/assets/videos/module_wizard_flows/TempModule_PlaceAdapter_L.webm' @@ -13,7 +14,11 @@ import { SPACING, RESPONSIVENESS, } from '@opentrons/components' -import { getModuleDisplayName } from '@opentrons/shared-data' +import { + CreateCommand, + getCalibrationAdapterLoadName, + getModuleDisplayName, +} from '@opentrons/shared-data' import { StyledText } from '../../atoms/text' import { GenericWizardTile } from '../../molecules/GenericWizardTile' @@ -25,9 +30,11 @@ import { import { LEFT_SLOTS } from './constants' import type { ModuleCalibrationWizardStepProps } from './types' +import { InProgressModal } from '../../molecules/InProgressModal/InProgressModal' interface PlaceAdapterProps extends ModuleCalibrationWizardStepProps { slotName: string + setCreatedAdapterId: (adapterId: string) => void } export const BODY_STYLE = css` @@ -40,13 +47,66 @@ export const BODY_STYLE = css` ` export const PlaceAdapter = (props: PlaceAdapterProps): JSX.Element | null => { - const { proceed, goBack, attachedModule, slotName } = props + const { + proceed, + goBack, + attachedModule, + slotName, + chainRunCommands, + setErrorMessage, + setCreatedAdapterId, + attachedPipette, + isRobotMoving, + } = props const { t } = useTranslation('module_wizard_flows') const moduleName = getModuleDisplayName(attachedModule.moduleModel) + const mount = attachedPipette.mount const handleOnClick = (): void => { - // TODO: send calibration/moveToMaintenance command here for the pipette - // that will be used in calibration - proceed() + const calibrationAdapterLoadName = getCalibrationAdapterLoadName( + attachedModule.moduleModel + ) + if (calibrationAdapterLoadName == null) { + console.error( + `could not get calibration adapter load name for ${attachedModule.moduleModel}` + ) + return + } + + const calibrationAdapterId = uuidv4() + const commands: CreateCommand[] = [ + { + commandType: 'loadModule', + params: { + location: { + slotName: slotName, + }, + model: attachedModule.moduleModel, + moduleId: attachedModule.id, + }, + }, + { + commandType: 'loadLabware', + params: { + labwareId: calibrationAdapterId, + location: { moduleId: attachedModule.id }, + version: 1, + namespace: 'opentrons', + loadName: calibrationAdapterLoadName, + }, + }, + { commandType: 'home' as const, params: {} }, + { + commandType: 'calibration/moveToMaintenancePosition', + params: { + mount: mount, + maintenancePosition: 'attachInstrument', + }, + }, + ] + chainRunCommands?.(commands, false) + .then(() => setCreatedAdapterId(calibrationAdapterId)) + .then(() => proceed()) + .catch((e: Error) => setErrorMessage(e.message)) } const bodyText = ( @@ -103,6 +163,12 @@ export const PlaceAdapter = (props: PlaceAdapterProps): JSX.Element | null => { ) + if (isRobotMoving) + return ( + + ) return ( { setCurrentStepIndex( - currentStepIndex !== totalStepCount ? 0 : currentStepIndex + currentStepIndex === 0 ? currentStepIndex : currentStepIndex - 1 ) } const [createdMaintenanceRunId, setCreatedMaintenanceRunId] = React.useState< string | null >(null) + const [createdAdapterId, setCreatedAdapterId] = React.useState( + null + ) // we should start checking for run deletion only after the maintenance run is created // and the useCurrentRun poll has returned that created id const [ @@ -196,20 +201,42 @@ export const ModuleWizardFlows = ( isExiting, } let modalContent: JSX.Element =
UNASSIGNED STEP
- if (isExiting) { + if (errorMessage != null) { + modalContent = ( + + {t('module_calibration_failed')} + {errorMessage} + + } + /> + ) + } else if (isExiting) { modalContent = - } - if (currentStep.section === SECTIONS.BEFORE_BEGINNING) { + } else if (currentStep.section === SECTIONS.BEFORE_BEGINNING) { modalContent = ( ) } else if (currentStep.section === SECTIONS.FIRMWARE_UPDATE) { - modalContent = + modalContent = ( + + ) } else if (currentStep.section === SECTIONS.SELECT_LOCATION) { modalContent = ( ) } else if (currentStep.section === SECTIONS.PLACE_ADAPTER) { - modalContent = + modalContent = ( + + ) } else if (currentStep.section === SECTIONS.ATTACH_PROBE) { - modalContent = + modalContent = ( + + ) + } else if (currentStep.section === SECTIONS.DETACH_PROBE) { + modalContent = } else if (currentStep.section === SECTIONS.SUCCESS) { modalContent = ( isCreateLoading: boolean + createdMaintenanceRunId: string | null requiredPipette?: LoadedPipette } export const BeforeBeginning = ( @@ -68,10 +69,13 @@ export const BeforeBeginning = ( isOnDevice, requiredPipette, maintenanceRunId, + createdMaintenanceRunId, } = props const { t } = useTranslation(['pipette_wizard_flows', 'shared']) React.useEffect(() => { - createMaintenanceRun({}) + if (createdMaintenanceRunId == null) { + createMaintenanceRun({}) + } }, []) const pipetteId = attachedPipettes[mount]?.serialNumber const isGantryEmpty = getIsGantryEmpty(attachedPipettes) diff --git a/app/src/organisms/PipetteWizardFlows/__tests__/BeforeBeginning.test.tsx b/app/src/organisms/PipetteWizardFlows/__tests__/BeforeBeginning.test.tsx index 75047182753..d6d75f881fd 100644 --- a/app/src/organisms/PipetteWizardFlows/__tests__/BeforeBeginning.test.tsx +++ b/app/src/organisms/PipetteWizardFlows/__tests__/BeforeBeginning.test.tsx @@ -59,6 +59,7 @@ describe('BeforeBeginning', () => { isRobotMoving: false, isOnDevice: false, requiredPipette: undefined, + createdMaintenanceRunId: null, } // mockNeedHelpLink.mockReturnValue(
mock need help link
) mockInProgressModal.mockReturnValue(
mock in progress
) diff --git a/app/src/organisms/PipetteWizardFlows/index.tsx b/app/src/organisms/PipetteWizardFlows/index.tsx index 8a29c35144f..cb0e08a8dfb 100644 --- a/app/src/organisms/PipetteWizardFlows/index.tsx +++ b/app/src/organisms/PipetteWizardFlows/index.tsx @@ -277,6 +277,7 @@ export const PipetteWizardFlows = ( {...currentStep} {...calibrateBaseProps} createMaintenanceRun={createMaintenanceRun} + createdMaintenanceRunId={createdMaintenanceRunId} isCreateLoading={isCreateLoading} requiredPipette={requiredPipette} /> diff --git a/app/src/organisms/RobotSettingsCalibration/index.tsx b/app/src/organisms/RobotSettingsCalibration/index.tsx index f40f672e04f..aed231b3ac9 100644 --- a/app/src/organisms/RobotSettingsCalibration/index.tsx +++ b/app/src/organisms/RobotSettingsCalibration/index.tsx @@ -27,7 +27,6 @@ import { CONNECTABLE } from '../../redux/discovery' import * as RobotApi from '../../redux/robot-api' import { getDeckCalibrationSession } from '../../redux/sessions/deck-calibration/selectors' import * as Sessions from '../../redux/sessions' -import { useFeatureFlag } from '../../redux/config' import { CalibrationDataDownload } from './CalibrationDataDownload' import { CalibrationHealthCheck } from './CalibrationHealthCheck' import { RobotSettingsDeckCalibration } from './RobotSettingsDeckCalibration' @@ -123,7 +122,6 @@ export function RobotSettingsCalibration({ ) // Modules Calibration - const enableModuleCalibration = useFeatureFlag('enableModuleCalibration') const attachedModules = useModulesQuery({ refetchInterval: CALS_FETCH_MS, @@ -327,15 +325,11 @@ export function RobotSettingsCalibration({ /> - {enableModuleCalibration ? ( - <> - - - - ) : null} + + ) : ( <> diff --git a/app/src/redux/config/constants.ts b/app/src/redux/config/constants.ts index 02852534fed..36b28bf8387 100644 --- a/app/src/redux/config/constants.ts +++ b/app/src/redux/config/constants.ts @@ -5,7 +5,6 @@ export const CONFIG_VERSION_LATEST: 1 = 1 export const DEV_INTERNAL_FLAGS: DevInternalFlag[] = [ 'enableExtendedHardware', 'lpcWithProbe', - 'enableModuleCalibration', ] // action type constants diff --git a/app/src/redux/config/schema-types.ts b/app/src/redux/config/schema-types.ts index 339b159477b..f859a4c3c2c 100644 --- a/app/src/redux/config/schema-types.ts +++ b/app/src/redux/config/schema-types.ts @@ -7,10 +7,7 @@ export type UpdateChannel = 'latest' | 'beta' | 'alpha' export type DiscoveryCandidates = string[] -export type DevInternalFlag = - | 'enableExtendedHardware' - | 'lpcWithProbe' - | 'enableModuleCalibration' +export type DevInternalFlag = 'enableExtendedHardware' | 'lpcWithProbe' export type FeatureFlags = Partial> diff --git a/protocol-designer/src/step-forms/reducers/index.ts b/protocol-designer/src/step-forms/reducers/index.ts index ffc0635246d..e457f805667 100644 --- a/protocol-designer/src/step-forms/reducers/index.ts +++ b/protocol-designer/src/step-forms/reducers/index.ts @@ -1227,7 +1227,13 @@ export const moduleInvariantProperties: Reducer< ) const modules = loadModuleCommands.reduce( (acc: ModuleEntities, command: LoadModuleCreateCommand) => { - const { moduleId, model } = command.params + const { moduleId, model, location } = command.params + if (moduleId == null) { + console.error( + `expected module ${model} in location ${location.slotName} to have an id, but id does not` + ) + return acc + } return { ...acc, [moduleId]: { diff --git a/shared-data/js/helpers/index.ts b/shared-data/js/helpers/index.ts index a0b56ec1ac5..2bfb8f4b0d2 100644 --- a/shared-data/js/helpers/index.ts +++ b/shared-data/js/helpers/index.ts @@ -4,8 +4,14 @@ import uniq from 'lodash/uniq' import { OPENTRONS_LABWARE_NAMESPACE } from '../constants' import standardDeckDefOt2 from '../../deck/definitions/3/ot2_standard.json' import standardDeckDefOt3 from '../../deck/definitions/3/ot3_standard.json' -import type { DeckDefinition, LabwareDefinition2 } from '../types' -import type { LoadedLabware, RobotType, ThermalAdapterName } from '..' +import type { + DeckDefinition, + LabwareDefinition2, + LoadedLabware, + ModuleModel, + RobotType, + ThermalAdapterName, +} from '../types' export { getWellNamePerMultiTip } from './getWellNamePerMultiTip' export { getWellTotalVolume } from './getWellTotalVolume' @@ -310,6 +316,24 @@ export const getAdapterName = (labwareLoadname: string): ThermalAdapterName => { return adapterName } +export const getCalibrationAdapterLoadName = ( + moduleModel: ModuleModel +): string | null => { + switch (moduleModel) { + case 'heaterShakerModuleV1': + return 'opentrons_calibration_adapter_heatershaker_module' + case 'temperatureModuleV2': + return 'opentrons_calibration_adapter_temperature_module' + case 'thermocyclerModuleV2': + return 'opentrons_calibration_adapter_thermocycler_module' + default: + console.error( + `${moduleModel} does not have an associated calibration adapter` + ) + return null + } +} + export const getRobotTypeFromLoadedLabware = ( labware: LoadedLabware[] ): RobotType => { diff --git a/shared-data/protocol/types/schemaV7/command/setup.ts b/shared-data/protocol/types/schemaV7/command/setup.ts index b157522e229..84f17313f25 100644 --- a/shared-data/protocol/types/schemaV7/command/setup.ts +++ b/shared-data/protocol/types/schemaV7/command/setup.ts @@ -123,7 +123,7 @@ interface MoveLabwareResult { offsetId: string } interface LoadModuleParams { - moduleId: string + moduleId?: string location: ModuleLocation model: ModuleModel }