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, components): add retract for aspirate and dispense to PD #17411

Open
wants to merge 17 commits into
base: edge
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
Expand Up @@ -150,6 +150,8 @@
"aspirate_mix_times": "2",
"aspirate_mix_volume": "30",
"aspirate_mmFromBottom": 1,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": true,
Expand All @@ -176,6 +178,8 @@
"dispense_mix_times": null,
"dispense_mix_volume": null,
"dispense_mmFromBottom": 0.5,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@
"aspirate_mix_times": null,
"aspirate_mix_volume": null,
"aspirate_mmFromBottom": 1,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": false,
Expand All @@ -208,6 +210,8 @@
"dispense_mix_times": null,
"dispense_mix_volume": null,
"dispense_mmFromBottom": 0.5,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@
"aspirate_mix_times": null,
"aspirate_mix_volume": null,
"aspirate_mmFromBottom": null,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": false,
Expand All @@ -225,6 +227,8 @@
"dispense_mix_times": null,
"dispense_mix_volume": null,
"dispense_mmFromBottom": null,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": false,
Expand Down
4 changes: 4 additions & 0 deletions protocol-designer/fixtures/protocol/8/doItAllV8.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@
"aspirate_mix_times": null,
"aspirate_mix_volume": null,
"aspirate_mmFromBottom": null,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": false,
Expand All @@ -185,6 +187,8 @@
"dispense_mix_times": null,
"dispense_mix_volume": null,
"dispense_mmFromBottom": null,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@
"aspirate_mix_times": 3,
"aspirate_mix_volume": "2",
"aspirate_mmFromBottom": 1,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": true,
Expand All @@ -147,6 +149,8 @@
"dispense_mix_times": 2,
"dispense_mix_volume": "3",
"dispense_mmFromBottom": 2.5,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
"aspirate_mix_times": null,
"aspirate_mix_volume": null,
"aspirate_mmFromBottom": 29,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": false,
Expand All @@ -89,6 +91,8 @@
"dispense_mix_times": null,
"dispense_mix_volume": null,
"dispense_mmFromBottom": null,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
"aspirate_mix_times": null,
"aspirate_mix_volume": null,
"aspirate_mmFromBottom": null,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": false,
Expand All @@ -88,6 +90,8 @@
"dispense_mix_times": null,
"dispense_mix_volume": null,
"dispense_mmFromBottom": null,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": false,
Expand Down Expand Up @@ -124,6 +128,8 @@
"aspirate_mix_times": null,
"aspirate_mix_volume": null,
"aspirate_mmFromBottom": null,
"aspirate_retract_delay_seconds": null,
"aspirate_retract_speed": null,
"aspirate_submerge_delay_seconds": null,
"aspirate_submerge_speed": null,
"aspirate_touchTip_checkbox": false,
Expand All @@ -150,6 +156,8 @@
"dispense_mix_times": null,
"dispense_mix_volume": null,
"dispense_mmFromBottom": null,
"dispense_retract_delay_seconds": null,
"dispense_retract_speed": null,
"dispense_submerge_delay_seconds": null,
"dispense_submerge_speed": null,
"dispense_touchTip_checkbox": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
"protocol_timeline": "Protocol timeline",
"rename": "Rename",
"rename_error": "Oops! Your step name is too long.",
"retract": "Retract",
"retract_speed": "Retract speed",
"save_errors": "{{stepType}} has been saved with {{numErrors}} error(s)",
"save_no_errors": "{{stepType}} has been saved",
"save_warnings": "{{stepType}} has been saved with {{numWarnings}} warning(s)",
Expand Down
2 changes: 2 additions & 0 deletions protocol-designer/src/assets/localization/en/tooltip.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"aspirate_mmFromBottom": "Adjust tip position for aspirate",
"aspirate_touchTip_checkbox": "Touch tip to each side of the well after aspirating",
"aspirate_touchTip_mmFromTop": "Distance from the top of the well",
"aspirate_retract": "Withdraw the tip from the liquid after aspirating",
"aspirate_submerge": "Lower the tip into the liquid before aspirating",
"aspirate_wells": "First select a source labware",
"blowout_checkbox": "Blow extra air through the tip",
Expand All @@ -51,6 +52,7 @@
"dispense_labware": "Pipette unable to access labware in staging area",
"dispense_mix_checkbox": "Aspirate and dispense repeatedly after main dispense",
"dispense_mmFromBottom": "Adjust tip position for dispense",
"dispense_retract": "Withdraw the tip from the liquid after dispensing",
"dispense_submerge": "Lower the tip into the liquid before dispensing",
"dispense_touchTip_checkbox": "Touch tip to each side of the well after dispensing",
"dispense_touchTip_mmFromTop": "Distance from the top of the well",
Expand Down
8 changes: 8 additions & 0 deletions protocol-designer/src/form-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export type StepFieldName = string
// | 'aspirate_mix_times'
// | 'aspirate_mix_volume'
// | 'aspirate_mmFromBottom'
// | 'aspirate_retract_delay_seconds'
// | 'aspirate_retract_speed'
// | 'aspirate_submerge_delay_seconds'
// | 'aspirate_submerge_speed'
// | 'aspirate_touchTip_checkbox'
Expand All @@ -53,6 +55,8 @@ export type StepFieldName = string
// | 'dispense_mix_times'
// | 'dispense_mix_volume'
// | 'dispense_mmFromBottom'
// | 'dispense_retract_delay_seconds'
// | 'dispense_retract_speed'
// | 'dispense_submerge_delay_seconds'
// | 'dispense_submerge_speed'
// | 'dispense_touchTip_checkbox'
Expand Down Expand Up @@ -256,6 +260,8 @@ export interface HydratedMoveLiquidFormData extends AnnotationFields {
aspirate_mix_times?: number | null
aspirate_mix_volume?: number | null
aspirate_mmFromBottom?: number | null
aspirate_retract_delay_seconds?: number | null
aspirate_retract_speed?: number | null
aspirate_submerge_delay_seconds?: number | null
aspirate_submerge_speed?: number | null
aspirate_touchTip_mmFromTop?: number | null
Expand All @@ -272,6 +278,8 @@ export interface HydratedMoveLiquidFormData extends AnnotationFields {
dispense_mix_times?: number | null
dispense_mix_volume?: number | null
dispense_mmFromBottom?: number | null
dispense_retract_delay_seconds?: number | null
dispense_retract_speed?: number | null
dispense_submerge_delay_seconds?: number | null
dispense_submerge_speed?: number | null
dispense_touchTip_mmFromTop?: number | null
Expand Down
4 changes: 4 additions & 0 deletions protocol-designer/src/load-file/migration/8_5_0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ export const migrateFile = (
matchingDispenseLabwareWellDepth,
1
),
aspirate_retract_delay_seconds: null,
dispense_retract_delay_seconds: null,
aspirate_retract_speed: null,
dispense_retract_speed: null,
aspirate_submerge_delay_seconds: null,
dispense_submerge_delay_seconds: null,
aspirate_submerge_speed: null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { useTranslation } from 'react-i18next'
import {
ALIGN_CENTER,
COLORS,
DIRECTION_COLUMN,
Flex,
Icon,
ListItem,
SPACING,
StyledText,
Tooltip,
useHoverTooltip,
} from '@opentrons/components'
import { InputStepFormField } from '../../../../../../molecules'
import { PositionField } from '../../PipetteFields'
import type { FieldPropsByName } from '../../types'

export interface StepInputFieldProps {
fieldTitle: string
fieldKey: string
units: string
errorToShow?: string | null
}
interface MultiInputFieldProps {
name: string
tab: 'aspirate' | 'dispense'
tooltipContent: string
propsForFields: FieldPropsByName
fields: StepInputFieldProps[]
isWellPosition?: boolean | null
labwareId?: string | null
}

export function MultiInputField(props: MultiInputFieldProps): JSX.Element {
const {
name,
tab,
tooltipContent,
isWellPosition,
fields,
propsForFields,
labwareId,
} = props
const [targetProps, tooltipProps] = useHoverTooltip()
const { t } = useTranslation(['protocol_steps', 'form', 'tooltip'])

return (
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing8}
padding={`0 ${SPACING.spacing16}`}
>
<Flex gridGap={SPACING.spacing8} alignItems={ALIGN_CENTER}>
<StyledText desktopStyle="bodyDefaultRegular" color={COLORS.grey60}>
{t(`protocol_steps:${name}`)}
</StyledText>
<Flex {...targetProps}>
<Icon
name="information"
size="1rem"
color={COLORS.grey60}
data-testid="information_icon"
/>
</Flex>
<Tooltip tooltipProps={tooltipProps}>{tooltipContent}</Tooltip>
</Flex>
<ListItem type="noActive">
<Flex
padding={SPACING.spacing12}
width="100%"
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing8}
>
{fields.map(({ fieldTitle, fieldKey, units, errorToShow }) => (
<InputStepFormField
key={fieldKey}
showTooltip={false}
padding="0"
title={t(fieldTitle)}
{...propsForFields[fieldKey]}
units={t(units)}
errorToShow={errorToShow}
/>
))}
{isWellPosition != null && (
<PositionField
padding="0"
prefix={tab}
propsForFields={propsForFields}
zField={`${tab}_mmFromBottom`}
xField={`${tab}_x_position`}
yField={`${tab}_y_position`}
labwareId={labwareId}
/>
)}
</Flex>
</ListItem>
</Flex>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { fireEvent, screen } from '@testing-library/react'
import { i18n } from '../../../../../../../assets/localization'
import { renderWithProviders } from '../../../../../../../__testing-utils__'
import { MultiInputField } from '../MultiInputField'

import type { ComponentProps } from 'react'
import { COLORS } from '@opentrons/components'

const render = (props: ComponentProps<typeof MultiInputField>) => {
return renderWithProviders(<MultiInputField {...props} />, {
i18nInstance: i18n,
})
}

describe('MultiInputField', () => {
let props: ComponentProps<typeof MultiInputField>

beforeEach(() => {
props = {
name: 'Submerge',
tab: 'aspirate',
tooltipContent: 'some tooltip content',
fields: [
{
fieldTitle: 'submerge speed',
fieldKey: 'submerge_speed',
units: 'mm/s',
},
{
fieldTitle: 'submerge delay seconds',
fieldKey: 'submerge_delay_seconds',
units: 'mm',
},
],
propsForFields: {
aspirate_submerge_speed: {
onFieldFocus: vi.fn(),
onFieldBlur: vi.fn(),
errorToShow: null,
disabled: false,
name: 'aspirate_submerge_speed',
updateValue: vi.fn(),
value: null,
},
},
}
})

it('should render input fields with caption and units wrapped by ListItem', () => {
render(props)
screen.getByText('Submerge')
screen.getByTestId('information_icon')
const listItem = screen.getByTestId('ListItem_noActive')
expect(listItem).toHaveStyle(`backgroundColor: ${COLORS.grey20}`)
screen.getByText('submerge speed')
screen.getByText('mm/s')
screen.getByText('submerge delay seconds')
screen.getByText('mm')
const inputs = screen.getAllByRole('textbox', { name: '' })
expect(inputs).toHaveLength(2)
fireEvent.change(inputs[0], { target: { value: ['5'] } })
expect(
props.propsForFields.aspirate_submerge_speed.updateValue
).toHaveBeenCalled()

Check failure on line 65 in protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MultiInputField.test.tsx

View workflow job for this annotation

GitHub Actions / protocol designer unit tests

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MultiInputField.test.tsx > MultiInputField > should render input fields with caption and units wrapped by ListItem

AssertionError: expected "spy" to be called at least once ❯ protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MultiInputField.test.tsx:65:7

Check failure on line 65 in protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MultiInputField.test.tsx

View workflow job for this annotation

GitHub Actions / protocol designer unit tests

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MultiInputField.test.tsx > MultiInputField > should render input fields with caption and units wrapped by ListItem

AssertionError: expected "spy" to be called at least once ❯ protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MultiInputField.test.tsx:65:7
syao1226 marked this conversation as resolved.
Show resolved Hide resolved
})

it('should render a well position listbutton when isWellPosition is true', () => {
props.isWellPosition = true
render(props)
})
})
Loading
Loading