Skip to content

Commit

Permalink
feat(protocol-designer): transfer tools advanced settings and batch e…
Browse files Browse the repository at this point in the history
…dit transfer (#16488)

closes AUTH-870, partially addresses AUTH-926
  • Loading branch information
jerader authored Oct 17, 2024
1 parent 61e886d commit 35efa6f
Show file tree
Hide file tree
Showing 15 changed files with 1,469 additions and 27 deletions.
21 changes: 20 additions & 1 deletion protocol-designer/src/assets/localization/en/protocol_steps.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
{
"add_details": "Add step details",
"advanced_settings": "Advanced pipetting settings",
"air_gap_volume": "Air gap volume",
"aspirate": "Aspirate",
"aspirated": "Aspirated",
"batch_edit_steps": "Batch edit steps",
"batch_edit": "Batch edit",
"batch_edits_saved": "Batch edits saved",
"blowout_location": "Blowout location",
"blowout_position": "Blowout position from bottom",
"change_tips": "Change tips",
"default_tip_option": "Default - get next tip",
"delay_duration": "Delay duration",
"delay_position": "Delay position from bottom",
"delete_steps": "Delete steps",
"delete": "Delete step",
"dispense": "Dispense",
"dispensed": "Dispensed",
"disposal_volume": "Disposal volume",
"duplicate_steps": "Duplicate steps",
"duplicate": "Duplicate step",
"edit_step": "Edit step",
"engage_height": "Engage height",
"final_deck_state": "Final deck state",
"flow_type_title": "{{type}} flow rate",
"from": "from",
"heater_shaker": {
"active": {
Expand All @@ -35,6 +45,9 @@
"disengage": "<semiBoldText>{{module}}</semiBoldText><text>disengaged</text>",
"engage": "<semiBoldText>{{module}}</semiBoldText><text>engaged to</text><tag/>"
},
"max_disposal_volume": "Max {{vol}} {{unit}}",
"mix_times": "Mix repititions",
"mix_volume": "Mix volume",
"mix": "Mix",
"mix_step": "<text>Mixing</text><tag/><text>{{times}} times in</text><semiBoldText>{{labware}}</semiBoldText>",
"mix_repetitions": "Mix repetitions",
Expand All @@ -48,6 +61,7 @@
"distribute": "<text>Distributing</text><tag/><text>from</text><semiBoldText>{{source}}</semiBoldText><text>to</text><semiBoldText>{{destination}}</semiBoldText>",
"transfer": "<text>Transferring</text><tag/><text>from</text><semiBoldText>{{source}}</semiBoldText><text>to</text><semiBoldText>{{destination}}</semiBoldText>"
},
"multi_dispense_options": "Distribute options",
"multiAspirate": "Consolidate path",
"multiDispense": "Distribute path",
"new_location": "New location",
Expand Down Expand Up @@ -105,6 +119,11 @@
}
},
"time": "Time",
"tip_position": "{{prefix}} tip position",
"touch_tip_position": "Touch tip position from top",
"valid_range": "Valid range between {{min}} - {{max}} {{unit}}",
"view_details": "View details",
"well_name": "Well {{wellName}}"
"well_name": "Well {{wellName}}",
"well_order_title": "{{prefix}} well order",
"well_position": "Well position (x,y,z): "
}
1 change: 1 addition & 0 deletions protocol-designer/src/assets/localization/en/shared.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"destination_well": "Destination Well",
"developer_ff": "Developer feature flags",
"done": "Done",
"pipette": "Pipette",
"edit_existing": "Edit existing protocol",
"edit_instruments": "Edit Instruments",
"edit_pipette": "Edit Pipette",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface CheckboxExpandStepFormFieldProps {
checkboxUpdateValue: (value: unknown) => void
checkboxValue: unknown
isChecked: boolean
children: React.ReactNode
children?: React.ReactNode
}
export function CheckboxExpandStepFormField(
props: CheckboxExpandStepFormFieldProps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type { FieldProps } from '../../pages/Designer/ProtocolSteps/StepForm/typ
export interface DropdownStepFormFieldProps extends FieldProps {
options: Options
title: string
addPadding?: boolean
width?: string
}

export function DropdownStepFormField(
Expand All @@ -18,15 +20,17 @@ export function DropdownStepFormField(
title,
errorToShow,
tooltipContent,
addPadding = true,
width = '17.5rem',
} = props
const { t } = useTranslation('tooltip')
const availableOptionId = options.find(opt => opt.value === value)

return (
<Flex padding={SPACING.spacing16}>
<Flex padding={addPadding ? SPACING.spacing16 : 0}>
<DropdownMenu
tooltipText={tooltipContent != null ? t(`${tooltipContent}`) : null}
width="17.5rem"
width={width}
error={errorToShow}
dropdownType="neutral"
filterOptions={options}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,251 @@
export function BatchEditMoveLiquidTools(): JSX.Element {
return <div>Todo: wire this up</div>
import { useTranslation } from 'react-i18next'
import { useState } from 'react'
import {
DIRECTION_COLUMN,
Divider,
Flex,
SPACING,
StyledText,
Tabs,
} from '@opentrons/components'
import {
CheckboxExpandStepFormField,
InputStepFormField,
} from '../../../../molecules'
import {
getBlowoutLocationOptionsForForm,
getLabwareFieldForPositioningField,
} from '../StepForm/utils'
import {
BlowoutLocationField,
BlowoutOffsetField,
FlowRateField,
PositionField,
WellsOrderField,
} from '../StepForm/PipetteFields'
import type { WellOrderOption } from '../../../../form-types'
import type { FieldPropsByName } from '../StepForm/types'

interface BatchEditMoveLiquidProps {
propsForFields: FieldPropsByName
}

export function BatchEditMoveLiquidTools(
props: BatchEditMoveLiquidProps
): JSX.Element {
const { t, i18n } = useTranslation(['button', 'tooltip', 'protocol_steps'])
const { propsForFields } = props
const [tab, setTab] = useState<'aspirate' | 'dispense'>('aspirate')
const aspirateTab = {
text: t('protocol_steps:aspirate'),
isActive: tab === 'aspirate',
onClick: () => {
setTab('aspirate')
},
}
const dispenseTab = {
text: t('protocol_steps:dispense'),

isActive: tab === 'dispense',
onClick: () => {
setTab('dispense')
},
}
const addFieldNamePrefix = (name: string): string => `${tab}_${name}`
const getPipetteIdForForm = (): string | null => {
const pipetteId = propsForFields.pipette?.value
return pipetteId ? String(pipetteId) : null
}
const getLabwareIdForPositioningField = (name: string): string | null => {
const labwareField = getLabwareFieldForPositioningField(name)
const labwareId = propsForFields[labwareField]?.value
return labwareId ? String(labwareId) : null
}
const getWellOrderFieldValue = (
name: string
): WellOrderOption | null | undefined => {
const val = propsForFields[name]?.value
if (val === 'l2r' || val === 'r2l' || val === 't2b' || val === 'b2t') {
return val
} else {
return null
}
}

return (
<Flex flexDirection={DIRECTION_COLUMN} width="100%">
<Flex padding={SPACING.spacing16}>
<Tabs tabs={[aspirateTab, dispenseTab]} />
</Flex>
<Divider marginY="0" />
<Flex padding={SPACING.spacing16} width="100%">
<FlowRateField
{...propsForFields[addFieldNamePrefix('flowRate')]}
pipetteId={getPipetteIdForForm()}
flowRateType={tab}
volume={propsForFields.volume?.value ?? 0}
tiprack={propsForFields.tipRack.value}
/>
</Flex>
<Divider marginY="0" />
<WellsOrderField
prefix={tab}
updateFirstWellOrder={
propsForFields[addFieldNamePrefix('wellOrder_first')].updateValue
}
updateSecondWellOrder={
propsForFields[addFieldNamePrefix('wellOrder_second')].updateValue
}
firstValue={getWellOrderFieldValue(
addFieldNamePrefix('wellOrder_first')
)}
secondValue={getWellOrderFieldValue(
addFieldNamePrefix('wellOrder_second')
)}
firstName={addFieldNamePrefix('wellOrder_first')}
secondName={addFieldNamePrefix('wellOrder_second')}
/>
<Divider marginY="0" />
<PositionField
prefix={tab}
propsForFields={propsForFields}
zField={`${tab}_mmFromBottom`}
xField={`${tab}_x_position`}
yField={`${tab}_y_position`}
labwareId={getLabwareIdForPositioningField(
addFieldNamePrefix('mmFromBottom')
)}
/>
<Divider marginY="0" />
<Flex
flexDirection={DIRECTION_COLUMN}
padding={SPACING.spacing12}
gridGap={SPACING.spacing8}
>
<StyledText desktopStyle="bodyDefaultSemiBold">
{t('protocol_steps:advanced_settings')}
</StyledText>
{tab === 'aspirate' ? (
<CheckboxExpandStepFormField
title={i18n.format(
t('form:step_edit_form.field.preWetTip.label'),
'capitalize'
)}
checkboxValue={propsForFields.preWetTip.value}
isChecked={propsForFields.preWetTip.value === true}
checkboxUpdateValue={propsForFields.preWetTip.updateValue}
/>
) : null}
<CheckboxExpandStepFormField
title={i18n.format(
t('form:step_edit_form.field.mix.label'),
'capitalize'
)}
checkboxValue={propsForFields[`${tab}_mix_checkbox`].value}
isChecked={propsForFields[`${tab}_mix_checkbox`].value === true}
checkboxUpdateValue={
propsForFields[`${tab}_mix_checkbox`].updateValue
}
>
{propsForFields[`${tab}_mix_checkbox`].value === true ? (
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing6}
width="100^"
>
<InputStepFormField
showTooltip={false}
padding="0"
title={t('protocol_steps:mix_volume')}
{...propsForFields[`${tab}_mix_volume`]}
units={t('application:units.microliter')}
/>
<InputStepFormField
showTooltip={false}
padding="0"
title={t('protocol_steps:mix_times')}
{...propsForFields[`${tab}_mix_times`]}
units={t('application:units.times')}
/>
</Flex>
) : null}
</CheckboxExpandStepFormField>
<CheckboxExpandStepFormField
title={i18n.format(
t('form:step_edit_form.field.delay.label'),
'capitalize'
)}
checkboxValue={propsForFields[`${tab}_delay_checkbox`].value}
isChecked={propsForFields[`${tab}_delay_checkbox`].value === true}
checkboxUpdateValue={
propsForFields[`${tab}_delay_checkbox`].updateValue
}
>
{propsForFields[`${tab}_delay_checkbox`].value === true ? (
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing6}
width="100^"
>
<InputStepFormField
showTooltip={false}
padding="0"
title={t('protocol_steps:delay_duration')}
{...propsForFields[`${tab}_delay_seconds`]}
units={t('application:units.seconds')}
/>
<PositionField
prefix={tab}
propsForFields={propsForFields}
zField={`${tab}_delay_mmFromBottom`}
labwareId={getLabwareIdForPositioningField(
addFieldNamePrefix('delay_mmFromBottom')
)}
/>
</Flex>
) : null}
</CheckboxExpandStepFormField>
{tab === 'dispense' ? (
<CheckboxExpandStepFormField
title={i18n.format(
t('form:step_edit_form.field.blowout.label'),
'capitalize'
)}
checkboxValue={propsForFields.blowout_checkbox.value}
isChecked={propsForFields.blowout_checkbox.value === true}
checkboxUpdateValue={propsForFields.blowout_checkbox.updateValue}
>
{propsForFields.blowout_checkbox.value === true ? (
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing6}
width="100^"
>
<BlowoutLocationField
{...propsForFields.blowout_location}
options={getBlowoutLocationOptionsForForm({
path: propsForFields.path.value as any,
stepType: 'moveLiquid',
})}
/>
<FlowRateField
{...propsForFields.blowout_flowRate}
pipetteId={getPipetteIdForForm()}
flowRateType="blowout"
volume={propsForFields.volume?.value ?? 0}
tiprack={propsForFields.tipRack.value}
/>
<BlowoutOffsetField
{...propsForFields.blowout_z_offset}
sourceLabwareId={propsForFields.aspirate_labware.value}
destLabwareId={propsForFields.dispense_labware.value}
blowoutLabwareId={propsForFields.blowout_location.value}
/>
</Flex>
) : null}
</CheckboxExpandStepFormField>
) : null}
</Flex>
</Flex>
)
}
Loading

0 comments on commit 35efa6f

Please sign in to comment.