Skip to content

Commit

Permalink
fix(app): configure modules during calibration, shorten heater shaker…
Browse files Browse the repository at this point in the history
… fixture name (#14953)

# Overview

At the beginning of the module calibration flow, the user is asked to
locate the module on the deck.
This integrated the deck configurator component directly into this
location selction step of the
module calibration wizard. the selected location will now be saved
directly to deck configuration.

Closes [RQA-2603](https://opentrons.atlassian.net/browse/RQA-2603)

# Review requests

- Run module calibration and confirm that the selected location reflects
the deck configuration

# Risk assessment
low


[RQA-2603]:
https://opentrons.atlassian.net/browse/RQA-2603?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
  • Loading branch information
b-cooper authored Apr 19, 2024
1 parent 229573f commit 4cc69eb
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 143 deletions.
4 changes: 3 additions & 1 deletion app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,12 @@ export function DeviceDetailsDeckConfiguration({
flexDirection={DIRECTION_COLUMN}
>
<DeckConfigurator
readOnly={
editableCutoutIds={
isRunRunning ||
isMaintenanceRunExisting ||
isEstopNotDisengaged
? []
: deckConfig.map(({ cutoutId }) => cutoutId)
}
deckConfig={deckConfig}
handleClickAdd={handleClickAdd}
Expand Down
35 changes: 4 additions & 31 deletions app/src/organisms/ModuleWizardFlows/BeforeBeginning.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as React from 'react'
import { UseMutateFunction } from 'react-query'
import { Trans, useTranslation } from 'react-i18next'

import {
Expand All @@ -12,12 +11,7 @@ import { StyledText } from '@opentrons/components'
import { GenericWizardTile } from '../../molecules/GenericWizardTile'
import { WizardRequiredEquipmentList } from '../../molecules/WizardRequiredEquipmentList'

import type {
CreateMaintenanceRunData,
MaintenanceRun,
AttachedModule,
} from '@opentrons/api-client'
import type { AxiosError } from 'axios'
import type { AttachedModule } from '@opentrons/api-client'
import type { ModuleCalibrationWizardStepProps } from './types'

interface EqipmentItem {
Expand All @@ -26,34 +20,14 @@ interface EqipmentItem {
subtitle?: string
}

interface BeforeBeginningProps extends ModuleCalibrationWizardStepProps {
createMaintenanceRun: UseMutateFunction<
MaintenanceRun,
AxiosError<any>,
CreateMaintenanceRunData,
unknown
>
isCreateLoading: boolean
createdMaintenanceRunId: string | null
}
type BeforeBeginningProps = ModuleCalibrationWizardStepProps

export const BeforeBeginning = (
props: BeforeBeginningProps
): JSX.Element | null => {
const {
proceed,
createMaintenanceRun,
isCreateLoading,
attachedModule,
maintenanceRunId,
createdMaintenanceRunId,
} = props
const { proceed, attachedModule } = props
const { t } = useTranslation(['module_wizard_flows', 'shared'])
React.useEffect(() => {
if (createdMaintenanceRunId == null) {
createMaintenanceRun({})
}
}, [])

const moduleDisplayName = getModuleDisplayName(attachedModule.moduleModel)

let adapterLoadname: string
Expand Down Expand Up @@ -109,7 +83,6 @@ export const BeforeBeginning = (
/>
}
proceedButtonText={t('start_setup')}
proceedIsDisabled={isCreateLoading || maintenanceRunId == null}
proceed={proceed}
/>
)
Expand Down
30 changes: 29 additions & 1 deletion app/src/organisms/ModuleWizardFlows/PlaceAdapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
TEMPERATURE_MODULE_MODELS,
THERMOCYCLER_MODULE_MODELS,
FLEX_SINGLE_SLOT_BY_CUTOUT_ID,
THERMOCYCLER_V2_FRONT_FIXTURE,
} from '@opentrons/shared-data'

import { InProgressModal } from '../../molecules/InProgressModal/InProgressModal'
Expand All @@ -32,10 +33,24 @@ import { LEFT_SLOTS } from './constants'

import type { DeckConfiguration, CreateCommand } from '@opentrons/shared-data'
import type { ModuleCalibrationWizardStepProps } from './types'
import type { AxiosError } from 'axios'
import type { UseMutateFunction } from 'react-query'
import type {
CreateMaintenanceRunData,
MaintenanceRun,
} from '@opentrons/api-client'

interface PlaceAdapterProps extends ModuleCalibrationWizardStepProps {
deckConfig: DeckConfiguration
setCreatedAdapterId: (adapterId: string) => void
createMaintenanceRun: UseMutateFunction<
MaintenanceRun,
AxiosError<any>,
CreateMaintenanceRunData,
unknown
>
isCreateLoading: boolean
createdMaintenanceRunId: string | null
}

export const BODY_STYLE = css`
Expand All @@ -58,11 +73,23 @@ export const PlaceAdapter = (props: PlaceAdapterProps): JSX.Element | null => {
setCreatedAdapterId,
attachedPipette,
isRobotMoving,
maintenanceRunId,
createMaintenanceRun,
isCreateLoading,
createdMaintenanceRunId,
} = props
const { t } = useTranslation('module_wizard_flows')
React.useEffect(() => {
if (createdMaintenanceRunId == null) {
createMaintenanceRun({})
}
}, [])
const mount = attachedPipette.mount
const cutoutId = deckConfig.find(
cc => cc.opentronsModuleSerialNumber === attachedModule.serialNumber
cc =>
cc.opentronsModuleSerialNumber === attachedModule.serialNumber &&
(attachedModule.moduleType !== THERMOCYCLER_MODULE_TYPE ||
cc.cutoutFixtureId === THERMOCYCLER_V2_FRONT_FIXTURE)
)?.cutoutId
const slotName =
cutoutId != null ? FLEX_SINGLE_SLOT_BY_CUTOUT_ID[cutoutId] : null
Expand Down Expand Up @@ -204,6 +231,7 @@ export const PlaceAdapter = (props: PlaceAdapterProps): JSX.Element | null => {
bodyText={bodyText}
proceedButtonText={t('confirm_placement')}
proceed={handleOnClick}
proceedIsDisabled={isCreateLoading || maintenanceRunId == null}
back={goBack}
/>
)
Expand Down
112 changes: 73 additions & 39 deletions app/src/organisms/ModuleWizardFlows/SelectLocation.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import * as React from 'react'
import isEqual from 'lodash/isEqual'
import { useTranslation } from 'react-i18next'
import { css } from 'styled-components'
import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client'
import {
getModuleDisplayName,
THERMOCYCLER_MODULE_TYPE,
getDeckDefFromRobotType,
FLEX_ROBOT_TYPE,
getCutoutIdsFromModuleSlotName,
getCutoutFixturesForModuleModel,
SINGLE_CENTER_SLOT_FIXTURE,
SINGLE_CENTER_CUTOUTS,
SINGLE_LEFT_SLOT_FIXTURE,
SINGLE_RIGHT_CUTOUTS,
SINGLE_RIGHT_SLOT_FIXTURE,
getFixtureIdByCutoutIdFromModuleAnchorCutoutId,
SINGLE_SLOT_FIXTURES,
} from '@opentrons/shared-data'
import {
DeckLocationSelect,
DeckConfigurator,
RESPONSIVENESS,
SIZE_1,
SPACING,
Expand All @@ -31,7 +32,6 @@ import type {
DeckConfiguration,
CutoutFixtureId,
CutoutId,
ModuleLocation,
} from '@opentrons/shared-data'

export const BODY_STYLE = css`
Expand All @@ -46,7 +46,7 @@ interface SelectLocationProps extends ModuleCalibrationWizardStepProps {
availableSlotNames: string[]
occupiedCutouts: CutoutConfig[]
deckConfig: DeckConfiguration
fixtureIdByCutoutId: { [cutoutId in CutoutId]?: CutoutFixtureId }
configuredFixtureIdByCutoutId: { [cutoutId in CutoutId]?: CutoutFixtureId }
}
export const SelectLocation = (
props: SelectLocationProps
Expand All @@ -55,9 +55,7 @@ export const SelectLocation = (
proceed,
attachedModule,
deckConfig,
availableSlotNames,
occupiedCutouts,
fixtureIdByCutoutId,
configuredFixtureIdByCutoutId,
} = props
const { t } = useTranslation('module_wizard_flows')
const moduleName = getModuleDisplayName(attachedModule.moduleModel)
Expand All @@ -80,24 +78,41 @@ export const SelectLocation = (
</>
)

const handleSetLocation = (loc: ModuleLocation): void => {
const moduleFixtures = getCutoutFixturesForModuleModel(
attachedModule.moduleModel,
deckDef
)
const selectedCutoutIds = getCutoutIdsFromModuleSlotName(
loc.slotName,
moduleFixtures,
deckDef
const moduleFixtures = getCutoutFixturesForModuleModel(
attachedModule.moduleModel,
deckDef
)
const mayMountToCutoutIds = moduleFixtures.reduce<CutoutId[]>(
(acc, { mayMountTo }) => [...acc, ...mayMountTo],
[]
)
const editableCutoutIds = deckConfig.reduce<CutoutId[]>(
(acc, { cutoutId, cutoutFixtureId, opentronsModuleSerialNumber }) => {
const isCurrentConfiguration =
Object.values(configuredFixtureIdByCutoutId).includes(
cutoutFixtureId
) && attachedModule.serialNumber === opentronsModuleSerialNumber
if (
mayMountToCutoutIds.includes(cutoutId) &&
(isCurrentConfiguration ||
SINGLE_SLOT_FIXTURES.includes(cutoutFixtureId))
) {
return [...acc, cutoutId]
}
return acc
},
[]
)

const handleAddFixture = (anchorCutoutId: CutoutId): void => {
const selectedFixtureIdByCutoutIds = getFixtureIdByCutoutIdFromModuleAnchorCutoutId(
anchorCutoutId,
moduleFixtures
)
if (
selectedCutoutIds.every(
selectedCutoutId => !(selectedCutoutId in fixtureIdByCutoutId)
)
) {
if (!isEqual(selectedFixtureIdByCutoutIds, configuredFixtureIdByCutoutId)) {
updateDeckConfiguration(
deckConfig.map(cc => {
if (cc.cutoutId in fixtureIdByCutoutId) {
if (cc.cutoutId in configuredFixtureIdByCutoutId) {
let replacementFixtureId: CutoutFixtureId = SINGLE_LEFT_SLOT_FIXTURE
if (SINGLE_CENTER_CUTOUTS.includes(cc.cutoutId)) {
replacementFixtureId = SINGLE_CENTER_SLOT_FIXTURE
Expand All @@ -109,13 +124,11 @@ export const SelectLocation = (
cutoutFixtureId: replacementFixtureId,
opentronsModuleSerialNumber: undefined,
}
} else if (selectedCutoutIds.includes(cc.cutoutId)) {
} else if (cc.cutoutId in selectedFixtureIdByCutoutIds) {
return {
...cc,
cutoutFixtureId:
Object.values(fixtureIdByCutoutId)[0] ??
moduleFixtures[0]?.id ??
cc.cutoutFixtureId,
selectedFixtureIdByCutoutIds[cc.cutoutId] ?? cc.cutoutFixtureId,
opentronsModuleSerialNumber: attachedModule.serialNumber,
}
} else {
Expand All @@ -125,22 +138,43 @@ export const SelectLocation = (
)
}
}

const handleRemoveFixture = (anchorCutoutId: CutoutId): void => {
const removedFixtureIdByCutoutIds = getFixtureIdByCutoutIdFromModuleAnchorCutoutId(
anchorCutoutId,
moduleFixtures
)
updateDeckConfiguration(
deckConfig.map(cc => {
if (cc.cutoutId in removedFixtureIdByCutoutIds) {
let replacementFixtureId: CutoutFixtureId = SINGLE_LEFT_SLOT_FIXTURE
if (SINGLE_CENTER_CUTOUTS.includes(cc.cutoutId)) {
replacementFixtureId = SINGLE_CENTER_SLOT_FIXTURE
} else if (SINGLE_RIGHT_CUTOUTS.includes(cc.cutoutId)) {
replacementFixtureId = SINGLE_RIGHT_SLOT_FIXTURE
}
return {
...cc,
cutoutFixtureId: replacementFixtureId,
opentronsModuleSerialNumber: undefined,
}
} else {
return cc
}
})
)
}

return (
<GenericWizardTile
header={t('select_location')}
rightHandBody={
<DeckLocationSelect
deckDef={deckDef}
selectedLocation={{
slotName: cutoutConfig?.cutoutId.replace('cutout', '') ?? '',
}}
setSelectedLocation={handleSetLocation}
availableSlotNames={availableSlotNames}
occupiedCutouts={occupiedCutouts}
isThermocycler={
attachedModule.moduleType === THERMOCYCLER_MODULE_TYPE
}
showTooltipOnDisabled={true}
<DeckConfigurator
deckConfig={deckConfig}
handleClickAdd={handleAddFixture}
handleClickRemove={handleRemoveFixture}
editableCutoutIds={editableCutoutIds}
height="250px"
/>
}
bodyText={bodyText}
Expand Down
15 changes: 5 additions & 10 deletions app/src/organisms/ModuleWizardFlows/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,7 @@ export const ModuleWizardFlows = (
} else if (isExiting) {
modalContent = <InProgressModal description={t('stand_back_exiting')} />
} else if (currentStep.section === SECTIONS.BEFORE_BEGINNING) {
modalContent = (
<BeforeBeginning
{...currentStep}
{...calibrateBaseProps}
createMaintenanceRun={createTargetedMaintenanceRun}
isCreateLoading={isCreateLoading}
createdMaintenanceRunId={createdMaintenanceRunId}
/>
)
modalContent = <BeforeBeginning {...currentStep} {...calibrateBaseProps} />
} else if (currentStep.section === SECTIONS.SELECT_LOCATION) {
modalContent = (
<SelectLocation
Expand All @@ -317,7 +309,7 @@ export const ModuleWizardFlows = (
availableSlotNames={availableSlotNames}
deckConfig={deckConfig}
occupiedCutouts={occupiedCutouts}
fixtureIdByCutoutId={fixtureIdByCutoutId}
configuredFixtureIdByCutoutId={fixtureIdByCutoutId}
/>
)
} else if (currentStep.section === SECTIONS.PLACE_ADAPTER) {
Expand All @@ -327,6 +319,9 @@ export const ModuleWizardFlows = (
{...calibrateBaseProps}
deckConfig={deckConfig}
setCreatedAdapterId={setCreatedAdapterId}
createMaintenanceRun={createTargetedMaintenanceRun}
isCreateLoading={isCreateLoading}
createdMaintenanceRunId={createdMaintenanceRunId}
/>
)
} else if (currentStep.section === SECTIONS.ATTACH_PROBE) {
Expand Down
2 changes: 1 addition & 1 deletion app/src/organisms/QuickTransferFlow/CreateNewTransfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function CreateNewTransfer(props: CreateNewTransferProps): JSX.Element {
<Flex width="50%">
<DeckConfigurator
deckConfig={deckConfig}
readOnly
editableCutoutIds={[]}
handleClickAdd={() => {}}
handleClickRemove={() => {}}
additionalStaticFixtures={[
Expand Down
Loading

0 comments on commit 4cc69eb

Please sign in to comment.