Skip to content

Commit

Permalink
feat(add support for stacking multiples of a single labware): support…
Browse files Browse the repository at this point in the history
… for stacking multiple labware

fix PLAT-499, PLAT-500, PLAT-502, PLAT-548
  • Loading branch information
smb2268 committed Oct 28, 2024
1 parent 7e3453d commit 8b5a0f9
Show file tree
Hide file tree
Showing 28 changed files with 16,676 additions and 486 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/src/assets/localization/en/protocol_setup.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
"labware_position_check_step_description": "Recommended workflow that helps you verify the position of each labware on the deck.",
"labware_position_check_step_title": "Labware Position Check",
"labware_position_check_text": "Labware Position Check is a recommended workflow that helps you verify the position of each labware on the deck. During this check, you can create Labware Offsets that adjust how the robot moves to each labware in the X, Y and Z directions.",
"labware_quantity": "Quantity: {{quantity}}",
"labware_setup_step_description": "Gather the following labware and full tip racks. To run your protocol without Labware Position Check, place and secure labware in their initial locations.",
"labware_setup_step_title": "Labware",
"last_calibrated": "Last calibrated: {{date}}",
Expand Down
156 changes: 98 additions & 58 deletions app/src/molecules/LabwareStackModal/LabwareStackModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
THERMOCYCLER_MODULE_TYPE,
} from '@opentrons/shared-data'
import tiprackAdapter from '/app/assets/images/labware/opentrons_flex_96_tiprack_adapter.png'
import tcLid from '/app/assets/images/labware/opentrons_tough_pcr_auto_sealing_lid.png'
import deckRiser from '/app/assets/images/labware/opentrons_flex_deck_riser.png'

import type { RobotType, RunTimeCommand } from '@opentrons/shared-data'

Expand All @@ -58,6 +60,13 @@ const LIST_ITEM_STYLE = css`
justify-content: ${JUSTIFY_SPACE_BETWEEN};
`

