Skip to content

Commit 85408a7

Browse files
authored
feat(protocol-designer): sort move labware source and destination by slot (#20078)
Sort the move labware step dropdown options (for both move target and destination) by slot, according to order in `FLEX_SINGLE_SLOT_ADDRESSABLE_AREAS` or `OT2_SINGLE_SLOT_ADDRESSABLE_AREAS` depending on robot type.
1 parent 95e81ed commit 85408a7

File tree

4 files changed

+96
-5
lines changed

4 files changed

+96
-5
lines changed

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLabwareTools/LabwareLocationField.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { getSlotInLocationStack } from '@opentrons/step-generation'
1111

1212
import { DropdownStepFormField } from '/protocol-designer/components/molecules'
13+
import { getRobotType } from '/protocol-designer/file-data/selectors'
1314
import {
1415
getUnoccupiedStackOptions,
1516
TIPRACK_LID_LOADNAME,
@@ -25,6 +26,8 @@ import {
2526
} from '/protocol-designer/top-selectors/labware-locations'
2627
import { hoverSelection } from '/protocol-designer/ui/steps/actions/actions'
2728

29+
import { getSortedAddressableArea } from './utils'
30+
2831
import type { AddressableAreaName } from '@opentrons/shared-data'
2932
import type { Option } from '/protocol-designer/top-selectors/labware-locations'
3033
import type { FieldProps } from '../../types'
@@ -66,7 +69,7 @@ export function LabwareLocationField(
6669
deckSetupLabware[labware]?.def.parameters.loadName === TIPRACK_LID_LOADNAME
6770
const unoccupiedLabwareLocationsOptionsSelector =
6871
useSelector(getUnoccupiedLabwareLocationOptions) ?? []
69-
72+
const robotType = useSelector(getRobotType)
7073
// invalid offDeck move filter
7174
let unoccupiedLabwareLocationsOptions = [
7275
...unoccupiedLabwareStackOptions,
@@ -109,11 +112,18 @@ export function LabwareLocationField(
109112
option => !allSlotNames.includes(option.value as AddressableAreaName)
110113
)
111114
}
112-
115+
const optionsSorted =
116+
robotState != null
117+
? getSortedAddressableArea(
118+
unoccupiedLabwareLocationsOptions,
119+
robotState,
120+
robotType
121+
)
122+
: unoccupiedLabwareLocationsOptions
113123
return (
114124
<DropdownStepFormField
115125
{...props}
116-
options={unoccupiedLabwareLocationsOptions}
126+
options={optionsSorted}
117127
errorToShow={props.errorToShow}
118128
width="100%"
119129
title={t('protocol_steps:new_location')}

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLabwareTools/MoveLabwareField.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import { useTranslation } from 'react-i18next'
2-
import { useDispatch } from 'react-redux'
2+
import { useDispatch, useSelector } from 'react-redux'
33

44
import { DropdownStepFormField } from '/protocol-designer/components/molecules'
5+
import { getRobotType } from '/protocol-designer/file-data/selectors'
56
import { useLabwareDropdownOptions } from '/protocol-designer/pages/Designer/utils'
7+
import { getRobotStateAtActiveItem } from '/protocol-designer/top-selectors/labware-locations'
68
import { hoverSelection } from '/protocol-designer/ui/steps/actions/actions'
79

10+
import { getSortedAddressableArea } from './utils'
11+
812
import type { FieldProps } from '../../types'
913

1014
interface MoveLabwareFieldProps extends FieldProps {
@@ -13,12 +17,19 @@ interface MoveLabwareFieldProps extends FieldProps {
1317
export function MoveLabwareField(props: MoveLabwareFieldProps): JSX.Element {
1418
const { useGripper } = props
1519
const options = useLabwareDropdownOptions('moveLabware', useGripper)
20+
const robotState = useSelector(getRobotStateAtActiveItem)
21+
const robotType = useSelector(getRobotType)
1622
const dispatch = useDispatch()
1723
const { t } = useTranslation(['protocol_steps', 'application'])
24+
const optionsSorted =
25+
robotState != null
26+
? getSortedAddressableArea(options, robotState, robotType)
27+
: options
28+
1829
return (
1930
<DropdownStepFormField
2031
{...props}
21-
options={options}
32+
options={optionsSorted}
2233
title={t('select_labware')}
2334
width="100%"
2435
onEnter={(id: string) => {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import {
2+
ALL_FLEX_ADDRESSABLE_AREAS_SORTED,
3+
FLEX_ROBOT_TYPE,
4+
OT2_SINGLE_SLOT_ADDRESSABLE_AREAS,
5+
} from '@opentrons/shared-data'
6+
import { getSlotInLocationStack } from '@opentrons/step-generation'
7+
8+
import type { DropdownOption } from '@opentrons/components'
9+
import type { AddressableAreaName, RobotType } from '@opentrons/shared-data'
10+
import type { TimelineFrame } from '@opentrons/step-generation'
11+
import type { Option } from '/protocol-designer/top-selectors/labware-locations'
12+
13+
export const getSortedAddressableArea = (
14+
options: Option[] | DropdownOption[],
15+
robotState: TimelineFrame,
16+
robotType: RobotType
17+
): Option[] | DropdownOption[] => {
18+
const sortedAddressableAreasReference =
19+
robotType === FLEX_ROBOT_TYPE
20+
? ALL_FLEX_ADDRESSABLE_AREAS_SORTED
21+
: OT2_SINGLE_SLOT_ADDRESSABLE_AREAS
22+
const { modules: modulesState, labware: labwareState } = robotState
23+
return options.sort((a, b) => {
24+
const getSlot = (value: string): string => {
25+
if (modulesState?.[value]?.slot != null) {
26+
return modulesState[value].slot
27+
}
28+
if (labwareState?.[value]?.stack != null) {
29+
return getSlotInLocationStack(labwareState[value]?.stack)
30+
}
31+
// value is a slot or OFFDECK
32+
return value
33+
}
34+
const slotA = getSlot(a.value) as AddressableAreaName
35+
const slotB = getSlot(b.value) as AddressableAreaName
36+
const indexA = sortedAddressableAreasReference.indexOf(slotA)
37+
const indexB = sortedAddressableAreasReference.indexOf(slotB)
38+
39+
if (indexA === -1 && indexB === -1) {
40+
return 0
41+
}
42+
if (indexA === -1) {
43+
return 1
44+
}
45+
if (indexB === -1) {
46+
return -1
47+
}
48+
49+
return indexA - indexB
50+
})
51+
}

shared-data/js/constants.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,25 @@ export const FLEX_STAGING_AREA_SLOT_ADDRESSABLE_AREAS: AddressableAreaName[] = [
589589
D4_ADDRESSABLE_AREA,
590590
]
591591

592+
export const ALL_FLEX_ADDRESSABLE_AREAS_SORTED: AddressableAreaName[] = [
593+
A1_ADDRESSABLE_AREA,
594+
A2_ADDRESSABLE_AREA,
595+
A3_ADDRESSABLE_AREA,
596+
A4_ADDRESSABLE_AREA,
597+
B1_ADDRESSABLE_AREA,
598+
B2_ADDRESSABLE_AREA,
599+
B3_ADDRESSABLE_AREA,
600+
B4_ADDRESSABLE_AREA,
601+
C1_ADDRESSABLE_AREA,
602+
C2_ADDRESSABLE_AREA,
603+
C3_ADDRESSABLE_AREA,
604+
C4_ADDRESSABLE_AREA,
605+
D1_ADDRESSABLE_AREA,
606+
D2_ADDRESSABLE_AREA,
607+
D3_ADDRESSABLE_AREA,
608+
D4_ADDRESSABLE_AREA,
609+
]
610+
592611
export const MOVABLE_TRASH_ADDRESSABLE_AREAS: AddressableAreaName[] = [
593612
MOVABLE_TRASH_A1_ADDRESSABLE_AREA,
594613
MOVABLE_TRASH_A3_ADDRESSABLE_AREA,

0 commit comments

Comments
 (0)