From 926ef097700bc366d6adc2ba36982b6213dbd431 Mon Sep 17 00:00:00 2001
From: Jethary Rader <66035149+jerader@users.noreply.github.com>
Date: Thu, 2 May 2024 14:24:29 -0400
Subject: [PATCH] fix(protocol-designer): clean up trash modal and new labware
dropdown logic (#15070)
closes RQA-2501, RQA-2143, RQA-1156, AUTH-378
---
.../LabwareSelectionModal.tsx | 4 +-
.../__tests__/LabwareSelectionModal.test.tsx | 2 +-
.../fields/LabwareLocationField/index.tsx | 25 +-------
.../modals/FilePipettesModal/index.tsx | 57 +++++++++++++++++--
.../src/components/modules/TrashModal.tsx | 13 +++--
.../src/localization/en/modules.json | 2 +
6 files changed, 67 insertions(+), 36 deletions(-)
diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx b/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx
index f0958eb1364..58da8b83dbc 100644
--- a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx
+++ b/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx
@@ -470,7 +470,7 @@ export function LabwareSelectionModal(): JSX.Element | null {
{customLabwareURIs.length > 0 ? (
{
})
render()
fireEvent.click(
- screen.getByText(nestedTextMatcher('adapter compatible labware'))
+ screen.getByText(nestedTextMatcher('Adapter Compatible Labware'))
)
screen.getByText('Opentrons GEB 1000uL Tiprack')
})
diff --git a/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx b/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx
index 072f7fa5e02..2cbb465c1fc 100644
--- a/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx
+++ b/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx
@@ -1,12 +1,8 @@
import * as React from 'react'
import { useSelector } from 'react-redux'
import { useTranslation } from 'react-i18next'
+import { getModuleDisplayName } from '@opentrons/shared-data'
import {
- getModuleDisplayName,
- WASTE_CHUTE_CUTOUT,
-} from '@opentrons/shared-data'
-import {
- getAdditionalEquipmentEntities,
getLabwareEntities,
getModuleEntities,
} from '../../../../step-forms/selectors'
@@ -14,7 +10,6 @@ import {
getRobotStateAtActiveItem,
getUnoccupiedLabwareLocationOptions,
} from '../../../../top-selectors/labware-locations'
-import { getHasWasteChute } from '../../../labware'
import { StepFormDropdown } from '../StepFormDropdownField'
export function LabwareLocationField(
@@ -27,32 +22,18 @@ export function LabwareLocationField(
const labwareEntities = useSelector(getLabwareEntities)
const robotState = useSelector(getRobotStateAtActiveItem)
const moduleEntities = useSelector(getModuleEntities)
- const additionalEquipmentEntities = useSelector(
- getAdditionalEquipmentEntities
- )
- const hasWasteChute = getHasWasteChute(additionalEquipmentEntities)
const isLabwareOffDeck =
labware != null ? robotState?.labware[labware]?.slot === 'offDeck' : false
- const displayWasteChuteValue =
- useGripper && hasWasteChute && !isLabwareOffDeck
let unoccupiedLabwareLocationsOptions =
useSelector(getUnoccupiedLabwareLocationOptions) ?? []
- if (isLabwareOffDeck && hasWasteChute) {
- unoccupiedLabwareLocationsOptions = unoccupiedLabwareLocationsOptions.filter(
- option =>
- option.value !== 'offDeck' && option.value !== WASTE_CHUTE_CUTOUT
- )
- } else if (useGripper || isLabwareOffDeck) {
+ if (useGripper || isLabwareOffDeck) {
unoccupiedLabwareLocationsOptions = unoccupiedLabwareLocationsOptions.filter(
option => option.value !== 'offDeck'
)
- } else if (!displayWasteChuteValue) {
- unoccupiedLabwareLocationsOptions = unoccupiedLabwareLocationsOptions.filter(
- option => option.name !== 'Waste Chute in D3'
- )
}
+
const location: string = value as string
const bothFieldsSelected = labware != null && value != null
diff --git a/protocol-designer/src/components/modals/FilePipettesModal/index.tsx b/protocol-designer/src/components/modals/FilePipettesModal/index.tsx
index 9567e753085..9b415280ef2 100644
--- a/protocol-designer/src/components/modals/FilePipettesModal/index.tsx
+++ b/protocol-designer/src/components/modals/FilePipettesModal/index.tsx
@@ -24,11 +24,6 @@ import {
OT2_ROBOT_TYPE,
getPipetteSpecsV2,
} from '@opentrons/shared-data'
-import { StepChangesConfirmModal } from '../EditPipettesModal/StepChangesConfirmModal'
-import { PipetteFields } from './PipetteFields'
-import { CrashInfoBox } from '../../modules'
-import styles from './FilePipettesModal.module.css'
-import modalStyles from '../modal.module.css'
import {
actions as stepFormActions,
selectors as stepFormSelectors,
@@ -42,14 +37,29 @@ import { INITIAL_DECK_SETUP_STEP_ID } from '../../../constants'
import { NewProtocolFields } from '../../../load-file'
import { getRobotType } from '../../../file-data/selectors'
import { uuid } from '../../../utils'
+import { getLabwareEntities } from '../../../step-forms/selectors'
+import {
+ createContainer,
+ deleteContainer,
+} from '../../../labware-ingred/actions'
import { actions as steplistActions } from '../../../steplist'
import { selectors as featureFlagSelectors } from '../../../feature-flags'
+import { CrashInfoBox } from '../../modules'
import { getCrashableModuleSelected } from '../CreateFileWizard/utils'
+import { adapter96ChannelDefUri } from '../CreateFileWizard'
+import { StepChangesConfirmModal } from '../EditPipettesModal/StepChangesConfirmModal'
+import { PipetteFields } from './PipetteFields'
+import type {
+ LabwareEntities,
+ NormalizedPipette,
+} from '@opentrons/step-generation'
import type { DeckSlot, ThunkDispatch } from '../../../types'
-import type { NormalizedPipette } from '@opentrons/step-generation'
import type { StepIdType } from '../../../form-types'
+import styles from './FilePipettesModal.module.css'
+import modalStyles from '../modal.module.css'
+
export type PipetteFieldsData = Omit<
PipetteOnDeck,
'id' | 'spec' | 'tiprackLabwareDef'
@@ -124,6 +134,7 @@ const validationSchema: any = Yup.object().shape({
})
const makeUpdatePipettes = (
+ labwareEntities: LabwareEntities,
prevPipettes: { [pipetteId: string]: PipetteOnDeck },
orderedStepIds: StepIdType[],
dispatch: ThunkDispatch,
@@ -159,6 +170,38 @@ const makeUpdatePipettes = (
}
}
})
+ const newTiprackUris = new Set(
+ newPipetteArray.flatMap(pipette => pipette.tiprackDefURI)
+ )
+ const previousTiprackLabwares = Object.values(labwareEntities).filter(
+ labware => labware.def.parameters.isTiprack
+ )
+
+ const previousTiprackUris = new Set(
+ previousTiprackLabwares.map(labware => labware.labwareDefURI)
+ )
+
+ // Find tipracks to delete (old tipracks not in new pipettes)
+ previousTiprackLabwares
+ .filter(labware => !newTiprackUris.has(labware.labwareDefURI))
+ .forEach(labware => dispatch(deleteContainer({ labwareId: labware.id })))
+
+ // Create new tipracks that are not in previous tiprackURIs
+ newTiprackUris.forEach(tiprackDefUri => {
+ if (!previousTiprackUris.has(tiprackDefUri)) {
+ const adapterUnderLabwareDefURI = newPipetteArray.some(
+ pipette => pipette.name === 'p1000_96'
+ )
+ ? adapter96ChannelDefUri
+ : undefined
+ dispatch(
+ createContainer({
+ labwareDefURI: tiprackDefUri,
+ adapterUnderLabwareDefURI,
+ })
+ )
+ }
+ })
dispatch(
stepFormActions.createPipettes(
@@ -275,6 +318,7 @@ export const FilePipettesModal = (props: Props): JSX.Element => {
const { t } = useTranslation(['modal', 'button', 'form'])
const robotType = useSelector(getRobotType)
const dispatch = useDispatch()
+ const labwareEntities = useSelector(getLabwareEntities)
const initialPipettes = useSelector(
stepFormSelectors.getPipettesForEditPipetteForm
)
@@ -295,6 +339,7 @@ export const FilePipettesModal = (props: Props): JSX.Element => {
modules: ModuleCreationArgs[]
pipettes: PipetteFieldsData[]
}) => void = makeUpdatePipettes(
+ labwareEntities,
prevPipettes,
orderedStepIds,
dispatch,
diff --git a/protocol-designer/src/components/modules/TrashModal.tsx b/protocol-designer/src/components/modules/TrashModal.tsx
index d8fffc264ee..dad0f799213 100644
--- a/protocol-designer/src/components/modules/TrashModal.tsx
+++ b/protocol-designer/src/components/modules/TrashModal.tsx
@@ -87,11 +87,14 @@ const TrashModalComponent = (props: TrashModalComponentProps): JSX.Element => {
name: 'selectedSlot',
defaultValue: defaultValue,
})
- const isSlotEmpty = getSlotIsEmpty(
- initialDeckSetup,
- selectedSlot,
- trashName === 'trashBin'
- )
+ const hasTrashAlreadyInSlot = Object.values(
+ initialDeckSetup.additionalEquipmentOnDeck
+ ).find(aE => aE.name === 'trashBin' && aE.location === selectedSlot)
+
+ const isSlotEmpty =
+ getSlotIsEmpty(initialDeckSetup, selectedSlot, trashName === 'trashBin') ||
+ hasTrashAlreadyInSlot
+
const slotFromCutout = selectedSlot.replace('cutout', '')
const flexDeck = getDeckDefFromRobotType(FLEX_ROBOT_TYPE)
diff --git a/protocol-designer/src/localization/en/modules.json b/protocol-designer/src/localization/en/modules.json
index 5cad25ca050..0f7911f45c4 100644
--- a/protocol-designer/src/localization/en/modules.json
+++ b/protocol-designer/src/localization/en/modules.json
@@ -1,4 +1,6 @@
{
+ "adapter_compatible_labware": "Adapter Compatible Labware",
+ "custom_labware": "Custom Labware",
"additional_equipment_display_names": {
"gripper": "Flex Gripper",
"stagingAreas": "Staging Area Slots",