From 05576af34e11191a1c07883293ebf98bb236a69f Mon Sep 17 00:00:00 2001 From: Jethary Date: Tue, 19 Mar 2024 16:01:26 -0400 Subject: [PATCH 1/5] fix dropdownselection --- .../StepEditForm/fields/LabwareField.tsx | 1 - .../StepEditForm/fields/MoveLabwareField.tsx | 10 ++ .../fields/StepFormDropdownField.tsx | 1 - .../components/StepEditForm/fields/index.ts | 1 + .../forms/MoveLabwareForm/index.tsx | 4 +- .../ui/labware/__tests__/selectors.test.ts | 35 +--- protocol-designer/src/ui/labware/selectors.ts | 169 ++++++++++++------ 7 files changed, 127 insertions(+), 94 deletions(-) create mode 100644 protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx diff --git a/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx b/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx index 75756800ac5..582dbf41092 100644 --- a/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx @@ -14,6 +14,5 @@ export const LabwareField = (props: FieldProps): JSX.Element => { props.name === 'dispense_labware' ? [...options, ...disposalOptions] : [...options] - return } diff --git a/protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx b/protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx new file mode 100644 index 00000000000..9ad2c230c0a --- /dev/null +++ b/protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx @@ -0,0 +1,10 @@ +import * as React from 'react' +import { useSelector } from 'react-redux' +import { getMoveLabwareOptions } from '../../../ui/labware/selectors' +import { StepFormDropdown } from './StepFormDropdownField' +import type { FieldProps } from '../types' + +export const MoveLabwareField = (props: FieldProps): JSX.Element => { + const options = useSelector(getMoveLabwareOptions) + return +} diff --git a/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx b/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx index a311c31c8d8..ccafb78e368 100644 --- a/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx @@ -27,7 +27,6 @@ export const StepFormDropdown = (props: StepFormDropdownProps): JSX.Element => { const availableOptionIds = options.map(opt => opt.value) // @ts-expect-error (ce, 2021-06-21) unknown not assignable to string const fieldValue = availableOptionIds.includes(value) ? String(value) : null - return ( { label={t('form:step_edit_form.labwareLabel.movedLabware')} className={styles.large_field} > - + {robotType === FLEX_ROBOT_TYPE ? ( { ]) }) - it('should return labware options for move labware with tips and trash', () => { - const labwareEntities = { - ...tipracks, - ...trash, - ...otherLabware, - } - const initialDeckSetup = { - labware: labwareEntities, - modules: {}, - pipettes: {}, - } - - const presavedStepForm = { - stepType: 'moveLabware', - } - expect( - // @ts-expect-error(jr, 7/17/23): resultFunc doesn't exist on type Selector - getLabwareOptions.resultFunc( - labwareEntities, - names, - initialDeckSetup, - presavedStepForm, - {}, - {} - ) - ).toEqual([ - { name: 'Opentrons Tip Rack 10 µL', value: 'tiprack10Id' }, - { name: 'Opentrons Tip Rack 1000 µL', value: 'tiprack100Id' }, - { name: 'Source Plate', value: 'wellPlateId' }, - { name: 'Trash', value: mockTrash }, - ]) - }) - it('should return labware options with module prefixes when a labware is on module', () => { const labware = { wellPlateId: { @@ -345,7 +312,7 @@ describe('labware selectors', () => { ) ).toEqual([ { name: 'Trash', value: mockTrash }, - { name: 'Well Plate', value: 'wellPlateId' }, + { name: 'Well Plate in Magnetic Module', value: 'wellPlateId' }, ]) }) }) diff --git a/protocol-designer/src/ui/labware/selectors.ts b/protocol-designer/src/ui/labware/selectors.ts index 24790e7174f..119805baa1c 100644 --- a/protocol-designer/src/ui/labware/selectors.ts +++ b/protocol-designer/src/ui/labware/selectors.ts @@ -11,6 +11,10 @@ import { getLabwareOffDeck, getLabwareInColumn4 } from './utils' import type { LabwareEntity } from '@opentrons/step-generation' import type { DropdownOption, Options } from '@opentrons/components' import type { Selector } from '../../types' +import { + AllTemporalPropertiesForTimelineFrame, + SavedStepFormState, +} from '../../step-forms' const TRASH = 'Trash Bin' @@ -35,30 +39,63 @@ export const _sortLabwareDropdownOptions = (options: Options): Options => return a.name.localeCompare(b.name) }) -/** Returns options for labware dropdowns. +const getNickNames = ( + nicknamesById: Record, + initialDeckSetup: AllTemporalPropertiesForTimelineFrame, + labwareId: string, + savedStepForms: SavedStepFormState +): string => { + const isOffDeck = getLabwareOffDeck( + initialDeckSetup, + savedStepForms ?? {}, + labwareId + ) + + const moduleOnDeck = getModuleUnderLabware( + initialDeckSetup, + savedStepForms ?? {}, + labwareId + ) + const module = + moduleOnDeck != null ? getModuleShortNames(moduleOnDeck.type) : null + + const isLabwareInColumn4 = getLabwareInColumn4( + initialDeckSetup, + savedStepForms ?? {}, + labwareId + ) + + let nickName = nicknamesById[labwareId] + if (module != null) { + nickName = `${nicknamesById[labwareId]} in ${module}` + } else if (isOffDeck) { + nickName = `${nicknamesById[labwareId]} off-deck` + } else if (isLabwareInColumn4) { + nickName = `${nicknamesById[labwareId]} in staging area slot` + } + return nickName +} + +/** Returns options for labware dropdowns for moveLabware. * Ordered by display name / nickname, but with trash at the bottom. */ -export const getLabwareOptions: Selector = createSelector( +export const getMoveLabwareOptions: Selector = createSelector( stepFormSelectors.getLabwareEntities, getLabwareNicknamesById, stepFormSelectors.getInitialDeckSetup, - stepFormSelectors.getPresavedStepForm, stepFormSelectors.getSavedStepForms, stepFormSelectors.getAdditionalEquipmentEntities, ( labwareEntities, nicknamesById, initialDeckSetup, - presavedStepForm, savedStepForms, additionalEquipmentEntities ) => { - const moveLabwarePresavedStep = presavedStepForm?.stepType === 'moveLabware' const wasteChuteLocation = Object.values(additionalEquipmentEntities).find( aE => aE.name === 'wasteChute' )?.location - - const labwareOptions = reduce( + const moveLabwareOptions = reduce( labwareEntities, ( acc: Options, @@ -73,66 +110,86 @@ export const getLabwareOptions: Selector = createSelector( ) const isAdapter = labwareEntity.def.allowedRoles?.includes('adapter') - const isOffDeck = getLabwareOffDeck( + const nickName = getNickNames( + nicknamesById, initialDeckSetup, - savedStepForms ?? {}, - labwareId + labwareId, + savedStepForms ) - const moduleOnDeck = getModuleUnderLabware( - initialDeckSetup, - savedStepForms ?? {}, - labwareId + // filter out moving trash, adapters, and labware in + // waste chute for moveLabware + return isAdapter || isLabwareInWasteChute + ? acc + : [ + ...acc, + { + name: nickName, + value: labwareId, + }, + ] + }, + [] + ) + return _sortLabwareDropdownOptions(moveLabwareOptions) + } +) + +/** Returns options for labware dropdowns for moveLiquids. + * Ordered by display name / nickname, but with trash at the bottom. + */ +export const getLabwareOptions: Selector = createSelector( + stepFormSelectors.getLabwareEntities, + getLabwareNicknamesById, + stepFormSelectors.getInitialDeckSetup, + stepFormSelectors.getSavedStepForms, + stepFormSelectors.getAdditionalEquipmentEntities, + ( + labwareEntities, + nicknamesById, + initialDeckSetup, + savedStepForms, + additionalEquipmentEntities + ) => { + const wasteChuteLocation = Object.values(additionalEquipmentEntities).find( + aE => aE.name === 'wasteChute' + )?.location + const labwareOptions = reduce( + labwareEntities, + ( + acc: Options, + labwareEntity: LabwareEntity, + labwareId: string + ): Options => { + const isLabwareInWasteChute = Object.values(savedStepForms).find( + form => + form.stepType === 'moveLabware' && + form.labware === labwareId && + form.newLocation === wasteChuteLocation ) - const module = - moduleOnDeck != null ? getModuleShortNames(moduleOnDeck.type) : null - const isLabwareInColumn4 = getLabwareInColumn4( + const isAdapter = labwareEntity.def.allowedRoles?.includes('adapter') + const nickName = getNickNames( + nicknamesById, initialDeckSetup, - savedStepForms ?? {}, - labwareId + labwareId, + savedStepForms ) - let nickName = nicknamesById[labwareId] - if (module != null) { - nickName = `${nicknamesById[labwareId]} in ${module}` - } else if (isOffDeck) { - nickName = `${nicknamesById[labwareId]} off-deck` - } else if (isLabwareInColumn4) { - nickName = `${nicknamesById[labwareId]} in staging area slot` - } - - if (!moveLabwarePresavedStep) { - // filter out tip racks, adapters, and labware in waste chute - // for aspirating/dispensing/mixing into - return getIsTiprack(labwareEntity.def) || - isAdapter || - isLabwareInWasteChute - ? acc - : [ - ...acc, - { - name: nickName, - value: labwareId, - }, - ] - } else { - // filter out moving trash, adapters, and labware in - // waste chute for moveLabware - return isAdapter || isLabwareInWasteChute - ? acc - : [ - ...acc, - { - name: nickName, - value: labwareId, - }, - ] - } + return getIsTiprack(labwareEntity.def) || + isAdapter || + isLabwareInWasteChute + ? acc + : [ + ...acc, + { + name: nickName, + value: labwareId, + }, + ] }, [] ) - return _sortLabwareDropdownOptions(labwareOptions) } ) From e6f226022fec3defc21603e859728f2e34bc5176 Mon Sep 17 00:00:00 2001 From: Jethary Date: Tue, 19 Mar 2024 16:26:57 -0400 Subject: [PATCH 2/5] remove lines --- .../src/components/StepEditForm/fields/LabwareField.tsx | 1 + .../src/components/StepEditForm/fields/StepFormDropdownField.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx b/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx index 582dbf41092..75756800ac5 100644 --- a/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/LabwareField.tsx @@ -14,5 +14,6 @@ export const LabwareField = (props: FieldProps): JSX.Element => { props.name === 'dispense_labware' ? [...options, ...disposalOptions] : [...options] + return } diff --git a/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx b/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx index ccafb78e368..7ed2835269e 100644 --- a/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx @@ -27,6 +27,7 @@ export const StepFormDropdown = (props: StepFormDropdownProps): JSX.Element => { const availableOptionIds = options.map(opt => opt.value) // @ts-expect-error (ce, 2021-06-21) unknown not assignable to string const fieldValue = availableOptionIds.includes(value) ? String(value) : null + return ( Date: Tue, 19 Mar 2024 16:28:35 -0400 Subject: [PATCH 3/5] fix lint --- .../components/StepEditForm/fields/StepFormDropdownField.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx b/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx index 7ed2835269e..a311c31c8d8 100644 --- a/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/StepFormDropdownField.tsx @@ -27,7 +27,7 @@ export const StepFormDropdown = (props: StepFormDropdownProps): JSX.Element => { const availableOptionIds = options.map(opt => opt.value) // @ts-expect-error (ce, 2021-06-21) unknown not assignable to string const fieldValue = availableOptionIds.includes(value) ? String(value) : null - + return ( Date: Wed, 20 Mar 2024 08:51:09 -0400 Subject: [PATCH 4/5] address feedback --- .../src/components/StepEditForm/fields/MoveLabwareField.tsx | 2 +- protocol-designer/src/components/StepEditForm/fields/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx b/protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx index 9ad2c230c0a..b0a6d51b463 100644 --- a/protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/MoveLabwareField.tsx @@ -4,7 +4,7 @@ import { getMoveLabwareOptions } from '../../../ui/labware/selectors' import { StepFormDropdown } from './StepFormDropdownField' import type { FieldProps } from '../types' -export const MoveLabwareField = (props: FieldProps): JSX.Element => { +export function MoveLabwareField(props: FieldProps): JSX.Element { const options = useSelector(getMoveLabwareOptions) return } diff --git a/protocol-designer/src/components/StepEditForm/fields/index.ts b/protocol-designer/src/components/StepEditForm/fields/index.ts index 680d050b2a6..15d7f4bb21f 100644 --- a/protocol-designer/src/components/StepEditForm/fields/index.ts +++ b/protocol-designer/src/components/StepEditForm/fields/index.ts @@ -12,8 +12,8 @@ export { DelayFields } from './DelayFields' export { DisposalVolumeField } from './DisposalVolumeField' export { FlowRateField } from './FlowRateField' export { LabwareField } from './LabwareField' -export { MoveLabwareField } from './MoveLabwareField' export { LabwareLocationField } from './LabwareLocationField' +export { MoveLabwareField } from './MoveLabwareField' export { PathField } from './PathField/PathField' export { PipetteField } from './PipetteField' export { ProfileItemRows } from './ProfileItemRows' From 8a3bf8d3abad7486a6bdc5f305cf52d0fd4750ea Mon Sep 17 00:00:00 2001 From: Jethary Date: Wed, 20 Mar 2024 09:00:24 -0400 Subject: [PATCH 5/5] address some more feedback --- protocol-designer/src/ui/labware/selectors.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/protocol-designer/src/ui/labware/selectors.ts b/protocol-designer/src/ui/labware/selectors.ts index 119805baa1c..61d5f5dab7a 100644 --- a/protocol-designer/src/ui/labware/selectors.ts +++ b/protocol-designer/src/ui/labware/selectors.ts @@ -11,7 +11,7 @@ import { getLabwareOffDeck, getLabwareInColumn4 } from './utils' import type { LabwareEntity } from '@opentrons/step-generation' import type { DropdownOption, Options } from '@opentrons/components' import type { Selector } from '../../types' -import { +import type { AllTemporalPropertiesForTimelineFrame, SavedStepFormState, } from '../../step-forms' @@ -39,7 +39,7 @@ export const _sortLabwareDropdownOptions = (options: Options): Options => return a.name.localeCompare(b.name) }) -const getNickNames = ( +const getNickname = ( nicknamesById: Record, initialDeckSetup: AllTemporalPropertiesForTimelineFrame, labwareId: string, @@ -65,7 +65,7 @@ const getNickNames = ( labwareId ) - let nickName = nicknamesById[labwareId] + let nickName: string = nicknamesById[labwareId] if (module != null) { nickName = `${nicknamesById[labwareId]} in ${module}` } else if (isOffDeck) { @@ -109,8 +109,9 @@ export const getMoveLabwareOptions: Selector = createSelector( form.newLocation === wasteChuteLocation ) - const isAdapter = labwareEntity.def.allowedRoles?.includes('adapter') - const nickName = getNickNames( + const isAdapter = + labwareEntity.def.allowedRoles?.includes('adapter') ?? false + const nickName = getNickname( nicknamesById, initialDeckSetup, labwareId, @@ -168,8 +169,9 @@ export const getLabwareOptions: Selector = createSelector( form.newLocation === wasteChuteLocation ) - const isAdapter = labwareEntity.def.allowedRoles?.includes('adapter') - const nickName = getNickNames( + const isAdapter = + labwareEntity.def.allowedRoles?.includes('adapter') ?? false + const nickName = getNickname( nicknamesById, initialDeckSetup, labwareId,