Skip to content

Commit

Permalink
feat(app, components, shared-data): disable invalid slots during modu…
Browse files Browse the repository at this point in the history
…le cal (#14411)

* feat(app, components, shared-data): disable incompatible fixture-occupied slots during module cal

closes RQA-2164
  • Loading branch information
ncdiehl11 authored Feb 7, 2024
1 parent 96f4468 commit c77a53b
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 56 deletions.
2 changes: 2 additions & 0 deletions app/src/assets/localization/en/module_wizard_flows.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"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>",
"install_adapter": "Place calibration adapter in {{module}}",
"install_calibration_adapter": "Install calibration adapter",
"location_occupied": "A {{fixture}} is currently specified here on the deck configuration",
"module_calibrating": "Stand back, {{moduleName}} is calibrating",
"module_calibration_failed": "<block>Module calibration was unsuccessful. Make sure the calibration adapter is fully seated on the module and try again. If you still have trouble, contact Opentrons Support.</block><block>{{error}}</block>",
"module_calibration": "Module calibration",
Expand All @@ -39,6 +40,7 @@
"recalibrate": "Recalibrate",
"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.",
"slot_unavailable": "Slot unavailable",
"stand_back_exiting": "Stand back, robot is in motion",
"stand_back": "Stand back, calibration in progress",
"start_setup": "Start setup",
Expand Down
45 changes: 33 additions & 12 deletions app/src/molecules/GenericWizardTile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import {
DISPLAY_INLINE_BLOCK,
ALIGN_CENTER,
ALIGN_FLEX_END,
useHoverTooltip,
} from '@opentrons/components'
import { getIsOnDevice } from '../../redux/config'
import { StyledText } from '../../atoms/text'
import { Tooltip } from '../../atoms/Tooltip'
import { NeedHelpLink } from '../../organisms/CalibrationPanels'
import { SmallButton } from '../../atoms/buttons'

Expand Down Expand Up @@ -90,6 +92,7 @@ export interface GenericWizardTileProps {
proceedIsDisabled?: boolean
proceedButton?: JSX.Element
backIsDisabled?: boolean
disableProceedReason?: string
}

export function GenericWizardTile(props: GenericWizardTileProps): JSX.Element {
Expand All @@ -104,9 +107,11 @@ export function GenericWizardTile(props: GenericWizardTileProps): JSX.Element {
proceedIsDisabled,
proceedButton,
backIsDisabled,
disableProceedReason,
} = props
const { t } = useTranslation('shared')
const isOnDevice = useSelector(getIsOnDevice)
const [targetProps, tooltipProps] = useHoverTooltip()

let buttonPositioning: string = ''
if (
Expand Down Expand Up @@ -158,19 +163,35 @@ export function GenericWizardTile(props: GenericWizardTileProps): JSX.Element {
{getHelp != null ? <NeedHelpLink href={getHelp} /> : null}
{proceed != null && proceedButton == null ? (
isOnDevice ? (
<SmallButton
disabled={proceedIsDisabled}
buttonText={proceedButtonText}
onClick={proceed}
/>
<>
<SmallButton
disabled={proceedIsDisabled}
buttonText={proceedButtonText}
onClick={proceed}
{...targetProps}
/>
{disableProceedReason != null && (
<Tooltip tooltipProps={tooltipProps}>
{disableProceedReason}
</Tooltip>
)}
</>
) : (
<PrimaryButton
disabled={proceedIsDisabled}
css={CAPITALIZE_FIRST_LETTER_STYLE}
onClick={proceed}
>
{proceedButtonText}
</PrimaryButton>
<>
<PrimaryButton
disabled={proceedIsDisabled}
css={CAPITALIZE_FIRST_LETTER_STYLE}
onClick={proceed}
{...targetProps}
>
{proceedButtonText}
</PrimaryButton>
{disableProceedReason != null && (
<Tooltip tooltipProps={tooltipProps}>
{disableProceedReason}
</Tooltip>
)}
</>
)
) : null}
{proceed == null && proceedButton != null ? proceedButton : null}
Expand Down
21 changes: 13 additions & 8 deletions app/src/organisms/ModuleWizardFlows/SelectLocation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { useTranslation } from 'react-i18next'
import { css } from 'styled-components'
import {
FLEX_ROBOT_TYPE,
ModuleLocation,
getDeckDefFromRobotType,
getModuleDisplayName,
THERMOCYCLER_MODULE_TYPE,
CutoutConfig,
} from '@opentrons/shared-data'
import {
RESPONSIVENESS,
Expand All @@ -31,6 +31,7 @@ export const BODY_STYLE = css`
interface SelectLocationProps extends ModuleCalibrationWizardStepProps {
setSlotName: React.Dispatch<React.SetStateAction<string>>
availableSlotNames: string[]
occupiedCutouts: CutoutConfig[]
}
export const SelectLocation = (
props: SelectLocationProps
Expand All @@ -41,6 +42,7 @@ export const SelectLocation = (
slotName,
setSlotName,
availableSlotNames,
occupiedCutouts,
} = props
const { t } = useTranslation('module_wizard_flows')
const moduleName = getModuleDisplayName(attachedModule.moduleModel)
Expand All @@ -58,6 +60,7 @@ export const SelectLocation = (
</Banner>
</>
)

return (
<GenericWizardTile
header={t('select_location')}
Expand All @@ -66,21 +69,23 @@ export const SelectLocation = (
deckDef={deckDef}
selectedLocation={{ slotName }}
setSelectedLocation={loc => setSlotName(loc.slotName)}
disabledLocations={deckDef.locations.addressableAreas.reduce<
ModuleLocation[]
>((acc, slot) => {
if (availableSlotNames.some(slotName => slotName === slot.id))
return acc
return [...acc, { slotName: slot.id }]
}, [])}
availableSlotNames={availableSlotNames}
occupiedCutouts={occupiedCutouts}
isThermocycler={
attachedModule.moduleType === THERMOCYCLER_MODULE_TYPE
}
showTooltipOnDisabled={true}
/>
}
bodyText={bodyText}
proceedButtonText={t('confirm_location')}
proceed={handleOnClick}
proceedIsDisabled={slotName == null}
disableProceedReason={
slotName == null
? 'Current deck configuration prevents module placement'
: undefined
}
/>
)
}
55 changes: 43 additions & 12 deletions app/src/organisms/ModuleWizardFlows/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import * as React from 'react'
import { useSelector } from 'react-redux'
import { Trans, useTranslation } from 'react-i18next'
import { useDeleteMaintenanceRunMutation } from '@opentrons/react-api-client'
import {
useDeleteMaintenanceRunMutation,
useCurrentMaintenanceRun,
useDeckConfigurationQuery,
} from '@opentrons/react-api-client'
import { COLORS } from '@opentrons/components'
import {
CreateCommand,
getModuleType,
getModuleDisplayName,
FLEX_CUTOUT_BY_SLOT_ID,
SINGLE_SLOT_FIXTURES,
} from '@opentrons/shared-data'

import { LegacyModalShell } from '../../molecules/LegacyModal'
import { Portal } from '../../App/portal'
import { StyledText } from '../../atoms/text'
Expand All @@ -29,9 +33,13 @@ import { PlaceAdapter } from './PlaceAdapter'
import { SelectLocation } from './SelectLocation'
import { Success } from './Success'
import { DetachProbe } from './DetachProbe'
import { useNotifyCurrentMaintenanceRun } from '../../resources/maintenance_runs/useNotifyCurrentMaintenanceRun'

import type { AttachedModule, CommandData } from '@opentrons/api-client'
import type {
CreateCommand,
CutoutConfig,
SingleSlotCutoutFixtureId,
} from '@opentrons/shared-data'

interface ModuleWizardFlowsProps {
attachedModule: AttachedModule
Expand Down Expand Up @@ -64,10 +72,26 @@ export const ModuleWizardFlows = (
: attachedPipettes.right

const moduleCalibrationSteps = getModuleCalibrationSteps()
const deckConfig = useDeckConfigurationQuery().data ?? []
const occupiedCutouts = deckConfig.filter(
(fixture: CutoutConfig) =>
!SINGLE_SLOT_FIXTURES.includes(
fixture.cutoutFixtureId as SingleSlotCutoutFixtureId
)
)
const availableSlotNames =
FLEX_SLOT_NAMES_BY_MOD_TYPE[getModuleType(attachedModule.moduleModel)] ?? []
FLEX_SLOT_NAMES_BY_MOD_TYPE[
getModuleType(attachedModule.moduleModel)
]?.filter(
slot =>
!occupiedCutouts.some(
(occCutout: CutoutConfig) =>
occCutout.cutoutId === FLEX_CUTOUT_BY_SLOT_ID[slot]
)
) ?? []

const [slotName, setSlotName] = React.useState(
initialSlotName != null ? initialSlotName : availableSlotNames?.[0] ?? 'D1'
initialSlotName != null ? initialSlotName : availableSlotNames?.[0] ?? null
)
const [currentStepIndex, setCurrentStepIndex] = React.useState<number>(0)
const totalStepCount = moduleCalibrationSteps.length - 1
Expand All @@ -91,7 +115,7 @@ export const ModuleWizardFlows = (
setMonitorMaintenanceRunForDeletion,
] = React.useState<boolean>(false)

const { data: maintenanceRunData } = useNotifyCurrentMaintenanceRun({
const { data: maintenanceRunData } = useCurrentMaintenanceRun({
refetchInterval: RUN_REFETCH_INTERVAL,
enabled: createdMaintenanceRunId != null,
})
Expand All @@ -104,7 +128,9 @@ export const ModuleWizardFlows = (
createTargetedMaintenanceRun,
isLoading: isCreateLoading,
} = useCreateTargetedMaintenanceRunMutation({
onSuccess: response => {
onSuccess: (response: {
data: { id: React.SetStateAction<string | null> }
}) => {
setCreatedMaintenanceRunId(response.data.id)
},
})
Expand Down Expand Up @@ -149,16 +175,20 @@ export const ModuleWizardFlows = (
}

const { deleteMaintenanceRun } = useDeleteMaintenanceRunMutation({
onSuccess: () => handleClose(),
onError: () => handleClose(),
onSuccess: () => {
handleClose()
},
onError: () => {
handleClose()
},
})

const handleCleanUpAndClose = (): void => {
setIsExiting(true)
if (maintenanceRunData?.data.id == null) handleClose()
else {
chainRunCommands(
maintenanceRunData?.data.id,
maintenanceRunData?.data.id as string,
[{ commandType: 'home' as const, params: {} }],
false
)
Expand Down Expand Up @@ -190,7 +220,7 @@ export const ModuleWizardFlows = (
continuePastCommandFailure: boolean
): Promise<CommandData[]> =>
chainRunCommands(
maintenanceRunData?.data.id,
maintenanceRunData?.data.id as string,
commands,
continuePastCommandFailure
)
Expand Down Expand Up @@ -275,6 +305,7 @@ export const ModuleWizardFlows = (
{...calibrateBaseProps}
availableSlotNames={availableSlotNames}
setSlotName={setSlotName}
occupiedCutouts={occupiedCutouts}
/>
)
} else if (currentStep.section === SECTIONS.PLACE_ADAPTER) {
Expand Down
Loading

0 comments on commit c77a53b

Please sign in to comment.