Skip to content

Commit

Permalink
add batch edit move liquid tools
Browse files Browse the repository at this point in the history
  • Loading branch information
jerader committed Oct 16, 2024
1 parent 5286092 commit f047228
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 45 deletions.
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>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import {
import { useKitchen } from '../../../../organisms/Kitchen/hooks'
import { deselectAllSteps } from '../../../../ui/steps/actions/actions'
import {
// changeBatchEditField,
changeBatchEditField,
resetBatchEditFieldChanges,
saveStepFormsMulti,
} from '../../../../step-forms/actions'
import { maskField } from '../../../../steplist/fieldLevel'
import { getBatchEditFormHasUnsavedChanges } from '../../../../step-forms/selectors'
import { makeBatchEditFieldProps } from './utils'
import { BatchEditMoveLiquidTools } from './BatchEditMoveLiquidTools'
import { BatchEditMixTools } from './BatchEditMixTools'
// import { maskField } from '../../../../steplist/fieldLevel'

// import type { StepFieldName } from '../../../../steplist/fieldLevel'
import type { StepFieldName } from '../../../../steplist/fieldLevel'
import type { ThunkDispatch } from 'redux-thunk'
import type { BaseState } from '../../../../types'

Expand All @@ -30,15 +32,16 @@ export const BatchEditToolbox = (): JSX.Element | null => {
const stepTypes = useSelector(getBatchEditSelectedStepTypes)
const disabledFields = useSelector(getMultiSelectDisabledFields)
const selectedStepIds = useSelector(getMultiSelectItemIds)
const batchEditFormHasChanges = useSelector(getBatchEditFormHasUnsavedChanges)

// const handleChangeFormInput = (name: StepFieldName, value: unknown): void => {
// const maskedValue = maskField(name, value)
// dispatch(changeBatchEditField({ [name]: maskedValue }))
// }
const handleChangeFormInput = (name: StepFieldName, value: unknown): void => {
const maskedValue = maskField(name, value)
dispatch(changeBatchEditField({ [name]: maskedValue }))
}

const handleSave = (): void => {
dispatch(saveStepFormsMulti(selectedStepIds))
makeSnackbar(t('batch_edits_saved') as string)
makeSnackbar(t('protocol_steps:batch_edits_saved') as string)
dispatch(deselectAllSteps('EXIT_BATCH_EDIT_MODE_BUTTON_PRESS'))
}

Expand All @@ -50,12 +53,12 @@ export const BatchEditToolbox = (): JSX.Element | null => {
const stepType = stepTypes.length === 1 ? stepTypes[0] : null

if (stepType !== null && fieldValues !== null && disabledFields !== null) {
// const propsForFields = makeBatchEditFieldProps(
// fieldValues,
// disabledFields,
// handleChangeFormInput,
// t
// )
const propsForFields = makeBatchEditFieldProps(
fieldValues,
disabledFields,
handleChangeFormInput,
t
)
if (stepType === 'moveLiquid' || stepType === 'mix') {
return (
<Toolbox
Expand All @@ -69,13 +72,17 @@ export const BatchEditToolbox = (): JSX.Element | null => {
onCloseClick={handleCancel}
closeButton={<Icon size="2rem" name="close" />}
confirmButton={
<PrimaryButton onClick={handleSave} width="100%">
<PrimaryButton
onClick={handleSave}
disabled={!batchEditFormHasChanges}
width="100%"
>
{t('shared:save')}
</PrimaryButton>
}
>
{stepType === 'moveLiquid' ? (
<BatchEditMoveLiquidTools />
<BatchEditMoveLiquidTools propsForFields={propsForFields} />
) : (
<BatchEditMixTools />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import { ZTipPositionModal } from '../../../../../components/StepEditForm/fields
import { getLabwareEntities } from '../../../../../step-forms/selectors'
import type { FieldProps } from '../types'

interface BlowoutZOffsetFieldProps extends FieldProps {
interface BlowoutOffsetFieldProps extends FieldProps {
destLabwareId: unknown
sourceLabwareId?: unknown
blowoutLabwareId?: unknown
}

export function BlowoutZOffsetField(
props: BlowoutZOffsetFieldProps
export function BlowoutOffsetField(
props: BlowoutOffsetFieldProps
): JSX.Element {
const {
disabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import {
} from '../../../../../molecules'
import { getBlowoutLocationOptionsForForm } from '../utils'
import { FlowRateField } from './FlowRateField'
import { BlowoutZOffsetField } from './BlowoutZOffsetField'
import { BlowoutOffsetField } from './BlowoutOffsetField'

import type { PathOption, StepType } from '../../../../../form-types'
import type { FieldPropsByName } from '../types'

interface DisposalVolumeFieldProps {
interface DisposalFieldProps {
path: PathOption
pipette: string | null
propsForFields: FieldPropsByName
Expand All @@ -27,9 +27,7 @@ interface DisposalVolumeFieldProps {
tipRack?: string | null
}

export const DisposalVolumeField = (
props: DisposalVolumeFieldProps
): JSX.Element => {
export const DisposalField = (props: DisposalFieldProps): JSX.Element => {
const {
path,
stepType,
Expand Down Expand Up @@ -104,7 +102,7 @@ export const DisposalVolumeField = (
volume={propsForFields.volume?.value ?? 0}
tiprack={propsForFields.tipRack.value}
/>
<BlowoutZOffsetField
<BlowoutOffsetField
{...propsForFields.blowout_z_offset}
sourceLabwareId={propsForFields.aspirate_labware.value}
destLabwareId={propsForFields.dispense_labware.value}
Expand Down
Loading

0 comments on commit f047228

Please sign in to comment.