Skip to content

Commit d7d7315

Browse files
authored
feat(protocol-designer): mix tools advanced settings and mix batch edit (#16509)
closes AUTH-930 AUTH-926
1 parent 61c2775 commit d7d7315

File tree

5 files changed

+372
-12
lines changed

5 files changed

+372
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,192 @@
1-
export function BatchEditMixTools(): JSX.Element {
2-
return <div>Todo: wire this up</div>
1+
import { useTranslation } from 'react-i18next'
2+
import { useState } from 'react'
3+
import {
4+
DIRECTION_COLUMN,
5+
Divider,
6+
Flex,
7+
SPACING,
8+
StyledText,
9+
Tabs,
10+
} from '@opentrons/components'
11+
import {
12+
CheckboxExpandStepFormField,
13+
InputStepFormField,
14+
} from '../../../../molecules'
15+
import {
16+
BlowoutLocationField,
17+
FlowRateField,
18+
PositionField,
19+
WellsOrderField,
20+
} from '../StepForm/PipetteFields'
21+
import {
22+
getBlowoutLocationOptionsForForm,
23+
getLabwareFieldForPositioningField,
24+
} from '../StepForm/utils'
25+
import type { WellOrderOption } from '../../../../form-types'
26+
import type { FieldPropsByName } from '../StepForm/types'
27+
28+
interface BatchEditMixToolsProps {
29+
propsForFields: FieldPropsByName
30+
}
31+
32+
export function BatchEditMixTools(props: BatchEditMixToolsProps): JSX.Element {
33+
const { propsForFields } = props
34+
const { t, i18n } = useTranslation(['form', 'button', 'tooltip'])
35+
const [tab, setTab] = useState<'aspirate' | 'dispense'>('aspirate')
36+
const aspirateTab = {
37+
text: i18n.format(t('aspirate'), 'capitalize'),
38+
isActive: tab === 'aspirate',
39+
onClick: () => {
40+
setTab('aspirate')
41+
},
42+
}
43+
const dispenseTab = {
44+
text: i18n.format(t('dispense'), 'capitalize'),
45+
isActive: tab === 'dispense',
46+
onClick: () => {
47+
setTab('dispense')
48+
},
49+
}
50+
51+
const getLabwareIdForPositioningField = (name: string): string | null => {
52+
const labwareField = getLabwareFieldForPositioningField(name)
53+
const labwareId = propsForFields[labwareField]?.value
54+
return labwareId ? String(labwareId) : null
55+
}
56+
57+
const getPipetteIdForForm = (): string | null => {
58+
const pipetteId = propsForFields.pipette?.value
59+
return pipetteId ? String(pipetteId) : null
60+
}
61+
62+
const getWellOrderFieldValue = (
63+
name: string
64+
): WellOrderOption | null | undefined => {
65+
const val = propsForFields[name]?.value
66+
if (val === 'l2r' || val === 'r2l' || val === 't2b' || val === 'b2t') {
67+
return val
68+
} else {
69+
return null
70+
}
71+
}
72+
73+
return (
74+
<Flex flexDirection={DIRECTION_COLUMN} width="100%">
75+
<Flex padding={SPACING.spacing16}>
76+
<Tabs tabs={[aspirateTab, dispenseTab]} />
77+
</Flex>
78+
<Divider marginY="0" />
79+
<Flex padding={SPACING.spacing16} width="100%">
80+
<FlowRateField
81+
{...propsForFields[`${tab}_flowRate`]}
82+
pipetteId={getPipetteIdForForm()}
83+
flowRateType={tab}
84+
volume={propsForFields.volume?.value ?? 0}
85+
tiprack={propsForFields.tipRack.value}
86+
/>
87+
</Flex>
88+
<Divider marginY="0" />
89+
{tab === 'aspirate' ? (
90+
<>
91+
<WellsOrderField
92+
prefix={tab}
93+
updateFirstWellOrder={
94+
propsForFields.mix_wellOrder_first.updateValue
95+
}
96+
updateSecondWellOrder={
97+
propsForFields.mix_wellOrder_second.updateValue
98+
}
99+
firstValue={getWellOrderFieldValue('mix_wellOrder_first')}
100+
secondValue={getWellOrderFieldValue('mix_wellOrder_second')}
101+
firstName="mix_wellOrder_first"
102+
secondName="mix_wellOrder_second"
103+
/>
104+
<Divider marginY="0" />
105+
<PositionField
106+
prefix="mix"
107+
propsForFields={propsForFields}
108+
zField="mix_mmFromBottom"
109+
xField="mix_x_position"
110+
yField="mix_y_position"
111+
labwareId={getLabwareIdForPositioningField('mix_mmFromBottom')}
112+
/>
113+
<Divider marginY="0" />
114+
</>
115+
) : null}
116+
<Flex
117+
flexDirection={DIRECTION_COLUMN}
118+
padding={SPACING.spacing12}
119+
gridGap={SPACING.spacing8}
120+
>
121+
<StyledText desktopStyle="bodyDefaultSemiBold">
122+
{t('protocol_steps:advanced_settings')}
123+
</StyledText>
124+
<CheckboxExpandStepFormField
125+
title={i18n.format(
126+
t('form:step_edit_form.field.delay.label'),
127+
'capitalize'
128+
)}
129+
checkboxValue={propsForFields[`${tab}_delay_checkbox`].value}
130+
isChecked={propsForFields[`${tab}_delay_checkbox`].value === true}
131+
checkboxUpdateValue={
132+
propsForFields[`${tab}_delay_checkbox`].updateValue
133+
}
134+
>
135+
{propsForFields[`${tab}_delay_checkbox`].value === true ? (
136+
<InputStepFormField
137+
showTooltip={false}
138+
padding="0"
139+
title={t('protocol_steps:delay_duration')}
140+
{...propsForFields[`${tab}_delay_seconds`]}
141+
units={t('application:units.seconds')}
142+
/>
143+
) : null}
144+
</CheckboxExpandStepFormField>
145+
{tab === 'dispense' ? (
146+
<>
147+
<CheckboxExpandStepFormField
148+
title={i18n.format(
149+
t('form:step_edit_form.field.blowout.label'),
150+
'capitalize'
151+
)}
152+
checkboxValue={propsForFields.blowout_checkbox.value}
153+
isChecked={propsForFields.blowout_checkbox.value === true}
154+
checkboxUpdateValue={propsForFields.blowout_checkbox.updateValue}
155+
>
156+
{propsForFields.blowout_checkbox.value === true ? (
157+
<BlowoutLocationField
158+
{...propsForFields.blowout_location}
159+
options={getBlowoutLocationOptionsForForm({
160+
stepType: 'mix',
161+
})}
162+
/>
163+
) : null}
164+
</CheckboxExpandStepFormField>
165+
<CheckboxExpandStepFormField
166+
title={i18n.format(
167+
t('form:step_edit_form.field.touchTip.label'),
168+
'capitalize'
169+
)}
170+
checkboxValue={propsForFields.mix_touchTip_checkbox.value}
171+
isChecked={propsForFields.mix_touchTip_checkbox.value === true}
172+
checkboxUpdateValue={
173+
propsForFields.mix_touchTip_checkbox.updateValue
174+
}
175+
>
176+
{propsForFields.mix_touchTip_checkbox.value === true ? (
177+
<PositionField
178+
prefix="dispense"
179+
propsForFields={propsForFields}
180+
zField="mix_touchTip_mmFromBottom"
181+
labwareId={getLabwareIdForPositioningField(
182+
'mix_touchTip_mmFromBottom'
183+
)}
184+
/>
185+
) : null}
186+
</CheckboxExpandStepFormField>
187+
</>
188+
) : null}
189+
</Flex>
190+
</Flex>
191+
)
3192
}

protocol-designer/src/pages/Designer/ProtocolSteps/BatchEditToolbox/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export const BatchEditToolbox = (): JSX.Element | null => {
9191
{stepType === 'moveLiquid' ? (
9292
<BatchEditMoveLiquidTools propsForFields={propsForFields} />
9393
) : (
94-
<BatchEditMixTools />
94+
<BatchEditMixTools propsForFields={propsForFields} />
9595
)}
9696
</Toolbox>
9797
)

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/PipetteFields/PositionField.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import type {
2626
import type { FieldPropsByName } from '../types'
2727
import type { PositionSpecs } from '../../../../../components/StepEditForm/fields/TipPositionField/TipPositionModal'
2828
interface PositionFieldProps {
29-
prefix: 'aspirate' | 'dispense'
29+
prefix: 'aspirate' | 'dispense' | 'mix'
3030
propsForFields: FieldPropsByName
3131
zField: TipZOffsetFields
3232
xField?: TipXOffsetFields

0 commit comments

Comments
 (0)