Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol-designer): transfer tools advanced settings and batch edit transfer #16488

Merged
merged 3 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -104,6 +118,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
}
}
jerader marked this conversation as resolved.
Show resolved Hide resolved

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
Loading