const ADAPTER_LOAD_NAMES_TO_SHOW_IMAGE: { [key: string]: string } = {
opentrons_flex_96_tiprack_adapter: tiprackAdapter,
opentrons_flex_deck_riser: deckRiser,
}
const LABWARE_LOAD_NAMES_TO_SHOW_IMAGE: { [key: string]: string } = {
opentrons_tough_pcr_auto_sealing_lid: tcLid,
}
interface LabwareStackModalProps {
labwareIdTop: string
commands: RunTimeCommand[] | null
Expand Down Expand Up @@ -87,6 +96,7 @@ export const LabwareStackModal = (
moduleModel,
labwareName,
labwareNickname,
labwareQuantity,
} = getLocationInfoNames(labwareIdTop, commands)

const topDefinition = getSlotLabwareDefinition(labwareIdTop, commands)
Expand All @@ -106,7 +116,26 @@ export const LabwareStackModal = (
moduleModel != null ? getModuleDisplayName(moduleModel) : null ?? ''
const isAdapterForTiprack =
adapterDef?.parameters.loadName === 'opentrons_flex_96_tiprack_adapter'
const tiprackAdapterImg = <img src={tiprackAdapter} css={IMAGE_STYLE} />

const labwareImg = Object.keys(LABWARE_LOAD_NAMES_TO_SHOW_IMAGE).includes(
topDefinition.parameters.loadName
) ? (
<img
src={LABWARE_LOAD_NAMES_TO_SHOW_IMAGE[topDefinition.parameters.loadName]}
css={IMAGE_STYLE}
/>
) : null

const adapterImg =
adapterDef != null &&
Object.keys(ADAPTER_LOAD_NAMES_TO_SHOW_IMAGE).includes(
adapterDef.parameters.loadName
) ? (
<img
src={ADAPTER_LOAD_NAMES_TO_SHOW_IMAGE[adapterDef?.parameters.loadName]}
css={IMAGE_STYLE}
/>
) : null
const moduleImg =
moduleModel != null ? (
<img src={getModuleImage(moduleModel, true)} css={IMAGE_STYLE} />
Expand Down Expand Up @@ -139,25 +168,33 @@ export const LabwareStackModal = (
<LabwareStackLabel
isOnDevice
text={labwareName}
subText={labwareNickname}
subText={
labwareQuantity > 1
? t('labware_quantity', { quantity: labwareQuantity })
: labwareNickname
}
/>
<Flex css={IMAGE_CONTAINER_STYLE}>
<LabwareStackRender
definitionTop={topDefinition}
definitionBottom={adapterDef}
highlightBottom={false}
highlightTop={adapterDef != null && !isAdapterForTiprack}
/>
</Flex>
{labwareImg != null ? (
<Flex css={IMAGE_CONTAINER_STYLE}>{labwareImg}</Flex>
) : (
<Flex css={IMAGE_CONTAINER_STYLE}>
<LabwareStackRender
definitionTop={topDefinition}
definitionBottom={adapterDef}
highlightBottom={false}
highlightTop={adapterDef != null && !isAdapterForTiprack}
/>
</Flex>
)}
</Flex>
<Divider marginY={SPACING.spacing16} />
</>
{adapterDef != null ? (
<>
<Divider marginY={SPACING.spacing16} />
<Flex css={LIST_ITEM_STYLE}>
<LabwareStackLabel text={adapterName ?? ''} isOnDevice />
{isAdapterForTiprack ? (
<Flex css={IMAGE_CONTAINER_STYLE}>{tiprackAdapterImg}</Flex>
{adapterImg != null ? (
<Flex css={IMAGE_CONTAINER_STYLE}>{adapterImg}</Flex>
) : (
<Flex css={IMAGE_CONTAINER_STYLE}>
<LabwareStackRender
Expand All @@ -169,16 +206,16 @@ export const LabwareStackModal = (
</Flex>
)}
</Flex>
{moduleModel != null ? (
<Divider marginY={SPACING.spacing16} />
) : null}
</>
) : null}
{moduleModel != null ? (
<Flex css={LIST_ITEM_STYLE}>
<LabwareStackLabel text={moduleDisplayName} isOnDevice />
<Flex css={IMAGE_CONTAINER_STYLE}>{moduleImg}</Flex>
</Flex>
<>
<Divider marginY={SPACING.spacing16} />
<Flex css={LIST_ITEM_STYLE}>
<LabwareStackLabel text={moduleDisplayName} isOnDevice />
<Flex css={IMAGE_CONTAINER_STYLE}>{moduleImg}</Flex>
</Flex>
</>
) : null}
</Flex>
</OddModal>
Expand All @@ -200,24 +237,35 @@ export const LabwareStackModal = (
<Flex flexDirection={DIRECTION_COLUMN}>
<>
<Flex css={LIST_ITEM_STYLE}>
<LabwareStackLabel text={labwareName} subText={labwareNickname} />
<Flex css={IMAGE_CONTAINER_STYLE}>
<LabwareStackRender
definitionTop={topDefinition}
definitionBottom={adapterDef}
highlightBottom={false}
highlightTop={adapterDef != null && !isAdapterForTiprack}
/>
</Flex>
<LabwareStackLabel
text={labwareName}
subText={
labwareQuantity > 1
? t('labware_quantity', { quantity: labwareQuantity })
: labwareNickname
}
/>
{labwareImg != null ? (
<Flex css={IMAGE_CONTAINER_STYLE}>{labwareImg}</Flex>
) : (
<Flex css={IMAGE_CONTAINER_STYLE}>
<LabwareStackRender
definitionTop={topDefinition}
definitionBottom={adapterDef}
highlightBottom={false}
highlightTop={adapterDef != null && !isAdapterForTiprack}
/>
</Flex>
)}
</Flex>
<Divider marginY={SPACING.spacing16} />
</>
{adapterDef != null ? (
<>
<Divider marginY={SPACING.spacing16} />
<Flex css={LIST_ITEM_STYLE}>
<LabwareStackLabel text={adapterName ?? ''} />
{isAdapterForTiprack ? (
<Flex css={IMAGE_CONTAINER_STYLE}>{tiprackAdapterImg}</Flex>
{adapterImg != null ? (
<Flex css={IMAGE_CONTAINER_STYLE}>{adapterImg}</Flex>
) : (
<Flex css={IMAGE_CONTAINER_STYLE}>
<LabwareStackRender
Expand All @@ -229,16 +277,16 @@ export const LabwareStackModal = (
</Flex>
)}
</Flex>
{moduleModel != null ? (
<Divider marginY={SPACING.spacing16} />
) : null}
</>
) : null}
{moduleModel != null ? (
<Flex css={LIST_ITEM_STYLE}>
<LabwareStackLabel text={moduleDisplayName} />
<Flex css={IMAGE_CONTAINER_STYLE}>{moduleImg}</Flex>
</Flex>
<>
<Divider marginY={SPACING.spacing16} />
<Flex css={LIST_ITEM_STYLE}>
<LabwareStackLabel text={moduleDisplayName} />
<Flex css={IMAGE_CONTAINER_STYLE}>{moduleImg}</Flex>
</Flex>
</>
) : null}
</Flex>
</Box>
Expand All @@ -253,31 +301,23 @@ interface LabwareStackLabelProps {
}
function LabwareStackLabel(props: LabwareStackLabelProps): JSX.Element {
const { text, subText, isOnDevice = false } = props
return isOnDevice ? (
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing4}
width="28rem"
flex="0 0 auto"
justifyContent={JUSTIFY_CENTER}
>
<StyledText oddStyle="bodyTextBold">{text}</StyledText>
{subText != null ? (
<StyledText oddStyle="bodyTextRegular" color={COLORS.grey60}>
{subText}
</StyledText>
) : null}
</Flex>
) : (
return (
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing4}
width="14.75rem"
width={isOnDevice ? '28rem' : '14.75rem'}
flex="0 0 auto"
justifyContent={isOnDevice ? JUSTIFY_CENTER : undefined}
>
<StyledText desktopStyle="bodyLargeSemiBold">{text}</StyledText>
<StyledText desktopStyle="bodyLargeSemiBold" oddStyle="bodyTextBold">
{text}
</StyledText>
{subText != null ? (
<StyledText desktopStyle="bodyDefaultRegular" color={COLORS.grey60}>
<StyledText
desktopStyle="bodyDefaultRegular"
oddStyle="bodyTextRegular"
color={COLORS.grey60}
>
{subText}
</StyledText>
) : null}
Expand Down
Loading

0 comments on commit 8b5a0f9

Please sign in to comment.