-
Notifications
You must be signed in to change notification settings - Fork 179
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, step-generation): single channel partial tip support for 'default' primaryNozzle only #17222
base: edge
Are you sure you want to change the base?
Changes from all commits
4edea49
7181278
10d626e
418edc3
422a6bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,6 +1,6 @@ | ||||||
import reduce from 'lodash/reduce' | ||||||
|
||||||
import { COLUMN } from '@opentrons/shared-data' | ||||||
import { COLUMN, SINGLE } from '@opentrons/shared-data' | ||||||
import { COLORS } from '@opentrons/components' | ||||||
|
||||||
import { | ||||||
|
@@ -39,7 +39,7 @@ export interface SelectableLabwareProps { | |||||
|
||||||
type ChannelType = 8 | 96 | ||||||
|
||||||
const getChannelsFromNozleType = (nozzleType: NozzleType): ChannelType => { | ||||||
const getChannelsFromNozzleType = (nozzleType: NozzleType): ChannelType => { | ||||||
if (nozzleType === '8-channel' || nozzleType === COLUMN) { | ||||||
return 8 | ||||||
} else { | ||||||
|
@@ -67,8 +67,8 @@ export const SelectableLabware = ( | |||||
selectedWells: WellGroup | ||||||
) => WellGroup = selectedWells => { | ||||||
// Returns PRIMARY WELLS from the selection. | ||||||
if (nozzleType != null) { | ||||||
const channels = getChannelsFromNozleType(nozzleType) | ||||||
if (nozzleType != null && nozzleType !== SINGLE) { | ||||||
const channels = getChannelsFromNozzleType(nozzleType) | ||||||
// for the wells that have been highlighted, | ||||||
// get all 8-well well sets and merge them | ||||||
const primaryWells: WellGroup = reduce( | ||||||
|
@@ -101,8 +101,8 @@ export const SelectableLabware = ( | |||||
rect | ||||||
) => { | ||||||
if (!e.shiftKey) { | ||||||
if (nozzleType != null) { | ||||||
const channels = getChannelsFromNozleType(nozzleType) | ||||||
if (nozzleType != null && nozzleType !== SINGLE) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
const channels = getChannelsFromNozzleType(nozzleType) | ||||||
const selectedWells = _getWellsFromRect(rect) | ||||||
const allWellsForMulti: WellGroup = reduce( | ||||||
selectedWells, | ||||||
|
@@ -142,8 +142,8 @@ export const SelectableLabware = ( | |||||
} | ||||||
|
||||||
const handleMouseEnterWell: (args: WellMouseEvent) => void = args => { | ||||||
if (nozzleType != null) { | ||||||
const channels = getChannelsFromNozleType(nozzleType) | ||||||
if (nozzleType != null && nozzleType !== SINGLE) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as the above |
||||||
const channels = getChannelsFromNozzleType(nozzleType) | ||||||
const wellSet = getWellSetForMultichannel({ | ||||||
labwareDef, | ||||||
wellName: args.wellName, | ||||||
|
@@ -158,11 +158,11 @@ export const SelectableLabware = ( | |||||
|
||||||
// For rendering, show all wells not just primary wells | ||||||
const allSelectedWells = | ||||||
nozzleType != null | ||||||
nozzleType != null && nozzleType !== SINGLE | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as the above |
||||||
? reduce<WellGroup, WellGroup>( | ||||||
selectedPrimaryWells, | ||||||
(acc, _, wellName): WellGroup => { | ||||||
const channels = getChannelsFromNozleType(nozzleType) | ||||||
const channels = getChannelsFromNozzleType(nozzleType) | ||||||
const wellSet = getWellSetForMultichannel({ | ||||||
labwareDef, | ||||||
wellName, | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,74 @@ | ||
import { useEffect, useState } from 'react' | ||
import { useState } from 'react' | ||
import { useTranslation } from 'react-i18next' | ||
import { useSelector } from 'react-redux' | ||
import { ALL, COLUMN } from '@opentrons/shared-data' | ||
import { ALL, COLUMN, SINGLE } from '@opentrons/shared-data' | ||
import { Flex, DropdownMenu, SPACING } from '@opentrons/components' | ||
import { getEnablePartialTipSupport } from '../../../../../feature-flags/selectors' | ||
import { getInitialDeckSetup } from '../../../../../step-forms/selectors' | ||
import type { PipetteV2Specs } from '@opentrons/shared-data' | ||
import type { DropdownOption } from '@opentrons/components' | ||
import type { FieldProps } from '../types' | ||
|
||
export function PartialTipField(props: FieldProps): JSX.Element { | ||
interface PartialTipFieldProps extends FieldProps { | ||
pipetteSpecs: PipetteV2Specs | ||
} | ||
export function PartialTipField(props: PartialTipFieldProps): JSX.Element { | ||
const { | ||
value: dropdownItem, | ||
updateValue, | ||
errorToShow, | ||
padding = `0 ${SPACING.spacing16}`, | ||
tooltipContent, | ||
pipetteSpecs, | ||
} = props | ||
const { t } = useTranslation('protocol_steps') | ||
const deckSetup = useSelector(getInitialDeckSetup) | ||
const enablePartialTip = useSelector(getEnablePartialTipSupport) | ||
const is96Channel = pipetteSpecs.channels === 96 | ||
|
||
const tipracks = Object.values(deckSetup.labware).filter( | ||
labware => labware.def.parameters.isTiprack | ||
) | ||
const tipracksNotOnAdapter = tipracks.filter( | ||
tiprack => deckSetup.labware[tiprack.slot] == null | ||
) | ||
const noTipracksOnAdapter = tipracksNotOnAdapter.length === 0 | ||
|
||
const options = [ | ||
const options: DropdownOption[] = [ | ||
{ | ||
name: t('all'), | ||
value: ALL, | ||
}, | ||
{ | ||
] | ||
if (is96Channel) { | ||
options.push({ | ||
name: t('column'), | ||
value: COLUMN, | ||
disabled: tipracksNotOnAdapter.length === 0, | ||
tooltipText: | ||
tipracksNotOnAdapter.length === 0 | ||
? t('form:step_edit_form.field.nozzles.option_tooltip.COLUMN') | ||
disabled: noTipracksOnAdapter, | ||
tooltipText: noTipracksOnAdapter | ||
? t('form:step_edit_form.field.nozzles.option_tooltip.partial') | ||
: undefined, | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we use |
||
if (enablePartialTip) { | ||
options.push({ | ||
name: t('single_nozzle'), | ||
value: SINGLE, | ||
disabled: noTipracksOnAdapter, | ||
tooltipText: noTipracksOnAdapter | ||
? t('form:step_edit_form.field.nozzles.option_tooltip.partial') | ||
: undefined, | ||
}, | ||
] | ||
}) | ||
} | ||
} else { | ||
options.push({ | ||
name: t('single_nozzle'), | ||
value: SINGLE, | ||
}) | ||
} | ||
|
||
const [selectedValue, setSelectedValue] = useState( | ||
dropdownItem || options[0].value | ||
) | ||
useEffect(() => { | ||
updateValue(selectedValue) | ||
}, [selectedValue]) | ||
|
||
return ( | ||
<Flex padding={padding}> | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -16,7 +16,10 @@ import { | |||||
getLabwareEntities, | ||||||
getPipetteEntities, | ||||||
} from '../../../../../../step-forms/selectors' | ||||||
import { getEnableReturnTip } from '../../../../../../feature-flags/selectors' | ||||||
import { | ||||||
getEnablePartialTipSupport, | ||||||
getEnableReturnTip, | ||||||
} from '../../../../../../feature-flags/selectors' | ||||||
import { | ||||||
BlowoutLocationField, | ||||||
BlowoutOffsetField, | ||||||
|
@@ -53,6 +56,7 @@ export function MixTools(props: StepFormProps): JSX.Element { | |||||
} = props | ||||||
const pipettes = useSelector(getPipetteEntities) | ||||||
const enableReturnTip = useSelector(getEnableReturnTip) | ||||||
const enablePartialTip = useSelector(getEnablePartialTipSupport) | ||||||
const labwares = useSelector(getLabwareEntities) | ||||||
const { t, i18n } = useTranslation(['application', 'form']) | ||||||
const aspirateTab = { | ||||||
|
@@ -74,6 +78,9 @@ export function MixTools(props: StepFormProps): JSX.Element { | |||||
const is96Channel = | ||||||
propsForFields.pipette.value != null && | ||||||
pipettes[String(propsForFields.pipette.value)].name === 'p1000_96' | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we use
Suggested change
|
||||||
const is8Channel = | ||||||
propsForFields.pipette.value != null && | ||||||
pipettes[String(propsForFields.pipette.value)].spec.channels === 8 | ||||||
const userSelectedPickUpTipLocation = | ||||||
labwares[String(propsForFields.pickUpTip_location.value)] != null | ||||||
const userSelectedDropTipLocation = | ||||||
|
@@ -88,7 +95,13 @@ export function MixTools(props: StepFormProps): JSX.Element { | |||||
paddingY={SPACING.spacing16} | ||||||
> | ||||||
<PipetteField {...propsForFields.pipette} /> | ||||||
{is96Channel ? <PartialTipField {...propsForFields.nozzles} /> : null} | ||||||
{propsForFields.pipette.value != null && | ||||||
(is96Channel || (is8Channel && enablePartialTip)) ? ( | ||||||
<PartialTipField | ||||||
{...propsForFields.nozzles} | ||||||
pipetteSpecs={pipettes[String(propsForFields.pipette.value)]?.spec} | ||||||
/> | ||||||
) : null} | ||||||
<Divider marginY="0" /> | ||||||
<TiprackField | ||||||
{...propsForFields.tipRack} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,10 @@ import { | |
Tabs, | ||
} from '@opentrons/components' | ||
import { getTrashOrLabware } from '@opentrons/step-generation' | ||
import { getEnableReturnTip } from '../../../../../../feature-flags/selectors' | ||
import { | ||
getEnablePartialTipSupport, | ||
getEnableReturnTip, | ||
} from '../../../../../../feature-flags/selectors' | ||
import { | ||
getAdditionalEquipmentEntities, | ||
getLabwareEntities, | ||
|
@@ -66,11 +69,11 @@ export function MoveLiquidTools(props: StepFormProps): JSX.Element { | |
const additionalEquipmentEntities = useSelector( | ||
getAdditionalEquipmentEntities | ||
) | ||
const enablePartialTip = useSelector(getEnablePartialTipSupport) | ||
const enableReturnTip = useSelector(getEnableReturnTip) | ||
const labwares = useSelector(getLabwareEntities) | ||
const pipettes = useSelector(getPipetteEntities) | ||
const addFieldNamePrefix = makeAddFieldNamePrefix(tab) | ||
|
||
const isWasteChuteSelected = | ||
propsForFields.dispense_labware?.value != null | ||
? additionalEquipmentEntities[ | ||
|
@@ -91,6 +94,9 @@ export function MoveLiquidTools(props: StepFormProps): JSX.Element { | |
const is96Channel = | ||
propsForFields.pipette.value != null && | ||
pipettes[String(propsForFields.pipette.value)].name === 'p1000_96' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as the above |
||
const is8Channel = | ||
propsForFields.pipette.value != null && | ||
pipettes[String(propsForFields.pipette.value)].spec.channels === 8 | ||
const isDisposalLocation = | ||
additionalEquipmentEntities[String(propsForFields.dispense_labware.value)] | ||
?.name === 'wasteChute' || | ||
|
@@ -143,10 +149,14 @@ export function MoveLiquidTools(props: StepFormProps): JSX.Element { | |
paddingY={SPACING.spacing16} | ||
> | ||
<PipetteField {...propsForFields.pipette} /> | ||
{is96Channel ? ( | ||
{propsForFields.pipette.value != null && | ||
(is96Channel || (is8Channel && enablePartialTip)) ? ( | ||
<> | ||
<Divider marginY="0" /> | ||
<PartialTipField {...propsForFields.nozzles} /> | ||
<PartialTipField | ||
{...propsForFields.nozzles} | ||
pipetteSpecs={pipettes[String(propsForFields.pipette.value)]?.spec} | ||
/> | ||
</> | ||
) : null} | ||
<Divider marginY="0" /> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i guess needs to merge edge into this branch since you fixed this already, don't you?