-
{
- setShowColorPicker(showColorPicker => !showColorPicker)
- }}
- >
-
-
- {showColorPicker ? (
-
-
{
- setShowColorPicker(false)
- }}
- />
- {
- onChange(color.hex)
- }}
- />
-
- ) : null}
-
- >
- )
-}
diff --git a/protocol-designer/src/components/ComputingSpinner.tsx b/protocol-designer/src/components/ComputingSpinner.tsx
deleted file mode 100644
index 71c8b527f91..00000000000
--- a/protocol-designer/src/components/ComputingSpinner.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { useSelector } from 'react-redux'
-import { css } from 'styled-components'
-import { Box, CURSOR_WAIT, POSITION_FIXED } from '@opentrons/components'
-import * as fileDataSelectors from '../file-data/selectors'
-
-const waitCursorStyle = css`
- cursor: ${CURSOR_WAIT};
-`
-
-export const ComputingSpinner = (): JSX.Element | null => {
- const showSpinner = useSelector(fileDataSelectors.getTimelineIsBeingComputed)
-
- return showSpinner ? (
-
- ) : null
-}
diff --git a/protocol-designer/src/components/DeckSetup/DeckSetup.module.css b/protocol-designer/src/components/DeckSetup/DeckSetup.module.css
deleted file mode 100644
index 2ecfd7e0a58..00000000000
--- a/protocol-designer/src/components/DeckSetup/DeckSetup.module.css
+++ /dev/null
@@ -1,22 +0,0 @@
-@import '@opentrons/components/styles';
-
-.deck_wrapper {
- flex: 1;
- margin-top: 1rem;
-}
-
-.deck_header {
- font-size: var(--fs-header); /* from legacy --font-header-dark */
- font-weight: var(--fw-semibold); /* from legacy --font-header-dark */
- color: var(--c-font-dark); /* from legacy --font-header-dark */
- text-align: center;
- padding: 1rem 0;
-}
-
-.deck_row {
- display: flex;
- justify-content: center;
- align-items: stretch;
- max-height: calc(100vh - 3rem);
- overflow-y: hidden;
-}
diff --git a/protocol-designer/src/components/DeckSetup/FlexModuleTag.tsx b/protocol-designer/src/components/DeckSetup/FlexModuleTag.tsx
deleted file mode 100644
index 9c5ba9fc7c5..00000000000
--- a/protocol-designer/src/components/DeckSetup/FlexModuleTag.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import {
- RobotCoordsForeignDiv,
- Text,
- COLORS,
- SPACING,
-} from '@opentrons/components'
-import type { ModuleDefinition } from '@opentrons/shared-data'
-
-interface FlexModuleTagProps {
- dimensions: ModuleDefinition['dimensions']
- displayName: string
-}
-
-export function FlexModuleTag(props: FlexModuleTagProps): JSX.Element {
- const { dimensions, displayName } = props
- return (
-
-
- {displayName}
-
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx
deleted file mode 100644
index 3be204f8fd7..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx
+++ /dev/null
@@ -1,184 +0,0 @@
-import { useRef } from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { useDrop } from 'react-dnd'
-import cx from 'classnames'
-import noop from 'lodash/noop'
-import { Icon, RobotCoordsForeignDiv } from '@opentrons/components'
-import { DND_TYPES } from '../../../constants'
-import {
- getAdapterLabwareIsAMatch,
- getLabwareIsCustom,
-} from '../../../utils/labwareModuleCompatibility'
-import {
- deleteContainer,
- moveDeckItem,
- openAddLabwareModal,
-} from '../../../labware-ingred/actions'
-import { selectors as labwareDefSelectors } from '../../../labware-defs'
-import { START_TERMINAL_ITEM_ID } from '../../../steplist'
-import { BlockedSlot } from './BlockedSlot'
-
-import type { DropTargetMonitor } from 'react-dnd'
-import type { CoordinateTuple, Dimensions } from '@opentrons/shared-data'
-import type { TerminalItemId } from '../../../steplist'
-import type { LabwareOnDeck } from '../../../step-forms'
-
-import styles from './LabwareOverlays.module.css'
-
-interface AdapterControlsProps {
- slotPosition: CoordinateTuple
- slotBoundingBox: Dimensions
- // labwareId is the adapter's labwareId
- labwareId: string
- allLabware: LabwareOnDeck[]
- onDeck: boolean
- selectedTerminalItemId?: TerminalItemId | null
- handleDragHover?: () => void
-}
-
-interface DroppedItem {
- labwareOnDeck: LabwareOnDeck
-}
-
-export const AdapterControls = (
- props: AdapterControlsProps
-): JSX.Element | null => {
- const {
- slotPosition,
- slotBoundingBox,
- selectedTerminalItemId,
- labwareId,
- onDeck,
- handleDragHover,
- allLabware,
- } = props
- const customLabwareDefs = useSelector(
- labwareDefSelectors.getCustomLabwareDefsByURI
- )
- const ref = useRef(null)
- const dispatch = useDispatch()
-
- const adapterName =
- allLabware.find(labware => labware.id === labwareId)?.def.metadata
- .displayName ?? ''
-
- const [{ itemType, draggedItem, isOver }, drop] = useDrop(
- () => ({
- accept: DND_TYPES.LABWARE,
- canDrop: (item: DroppedItem) => {
- const draggedDef = item.labwareOnDeck?.def
- console.assert(
- draggedDef,
- 'no labware def of dragged item, expected it on drop'
- )
-
- if (draggedDef != null) {
- const isCustomLabware = getLabwareIsCustom(
- customLabwareDefs,
- item.labwareOnDeck
- )
- return (
- getAdapterLabwareIsAMatch(
- labwareId,
- allLabware,
- draggedDef.parameters.loadName
- ) || isCustomLabware
- )
- }
- return true
- },
- drop: (item: DroppedItem) => {
- const droppedLabware = item
- if (droppedLabware.labwareOnDeck != null) {
- const droppedSlot = droppedLabware.labwareOnDeck.slot
- dispatch(moveDeckItem(droppedSlot, labwareId))
- }
- },
- hover: () => {
- if (handleDragHover != null) {
- handleDragHover()
- }
- },
- collect: (monitor: DropTargetMonitor) => ({
- itemType: monitor.getItemType(),
- isOver: !!monitor.isOver(),
- draggedItem: monitor.getItem() as DroppedItem,
- }),
- }),
- []
- )
-
- if (
- selectedTerminalItemId !== START_TERMINAL_ITEM_ID ||
- (itemType !== DND_TYPES.LABWARE && itemType !== null)
- )
- return null
- const draggedDef = draggedItem?.labwareOnDeck?.def
- const isCustomLabware = draggedItem
- ? getLabwareIsCustom(customLabwareDefs, draggedItem.labwareOnDeck)
- : false
-
- let slotBlocked: string | null = null
-
- if (isOver && draggedDef != null && isCustomLabware) {
- slotBlocked = 'Custom Labware incompatible with this adapter'
- } else if (
- isOver &&
- draggedDef != null &&
- !getAdapterLabwareIsAMatch(
- labwareId,
- allLabware,
- draggedDef.parameters.loadName
- )
- ) {
- slotBlocked = 'Labware incompatible with this adapter'
- }
-
- drop(ref)
-
- return (
-
- {slotBlocked ? (
-
- ) : (
-
- dispatch(openAddLabwareModal({ slot: labwareId }))}
- >
- {!isOver && }
- {isOver ? 'Place Here' : 'Add Labware'}
-
- {
- window.confirm(
- `"Are you sure you want to remove this ${adapterName}?`
- ) && dispatch(deleteContainer({ labwareId: labwareId }))
- }}
- >
- {!isOver && }
- {'Delete'}
-
-
- )}
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/BlockedSlot.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/BlockedSlot.tsx
deleted file mode 100644
index aabb977e2e0..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/BlockedSlot.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { useTranslation } from 'react-i18next'
-import { RobotCoordsForeignDiv } from '@opentrons/components'
-import styles from './LabwareOverlays.module.css'
-
-type BlockedSlotMessage =
- | 'MODULE_INCOMPATIBLE_SINGLE_LABWARE'
- | 'MODULE_INCOMPATIBLE_LABWARE_SWAP'
- | 'LABWARE_INCOMPATIBLE_WITH_ADAPTER'
-
-interface Props {
- x: number
- y: number
- width: number
- height: number
- message: BlockedSlotMessage
-}
-
-export const BlockedSlot = (props: Props): JSX.Element => {
- const { t } = useTranslation('deck')
- const { x, y, width, height, message } = props
- return (
-
-
-
- {t(`blocked_slot.${message}`)}
-
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/BrowseLabware.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/BrowseLabware.tsx
deleted file mode 100644
index 06650910a53..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/BrowseLabware.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { useTranslation } from 'react-i18next'
-import cx from 'classnames'
-import { useDispatch } from 'react-redux'
-import { Icon } from '@opentrons/components'
-import { drillDownOnLabware } from '../../../labware-ingred/actions'
-import { resetScrollElements } from '../../../ui/steps/utils'
-import styles from './LabwareOverlays.module.css'
-
-import type { LabwareEntity } from '@opentrons/step-generation'
-import type { LabwareOnDeck } from '../../../step-forms'
-
-interface Props {
- labwareOnDeck: LabwareOnDeck | LabwareEntity
-}
-
-export function BrowseLabware(props: Props): JSX.Element | null {
- const { t } = useTranslation('deck')
- const { labwareOnDeck } = props
- const dispatch = useDispatch()
-
- const drillDown = (): void => {
- resetScrollElements()
- dispatch(drillDownOnLabware(labwareOnDeck.id))
- }
-
- if (
- props.labwareOnDeck.def.parameters.isTiprack ||
- props.labwareOnDeck.def.allowedRoles?.includes('adapter')
- )
- return null
- return (
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabware.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabware.tsx
deleted file mode 100644
index 3c3e577ecf0..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabware.tsx
+++ /dev/null
@@ -1,160 +0,0 @@
-import * as React from 'react'
-import { useTranslation } from 'react-i18next'
-import { useDispatch, useSelector } from 'react-redux'
-import cx from 'classnames'
-import { Icon } from '@opentrons/components'
-import { getLabwareDisplayName } from '@opentrons/shared-data'
-import { useDrag, useDrop } from 'react-dnd'
-import { NameThisLabware } from './NameThisLabware'
-import { DND_TYPES } from '../../../constants'
-import {
- deleteContainer,
- duplicateLabware,
- moveDeckItem,
- openIngredientSelector,
-} from '../../../labware-ingred/actions'
-import { selectors as labwareIngredSelectors } from '../../../labware-ingred/selectors'
-import styles from './LabwareOverlays.module.css'
-import type { DropTargetMonitor } from 'react-dnd'
-import type { ThunkDispatch } from '../../../types'
-import type { LabwareOnDeck } from '../../../step-forms'
-
-interface Props {
- labwareOnDeck: LabwareOnDeck
- setHoveredLabware: (val?: LabwareOnDeck | null) => void
- setDraggedLabware: (val?: LabwareOnDeck | null) => void
- swapBlocked: boolean
-}
-
-interface DroppedItem {
- labwareOnDeck: LabwareOnDeck
-}
-export const EditLabware = (props: Props): JSX.Element | null => {
- const {
- labwareOnDeck,
- swapBlocked,
- setDraggedLabware,
- setHoveredLabware,
- } = props
- const savedLabware = useSelector(labwareIngredSelectors.getSavedLabware)
- const dispatch = useDispatch
>()
- const { t } = useTranslation('deck')
- const ref = React.useRef(null)
-
- const { isTiprack } = labwareOnDeck.def.parameters
- const hasName = savedLabware[labwareOnDeck.id]
- const isYetUnnamed = !labwareOnDeck.def.parameters.isTiprack && !hasName
-
- const editLiquids = (): void => {
- dispatch(openIngredientSelector(labwareOnDeck.id))
- }
-
- const [, drag] = useDrag(
- () => ({
- type: DND_TYPES.LABWARE,
- item: { labwareOnDeck },
- }),
- [labwareOnDeck]
- )
-
- const [{ draggedLabware, isOver }, drop] = useDrop(
- () => ({
- accept: DND_TYPES.LABWARE,
- canDrop: (item: DroppedItem) => {
- const draggedLabware = item?.labwareOnDeck
- const isDifferentSlot =
- draggedLabware && draggedLabware.slot !== labwareOnDeck.slot
- return isDifferentSlot && !swapBlocked
- },
- drop: (item: DroppedItem) => {
- const draggedLabware = item?.labwareOnDeck
- if (draggedLabware != null) {
- dispatch(moveDeckItem(draggedLabware.slot, labwareOnDeck.slot))
- }
- },
- hover: () => {
- setHoveredLabware(labwareOnDeck)
- },
- collect: (monitor: DropTargetMonitor) => ({
- isOver: monitor.isOver(),
- draggedLabware: monitor.getItem() as DroppedItem,
- }),
- }),
- [labwareOnDeck]
- )
-
- React.useEffect(() => {
- if (draggedLabware?.labwareOnDeck != null) {
- setDraggedLabware(draggedLabware?.labwareOnDeck)
- } else {
- setHoveredLabware(null)
- setDraggedLabware(null)
- }
- }, [draggedLabware])
-
- let contents: React.ReactNode | null = null
-
- const isBeingDragged =
- draggedLabware?.labwareOnDeck?.slot === labwareOnDeck.slot
-
- if (isYetUnnamed && !isTiprack) {
- contents = (
-
- )
- } else if (swapBlocked) {
- contents = null
- } else if (draggedLabware != null) {
- contents = null
- } else {
- contents = (
- <>
- {!isTiprack ? (
-
-
- {t('overlay.edit.name_and_liquids')}
-
- ) : (
-
- )}
- dispatch(duplicateLabware(labwareOnDeck.id))}
- >
-
- {t('overlay.edit.duplicate')}
-
- {
- window.confirm(
- `Are you sure you want to permanently delete this ${getLabwareDisplayName(
- labwareOnDeck.def
- )}?`
- ) && dispatch(deleteContainer({ labwareId: labwareOnDeck.id }))
- }}
- >
-
- {t('overlay.edit.delete')}
-
- >
- )
- }
-
- drag(drop(ref))
-
- return (
-
- {contents}
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx
deleted file mode 100644
index c6a5a444d0c..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import { useDispatch, useSelector } from 'react-redux'
-import { useTranslation } from 'react-i18next'
-import { css } from 'styled-components'
-import {
- ALIGN_FLEX_START,
- BORDERS,
- COLORS,
- DIRECTION_COLUMN,
- Icon,
- JUSTIFY_SPACE_AROUND,
- POSITION_ABSOLUTE,
- SPACING,
-} from '@opentrons/components'
-import { getLabwareDisplayName } from '@opentrons/shared-data'
-import {
- deleteContainer,
- duplicateLabware,
- openIngredientSelector,
-} from '../../../labware-ingred/actions'
-import { selectors as labwareIngredSelectors } from '../../../labware-ingred/selectors'
-import { NameThisLabware } from './NameThisLabware'
-import styles from './LabwareOverlays.module.css'
-
-import type { LabwareEntity } from '@opentrons/step-generation'
-import type { ThunkDispatch } from '../../../types'
-
-const NAME_LABWARE_OVERLAY_STYLE = css`
- z-index: 1;
- bottom: 0;
- position: ${POSITION_ABSOLUTE};
- width: 127.76px;
- height: 85.45px;
- opacity: 0;
- &:hover {
- opacity: 1;
- }
-`
-
-const REGULAR_OVERLAY_STYLE = css`
- z-index: 1;
- padding: ${SPACING.spacing8};
- background-color: ${COLORS.black90}${COLORS.opacity90HexCode};
- flex-direction: ${DIRECTION_COLUMN};
- color: ${COLORS.white};
- display: flex;
- align-items: ${ALIGN_FLEX_START};
- justify-content: ${JUSTIFY_SPACE_AROUND};
- border-radius: ${BORDERS.borderRadius16};
- bottom: 0;
- font-size: 0.7rem;
- position: ${POSITION_ABSOLUTE};
- width: 127.76px;
- height: 85.45px;
- opacity: 0;
- &:hover {
- opacity: 1;
- }
-`
-
-interface EditLabwareOffDeckProps {
- labwareEntity: LabwareEntity
-}
-
-export function EditLabwareOffDeck(
- props: EditLabwareOffDeckProps
-): JSX.Element {
- const { labwareEntity } = props
- const { t } = useTranslation('deck')
- const dispatch = useDispatch>()
- const allSavedLabware = useSelector(labwareIngredSelectors.getSavedLabware)
- const hasName = allSavedLabware[labwareEntity.id]
- const { isTiprack } = labwareEntity.def.parameters
-
- const isYetUnnamed = isTiprack && !hasName
-
- const editLiquids = (): void => {
- dispatch(openIngredientSelector(labwareEntity.id))
- }
-
- if (isYetUnnamed && !isTiprack) {
- return (
-
-
-
- )
- } else {
- return (
-
- )
- }
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareControls.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareControls.tsx
deleted file mode 100644
index 1c31a962e75..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareControls.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import cx from 'classnames'
-import { RobotCoordsForeignDiv } from '@opentrons/components'
-
-import { START_TERMINAL_ITEM_ID } from '../../../steplist'
-import { BlockedSlot } from './BlockedSlot'
-import { BrowseLabware } from './BrowseLabware'
-import { EditLabware } from './EditLabware'
-import { LabwareName } from './LabwareName'
-import { LabwareHighlight } from './LabwareHighlight'
-import styles from './LabwareOverlays.module.css'
-
-import type { CoordinateTuple } from '@opentrons/shared-data'
-import type { TerminalItemId } from '../../../steplist'
-import type { LabwareOnDeck } from '../../../step-forms'
-
-interface LabwareControlsProps {
- labwareOnDeck: LabwareOnDeck
- slotPosition: CoordinateTuple
- setHoveredLabware: (labware?: LabwareOnDeck | null) => void
- setDraggedLabware: (labware?: LabwareOnDeck | null) => void
- swapBlocked: boolean
- selectedTerminalItemId?: TerminalItemId | null
-}
-
-export const LabwareControls = (props: LabwareControlsProps): JSX.Element => {
- const {
- labwareOnDeck,
- slotPosition,
- selectedTerminalItemId,
- setHoveredLabware,
- setDraggedLabware,
- swapBlocked,
- } = props
-
- const canEdit = selectedTerminalItemId === START_TERMINAL_ITEM_ID
- const [x, y] = slotPosition
- const width = labwareOnDeck.def.dimensions.xDimension
- const height = labwareOnDeck.def.dimensions.yDimension
- return (
- <>
-
-
- {canEdit ? (
-
- ) : (
-
- )}
-
-
- {swapBlocked && (
-
- )}
- >
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareHighlight.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareHighlight.tsx
deleted file mode 100644
index 78d0a8ada5c..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareHighlight.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import cx from 'classnames'
-import { useSelector } from 'react-redux'
-import { Icon } from '@opentrons/components'
-import { getHoveredStepLabware, getHoveredStepId } from '../../../ui/steps'
-import {
- getLabwareEntities,
- getSavedStepForms,
-} from '../../../step-forms/selectors'
-import { THERMOCYCLER_PROFILE } from '../../../constants'
-
-import styles from './LabwareOverlays.module.css'
-import type { LabwareOnDeck } from '../../../step-forms'
-
-interface LabwareHighlightProps {
- labwareOnDeck: LabwareOnDeck
-}
-
-export const LabwareHighlight = (
- props: LabwareHighlightProps
-): JSX.Element | null => {
- const { labwareOnDeck } = props
- const labwareEntities = useSelector(getLabwareEntities)
- const adapterId =
- labwareEntities[labwareOnDeck.slot] != null
- ? labwareEntities[labwareOnDeck.slot].id
- : null
-
- const highlighted = useSelector(getHoveredStepLabware).includes(
- adapterId ?? labwareOnDeck.id
- )
-
- let isTcProfile = false
- const form = useSelector(getSavedStepForms)
- const hoveredStepId = useSelector(getHoveredStepId)
- const formData = hoveredStepId ? form[hoveredStepId] : null
-
- if (
- formData &&
- formData.stepType === 'thermocycler' &&
- formData.thermocyclerFormType === THERMOCYCLER_PROFILE
- ) {
- isTcProfile = true
- }
- if (highlighted) {
- return (
-
- {isTcProfile && (
-
- )}
-
- )
- }
- return null
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareName.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareName.tsx
deleted file mode 100644
index 15d07bd9886..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareName.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { useSelector } from 'react-redux'
-import { LabwareNameOverlay, truncateString } from '@opentrons/components'
-import { getLabwareDisplayName } from '@opentrons/shared-data'
-import { selectors as uiLabwareSelectors } from '../../../ui/labware'
-import type { LabwareOnDeck } from '../../../step-forms'
-interface LabwareNameProps {
- labwareOnDeck: LabwareOnDeck
-}
-
-export function LabwareName(props: LabwareNameProps): JSX.Element {
- const { labwareOnDeck } = props
- const nicknames = useSelector(uiLabwareSelectors.getLabwareNicknamesById)
- const nickname = nicknames[labwareOnDeck.id]
- const truncatedNickName =
- nickname != null ? truncateString(nickname, 75, 25) : null
- const title = truncatedNickName ?? getLabwareDisplayName(labwareOnDeck.def)
- return
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareOverlays.module.css b/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareOverlays.module.css
deleted file mode 100644
index 676da1993b3..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/LabwareOverlays.module.css
+++ /dev/null
@@ -1,155 +0,0 @@
-@import '@opentrons/components/styles';
-
-.labware_controls {
- height: 100%;
- width: 100%;
- display: flex;
- flex-direction: column;
- justify-content: flex-end;
- border-radius: 0.5rem;
-}
-
-.labware_controls.can_edit {
- cursor: grab;
-}
-
-.slot_overlay {
- position: absolute;
-
- /* from legacy --absolute-fill */
- top: 0;
-
- /* from legacy --absolute-fill */
- right: 0;
-
- /* from legacy --absolute-fill */
- bottom: 0;
-
- /* from legacy --absolute-fill */
- left: 0;
-
- /* from legacy --absolute-fill */
-
- z-index: 1;
- padding: 0.5rem;
- background-color: color-mod(var(--c-black) alpha(0.75));
- display: flex;
- flex-direction: column;
- justify-content: space-around;
- align-items: flex-start;
- color: white;
- font-size: var(--fs-body-1);
- border-radius: 0.5rem;
-}
-
-.slot_overlay.with_form {
- background-color: color-mod(var(--c-black) alpha(1));
-}
-
-.slot_overlay.disabled {
- background-color: color-mod(var(--c-light-gray) alpha(0.7));
- color: var(--c-font-dark);
-}
-
-.name_input_wrapper {
- flex: 1;
-}
-
-.name_input {
- padding: 0 0 0 0.25rem;
- width: 7rem;
-}
-
-.overlay_button {
- flex: 1;
- text-decoration: none;
- color: white;
- display: flex;
- align-items: center;
- cursor: pointer;
-}
-
-.overlay_button:active {
- opacity: 0.5;
-}
-
-.overlay_button.drag_text {
- color: var(--c-font-dark);
-}
-
-.button_spacer {
- flex: 1;
-}
-
-.overlay_icon {
- height: 1rem;
- width: 1rem;
- margin-right: 0.25rem;
-}
-
-.appear_on_mouseover {
- opacity: 0;
-
- &:hover {
- opacity: 1;
- }
-}
-
-.appear {
- opacity: 1;
-}
-
-.drag_preview {
- position: absolute;
- cursor: grabbing;
-}
-
-.highlighted_border_div {
- position: absolute;
-
- /* from legacy --absolute-fill */
- top: 0;
-
- /* from legacy --absolute-fill */
- right: 0;
-
- /* from legacy --absolute-fill */
- bottom: 0;
-
- /* from legacy --absolute-fill */
- left: 0;
-
- /* from legacy --absolute-fill */
-
- border-color: var(--c-highlight);
- border-width: 3px;
- border-style: solid;
- border-radius: 0.5rem;
-}
-
-.highlight_fill {
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: color-mod(var(--c-highlight) alpha(0.25));
-}
-
-.thermocycler_icon {
- height: 60%;
- color: var(--c-selected-dark);
-}
-
-.blocked_slot_background {
- fill: rgba(200, 115, 0, 0.75);
- stroke: var(--c-red);
- rx: 6;
-}
-
-.blocked_slot_content {
- height: 100%;
- margin: -1.5rem 0.5rem;
- color: var(--c-white);
- font-size: var(--fs-caption);
- text-align: center;
- line-height: 1.5;
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/NameThisLabware.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/NameThisLabware.tsx
deleted file mode 100644
index 71bf91cf2e5..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/NameThisLabware.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import * as React from 'react'
-import { useTranslation } from 'react-i18next'
-import { useDispatch } from 'react-redux'
-import cx from 'classnames'
-import { Icon, useOnClickOutside } from '@opentrons/components'
-import { renameLabware } from '../../../labware-ingred/actions'
-import styles from './LabwareOverlays.module.css'
-
-import type { LabwareEntity } from '@opentrons/step-generation'
-import type { ThunkDispatch } from '../../../types'
-import type { LabwareOnDeck } from '../../../step-forms'
-
-interface NameThisLabwareProps {
- labwareOnDeck: LabwareOnDeck | LabwareEntity
- editLiquids: () => void
-}
-
-export function NameThisLabware(props: NameThisLabwareProps): JSX.Element {
- const { labwareOnDeck } = props
- const dispatch: ThunkDispatch = useDispatch()
- const [inputValue, setInputValue] = React.useState('')
- const { t } = useTranslation('deck')
-
- const setLabwareName = (name: string | null | undefined): void => {
- dispatch(renameLabware({ labwareId: labwareOnDeck.id, name }))
- }
-
- const saveNickname = (): void => {
- setLabwareName(inputValue ?? null)
- }
- const wrapperRef: React.RefObject = useOnClickOutside({
- onClickOutside: saveNickname,
- })
-
- const handleChange = (e: React.ChangeEvent): void => {
- setInputValue(e.target.value)
- }
-
- const handleKeyUp = (e: React.KeyboardEvent): void => {
- if (e.key === 'Enter') {
- saveNickname()
- }
- }
- const addLiquids = (): void => {
- saveNickname()
- props.editLiquids()
- }
-
- return (
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx
deleted file mode 100644
index 614d2fc9d55..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx
+++ /dev/null
@@ -1,184 +0,0 @@
-import { useRef } from 'react'
-import { useTranslation } from 'react-i18next'
-import { useSelector, useDispatch } from 'react-redux'
-import noop from 'lodash/noop'
-import { useDrop, useDrag } from 'react-dnd'
-import cx from 'classnames'
-import { Icon, RobotCoordsForeignDiv } from '@opentrons/components'
-import { DND_TYPES } from '../../../constants'
-import {
- getLabwareIsCompatible,
- getLabwareIsCustom,
-} from '../../../utils/labwareModuleCompatibility'
-import {
- moveDeckItem,
- openAddLabwareModal,
-} from '../../../labware-ingred/actions'
-import { selectors as labwareDefSelectors } from '../../../labware-defs'
-import { START_TERMINAL_ITEM_ID } from '../../../steplist'
-import { BlockedSlot } from './BlockedSlot'
-import styles from './LabwareOverlays.module.css'
-
-import type { DropTargetMonitor } from 'react-dnd'
-import type {
- CoordinateTuple,
- Dimensions,
- ModuleType,
-} from '@opentrons/shared-data'
-import type { LabwareOnDeck } from '../../../step-forms'
-import type { TerminalItemId } from '../../../steplist'
-
-interface SlotControlsProps {
- slotPosition: CoordinateTuple | null
- slotBoundingBox: Dimensions
- // NOTE: slotId can be either AddressableAreaName or moduleId
- slotId: string
- moduleType: ModuleType | null
- selectedTerminalItemId?: TerminalItemId | null
- handleDragHover?: () => void
-}
-
-interface DroppedItem {
- labwareOnDeck: LabwareOnDeck
-}
-
-export const SlotControls = (props: SlotControlsProps): JSX.Element | null => {
- const {
- slotBoundingBox,
- slotPosition,
- slotId,
- selectedTerminalItemId,
- moduleType,
- handleDragHover,
- } = props
- const customLabwareDefs = useSelector(
- labwareDefSelectors.getCustomLabwareDefsByURI
- )
- const ref = useRef(null)
- const dispatch = useDispatch()
-
- const { t } = useTranslation('deck')
-
- const [, drag] = useDrag({
- type: DND_TYPES.LABWARE,
- item: { labwareOnDeck: null },
- })
-
- const [{ draggedItem, itemType, isOver }, drop] = useDrop(
- () => ({
- accept: DND_TYPES.LABWARE,
- canDrop: (item: DroppedItem) => {
- const draggedDef = item?.labwareOnDeck?.def
- console.assert(
- draggedDef,
- 'no labware def of dragged item, expected it on drop'
- )
-
- if (moduleType != null && draggedDef != null) {
- // this is a module slot, prevent drop if the dragged labware is not compatible
- const isCustomLabware = getLabwareIsCustom(
- customLabwareDefs,
- item.labwareOnDeck
- )
-
- return (
- getLabwareIsCompatible(draggedDef, moduleType) || isCustomLabware
- )
- }
- return true
- },
- drop: (item: DroppedItem) => {
- const droppedLabware = item
- if (droppedLabware.labwareOnDeck != null) {
- const droppedSlot = droppedLabware.labwareOnDeck.slot
- dispatch(moveDeckItem(droppedSlot, slotId))
- }
- },
- hover: () => {
- if (handleDragHover != null) {
- handleDragHover()
- }
- },
- collect: (monitor: DropTargetMonitor) => ({
- itemType: monitor.getItemType(),
- isOver: !!monitor.isOver(),
- draggedItem: monitor.getItem() as DroppedItem,
- }),
- }),
- []
- )
-
- if (
- selectedTerminalItemId !== START_TERMINAL_ITEM_ID ||
- (itemType !== DND_TYPES.LABWARE && itemType !== null) ||
- slotPosition == null
- )
- return null
-
- const draggedDef = draggedItem?.labwareOnDeck?.def
-
- const isCustomLabware = draggedItem
- ? getLabwareIsCustom(customLabwareDefs, draggedItem.labwareOnDeck)
- : false
-
- let slotBlocked: string | null = null
- if (
- isOver &&
- moduleType != null &&
- draggedDef != null &&
- !getLabwareIsCompatible(draggedDef, moduleType) &&
- !isCustomLabware
- ) {
- slotBlocked = 'Labware incompatible with this module'
- }
-
- const isOnHeaterShaker = moduleType === 'heaterShakerModuleType'
- const isNoAdapterOption =
- moduleType === 'magneticBlockType' ||
- moduleType === 'magneticModuleType' ||
- moduleType === 'thermocyclerModuleType'
- let overlayText: string = 'add_adapter_or_labware'
- if (isOnHeaterShaker) {
- overlayText = 'add_adapter'
- } else if (isNoAdapterOption) {
- overlayText = 'add_labware'
- }
-
- const addLabware = (): void => {
- dispatch(openAddLabwareModal({ slot: slotId }))
- }
-
- drag(drop(ref))
-
- return (
-
- {slotBlocked ? (
-
- ) : (
-
-
- {!isOver && }
- {t(`overlay.slot.${isOver ? 'place_here' : overlayText}`)}
-
-
- )}
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/__tests__/SlotControls.test.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/__tests__/SlotControls.test.tsx
deleted file mode 100644
index 60972821a90..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/__tests__/SlotControls.test.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { describe, it } from 'vitest'
-
-describe('SlotControlsComponent', () => {
- it.todo('replace deprecated enzyme test')
-})
diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/index.ts b/protocol-designer/src/components/DeckSetup/LabwareOverlays/index.ts
deleted file mode 100644
index cd857edd17a..00000000000
--- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export { SlotControls } from './SlotControls'
-export { AdapterControls } from './AdapterControls'
-export { LabwareControls } from './LabwareControls'
diff --git a/protocol-designer/src/components/DeckSetup/NullDeckState.tsx b/protocol-designer/src/components/DeckSetup/NullDeckState.tsx
deleted file mode 100644
index f2c26f579cc..00000000000
--- a/protocol-designer/src/components/DeckSetup/NullDeckState.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { useMemo } from 'react'
-import { getDeckDefinitions } from '@opentrons/shared-data'
-import { useTranslation } from 'react-i18next'
-import {
- FONT_SIZE_BODY_1,
- FONT_WEIGHT_BOLD,
- RobotCoordsText,
- RobotWorkSpace,
- TEXT_TRANSFORM_UPPERCASE,
-} from '@opentrons/components'
-import {
- VIEWBOX_HEIGHT,
- VIEWBOX_MIN_X,
- VIEWBOX_MIN_Y,
- VIEWBOX_WIDTH,
-} from './constants'
-import { DECK_LAYER_BLOCKLIST } from './index'
-
-import styles from './DeckSetup.module.css'
-
-export const NullDeckState = (): JSX.Element => {
- const deckDef = useMemo(() => getDeckDefinitions().ot2_standard, [])
- const { t } = useTranslation('deck')
- return (
-
-
-
- {() => (
-
- {t('inactive_deck')}
-
- )}
-
-
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/Ot2ModuleTag.tsx b/protocol-designer/src/components/DeckSetup/Ot2ModuleTag.tsx
deleted file mode 100644
index 6c5c7d57b5c..00000000000
--- a/protocol-designer/src/components/DeckSetup/Ot2ModuleTag.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import {
- RobotCoordsForeignDiv,
- Text,
- COLORS,
- SPACING,
-} from '@opentrons/components'
-import {
- getModuleDisplayName,
- THERMOCYCLER_MODULE_V1,
- THERMOCYCLER_MODULE_V2,
-} from '@opentrons/shared-data'
-import type {
- ModuleDefinition,
- ModuleModel,
- ModuleOrientation,
-} from '@opentrons/shared-data'
-
-interface Ot2ModuleTagProps {
- dimensions: ModuleDefinition['dimensions']
- model: ModuleModel
- orientation: ModuleOrientation
-}
-
-export function Ot2ModuleTag(props: Ot2ModuleTagProps): JSX.Element {
- const { dimensions, model, orientation } = props
- const displayName = getModuleDisplayName(model)
- const isThermocyclerModel =
- model === THERMOCYCLER_MODULE_V1 || model === THERMOCYCLER_MODULE_V2
- const xDimension = dimensions.labwareInterfaceXDimension ?? 0
- const xCoordinateForOtherMods =
- orientation === 'left'
- ? -(xDimension / 2)
- : dimensions.labwareInterfaceXDimension
-
- return (
-
-
- {displayName}
-
-
- )
-}
diff --git a/protocol-designer/src/components/DeckSetup/SlotLabels.tsx b/protocol-designer/src/components/DeckSetup/SlotLabels.tsx
deleted file mode 100644
index a4262ba26b9..00000000000
--- a/protocol-designer/src/components/DeckSetup/SlotLabels.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import { FLEX_ROBOT_TYPE } from '@opentrons/shared-data'
-import {
- DeckInfoLabel,
- Flex,
- JUSTIFY_CENTER,
- RobotCoordsForeignObject,
- ALIGN_CENTER,
- DIRECTION_COLUMN,
-} from '@opentrons/components'
-
-import type { RobotType } from '@opentrons/shared-data'
-
-interface SlotLabelsProps {
- robotType: RobotType
- hasStagingAreas: boolean
- hasWasteChute: boolean
-}
-
-/**
- * This is an almost copy of SlotLabels in @opentrons/components
- * in order to keep the changes between PD and the rest
- * of the repo separate
- */
-export const SlotLabels = ({
- robotType,
- hasStagingAreas,
- hasWasteChute,
-}: SlotLabelsProps): JSX.Element | null => {
- return robotType === FLEX_ROBOT_TYPE ? (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {hasStagingAreas ? (
-
-
-
- ) : null}
-
-
- >
- ) : null
-}
diff --git a/protocol-designer/src/components/DeckSetup/__tests__/DeckSetup.test.ts b/protocol-designer/src/components/DeckSetup/__tests__/DeckSetup.test.ts
deleted file mode 100644
index 5051d10610a..00000000000
--- a/protocol-designer/src/components/DeckSetup/__tests__/DeckSetup.test.ts
+++ /dev/null
@@ -1,233 +0,0 @@
-import { describe, expect, it, beforeEach, afterEach, vi } from 'vitest'
-import {
- fixture_96_plate,
- fixture_24_tuberack,
-} from '@opentrons/shared-data/labware/fixtures/2'
-import {
- MAGNETIC_MODULE_TYPE,
- TEMPERATURE_MODULE_TYPE,
- MAGNETIC_MODULE_V1,
- TEMPERATURE_MODULE_V1,
-} from '@opentrons/shared-data'
-import { TEMPERATURE_AT_TARGET } from '@opentrons/step-generation'
-import * as labwareModuleCompatibility from '../../../utils/labwareModuleCompatibility'
-import { getSwapBlocked } from '../utils'
-
-import type { MockInstance } from 'vitest'
-import type { LabwareDefinition2 } from '@opentrons/shared-data'
-import type { SwapBlockedArgs } from '../utils'
-
-describe('DeckSetup', () => {
- describe('getSwapBlocked', () => {
- const plateInSlot3 = {
- labwareDefURI: 'fixture/fixture_96_plate',
- id: 'plate123',
- slot: '3',
- def: fixture_96_plate as LabwareDefinition2,
- }
- const tuberackInSlot4 = {
- labwareDefURI: 'fixture/fixtures_24_tuberack',
- id: 'tuberack098',
- slot: '4',
- def: fixture_24_tuberack as LabwareDefinition2,
- }
-
- const magneticModule = {
- id: 'magnet123',
- type: MAGNETIC_MODULE_TYPE,
- model: MAGNETIC_MODULE_V1,
- moduleState: {
- type: MAGNETIC_MODULE_TYPE,
- engaged: false,
- },
- slot: '1',
- }
- const temperatureModule = {
- id: 'temperature098',
- type: TEMPERATURE_MODULE_TYPE,
- model: TEMPERATURE_MODULE_V1,
- moduleState: {
- type: TEMPERATURE_MODULE_TYPE,
- status: TEMPERATURE_AT_TARGET,
- targetTemperature: 45,
- },
- slot: '7',
- }
-
- let getLabwareIsCompatibleSpy: MockInstance
- beforeEach(() => {
- getLabwareIsCompatibleSpy = vi.spyOn(
- labwareModuleCompatibility,
- 'getLabwareIsCompatible'
- )
- })
-
- afterEach(() => {
- getLabwareIsCompatibleSpy.mockClear()
- })
-
- it('is not blocked when there is no labware in slot', () => {
- const args: SwapBlockedArgs = {
- hoveredLabware: null,
- draggedLabware: plateInSlot3,
- modulesById: {},
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(false)
- })
-
- it('is not blocked when no dragged labware', () => {
- const args: SwapBlockedArgs = {
- hoveredLabware: plateInSlot3,
- draggedLabware: null,
- modulesById: {},
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(false)
- })
-
- it('is not blocked when dragged labware to swap on module is custom', () => {
- tuberackInSlot4.slot = 'magnet123'
- getLabwareIsCompatibleSpy.mockReturnValue(false)
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {
- magnet123: magneticModule,
- },
- customLabwareDefs: {
- 'fixture/fixture_96_plate': fixture_96_plate as LabwareDefinition2,
- },
- }
-
- const isBlocked = getSwapBlocked(args as SwapBlockedArgs)
-
- expect(isBlocked).toEqual(false)
- })
-
- it('is blocked when dragged labware on module to swap on another module is not custom and not compatible', () => {
- tuberackInSlot4.slot = 'magnet123'
- getLabwareIsCompatibleSpy.mockReturnValue(false)
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {
- magnet123: magneticModule,
- },
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(true)
- })
-
- it('is blocked when target labware on module to swap is incompatible with dragged labware', () => {
- tuberackInSlot4.slot = 'magnet123'
- getLabwareIsCompatibleSpy.mockReturnValue(false)
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {
- magnet123: magneticModule,
- },
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(true)
- })
-
- it('is not blocked when labwares to swap on both modules are compatible', () => {
- tuberackInSlot4.slot = 'magnet123'
- plateInSlot3.slot = 'temperature098'
- getLabwareIsCompatibleSpy.mockReturnValue(true)
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {
- magnet123: magneticModule,
- temperature098: temperatureModule,
- },
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(false)
- })
-
- it('is blocked when both dragged and target labwares on the modules are incompatible', () => {
- tuberackInSlot4.slot = 'magnet123'
- plateInSlot3.slot = 'temperature098'
- getLabwareIsCompatibleSpy.mockReturnValue(false)
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {
- magnet123: magneticModule,
- temperature098: temperatureModule,
- },
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(true)
- })
-
- it('is not blocked when swapping labware from module with compatible labware on deck slot', () => {
- plateInSlot3.slot = 'temperature098'
- getLabwareIsCompatibleSpy.mockReturnValue(true)
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {
- temperature098: temperatureModule,
- },
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(false)
- })
-
- it('is not blocked when swapping labware from one deck slot with another labware on deck slot', () => {
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {},
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(false)
- })
-
- it('is not blocked when swapping compatible labware on deck slot with labware on module', () => {
- tuberackInSlot4.slot = 'magnet123'
- getLabwareIsCompatibleSpy.mockReturnValue(true)
- const args: SwapBlockedArgs = {
- hoveredLabware: tuberackInSlot4,
- draggedLabware: plateInSlot3,
- modulesById: {
- magnet123: magneticModule,
- },
- customLabwareDefs: {},
- }
-
- const isBlocked = getSwapBlocked(args)
-
- expect(isBlocked).toEqual(false)
- })
- })
-})
diff --git a/protocol-designer/src/components/DeckSetup/__tests__/FlexModuleTag.test.tsx b/protocol-designer/src/components/DeckSetup/__tests__/FlexModuleTag.test.tsx
deleted file mode 100644
index 4fb9c967c5e..00000000000
--- a/protocol-designer/src/components/DeckSetup/__tests__/FlexModuleTag.test.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import type * as React from 'react'
-import { screen } from '@testing-library/react'
-import { describe, it, vi } from 'vitest'
-import { renderWithProviders } from '../../../__testing-utils__'
-import { FlexModuleTag } from '../FlexModuleTag'
-import type { ModuleDimensions } from '@opentrons/shared-data'
-
-vi.mock('@opentrons/components', async () => {
- const actual = await vi.importActual('@opentrons/components')
- return {
- ...actual,
- RobotCoordsForeignDiv: ({ children }: { children: React.ReactNode }) => (
- {children}
- ),
- }
-})
-
-const render = (props: React.ComponentProps) => {
- return renderWithProviders( )[0]
-}
-
-const mockDimensions: ModuleDimensions = {
- labwareInterfaceXDimension: 5,
-} as any
-
-describe('FlexModuleTag', () => {
- it('renders the flex module tag for magnetic block', () => {
- render({
- dimensions: mockDimensions,
- displayName: 'mock Magnetic Block',
- })
- screen.getByText('mock Magnetic Block')
- })
- it('renders the flex module tag for heater-shaker', () => {
- render({
- dimensions: mockDimensions,
- displayName: 'mock Heater-shaker',
- })
- screen.getByText('mock Heater-shaker')
- })
-})
diff --git a/protocol-designer/src/components/DeckSetup/__tests__/Ot2ModuleTag.test.tsx b/protocol-designer/src/components/DeckSetup/__tests__/Ot2ModuleTag.test.tsx
deleted file mode 100644
index 279855682a9..00000000000
--- a/protocol-designer/src/components/DeckSetup/__tests__/Ot2ModuleTag.test.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { describe, it } from 'vitest'
-import type * as React from 'react'
-import { screen } from '@testing-library/react'
-import { renderWithProviders } from '../../../__testing-utils__'
-import { Ot2ModuleTag } from '../Ot2ModuleTag'
-import type { ModuleDimensions } from '@opentrons/shared-data'
-
-const render = (props: React.ComponentProps) => {
- return renderWithProviders( )[0]
-}
-
-const mockDimensions: ModuleDimensions = {
- labwareInterfaceXDimension: 5,
-} as any
-
-describe('Ot2ModuleTag', () => {
- it('renders module tag for left magnetic module', () => {
- render({
- dimensions: mockDimensions,
- orientation: 'left',
- model: 'magneticModuleV1',
- })
- screen.getByText('Magnetic Module GEN1')
- })
- it('renders module tag for right heater-shaker', () => {
- render({
- dimensions: mockDimensions,
- orientation: 'right',
- model: 'heaterShakerModuleV1',
- })
- screen.getByText('Heater-Shaker Module GEN1')
- })
- it('renders module tag for thermocycler', () => {
- render({
- dimensions: mockDimensions,
- orientation: 'left',
- model: 'thermocyclerModuleV1',
- })
- screen.getByText('Thermocycler Module GEN1')
- })
-})
diff --git a/protocol-designer/src/components/DeckSetup/constants.ts b/protocol-designer/src/components/DeckSetup/constants.ts
deleted file mode 100644
index 2037126b253..00000000000
--- a/protocol-designer/src/components/DeckSetup/constants.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const VIEWBOX_MIN_X = -64
-export const VIEWBOX_MIN_Y = -10
-export const VIEWBOX_WIDTH = 520
-export const VIEWBOX_HEIGHT = 414
diff --git a/protocol-designer/src/components/DeckSetup/index.tsx b/protocol-designer/src/components/DeckSetup/index.tsx
deleted file mode 100644
index 736753e715a..00000000000
--- a/protocol-designer/src/components/DeckSetup/index.tsx
+++ /dev/null
@@ -1,677 +0,0 @@
-import * as React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import compact from 'lodash/compact'
-import values from 'lodash/values'
-import {
- COLORS,
- DeckFromLayers,
- FlexTrash,
- Module,
- RobotCoordinateSpaceWithRef,
- SingleSlotFixture,
- StagingAreaFixture,
- useOnClickOutside,
- WasteChuteFixture,
- WasteChuteStagingAreaFixture,
-} from '@opentrons/components'
-import { MODULES_WITH_COLLISION_ISSUES } from '@opentrons/step-generation'
-import {
- FLEX_ROBOT_TYPE,
- getAddressableAreaFromSlotId,
- getDeckDefFromRobotType,
- getLabwareHasQuirk,
- getModuleDef2,
- getModuleDisplayName,
- getPositionFromSlotId,
- inferModuleOrientationFromSlot,
- inferModuleOrientationFromXCoordinate,
- isAddressableAreaStandardSlot,
- OT2_ROBOT_TYPE,
- STAGING_AREA_CUTOUTS,
- THERMOCYCLER_MODULE_TYPE,
- TRASH_BIN_ADAPTER_FIXTURE,
- WASTE_CHUTE_CUTOUT,
-} from '@opentrons/shared-data'
-import { SPAN7_8_10_11_SLOT } from '../../constants'
-import { selectors as labwareDefSelectors } from '../../labware-defs'
-
-import { selectors as featureFlagSelectors } from '../../feature-flags'
-import { getStagingAreaAddressableAreas } from '../../utils'
-import { getSlotIdsBlockedBySpanning, getSlotIsEmpty } from '../../step-forms'
-import * as labwareIngredActions from '../../labware-ingred/actions'
-import { getDeckSetupForActiveItem } from '../../top-selectors/labware-locations'
-import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
-import { getSelectedTerminalItemId } from '../../ui/steps'
-import { getRobotType } from '../../file-data/selectors'
-import { BrowseLabwareModal } from '../labware'
-import { SlotWarning } from './SlotWarning'
-import { LabwareOnDeck } from './LabwareOnDeck'
-import {
- AdapterControls,
- SlotControls,
- LabwareControls,
-} from './LabwareOverlays'
-import { FlexModuleTag } from './FlexModuleTag'
-import { Ot2ModuleTag } from './Ot2ModuleTag'
-import { SlotLabels } from './SlotLabels'
-import { getHasGen1MultiChannelPipette, getSwapBlocked } from './utils'
-
-import type {
- AdditionalEquipmentEntity,
- ModuleTemporalProperties,
-} from '@opentrons/step-generation'
-import type { StagingAreaLocation, TrashCutoutId } from '@opentrons/components'
-import type {
- AddressableAreaName,
- CutoutFixture,
- CutoutId,
- DeckDefinition,
- RobotType,
-} from '@opentrons/shared-data'
-import type { TerminalItemId } from '../../steplist'
-import type {
- InitialDeckSetup,
- LabwareOnDeck as LabwareOnDeckType,
- ModuleOnDeck,
-} from '../../step-forms'
-
-import styles from './DeckSetup.module.css'
-
-export const DECK_LAYER_BLOCKLIST = [
- 'calibrationMarkings',
- 'fixedBase',
- 'doorStops',
- 'metalFrame',
- 'removalHandle',
- 'removableDeckOutline',
- 'screwHoles',
-]
-
-const OT2_STANDARD_DECK_VIEW_LAYER_BLOCK_LIST: string[] = [
- 'calibrationMarkings',
- 'fixedBase',
- 'doorStops',
- 'metalFrame',
- 'removalHandle',
- 'removableDeckOutline',
- 'screwHoles',
-]
-
-interface ContentsProps {
- activeDeckSetup: InitialDeckSetup
- selectedTerminalItemId?: TerminalItemId | null
- showGen1MultichannelCollisionWarnings: boolean
- deckDef: DeckDefinition
- robotType: RobotType
- stagingAreaCutoutIds: CutoutId[]
- trashSlot: string | null
-}
-
-const lightFill = COLORS.grey35
-const darkFill = COLORS.grey60
-
-export const DeckSetupContents = (props: ContentsProps): JSX.Element => {
- const {
- activeDeckSetup,
- showGen1MultichannelCollisionWarnings,
- deckDef,
- robotType,
- trashSlot,
- stagingAreaCutoutIds,
- } = props
- // NOTE: handling module<>labware compat when moving labware to empty module
- // is handled by SlotControls.
- // But when swapping labware when at least one is on a module, we need to be aware
- // of not only what labware is being dragged, but also what labware is **being
- // hovered over**. The intrinsic state of `react-dnd` is not designed to handle that.
- // So we need to use our own state here to determine
- // whether swapping will be blocked due to labware<>module compat:
- const [hoveredLabware, setHoveredLabware] = React.useState<
- LabwareOnDeckType | null | undefined
- >(null)
- const [draggedLabware, setDraggedLabware] = React.useState<
- LabwareOnDeckType | null | undefined
- >(null)
-
- const customLabwareDefs = useSelector(
- labwareDefSelectors.getCustomLabwareDefsByURI
- )
- const swapBlocked = getSwapBlocked({
- hoveredLabware,
- draggedLabware,
- modulesById: activeDeckSetup.modules,
- customLabwareDefs,
- })
-
- const handleHoverEmptySlot = React.useCallback(() => {
- setHoveredLabware(null)
- }, [])
-
- const slotIdsBlockedBySpanning = getSlotIdsBlockedBySpanning(activeDeckSetup)
-
- const allLabware: LabwareOnDeckType[] = Object.keys(
- activeDeckSetup.labware
- ).reduce((acc, labwareId) => {
- const labware = activeDeckSetup.labware[labwareId]
- return getLabwareHasQuirk(labware.def, 'fixedTrash')
- ? acc
- : [...acc, labware]
- }, [])
-
- const allModules: ModuleOnDeck[] = values(activeDeckSetup.modules)
-
- // NOTE: naively hard-coded to show warning north of slots 1 or 3 when occupied by any module
- const multichannelWarningSlotIds: AddressableAreaName[] = showGen1MultichannelCollisionWarnings
- ? compact([
- allModules.some(
- moduleOnDeck =>
- moduleOnDeck.slot === '1' &&
- MODULES_WITH_COLLISION_ISSUES.includes(moduleOnDeck.model)
- )
- ? deckDef.locations.addressableAreas.find(s => s.id === '4')?.id
- : null,
- allModules.some(
- moduleOnDeck =>
- moduleOnDeck.slot === '3' &&
- MODULES_WITH_COLLISION_ISSUES.includes(moduleOnDeck.model)
- )
- ? deckDef.locations.addressableAreas.find(s => s.id === '6')?.id
- : null,
- ])
- : []
-
- return (
- <>
- {/* all modules */}
- {allModules.map(moduleOnDeck => {
- const slotId =
- moduleOnDeck.slot === SPAN7_8_10_11_SLOT ? '7' : moduleOnDeck.slot
-
- const slotPosition = getPositionFromSlotId(slotId, deckDef)
- if (slotPosition == null) {
- console.warn(`no slot ${slotId} for module ${moduleOnDeck.id}`)
- return null
- }
- const moduleDef = getModuleDef2(moduleOnDeck.model)
-
- const getModuleInnerProps = (
- moduleState: ModuleTemporalProperties['moduleState']
- ): React.ComponentProps['innerProps'] => {
- if (moduleState.type === THERMOCYCLER_MODULE_TYPE) {
- let lidMotorState = 'unknown'
- if (moduleState.lidOpen === true) {
- lidMotorState = 'open'
- } else if (moduleState.lidOpen === false) {
- lidMotorState = 'closed'
- }
- return {
- lidMotorState,
- blockTargetTemp: moduleState.blockTargetTemp,
- }
- } else if (
- 'targetTemperature' in moduleState &&
- moduleState.type === 'temperatureModuleType'
- ) {
- return {
- targetTemperature: moduleState.targetTemperature,
- }
- } else if ('targetTemp' in moduleState) {
- return {
- targetTemp: moduleState.targetTemp,
- }
- }
- }
- const labwareLoadedOnModule = allLabware.find(
- lw => lw.slot === moduleOnDeck.id
- )
- const shouldHideChildren =
- moduleOnDeck.moduleState.type === THERMOCYCLER_MODULE_TYPE &&
- moduleOnDeck.moduleState.lidOpen === false
- const labwareInterfaceBoundingBox = {
- xDimension: moduleDef.dimensions.labwareInterfaceXDimension ?? 0,
- yDimension: moduleDef.dimensions.labwareInterfaceYDimension ?? 0,
- zDimension: 0,
- }
-
- const moduleOrientation = inferModuleOrientationFromSlot(
- moduleOnDeck.slot
- )
-
- const isAdapter = labwareLoadedOnModule?.def.allowedRoles?.includes(
- 'adapter'
- )
- return (
-
- {labwareLoadedOnModule != null && !shouldHideChildren ? (
- <>
-
- {isAdapter ? (
-
- ) : (
-
- )}
- >
- ) : null}
-
- {labwareLoadedOnModule == null &&
- !shouldHideChildren &&
- !isAdapter ? (
-
- ) : null}
- {robotType === FLEX_ROBOT_TYPE ? (
-
- ) : (
-
- )}
-
- )
- })}
-
- {/* on-deck warnings */}
- {multichannelWarningSlotIds.map(slotId => {
- const slotPosition = getPositionFromSlotId(slotId, deckDef)
- const slotBoundingBox = getAddressableAreaFromSlotId(slotId, deckDef)
- ?.boundingBox
- return slotPosition != null && slotBoundingBox != null ? (
-
- ) : null
- })}
-
- {/* SlotControls for all empty deck */}
- {deckDef.locations.addressableAreas
- .filter(addressableArea => {
- const stagingAreaAddressableAreas = getStagingAreaAddressableAreas(
- stagingAreaCutoutIds
- )
- const addressableAreas =
- isAddressableAreaStandardSlot(addressableArea.id, deckDef) ||
- stagingAreaAddressableAreas.includes(addressableArea.id)
- return (
- addressableAreas &&
- !slotIdsBlockedBySpanning.includes(addressableArea.id) &&
- getSlotIsEmpty(activeDeckSetup, addressableArea.id) &&
- addressableArea.id !== trashSlot
- )
- })
- .map(addressableArea => {
- return (
-
- )
- })}
-
- {/* all labware on deck NOT those in modules */}
- {allLabware.map(labware => {
- if (
- labware.slot === 'offDeck' ||
- allModules.some(m => m.id === labware.slot) ||
- allLabware.some(lab => lab.id === labware.slot)
- )
- return null
-
- const slotPosition = getPositionFromSlotId(labware.slot, deckDef)
- const slotBoundingBox = getAddressableAreaFromSlotId(
- labware.slot,
- deckDef
- )?.boundingBox
- if (slotPosition == null || slotBoundingBox == null) {
- console.warn(`no slot ${labware.slot} for labware ${labware.id}!`)
- return null
- }
- const labwareIsAdapter = labware.def.allowedRoles?.includes('adapter')
- return (
-
-
-
- {labwareIsAdapter ? (
-
- ) : (
-
- )}
-
-
- )
- })}
-
- {/* all adapters on deck and not on module */}
- {allLabware.map(labware => {
- if (
- allModules.some(m => m.id === labware.slot) ||
- labware.slot === 'offDeck'
- )
- return null
- if (
- deckDef.locations.addressableAreas.some(
- addressableArea => addressableArea.id === labware.slot
- )
- ) {
- return null
- }
- const slotForOnTheDeck = allLabware.find(lab => lab.id === labware.slot)
- ?.slot
- const slotForOnMod = allModules.find(mod => mod.id === slotForOnTheDeck)
- ?.slot
- let slotPosition = null
- if (slotForOnMod != null) {
- slotPosition = getPositionFromSlotId(slotForOnMod, deckDef)
- } else if (slotForOnTheDeck != null) {
- slotPosition = getPositionFromSlotId(slotForOnTheDeck, deckDef)
- }
- if (slotPosition == null) {
- console.warn(`no slot ${labware.slot} for labware ${labware.id}!`)
- return null
- }
- return (
-
-
-
-
-
-
- )
- })}
- >
- )
-}
-
-export const LegacyDeckSetup = (): JSX.Element => {
- const drilledDown =
- useSelector(labwareIngredSelectors.getDrillDownLabwareId) != null
- const selectedTerminalItemId = useSelector(getSelectedTerminalItemId)
- const activeDeckSetup = useSelector(getDeckSetupForActiveItem)
- const _disableCollisionWarnings = useSelector(
- featureFlagSelectors.getDisableModuleRestrictions
- )
- const trash = Object.values(activeDeckSetup.additionalEquipmentOnDeck).find(
- ae => ae.name === 'trashBin'
- )
-
- const trashSlot = trash?.location
- const robotType = useSelector(getRobotType)
- const dispatch = useDispatch()
-
- const _hasGen1MultichannelPipette = React.useMemo(
- () => getHasGen1MultiChannelPipette(activeDeckSetup.pipettes),
- [activeDeckSetup.pipettes]
- )
- const showGen1MultichannelCollisionWarnings =
- !_disableCollisionWarnings && _hasGen1MultichannelPipette
-
- const deckDef = React.useMemo(() => getDeckDefFromRobotType(robotType), [])
- const wrapperRef: React.RefObject = useOnClickOutside({
- onClickOutside: () => {
- if (drilledDown) dispatch(labwareIngredActions.drillUpFromLabware())
- },
- })
- const trashBinFixtures = [
- {
- cutoutId: trash?.location as CutoutId,
- cutoutFixtureId: TRASH_BIN_ADAPTER_FIXTURE,
- },
- ]
- const wasteChuteFixtures = Object.values(
- activeDeckSetup.additionalEquipmentOnDeck
- ).filter(
- aE =>
- WASTE_CHUTE_CUTOUT.includes(aE.location as CutoutId) &&
- aE.name === 'wasteChute'
- )
- const stagingAreaFixtures: AdditionalEquipmentEntity[] = Object.values(
- activeDeckSetup.additionalEquipmentOnDeck
- ).filter(
- aE =>
- STAGING_AREA_CUTOUTS.includes(aE.location as CutoutId) &&
- aE.name === 'stagingArea'
- )
-
- const wasteChuteStagingAreaFixtures = Object.values(
- activeDeckSetup.additionalEquipmentOnDeck
- ).filter(
- aE =>
- STAGING_AREA_CUTOUTS.includes(aE.location as CutoutId) &&
- aE.name === 'stagingArea' &&
- aE.location === WASTE_CHUTE_CUTOUT &&
- wasteChuteFixtures.length > 0
- )
-
- const hasWasteChute =
- wasteChuteFixtures.length > 0 || wasteChuteStagingAreaFixtures.length > 0
-
- const filteredAddressableAreas = deckDef.locations.addressableAreas.filter(
- aa => isAddressableAreaStandardSlot(aa.id, deckDef)
- )
- return (
-
- {drilledDown &&
}
-
-
-
- {() => (
- <>
- {robotType === OT2_ROBOT_TYPE ? (
-
- ) : (
- <>
- {filteredAddressableAreas.map(addressableArea => {
- const cutoutId = getCutoutIdForAddressableArea(
- addressableArea.id,
- deckDef.cutoutFixtures
- )
- return cutoutId != null ? (
-
- ) : null
- })}
- {stagingAreaFixtures.map(fixture => (
-
- ))}
- {trash != null
- ? trashBinFixtures.map(({ cutoutId }) =>
- cutoutId != null ? (
-
-
-
-
- ) : null
- )
- : null}
- {wasteChuteFixtures.map(fixture => (
-
- ))}
- {wasteChuteStagingAreaFixtures.map(fixture => (
-
- ))}
- >
- )}
- areas.location as CutoutId
- )}
- {...{
- deckDef,
-
- showGen1MultichannelCollisionWarnings,
- }}
- />
- 0}
- hasWasteChute={hasWasteChute}
- />
- >
- )}
-
-
-
- )
-}
-
-function getCutoutIdForAddressableArea(
- addressableArea: AddressableAreaName,
- cutoutFixtures: CutoutFixture[]
-): CutoutId | null {
- return cutoutFixtures.reduce((acc, cutoutFixture) => {
- const [cutoutId] =
- Object.entries(
- cutoutFixture.providesAddressableAreas
- ).find(([_cutoutId, providedAAs]) =>
- providedAAs.includes(addressableArea)
- ) ?? []
- return (cutoutId as CutoutId) ?? acc
- }, null)
-}
diff --git a/protocol-designer/src/components/DeckSetup/utils.ts b/protocol-designer/src/components/DeckSetup/utils.ts
deleted file mode 100644
index c21607050a1..00000000000
--- a/protocol-designer/src/components/DeckSetup/utils.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { GEN_ONE_MULTI_PIPETTES } from '@opentrons/shared-data'
-import {
- getLabwareIsCompatible,
- getLabwareIsCustom,
-} from '../../utils/labwareModuleCompatibility'
-import type { InitialDeckSetup, LabwareOnDeck } from '../../step-forms'
-import type { ModuleType } from '@opentrons/shared-data'
-import type { LabwareDefByDefURI } from '../../labware-defs'
-
-export interface SwapBlockedArgs {
- hoveredLabware?: LabwareOnDeck | null
- draggedLabware?: LabwareOnDeck | null
- modulesById: InitialDeckSetup['modules']
- customLabwareDefs: LabwareDefByDefURI
-}
-
-export const getSwapBlocked = (args: SwapBlockedArgs): boolean => {
- const {
- hoveredLabware,
- draggedLabware,
- modulesById,
- customLabwareDefs,
- } = args
- if (!hoveredLabware || !draggedLabware) {
- return false
- }
-
- const sourceModuleType: ModuleType | null =
- modulesById[draggedLabware.slot]?.type || null
- const destModuleType: ModuleType | null =
- modulesById[hoveredLabware.slot]?.type || null
-
- const draggedLabwareIsCustom = getLabwareIsCustom(
- customLabwareDefs,
- draggedLabware
- )
- const hoveredLabwareIsCustom = getLabwareIsCustom(
- customLabwareDefs,
- hoveredLabware
- )
-
- // dragging custom labware to module gives not compat error
- const labwareSourceToDestBlocked = sourceModuleType
- ? !getLabwareIsCompatible(hoveredLabware.def, sourceModuleType) &&
- !hoveredLabwareIsCustom
- : false
- const labwareDestToSourceBlocked = destModuleType
- ? !getLabwareIsCompatible(draggedLabware.def, destModuleType) &&
- !draggedLabwareIsCustom
- : false
-
- return labwareSourceToDestBlocked || labwareDestToSourceBlocked
-}
-
-export const getHasGen1MultiChannelPipette = (
- pipettes: InitialDeckSetup['pipettes']
-): boolean => {
- const pipetteIds = Object.keys(pipettes)
- return pipetteIds.some(pipetteId =>
- GEN_ONE_MULTI_PIPETTES.includes(pipettes[pipetteId]?.name)
- )
-}
diff --git a/protocol-designer/src/components/DeckSetupManager.tsx b/protocol-designer/src/components/DeckSetupManager.tsx
deleted file mode 100644
index bbe87287b41..00000000000
--- a/protocol-designer/src/components/DeckSetupManager.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useSelector } from 'react-redux'
-import {
- getBatchEditSelectedStepTypes,
- getHoveredItem,
-} from '../ui/steps/selectors'
-import { LegacyDeckSetup } from './DeckSetup'
-import { NullDeckState } from './DeckSetup/NullDeckState'
-import { OffDeckLabwareButton } from './OffDeckLabwareButton'
-
-export const DeckSetupManager = (): JSX.Element => {
- const batchEditSelectedStepTypes = useSelector(getBatchEditSelectedStepTypes)
- const hoveredItem = useSelector(getHoveredItem)
-
- if (batchEditSelectedStepTypes.length === 0 || hoveredItem !== null) {
- // not batch edit mode, or batch edit while item is hovered: show the deck
- return (
- <>
-
-
- >
- )
- } else {
- return
- }
-}
diff --git a/protocol-designer/src/components/EditModules.tsx b/protocol-designer/src/components/EditModules.tsx
deleted file mode 100644
index 31b392c29a5..00000000000
--- a/protocol-designer/src/components/EditModules.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import { useState } from 'react'
-import { useSelector, useDispatch } from 'react-redux'
-import {
- FLEX_ROBOT_TYPE,
- HEATERSHAKER_MODULE_TYPE,
- MAGNETIC_BLOCK_TYPE,
- TEMPERATURE_MODULE_TYPE,
-} from '@opentrons/shared-data'
-import {
- selectors as stepFormSelectors,
- actions as stepFormActions,
-} from '../step-forms'
-import { moveDeckItem } from '../labware-ingred/actions/actions'
-import { getRobotType } from '../file-data/selectors'
-import { EditMultipleModulesModal } from './modals/EditModulesModal/EditMultipleModulesModal'
-import { useBlockingHint } from './Hints/useBlockingHint'
-import { MagneticModuleWarningModalContent } from './modals/EditModulesModal/MagneticModuleWarningModalContent'
-import { EditModulesModal } from './modals/EditModulesModal'
-import type { ModuleModel, ModuleType } from '@opentrons/shared-data'
-
-export interface EditModulesProps {
- moduleToEdit: {
- moduleId?: string | null
- moduleType: ModuleType
- }
- onCloseClick: () => void
-}
-
-export interface ModelModuleInfo {
- model: ModuleModel
- slot: string
-}
-
-export const EditModules = (props: EditModulesProps): JSX.Element => {
- const { onCloseClick, moduleToEdit } = props
- const { moduleId, moduleType } = moduleToEdit
- const _initialDeckSetup = useSelector(stepFormSelectors.getInitialDeckSetup)
- const robotType = useSelector(getRobotType)
-
- const MOAM_MODULE_TYPES: ModuleType[] = [
- TEMPERATURE_MODULE_TYPE,
- HEATERSHAKER_MODULE_TYPE,
- MAGNETIC_BLOCK_TYPE,
- ]
-
- const showMultipleModuleModal =
- robotType === FLEX_ROBOT_TYPE && MOAM_MODULE_TYPES.includes(moduleType)
-
- const moduleOnDeck = moduleId ? _initialDeckSetup.modules[moduleId] : null
- const [
- changeModuleWarningInfo,
- displayModuleWarning,
- ] = useState(null)
- const dispatch = useDispatch()
-
- const editModuleModel = (selectedModel: ModuleModel): void => {
- if (moduleOnDeck?.id != null) {
- dispatch(
- stepFormActions.editModule({
- id: moduleOnDeck.id,
- model: selectedModel,
- })
- )
- } else {
- console.error(
- `cannot edit module model without module id. This shouldn't be able to happen`
- )
- }
- }
- const editModuleSlot = (selectedSlot: string): void => {
- if (selectedSlot && moduleOnDeck && moduleOnDeck.slot !== selectedSlot) {
- dispatch(moveDeckItem(moduleOnDeck.slot, selectedSlot))
- }
- }
-
- const changeModuleWarning = useBlockingHint({
- hintKey: 'change_magnet_module_model',
- handleCancel: () => {
- displayModuleWarning(null)
- },
- handleContinue: () => {
- if (changeModuleWarningInfo) {
- editModuleModel(changeModuleWarningInfo.model)
- editModuleSlot(changeModuleWarningInfo.slot)
- } else {
- console.error('no module info set, could not edit module')
- }
- displayModuleWarning(null)
- onCloseClick()
- },
- content: ,
- enabled: changeModuleWarningInfo !== null,
- })
-
- let modal = (
-
- )
- if (showMultipleModuleModal) {
- modal = (
-
- )
- }
- return changeModuleWarning ?? modal
-}
diff --git a/protocol-designer/src/components/EditableTextField.tsx b/protocol-designer/src/components/EditableTextField.tsx
deleted file mode 100644
index 1b5adcb56be..00000000000
--- a/protocol-designer/src/components/EditableTextField.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-// TODO: Ian 2018-10-30 if we like this, add it to components library
-import * as React from 'react'
-import { ClickOutside, Icon, LegacyInputField } from '@opentrons/components'
-import styles from './editableTextField.module.css'
-
-interface Props {
- className?: string
- value?: string | null
- saveEdit: (newValue: string) => unknown
-}
-
-export function EditableTextField(props: Props): JSX.Element {
- const { className, value, saveEdit } = props
- const [editing, setEditing] = React.useState(false)
- const [transientValue, setTransientValue] = React.useState<
- string | null | undefined
- >(value)
-
- const enterEditMode = (): void => {
- setEditing(true)
- setTransientValue(value)
- }
- const handleCancel = (): void => {
- setEditing(false)
- setTransientValue(value)
- }
-
- const handleKeyUp = (e: React.KeyboardEvent): void => {
- if (e.key === 'Escape') {
- handleCancel()
- }
- }
-
- const handleSubmit = (): void => {
- setEditing(false)
- saveEdit(transientValue ?? '')
- }
- const handleFormSubmit = (e: React.FormEvent): void => {
- e.preventDefault() // avoid 'form is not connected' warning
- handleSubmit()
- }
-
- const updateValue = (e: React.ChangeEvent): void => {
- setTransientValue(e.currentTarget.value)
- }
- if (editing) {
- return (
-
- {({ ref }) => (
-
- )}
-
- )
- }
-
- return (
-
- )
-}
diff --git a/protocol-designer/src/components/FilePage.module.css b/protocol-designer/src/components/FilePage.module.css
deleted file mode 100644
index 787f00b4866..00000000000
--- a/protocol-designer/src/components/FilePage.module.css
+++ /dev/null
@@ -1,51 +0,0 @@
-@import '@opentrons/components/styles';
-
-.file_page {
- position: relative;
- height: 100%;
- min-height: 100vh;
-}
-
-.card_content {
- padding: 1rem;
-}
-
-.file_page h1 {
- font-size: var(--fs-header); /* from legacy --font-header-dark */
- font-weight: var(--fw-semibold); /* from legacy --font-header-dark */
- color: var(--c-font-dark); /* from legacy --font-header-dark */
-}
-
-.file_page > * {
- margin: 1rem 2.5rem;
-}
-
-.pipette_button_row {
- display: flex;
- justify-content: center;
-}
-
-.swap_button {
- display: block;
- margin: 0 0.5rem;
- width: 8rem;
-
- &:focus {
- background-color: transparent;
- }
-}
-
-.edit_button {
- display: block;
- margin: 0 0.5rem;
- width: 8rem;
-}
-
-.update_button {
- width: 8rem;
- align-self: flex-start;
-}
-
-.continue_button {
- width: 14rem;
-}
diff --git a/protocol-designer/src/components/FilePage.tsx b/protocol-designer/src/components/FilePage.tsx
deleted file mode 100644
index 2167ece1071..00000000000
--- a/protocol-designer/src/components/FilePage.tsx
+++ /dev/null
@@ -1,282 +0,0 @@
-import { useState, useEffect } from 'react'
-import { createPortal } from 'react-dom'
-import { Controller, useForm } from 'react-hook-form'
-import { useTranslation } from 'react-i18next'
-import { useSelector, useDispatch } from 'react-redux'
-import mapValues from 'lodash/mapValues'
-import { format } from 'date-fns'
-import cx from 'classnames'
-
-import {
- Card,
- FormGroup,
- InstrumentGroup,
- OutlineButton,
- DeprecatedPrimaryButton,
- LegacyInputField,
-} from '@opentrons/components'
-import { resetScrollElements } from '../ui/steps/utils'
-import { EditModulesCard } from './modules'
-import { EditModules } from './EditModules'
-
-import styles from './FilePage.module.css'
-import modalStyles from '../components/modals/modal.module.css'
-import formStyles from '../components/forms/forms.module.css'
-import { actions, selectors as fileSelectors } from '../file-data'
-import { actions as navActions } from '../navigation'
-import { actions as steplistActions } from '../steplist'
-import { selectors as stepFormSelectors } from '../step-forms'
-import { INITIAL_DECK_SETUP_STEP_ID } from '../constants'
-import { FilePipettesModal } from './modals/FilePipettesModal'
-import { getTopPortalEl } from './portals/TopPortal'
-
-import type { ModuleType } from '@opentrons/shared-data'
-import type { FileMetadataFields } from '../file-data'
-
-// TODO(mc, 2020-02-28): explore l10n for these dates
-const DATE_ONLY_FORMAT = 'MMM dd, yyyy'
-const DATETIME_FORMAT = 'MMM dd, yyyy | h:mm a'
-export const FilePage = (): JSX.Element => {
- const { t } = useTranslation(['button', 'application'])
- const dispatch = useDispatch()
-
- const formValues = useSelector(fileSelectors.getFileMetadata)
- const instruments = useSelector(
- stepFormSelectors.getPipettesForInstrumentGroup
- )
- const modules = useSelector(stepFormSelectors.getModulesForEditModulesCard)
- const initialDeckSetup = useSelector(stepFormSelectors.getInitialDeckSetup)
- const [isEditPipetteModalOpen, setEditPipetteModalOpen] = useState(
- false
- )
- const [moduleToEdit, setModuleToEdit] = useState<{
- moduleType: ModuleType
- moduleId?: string | null
- } | null>(null)
-
- const swapPipetteUpdate = mapValues(initialDeckSetup.pipettes, pipette => {
- if (!pipette.mount) return pipette.mount
- return pipette.mount === 'left' ? 'right' : 'left'
- })
-
- const openEditPipetteModal = (): void => {
- resetScrollElements()
- setEditPipetteModalOpen(true)
- }
-
- const closeEditPipetteModal = (): void => {
- setEditPipetteModalOpen(false)
- }
- const handleEditModule = (
- moduleType: ModuleType,
- moduleId?: string | null
- ): void => {
- resetScrollElements()
- setModuleToEdit({ moduleType: moduleType, moduleId: moduleId })
- }
-
- const closeEditModulesModal = (): void => {
- setModuleToEdit(null)
- }
-
- const saveFileMetadata = (nextFormValues: FileMetadataFields): void => {
- dispatch(actions.saveFileMetadata(nextFormValues))
- setManualDirty(false)
- }
- const [isManualDirty, setManualDirty] = useState(false)
- const {
- handleSubmit,
- watch,
- control,
- setValue,
- formState: { isDirty },
- } = useForm({ defaultValues: formValues })
- // to ensure that values from watch are up to date if the defaultValues
- // change
- useEffect(() => {
- setValue('protocolName', formValues.protocolName)
- setValue('created', formValues.created)
- setValue('lastModified', formValues.lastModified)
- setValue('author', formValues.author)
- setValue('description', formValues.description)
- }, [
- formValues.protocolName,
- formValues.created,
- formValues.lastModified,
- formValues.author,
- formValues.description,
- ])
-
- const [created, lastModified, protocolName, author, description] = watch([
- 'created',
- 'lastModified',
- 'protocolName',
- 'author',
- 'description',
- ])
- return (
-
-
-
-
-
-
-
-
-
-
- {t('edit')}
-
-
- dispatch(
- steplistActions.changeSavedStepForm({
- stepId: INITIAL_DECK_SETUP_STEP_ID,
- update: {
- pipetteLocationUpdate: swapPipetteUpdate,
- },
- })
- )
- }
- className={styles.swap_button}
- iconName="swap-horizontal"
- name="swapPipettes"
- disabled={instruments?.left?.pipetteSpecs?.channels === 96}
- >
- {t('swap')}
-
-
-
-
-
-
-
-
- dispatch(navActions.navigateToPage('liquids'))}
- className={styles.continue_button}
- iconName="arrow-right"
- name="continueToLiquids"
- >
- {t('continue_to_liquids')}
-
-
- {createPortal(
- <>
- {isEditPipetteModalOpen && (
-
- )}
- {moduleToEdit != null && (
-
- )}
- >,
- getTopPortalEl()
- )}
-
- )
-}
diff --git a/protocol-designer/src/components/FileSidebar/FileSidebar.module.css b/protocol-designer/src/components/FileSidebar/FileSidebar.module.css
deleted file mode 100644
index b94d2658d01..00000000000
--- a/protocol-designer/src/components/FileSidebar/FileSidebar.module.css
+++ /dev/null
@@ -1,16 +0,0 @@
-@import '@opentrons/components/styles';
-
-.file_sidebar {
- padding: 2rem 4.5rem 0;
-}
-
-.upload_button,
-.button {
- margin: 0.75rem 0;
- width: 100%;
-}
-
-.upload_button input {
- position: fixed;
- clip: rect(1px 1px 1px 1px);
-}
diff --git a/protocol-designer/src/components/FileSidebar/FileSidebar.tsx b/protocol-designer/src/components/FileSidebar/FileSidebar.tsx
deleted file mode 100644
index 52e312b37e0..00000000000
--- a/protocol-designer/src/components/FileSidebar/FileSidebar.tsx
+++ /dev/null
@@ -1,475 +0,0 @@
-import * as React from 'react'
-import cx from 'classnames'
-import { useDispatch, useSelector } from 'react-redux'
-import { useTranslation } from 'react-i18next'
-import {
- DeprecatedPrimaryButton,
- AlertModal,
- OutlineButton,
- SidePanel,
-} from '@opentrons/components'
-import {
- actions as loadFileActions,
- selectors as loadFileSelectors,
-} from '../../load-file'
-import { actions, selectors } from '../../navigation'
-import { selectors as fileDataSelectors } from '../../file-data'
-import { selectors as stepFormSelectors } from '../../step-forms'
-import { getRobotType } from '../../file-data/selectors'
-import { getAdditionalEquipment } from '../../step-forms/selectors'
-import { resetScrollElements } from '../../ui/steps/utils'
-import { getMainPagePortalEl } from '../portals/MainPageModalPortal'
-import { useBlockingHint } from '../Hints/useBlockingHint'
-import { KnowledgeBaseLink } from '../KnowledgeBaseLink'
-import {
- getUnusedEntities,
- getUnusedTrash,
- getUnusedStagingAreas,
-} from './utils'
-import modalStyles from '../modals/modal.module.css'
-import styles from './FileSidebar.module.css'
-
-import type {
- CreateCommand,
- ProtocolFile,
- RobotType,
-} from '@opentrons/shared-data'
-import type { HintKey } from '../../tutorial'
-import type {
- InitialDeckSetup,
- SavedStepFormState,
- ModuleOnDeck,
- PipetteOnDeck,
-} from '../../step-forms'
-import type { ThunkDispatch } from '../../types'
-import { createPortal } from 'react-dom'
-
-export interface AdditionalEquipment {
- [additionalEquipmentId: string]: {
- name: 'gripper' | 'wasteChute' | 'stagingArea' | 'trashBin'
- id: string
- location?: string
- }
-}
-
-export interface Props {
- loadFile: (event: React.ChangeEvent) => unknown
- createNewFile?: () => unknown
- canDownload: boolean
- onDownload: () => unknown
- fileData?: ProtocolFile | null
- pipettesOnDeck: InitialDeckSetup['pipettes']
- modulesOnDeck: InitialDeckSetup['modules']
- savedStepForms: SavedStepFormState
- robotType: RobotType
- additionalEquipment: AdditionalEquipment
-}
-
-interface WarningContent {
- content: React.ReactNode
- heading: string
-}
-
-interface Fixture {
- trashBin: boolean
- wasteChute: boolean
- stagingAreaSlots: string[]
-}
-interface MissingContent {
- noCommands: boolean
- pipettesWithoutStep: PipetteOnDeck[]
- modulesWithoutStep: ModuleOnDeck[]
- gripperWithoutStep: boolean
- fixtureWithoutStep: Fixture
- t: any
-}
-
-const LOAD_COMMANDS: Array = [
- 'loadLabware',
- 'loadModule',
- 'loadPipette',
- 'loadLiquid',
-]
-
-function getWarningContent({
- noCommands,
- pipettesWithoutStep,
- modulesWithoutStep,
- gripperWithoutStep,
- fixtureWithoutStep,
- t,
-}: MissingContent): WarningContent | null {
- if (noCommands) {
- return {
- content: (
- <>
- {t('export_warnings.no_commands.body1')}
-
- {t('export_warnings.no_commands.body2')}
- here .
-
- >
- ),
- heading: t('export_warnings.no_commands.heading'),
- }
- }
-
- if (gripperWithoutStep) {
- return {
- content: (
- <>
- {t('export_warnings.unused_gripper.body1')}
- {t('export_warnings.unused_gripper.body2')}
- >
- ),
- heading: t('export_warnings.unused_gripper.heading'),
- }
- }
-
- const pipettesDetails = pipettesWithoutStep
- .map(pipette =>
- pipette.spec.channels === 96
- ? `${pipette.spec.displayName} pipette`
- : `${pipette.mount} ${pipette.spec.displayName} pipette`
- )
- .join(' and ')
-
- const unusedModuleCounts = modulesWithoutStep.reduce<{
- [key: string]: number
- }>((acc, mod) => {
- if (!(mod.type in acc)) {
- return { ...acc, [mod.type]: 1 }
- } else {
- return { ...acc, [mod.type]: acc[mod.type] + 1 }
- }
- }, {})
-
- const modulesDetails = Object.keys(unusedModuleCounts)
- // sorting by module count
- .sort((k1, k2) => {
- if (unusedModuleCounts[k1] < unusedModuleCounts[k2]) {
- return 1
- } else if (unusedModuleCounts[k1] > unusedModuleCounts[k2]) {
- return -1
- } else {
- return 0
- }
- })
- .map(modType =>
- unusedModuleCounts[modType] === 1
- ? t(`modules:module_long_names.${modType}`)
- : `${t(`modules:module_long_names.${modType}`)}s`
- )
- // transform list of modules with counts to string
- .reduce((acc, modName, index, arr) => {
- if (arr.length > 2) {
- if (index === arr.length - 1) {
- return `${acc} and ${modName}`
- } else {
- return `${acc}${modName}, `
- }
- } else if (arr.length === 2) {
- return index === 0 ? `${modName} and ` : `${acc}${modName}`
- } else {
- return modName
- }
- }, '')
-
- if (pipettesWithoutStep.length && modulesWithoutStep.length) {
- return {
- content: (
- <>
-
- {t('export_warnings.unused_pipette_and_module.body1', {
- modulesDetails,
- pipettesDetails,
- })}
-
- {t('export_warnings.unused_pipette_and_module.body2')}
- >
- ),
- heading: t('export_warnings.unused_pipette_and_module.heading'),
- }
- }
-
- if (pipettesWithoutStep.length) {
- return {
- content: (
- <>
-
- {t('export_warnings.unused_pipette.body1', {
- pipettesDetails,
- })}
-
- {t('export_warnings.unused_pipette.body2')}
- >
- ),
- heading: t('export_warnings.unused_pipette.heading'),
- }
- }
-
- if (modulesWithoutStep.length) {
- const moduleCase =
- modulesWithoutStep.length > 1 ? 'unused_modules' : 'unused_module'
- const slotName = modulesWithoutStep.map(module => module.slot)
- return {
- content: (
- <>
-
- {t(`export_warnings.${moduleCase}.body1`, {
- modulesDetails,
- slotName: slotName,
- })}
-
- {t(`export_warnings.${moduleCase}.body2`)}
- >
- ),
- heading: t(`export_warnings.${moduleCase}.heading`),
- }
- }
-
- if (fixtureWithoutStep.trashBin || fixtureWithoutStep.wasteChute) {
- return {
- content:
- (fixtureWithoutStep.trashBin && !fixtureWithoutStep.wasteChute) ||
- (!fixtureWithoutStep.trashBin && fixtureWithoutStep.wasteChute) ? (
-
- {t('export_warnings.unused_trash.body', {
- name: fixtureWithoutStep.trashBin ? 'trash bin' : 'waste chute',
- })}
-
- ) : (
-
- {t('export_warnings.unused_trash.body_both', {
- trashName: 'trash bin',
- wasteName: 'waste chute',
- })}
-
- ),
- heading: t('export_warnings.unused_trash.heading'),
- }
- }
-
- if (fixtureWithoutStep.stagingAreaSlots.length) {
- return {
- content: (
- <>
-
- {t('export_warnings.unused_staging_area.body1', {
- count: fixtureWithoutStep.stagingAreaSlots.length,
- slot: fixtureWithoutStep.stagingAreaSlots,
- })}
-
-
- {t('export_warnings.unused_staging_area.body2', {
- count: fixtureWithoutStep.stagingAreaSlots.length,
- })}
-
- >
- ),
- heading: t('export_warnings.unused_staging_area.heading'),
- }
- }
-
- return null
-}
-
-export function v8WarningContent(t: any): JSX.Element {
- return (
-
-
- {t(`alert:hint.export_v8_1_protocol_7_3.body1`)}{' '}
- {t(`alert:hint.export_v8_1_protocol_7_3.body2`)}
- {t(`alert:hint.export_v8_1_protocol_7_3.body3`)}
-
-
- )
-}
-export function FileSidebar(): JSX.Element {
- const fileData = useSelector(fileDataSelectors.createFile)
- const currentPage = useSelector(selectors.getCurrentPage)
- const canDownload = currentPage !== 'file-splash'
- const initialDeckSetup = useSelector(stepFormSelectors.getInitialDeckSetup)
- const modulesOnDeck = initialDeckSetup.modules
- const pipettesOnDeck = initialDeckSetup.pipettes
- const robotType = useSelector(getRobotType)
- const additionalEquipment = useSelector(getAdditionalEquipment)
- const savedStepForms = useSelector(stepFormSelectors.getSavedStepForms)
- const newProtocolModal = useSelector(selectors.getNewProtocolModal)
- const hasUnsavedChanges = useSelector(loadFileSelectors.getHasUnsavedChanges)
- const canCreateNew = !newProtocolModal
- const dispatch: ThunkDispatch = useDispatch()
-
- const [
- showExportWarningModal,
- setShowExportWarningModal,
- ] = React.useState(false)
- const { t } = useTranslation(['alert', 'modules'])
- const isGripperAttached = Object.values(additionalEquipment).some(
- equipment => equipment?.name === 'gripper'
- )
- const { trashBinUnused, wasteChuteUnused } = getUnusedTrash(
- additionalEquipment,
- fileData?.commands
- )
-
- const fixtureWithoutStep: Fixture = {
- trashBin: trashBinUnused,
- wasteChute: wasteChuteUnused,
- stagingAreaSlots: getUnusedStagingAreas(
- additionalEquipment,
- fileData?.commands
- ),
- }
- const [showBlockingHint, setShowBlockingHint] = React.useState(false)
-
- const cancelModal = (): void => {
- setShowExportWarningModal(false)
- }
-
- const loadFile = (
- fileChangeEvent: React.ChangeEvent
- ): void => {
- if (!hasUnsavedChanges || window.confirm(t('confirm_import') as string)) {
- dispatch(loadFileActions.loadProtocolFile(fileChangeEvent))
- }
- }
-
- const createNewFile = (): void => {
- if (canCreateNew) {
- dispatch(actions.toggleNewProtocolModal(true))
- }
- }
-
- const nonLoadCommands =
- fileData?.commands.filter(
- command => !LOAD_COMMANDS.includes(command.commandType)
- ) ?? []
-
- const gripperInUse =
- fileData?.commands.find(
- command =>
- command.commandType === 'moveLabware' &&
- command.params.strategy === 'usingGripper'
- ) != null
-
- const noCommands = fileData ? nonLoadCommands.length === 0 : true
- const pipettesWithoutStep = getUnusedEntities(
- pipettesOnDeck,
- savedStepForms,
- 'pipette',
- robotType
- )
- const modulesWithoutStep = getUnusedEntities(
- modulesOnDeck,
- savedStepForms,
- 'moduleId',
- robotType
- )
- const gripperWithoutStep = isGripperAttached && !gripperInUse
-
- const hasWarning =
- noCommands ||
- modulesWithoutStep.length > 0 ||
- pipettesWithoutStep.length > 0 ||
- gripperWithoutStep ||
- fixtureWithoutStep.trashBin ||
- fixtureWithoutStep.wasteChute ||
- fixtureWithoutStep.stagingAreaSlots.length > 0
-
- const warning =
- hasWarning &&
- getWarningContent({
- noCommands,
- pipettesWithoutStep,
- modulesWithoutStep,
- gripperWithoutStep,
- fixtureWithoutStep,
- t,
- })
-
- const getExportHintContent = (): {
- hintKey: HintKey
- content: React.ReactNode
- } => {
- return {
- hintKey: 'export_v8_1_protocol_7_3',
- content: v8WarningContent(t),
- }
- }
-
- const { hintKey, content } = getExportHintContent()
-
- const blockingExportHint = useBlockingHint({
- enabled: showBlockingHint,
- hintKey,
- content,
- handleCancel: () => {
- setShowBlockingHint(false)
- },
- handleContinue: () => {
- setShowBlockingHint(false)
- dispatch(loadFileActions.saveProtocolFile())
- },
- })
- return (
- <>
- {blockingExportHint}
- {showExportWarningModal &&
- createPortal(
- {
- setShowExportWarningModal(false)
- setShowBlockingHint(true)
- },
- },
- ]}
- >
- {warning && warning.content}
- ,
- getMainPagePortalEl()
- )}
-
-
-
- {t('create_new')}
-
-
-
- {t('import')}
-
-
-
-
- {
- if (hasWarning) {
- resetScrollElements()
- setShowExportWarningModal(true)
- } else {
- resetScrollElements()
- setShowBlockingHint(true)
- }
- }}
- disabled={!canDownload}
- >
- {t('export')}
-
-
-
-
- >
- )
-}
diff --git a/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx b/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx
deleted file mode 100644
index c8d2a7c8fe9..00000000000
--- a/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx
+++ /dev/null
@@ -1,285 +0,0 @@
-import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'
-import { fireEvent, screen } from '@testing-library/react'
-import { FLEX_ROBOT_TYPE, fixtureTiprack300ul } from '@opentrons/shared-data'
-import { renderWithProviders } from '../../../__testing-utils__'
-import { createFile, getRobotType } from '../../../file-data/selectors'
-import {
- getCurrentPage,
- getNewProtocolModal,
-} from '../../../navigation/selectors'
-import { i18n } from '../../../assets/localization'
-import {
- getAdditionalEquipment,
- getInitialDeckSetup,
- getSavedStepForms,
-} from '../../../step-forms/selectors'
-import { toggleNewProtocolModal } from '../../../navigation/actions'
-import { getHasUnsavedChanges } from '../../../load-file/selectors'
-import { useBlockingHint } from '../../Hints/useBlockingHint'
-import { getUnusedStagingAreas } from '../utils/getUnusedStagingAreas'
-import { getUnusedTrash } from '../utils/getUnusedTrash'
-import { FileSidebar } from '../FileSidebar'
-import type { LabwareDefinition2 } from '@opentrons/shared-data'
-
-vi.mock('../../../step-forms/selectors')
-vi.mock('../../../load-file/selectors')
-vi.mock('../../../navigation/actions')
-vi.mock('../../../navigation/selectors')
-vi.mock('../../../file-data/selectors')
-vi.mock('../../Hints/useBlockingHint')
-vi.mock('../utils/getUnusedStagingAreas')
-vi.mock('../utils/getUnusedTrash')
-const render = () => {
- return renderWithProviders( , { i18nInstance: i18n })[0]
-}
-
-describe('FileSidebar', () => {
- beforeEach(() => {
- vi.mocked(getUnusedStagingAreas).mockReturnValue([])
- vi.mocked(getUnusedTrash).mockReturnValue({
- trashBinUnused: false,
- wasteChuteUnused: false,
- })
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- modules: {},
- pipettes: {},
- additionalEquipmentOnDeck: {},
- labware: {},
- })
- vi.mocked(getHasUnsavedChanges).mockReturnValue(false)
- vi.mocked(getNewProtocolModal).mockReturnValue(false)
- vi.mocked(getSavedStepForms).mockReturnValue({})
- vi.mocked(getAdditionalEquipment).mockReturnValue({})
- vi.mocked(getRobotType).mockReturnValue(FLEX_ROBOT_TYPE)
- vi.mocked(getCurrentPage).mockReturnValue('settings-app')
- vi.mocked(useBlockingHint).mockReturnValue(null)
- vi.mocked(createFile).mockReturnValue({
- commands: [
- {
- commandType: 'moveToAddressableArea',
- params: {
- addressableAreaName: 'movableTrashA3',
- pipetteId: 'mockId',
- offset: { x: 0, y: 0, z: 0 },
- },
- },
- ],
- } as any)
- })
- afterEach(() => {
- vi.resetAllMocks()
- })
- it('renders the file sidebar and exports with blocking hint for exporting', () => {
- vi.mocked(useBlockingHint).mockReturnValue(mock blocking hint
)
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- expect(vi.mocked(useBlockingHint)).toHaveBeenCalled()
- screen.getByText('mock blocking hint')
- })
- it('renders the file sidebar and buttons work as expected with no warning upon export', () => {
- render()
- screen.getByText('Protocol File')
- fireEvent.click(screen.getByRole('button', { name: 'Create New' }))
- expect(vi.mocked(toggleNewProtocolModal)).toHaveBeenCalled()
- screen.getByText('Import')
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- expect(vi.mocked(useBlockingHint)).toHaveBeenCalled()
- })
- it('renders the no commands warning', () => {
- vi.mocked(createFile).mockReturnValue({
- commands: [],
- } as any)
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Your protocol has no steps')
- })
- it('renders the unused pipette warning', () => {
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- modules: {},
- pipettes: {
- pipetteId: {
- mount: 'left',
- name: 'p1000_96',
- id: 'pipetteId',
- tiprackLabwareDef: [fixtureTiprack300ul as LabwareDefinition2],
- tiprackDefURI: ['mockDefUri'],
- spec: {
- displayName: 'mock display name',
- } as any,
- },
- },
- additionalEquipmentOnDeck: {},
- labware: {},
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Unused pipette')
- })
- it('renders the unused pieptte and module warning', () => {
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- modules: {
- moduleId: {
- slot: 'A1',
- moduleState: {} as any,
- id: 'moduleId',
- type: 'temperatureModuleType',
- model: 'temperatureModuleV2',
- },
- },
- pipettes: {
- pipetteId: {
- mount: 'left',
- name: 'p1000_96',
- id: 'pipetteId',
- tiprackLabwareDef: [fixtureTiprack300ul as LabwareDefinition2],
- tiprackDefURI: ['mockDefUri'],
- spec: {
- displayName: 'mock display name',
- } as any,
- },
- },
- additionalEquipmentOnDeck: {},
- labware: {},
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Unused pipette and module')
- })
- it('renders the unused trash warning', () => {
- vi.mocked(getUnusedTrash).mockReturnValue({
- trashBinUnused: true,
- wasteChuteUnused: false,
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Unused trash')
- })
- it('renders the unused waste chute warning', () => {
- vi.mocked(getUnusedTrash).mockReturnValue({
- trashBinUnused: false,
- wasteChuteUnused: true,
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Unused trash')
- })
- it('renders the unused staging area slot warning', () => {
- vi.mocked(getUnusedStagingAreas).mockReturnValue(['D4'])
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('One or more staging area slots are unused')
- })
- it('renders the unused gripper warning', () => {
- vi.mocked(getAdditionalEquipment).mockReturnValue({
- gripperId: { name: 'gripper', id: 'gripperId' },
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Unused gripper')
- })
- it('renders the unused module warning', () => {
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- modules: {
- moduleId: {
- slot: 'A1',
- moduleState: {} as any,
- id: 'moduleId',
- type: 'temperatureModuleType',
- model: 'temperatureModuleV2',
- },
- },
- pipettes: {},
- additionalEquipmentOnDeck: {},
- labware: {},
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Unused module')
- screen.getByText(
- 'The Temperature module specified in your protocol in Slot A1 is not currently used in any step. In order to run this protocol you will need to power up and connect the module to your robot.'
- )
- })
- it('renders the unused modules warning', () => {
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- modules: {
- moduleId: {
- slot: 'A1',
- moduleState: {} as any,
- id: 'moduleId',
- type: 'temperatureModuleType',
- model: 'temperatureModuleV2',
- },
- moduleId2: {
- slot: 'B1',
- moduleState: {} as any,
- id: 'moduleId2',
- type: 'temperatureModuleType',
- model: 'temperatureModuleV2',
- },
- },
- pipettes: {},
- additionalEquipmentOnDeck: {},
- labware: {},
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText('Unused modules')
- screen.getByText(
- 'One or more modules specified in your protocol in Slot(s) A1,B1 are not currently used in any step. In order to run this protocol you will need to power up and connect the modules to your robot.'
- )
- })
- it('renders the formatted unused pipettes and modules warning sorted by count', () => {
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- modules: {
- moduleId1: {
- slot: 'A1',
- moduleState: {} as any,
- id: 'moduleId',
- type: 'thermocyclerModuleType',
- model: 'thermocyclerModuleV2',
- },
- moduleId2: {
- slot: 'C3',
- moduleState: {} as any,
- id: 'moduleId1',
- type: 'temperatureModuleType',
- model: 'temperatureModuleV2',
- },
- moduleId3: {
- slot: 'D3',
- moduleState: {} as any,
- id: 'moduleId2',
- type: 'temperatureModuleType',
- model: 'temperatureModuleV2',
- },
- moduleId4: {
- slot: 'C1',
- moduleState: {} as any,
- id: 'moduleId3',
- type: 'heaterShakerModuleType',
- model: 'heaterShakerModuleV1',
- },
- },
- pipettes: {
- pipetteId: {
- mount: 'left',
- name: 'p1000_96',
- id: 'pipetteId',
- tiprackLabwareDef: [fixtureTiprack300ul as LabwareDefinition2],
- tiprackDefURI: ['mockDefUri'],
- spec: {
- displayName: 'mock display name',
- channels: 96,
- } as any,
- },
- },
- additionalEquipmentOnDeck: {},
- labware: {},
- })
- render()
- fireEvent.click(screen.getByRole('button', { name: 'Export' }))
- screen.getByText(
- 'The mock display name pipette and Temperature modules, Thermocycler module, and Heater-Shaker module in your protocol are not currently used in any step. In order to run this protocol you will need to attach this pipette as well as power up and connect the module to your robot.'
- )
- })
-})
diff --git a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedEntities.test.ts b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedEntities.test.ts
deleted file mode 100644
index 3e2897ec27d..00000000000
--- a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedEntities.test.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-import { describe, expect, it } from 'vitest'
-import {
- fixtureP10Single,
- fixtureP300Single,
-} from '@opentrons/shared-data/pipette/fixtures/name'
-import { fixture_tiprack_10_ul } from '@opentrons/shared-data/labware/fixtures/2'
-import {
- MAGNETIC_MODULE_TYPE,
- TEMPERATURE_MODULE_TYPE,
- MAGNETIC_MODULE_V1,
- TEMPERATURE_MODULE_V1,
- MAGNETIC_BLOCK_TYPE,
- MAGNETIC_BLOCK_V1,
-} from '@opentrons/shared-data'
-import { TEMPERATURE_DEACTIVATED } from '@opentrons/step-generation'
-import { getUnusedEntities } from '../getUnusedEntities'
-import type { SavedStepFormState } from '../../../../step-forms'
-
-describe('getUnusedEntities', () => {
- it('pipette entities not used in steps are returned', () => {
- const stepForms: SavedStepFormState = {
- step123: {
- pipette: 'pipette123',
- id: 'step123',
- stepType: 'moveLiquid',
- },
- }
- const pipettesOnDeck = {
- pipette123: {
- name: 'string',
- id: 'pipette123',
- tiprackDefURI: 'test',
- tiprackLabwareDef: fixture_tiprack_10_ul,
- spec: fixtureP10Single,
- mount: 'right',
- },
- pipette456: {
- name: 'string',
- id: 'pipette456',
- tiprackDefURI: 'test',
- tiprackLabwareDef: fixture_tiprack_10_ul,
- spec: fixtureP300Single,
- mount: 'left',
- },
- }
-
- const result = getUnusedEntities(
- pipettesOnDeck,
- stepForms,
- 'pipette',
- 'OT-2 Standard'
- )
-
- expect(result).toEqual([pipettesOnDeck.pipette456])
- })
-
- it('module entities not used in steps are returned', () => {
- const stepForms: SavedStepFormState = {
- step123: {
- moduleId: 'magnet123',
- id: 'step123',
- magnetAction: 'engage',
- engageHeight: '10',
- stepType: 'magnet',
- stepName: 'magnet',
- stepDetails: '',
- },
- }
- const modulesOnDeck = {
- magnet123: {
- id: 'magnet123',
- type: MAGNETIC_MODULE_TYPE,
- model: MAGNETIC_MODULE_V1,
- slot: '3',
- moduleState: {
- type: MAGNETIC_MODULE_TYPE,
- engaged: false,
- },
- },
- temperature456: {
- id: 'temperature456',
- type: TEMPERATURE_MODULE_TYPE,
- model: TEMPERATURE_MODULE_V1,
- moduleState: {
- type: TEMPERATURE_MODULE_TYPE,
- status: TEMPERATURE_DEACTIVATED,
- targetTemperature: null,
- },
- slot: '9',
- },
- }
-
- const result = getUnusedEntities(
- modulesOnDeck,
- stepForms,
- 'moduleId',
- 'OT-2 Standard'
- )
-
- expect(result).toEqual([modulesOnDeck.temperature456])
- })
-
- it('filters out magnetic block and shows module entities not used in steps are returned for Flex', () => {
- const stepForms: SavedStepFormState = {
- step123: {
- moduleId: 'magnet123',
- id: 'step123',
- magnetAction: 'engage',
- engageHeight: '10',
- stepType: 'magnet',
- stepName: 'magnet',
- stepDetails: '',
- },
- }
- const modulesOnDeck = {
- magnet123: {
- id: 'magnet123',
- type: MAGNETIC_BLOCK_TYPE,
- model: MAGNETIC_BLOCK_V1,
- slot: '3',
- moduleState: {
- type: MAGNETIC_BLOCK_TYPE,
- engaged: false,
- },
- },
- temperature456: {
- id: 'temperature456',
- type: TEMPERATURE_MODULE_TYPE,
- model: TEMPERATURE_MODULE_V1,
- moduleState: {
- type: TEMPERATURE_MODULE_TYPE,
- status: TEMPERATURE_DEACTIVATED,
- targetTemperature: null,
- },
- slot: '9',
- },
- }
-
- const result = getUnusedEntities(
- modulesOnDeck,
- stepForms,
- 'moduleId',
- 'OT-3 Standard'
- )
-
- expect(result).toEqual([modulesOnDeck.temperature456])
- })
-})
diff --git a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts
deleted file mode 100644
index 55160505383..00000000000
--- a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { describe, expect, it } from 'vitest'
-import { getUnusedStagingAreas } from '../getUnusedStagingAreas'
-import type { CreateCommand } from '@opentrons/shared-data'
-import type { AdditionalEquipment } from '../../FileSidebar'
-
-describe('getUnusedStagingAreas', () => {
- it('returns true for unused staging area', () => {
- const stagingArea = 'stagingAreaId'
- const mockAdditionalEquipment = {
- [stagingArea]: {
- name: 'stagingArea',
- id: stagingArea,
- location: 'cutoutA3',
- },
- } as AdditionalEquipment
-
- expect(getUnusedStagingAreas(mockAdditionalEquipment, [])).toEqual(['A4'])
- })
- it('returns true for multi unused staging areas', () => {
- const stagingArea = 'stagingAreaId'
- const stagingArea2 = 'stagingAreaId2'
- const mockAdditionalEquipment = {
- [stagingArea]: {
- name: 'stagingArea',
- id: stagingArea,
- location: 'cutoutA3',
- },
- [stagingArea2]: {
- name: 'stagingArea',
- id: stagingArea2,
- location: 'cutoutB3',
- },
- } as AdditionalEquipment
-
- expect(getUnusedStagingAreas(mockAdditionalEquipment, [])).toEqual([
- 'A4',
- 'B4',
- ])
- })
- it('returns false for unused staging area', () => {
- const stagingArea = 'stagingAreaId'
- const mockAdditionalEquipment = {
- [stagingArea]: {
- name: 'stagingArea',
- id: stagingArea,
- location: 'cutoutA3',
- },
- } as AdditionalEquipment
- const mockCommand = [
- {
- commandType: 'loadLabware',
- params: { location: { addressableAreaName: 'A4' } },
- },
- ] as CreateCommand[]
-
- expect(getUnusedStagingAreas(mockAdditionalEquipment, mockCommand)).toEqual(
- []
- )
- })
-})
diff --git a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedTrash.test.ts b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedTrash.test.ts
deleted file mode 100644
index 658b9d2d7a4..00000000000
--- a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedTrash.test.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { describe, expect, it } from 'vitest'
-import { getUnusedTrash } from '../getUnusedTrash'
-import {
- EIGHT_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA,
- ONE_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA,
-} from '@opentrons/shared-data'
-import type { CreateCommand } from '@opentrons/shared-data'
-import type { AdditionalEquipment } from '../../FileSidebar'
-
-describe('getUnusedTrash', () => {
- it('returns true for unused trash bin', () => {
- const mockTrashId = 'mockTrashId'
- const mockTrash = {
- [mockTrashId]: {
- name: 'trashBin',
- id: mockTrashId,
- location: 'cutoutA3',
- },
- } as AdditionalEquipment
-
- expect(getUnusedTrash(mockTrash, [])).toEqual({
- trashBinUnused: true,
- wasteChuteUnused: false,
- })
- })
- it('returns false for unused trash bin', () => {
- const mockTrashId = 'mockTrashId'
- const mockTrash = {
- [mockTrashId]: {
- name: 'trashBin',
- id: mockTrashId,
- location: 'cutoutA3',
- },
- } as AdditionalEquipment
- const mockCommand = [
- {
- commandType: 'moveToAddressableArea',
- params: { addressableAreaName: 'movableTrashA3' },
- },
- ] as CreateCommand[]
-
- expect(getUnusedTrash(mockTrash, mockCommand)).toEqual({
- trashBinUnused: false,
- wasteChuteUnused: false,
- })
- })
- it('returns true for unused waste chute', () => {
- const wasteChute = 'wasteChuteId'
- const mockAdditionalEquipment = {
- [wasteChute]: {
- name: 'wasteChute',
- id: wasteChute,
- location: 'cutoutD3',
- },
- } as AdditionalEquipment
- expect(getUnusedTrash(mockAdditionalEquipment, [])).toEqual({
- trashBinUnused: false,
- wasteChuteUnused: true,
- })
- })
- it('returns false for unused waste chute with single channel', () => {
- const wasteChute = 'wasteChuteId'
- const mockAdditionalEquipment = {
- [wasteChute]: {
- name: 'wasteChute',
- id: wasteChute,
- location: 'cutoutD3',
- },
- } as AdditionalEquipment
- const mockCommand = [
- {
- commandType: 'moveToAddressableArea',
- params: {
- pipetteId: 'mockId',
- addressableAreaName: ONE_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA,
- },
- },
- ] as CreateCommand[]
- expect(getUnusedTrash(mockAdditionalEquipment, mockCommand)).toEqual({
- trashBinUnused: false,
- wasteChuteUnused: false,
- })
- })
- it('returns false for unused waste chute with 8-channel', () => {
- const wasteChute = 'wasteChuteId'
- const mockAdditionalEquipment = {
- [wasteChute]: {
- name: 'wasteChute',
- id: wasteChute,
- location: 'cutoutD3',
- },
- } as AdditionalEquipment
- const mockCommand = [
- {
- commandType: 'moveToAddressableArea',
- params: {
- pipetteId: 'mockId',
- addressableAreaName: EIGHT_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA,
- },
- },
- ] as CreateCommand[]
- expect(getUnusedTrash(mockAdditionalEquipment, mockCommand)).toEqual({
- trashBinUnused: false,
- wasteChuteUnused: false,
- })
- })
- it('returns false for unused trash bin with moveToAddressableAreaForDropTip command', () => {
- const mockTrashId = 'mockTrashId'
- const mockTrash = {
- [mockTrashId]: {
- name: 'trashBin',
- id: mockTrashId,
- location: 'cutoutA3',
- },
- } as AdditionalEquipment
- const mockCommand = [
- {
- commandType: 'moveToAddressableAreaForDropTip',
- params: { addressableAreaName: 'movableTrashA3', pipetteId: 'mockPip' },
- },
- ] as CreateCommand[]
-
- expect(getUnusedTrash(mockTrash, mockCommand)).toEqual({
- trashBinUnused: false,
- wasteChuteUnused: false,
- })
- })
-})
diff --git a/protocol-designer/src/components/FileSidebar/utils/getUnusedEntities.ts b/protocol-designer/src/components/FileSidebar/utils/getUnusedEntities.ts
deleted file mode 100644
index 12e34c04e75..00000000000
--- a/protocol-designer/src/components/FileSidebar/utils/getUnusedEntities.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import some from 'lodash/some'
-import reduce from 'lodash/reduce'
-import { FLEX_ROBOT_TYPE } from '@opentrons/shared-data'
-import type { RobotType } from '@opentrons/shared-data'
-import type { SavedStepFormState } from '../../../step-forms'
-
-/** Pull out all entities never specified by step forms. Assumes that all forms share the entityKey */
-export function getUnusedEntities(
- entities: Record,
- stepForms: SavedStepFormState,
- entityKey: 'pipette' | 'moduleId',
- robotType: RobotType
-): T[] {
- const unusedEntities = reduce(
- entities,
- (acc, entity: T, entityId): T[] => {
- const stepContainsEntity = some(
- stepForms,
- form => form[entityKey] === entityId
- )
-
- if (
- robotType === FLEX_ROBOT_TYPE &&
- entityKey === 'moduleId' &&
- (entity as any).type === 'magneticBlockType'
- ) {
- return acc
- }
-
- return stepContainsEntity ? acc : [...acc, entity]
- },
- [] as T[]
- )
-
- return unusedEntities
-}
diff --git a/protocol-designer/src/components/FileSidebar/utils/getUnusedStagingAreas.ts b/protocol-designer/src/components/FileSidebar/utils/getUnusedStagingAreas.ts
deleted file mode 100644
index 9c22d52b679..00000000000
--- a/protocol-designer/src/components/FileSidebar/utils/getUnusedStagingAreas.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { getStagingAreaAddressableAreas } from '../../../utils'
-import type { CreateCommand, CutoutId } from '@opentrons/shared-data'
-import type { AdditionalEquipment } from '../FileSidebar'
-
-export const getUnusedStagingAreas = (
- additionalEquipment: AdditionalEquipment,
- commands?: CreateCommand[]
-): string[] => {
- const stagingAreaCutoutIds = Object.values(additionalEquipment)
- .filter(equipment => equipment?.name === 'stagingArea')
- .map(equipment => {
- if (equipment.location == null) {
- console.error(
- `expected to find staging area slot location with id ${equipment.id} but could not.`
- )
- }
- return equipment.location ?? ''
- })
-
- const stagingAreaAddressableAreaNames = getStagingAreaAddressableAreas(
- // TODO(jr, 11/13/23): fix AdditionalEquipment['location'] from type string to CutoutId
- stagingAreaCutoutIds as CutoutId[]
- )
-
- const stagingAreaCommandSlots: string[] = stagingAreaAddressableAreaNames.filter(
- location =>
- (commands ?? [])?.some(
- command =>
- (command.commandType === 'loadLabware' &&
- command.params.location !== 'offDeck' &&
- 'addressableAreaName' in command.params.location &&
- command.params.location.addressableAreaName === location) ||
- (command.commandType === 'moveLabware' &&
- command.params.newLocation !== 'offDeck' &&
- 'addressableAreaName' in command.params.newLocation &&
- command.params.newLocation.addressableAreaName === location)
- )
- ? null
- : location
- )
- return stagingAreaCommandSlots
-}
diff --git a/protocol-designer/src/components/FileSidebar/utils/getUnusedTrash.ts b/protocol-designer/src/components/FileSidebar/utils/getUnusedTrash.ts
deleted file mode 100644
index 5c97305c16b..00000000000
--- a/protocol-designer/src/components/FileSidebar/utils/getUnusedTrash.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import {
- FIXED_TRASH_ID,
- MOVABLE_TRASH_ADDRESSABLE_AREAS,
- WASTE_CHUTE_ADDRESSABLE_AREAS,
-} from '@opentrons/shared-data'
-import type { AddressableAreaName, CreateCommand } from '@opentrons/shared-data'
-import type { InitialDeckSetup } from '../../../step-forms'
-
-interface UnusedTrash {
- trashBinUnused: boolean
- wasteChuteUnused: boolean
-}
-
-export const getUnusedTrash = (
- additionalEquipment: InitialDeckSetup['additionalEquipmentOnDeck'],
- commands?: CreateCommand[]
-): UnusedTrash => {
- const trashBin = Object.values(additionalEquipment).find(
- aE => aE.name === 'trashBin'
- )
-
- const hasTrashBinCommands =
- trashBin != null
- ? commands?.some(
- command =>
- (command.commandType === 'moveToAddressableArea' &&
- (MOVABLE_TRASH_ADDRESSABLE_AREAS.includes(
- command.params.addressableAreaName as AddressableAreaName
- ) ||
- command.params.addressableAreaName === FIXED_TRASH_ID)) ||
- command.commandType === 'moveToAddressableAreaForDropTip'
- )
- : null
- const wasteChute = Object.values(additionalEquipment).find(
- aE => aE.name === 'wasteChute'
- )
- const hasWasteChuteCommands =
- wasteChute != null
- ? commands?.some(
- command =>
- (command.commandType === 'moveToAddressableArea' &&
- WASTE_CHUTE_ADDRESSABLE_AREAS.includes(
- command.params.addressableAreaName as AddressableAreaName
- )) ||
- (command.commandType === 'moveLabware' &&
- command.params.newLocation !== 'offDeck' &&
- 'addressableAreaName' in command.params.newLocation &&
- command.params.newLocation.addressableAreaName ===
- 'gripperWasteChute')
- )
- : null
- return {
- trashBinUnused: trashBin != null && !hasTrashBinCommands,
- wasteChuteUnused: wasteChute != null && !hasWasteChuteCommands,
- }
-}
diff --git a/protocol-designer/src/components/FileSidebar/utils/index.ts b/protocol-designer/src/components/FileSidebar/utils/index.ts
deleted file mode 100644
index 69cca896b00..00000000000
--- a/protocol-designer/src/components/FileSidebar/utils/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './getUnusedEntities'
-export * from './getUnusedStagingAreas'
-export * from './getUnusedTrash'
diff --git a/protocol-designer/src/components/FormManager/index.tsx b/protocol-designer/src/components/FormManager/index.tsx
deleted file mode 100644
index e0241100d94..00000000000
--- a/protocol-designer/src/components/FormManager/index.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { useSelector } from 'react-redux'
-import { Box, POSITION_STICKY, C_SELECTED_DARK } from '@opentrons/components'
-import { StepEditForm } from '../StepEditForm'
-import { BatchEditForm } from '../BatchEditForm'
-import { StepSelectionBanner } from '../StepSelectionBanner'
-import { getIsMultiSelectMode } from '../../ui/steps/selectors'
-
-export const FormManager = (): JSX.Element => {
- const isMultiSelectMode = useSelector(getIsMultiSelectMode)
-
- if (isMultiSelectMode) {
- return (
-
-
-
-
- )
- }
- return
-}
diff --git a/protocol-designer/src/components/Hints/hints.module.css b/protocol-designer/src/components/Hints/hints.module.css
deleted file mode 100644
index ebd360b9131..00000000000
--- a/protocol-designer/src/components/Hints/hints.module.css
+++ /dev/null
@@ -1,71 +0,0 @@
-@import '@opentrons/components/styles';
-
-.dont_show_again {
- float: left;
-}
-
-.ok_button {
- float: right;
-}
-
-.summary {
- padding-bottom: 2rem;
-}
-
-.numbered_list {
- margin: 0 2rem 2rem 2rem;
-
- & > li::before {
- margin-right: 1rem;
- }
-
- & li span {
- position: relative;
- left: 1rem;
- }
-}
-
-.step_description {
- margin-bottom: 1rem;
-
- & span:first-of-type {
- font-weight: var(--fw-semibold);
- }
-}
-
-.hint_contents {
- font-size: var(--fs-body-2); /* from legacy --font-body-2-dark */
- font-weight: var(--fw-regular); /* from legacy --font-body-2-dark */
- color: var(--c-font-dark); /* from legacy --font-body-2-dark */
- line-height: var(--lh-copy);
-
- & p {
- margin-bottom: 1rem;
- }
-}
-
-.heading {
- font-size: var(--fs-header); /* from legacy --font-header-dark */
- font-weight: var(--fw-semibold); /* from legacy --font-header-dark */
- color: var(--c-font-dark); /* from legacy --font-header-dark */
- margin-bottom: 1rem;
-}
-
-.column_left {
- width: 35%;
-}
-
-.column_right {
- margin-left: 5%;
- width: 60%;
-}
-
-.column_left,
-.column_right {
- display: inline-block;
- vertical-align: top;
-
- & > * {
- width: 100%;
- }
-}
diff --git a/protocol-designer/src/components/Hints/index.tsx b/protocol-designer/src/components/Hints/index.tsx
deleted file mode 100644
index cbc40cb0a97..00000000000
--- a/protocol-designer/src/components/Hints/index.tsx
+++ /dev/null
@@ -1,177 +0,0 @@
-import { useState, useCallback } from 'react'
-import { useTranslation } from 'react-i18next'
-import { createPortal } from 'react-dom'
-import { useSelector, useDispatch } from 'react-redux'
-import {
- AlertModal,
- DeprecatedCheckboxField,
- Flex,
- OutlineButton,
- Text,
-} from '@opentrons/components'
-import { actions, selectors } from '../../tutorial'
-import { getMainPagePortalEl } from '../portals/MainPageModalPortal'
-import styles from './hints.module.css'
-import EXAMPLE_ADD_LIQUIDS_IMAGE from '../../assets/images/example_add_liquids.png'
-import EXAMPLE_WATCH_LIQUIDS_MOVE_IMAGE from '../../assets/images/example_watch_liquids_move.png'
-import EXAMPLE_BATCH_EDIT_IMAGE from '../../assets/images/announcements/multi_select.gif'
-import type { HintKey } from '../../tutorial'
-
-const HINT_IS_ALERT: HintKey[] = ['add_liquids_and_labware']
-
-export const Hints = (): JSX.Element | null => {
- const { t } = useTranslation(['alert', 'nav', 'button'])
- const [rememberDismissal, setRememberDismissal] = useState(false)
-
- const toggleRememberDismissal = useCallback(() => {
- setRememberDismissal(prevDismissal => !prevDismissal)
- }, [])
- const hintKey = useSelector(selectors.getHint)
- const dispatch = useDispatch()
- const removeHint = (hintKey: HintKey): void => {
- dispatch(actions.removeHint(hintKey, rememberDismissal))
- }
-
- const makeHandleCloseClick = (hintKey: HintKey): (() => void) => {
- return () => {
- removeHint(hintKey)
- }
- }
-
- const renderHintContents = (hintKey: HintKey): JSX.Element | null => {
- // Only hints that have no outside effects should go here.
- // For hints that have an effect, use BlockingHint.
- switch (hintKey) {
- case 'add_liquids_and_labware':
- return (
- <>
-
- {t('hint.add_liquids_and_labware.summary', {
- deck_setup_step: t('nav:terminal_item.__initial_setup__'),
- })}
-
-
-
-
- Step 1:
- {t('hint.add_liquids_and_labware.step1')}
-
-
-
-
-
-
- Step 2:
- {t('hint.add_liquids_and_labware.step2')}
-
-
-
- >
- )
- case 'deck_setup_explanation':
- return (
- <>
- {t(`hint.${hintKey}.body1`)}
- {t(`hint.${hintKey}.body2`)}
- {t(`hint.${hintKey}.body3`)}
- >
- )
- case 'multiple_modules_without_labware':
- case 'module_without_labware':
- return (
- <>
- {t(`alert:hint.${hintKey}.body`)}
- >
- )
-
- case 'thermocycler_lid_passive_cooling':
- return (
- <>
-
- {t(`alert:hint.${hintKey}.body1a`)}
- {t(`alert:hint.${hintKey}.strong_body1`)}
- {t(`alert:hint.${hintKey}.body1b`)}
-
-
-
- {t(`alert:hint.${hintKey}.li1`)}
-
-
- {t(`alert:hint.${hintKey}.li2`)}
-
-
- >
- )
- case 'protocol_can_enter_batch_edit':
- return (
- <>
-
-
-
-
- {t(`alert:hint.${hintKey}.body1`)}
-
- {`alert:hint.${hintKey}.body2`}
-
-
- {t(`alert:hint.${hintKey}.li1a`)}
- {t(`alert:hint.${hintKey}.strong_li1`)}
- {t(`alert:hint.${hintKey}.li1b`)}
-
-
- {t(`alert:hint.${hintKey}.li2a`)}
- {t(`alert:hint.${hintKey}.strong_li2`)}
- {t(`alert:hint.${hintKey}.li2b`)}
-
-
-
-
- {t(`alert:hint.${hintKey}.body3a`)}
- {t(`alert:hint.${hintKey}.body3b`)}
-
-
- {t(`alert:hint.${hintKey}.body4a`)}
- {t(`alert:hint.${hintKey}.body4b`)}
-
-
- >
- )
- case 'waste_chute_warning':
- return (
-
- {t(`hint.${hintKey}.body1`)}
-
- )
- default:
- return null
- }
- }
-
- if (hintKey == null) return null
-
- const headingText = t(`hint.${hintKey}.title`)
- const hintIsAlert = HINT_IS_ALERT.includes(hintKey)
- return createPortal(
-
- {!hintIsAlert ? (
- {headingText}
- ) : null}
- {renderHintContents(hintKey)}
-
-
-
- {t('button:ok')}
-
-
- ,
- getMainPagePortalEl()
- )
-}
diff --git a/protocol-designer/src/components/Hints/useBlockingHint.tsx b/protocol-designer/src/components/Hints/useBlockingHint.tsx
deleted file mode 100644
index 6b1283bd234..00000000000
--- a/protocol-designer/src/components/Hints/useBlockingHint.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-// BlockingHint is an "are you sure" modal that can be dismissed.
-// Instances of BlockingHint need to be individually placed by whatever component
-// is controlling the flow that this modal will block, via useBlockingHint.
-import * as React from 'react'
-import { createPortal } from 'react-dom'
-import { useTranslation } from 'react-i18next'
-import { useDispatch, useSelector } from 'react-redux'
-import { ContinueModal, DeprecatedCheckboxField } from '@opentrons/components'
-import { actions, selectors } from '../../tutorial'
-import { getMainPagePortalEl } from '../portals/MainPageModalPortal'
-import styles from './hints.module.css'
-import type { HintKey } from '../../tutorial'
-
-export interface HintProps {
- hintKey: HintKey
- handleCancel: () => void
- handleContinue: () => void
- content: React.ReactNode
-}
-
-// This component handles the checkbox and dispatching `removeHint` action on continue/cancel
-export const BlockingHint = (props: HintProps): JSX.Element => {
- const { t } = useTranslation('alert')
- const { hintKey, handleCancel, handleContinue } = props
- const dispatch = useDispatch()
-
- const [rememberDismissal, setRememberDismissal] = React.useState(
- false
- )
-
- const toggleRememberDismissal = React.useCallback(() => {
- setRememberDismissal(prevDismissal => !prevDismissal)
- }, [])
-
- const onCancelClick = (): void => {
- dispatch(actions.removeHint(hintKey, rememberDismissal))
- handleCancel()
- }
-
- const onContinueClick = (): void => {
- dispatch(actions.removeHint(hintKey, rememberDismissal))
- handleContinue()
- }
-
- return createPortal(
-
- {props.content}
-
-
-
- ,
- getMainPagePortalEl()
- )
-}
-
-export interface HintArgs {
- /** `enabled` should be a condition that the parent uses to toggle whether the hint should be active or not.
- * If the hint is enabled but has been dismissed, it will automatically call `handleContinue` when enabled.
- * useBlockingHint expects the parent to disable the hint on cancel/continue */
- enabled: boolean
- hintKey: HintKey
- content: React.ReactNode
- handleCancel: () => void
- handleContinue: () => void
-}
-
-export const useBlockingHint = (args: HintArgs): JSX.Element | null => {
- const { enabled, hintKey, handleCancel, handleContinue, content } = args
- const isDismissed = useSelector(selectors.getDismissedHints).includes(hintKey)
-
- if (isDismissed) {
- if (enabled) {
- handleContinue()
- }
- return null
- }
-
- if (!enabled) {
- return null
- }
-
- return (
-
- )
-}
diff --git a/protocol-designer/src/components/IngredientsList/IngredientsList.module.css b/protocol-designer/src/components/IngredientsList/IngredientsList.module.css
deleted file mode 100644
index d6e76be8236..00000000000
--- a/protocol-designer/src/components/IngredientsList/IngredientsList.module.css
+++ /dev/null
@@ -1,16 +0,0 @@
-@import '@opentrons/components/styles';
-
-.close_icon {
- & > svg {
- width: 100%;
- max-height: 1rem;
- }
-
- &:hover {
- color: var(--c-red);
- }
-}
-
-.ingredient_row_header {
- font-weight: var(--fw-bold);
-}
diff --git a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/LabwareDetailsCard.tsx b/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/LabwareDetailsCard.tsx
deleted file mode 100644
index 80afd8f9624..00000000000
--- a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/LabwareDetailsCard.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-import { useDispatch, useSelector } from 'react-redux'
-import { useTranslation } from 'react-i18next'
-import cx from 'classnames'
-import { getLabwareDisplayName } from '@opentrons/shared-data'
-import { selectors as stepFormSelectors } from '../../../step-forms'
-import { selectors as uiLabwareSelectors } from '../../../ui/labware'
-import { selectors as labwareIngredSelectors } from '../../../labware-ingred/selectors'
-import * as labwareIngredActions from '../../../labware-ingred/actions'
-import { PDTitledList, PDListItem } from '../../lists'
-import { EditableTextField } from '../../EditableTextField'
-import styles from './labwareDetailsCard.module.css'
-import type { ThunkDispatch } from '../../../types'
-
-export function LabwareDetailsCard(): JSX.Element {
- const { t } = useTranslation('form')
- const dispatch = useDispatch>()
- const labwareNicknamesById = useSelector(
- uiLabwareSelectors.getLabwareNicknamesById
- )
- const labwareId = useSelector(labwareIngredSelectors.getSelectedLabwareId)
- const labwareEntities = useSelector(stepFormSelectors.getLabwareEntities)
- const labwareDefDisplayName =
- labwareId != null
- ? getLabwareDisplayName(labwareEntities[labwareId].def)
- : null
-
- console.assert(
- labwareId,
- 'Expected labware id to exist in connected labware details card'
- )
-
- const renameLabware = (name: string): void => {
- console.assert(
- labwareId,
- 'renameLabware in LabwareDetailsCard expected a labwareId'
- )
-
- if (labwareId) {
- dispatch(
- labwareIngredActions.renameLabware({
- labwareId: labwareId,
- name,
- })
- )
- }
- }
-
- return (
-
-
-
-
- {t('generic.labware_type')}
-
- {labwareDefDisplayName}
-
-
-
-
-
- {t('generic.nickname')}
-
-
-
-
-
- )
-}
diff --git a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/labwareDetailsCard.module.css b/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/labwareDetailsCard.module.css
deleted file mode 100644
index 76d446c0767..00000000000
--- a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/labwareDetailsCard.module.css
+++ /dev/null
@@ -1,22 +0,0 @@
-@import '@opentrons/components/styles';
-
-.column_1_3 {
- lost-column: 1/3;
-}
-
-.column_2_3 {
- lost-column: 2/3;
- margin-bottom: 0.2rem;
- overflow: hidden;
- display: inline-block;
- text-overflow: ellipsis;
-}
-
-.row {
- lost-utility: clearfix;
- text-align: left;
-}
-
-.label {
- font-weight: var(--fw-bold);
-}
diff --git a/protocol-designer/src/components/IngredientsList/index.tsx b/protocol-designer/src/components/IngredientsList/index.tsx
deleted file mode 100644
index 125b81e6a10..00000000000
--- a/protocol-designer/src/components/IngredientsList/index.tsx
+++ /dev/null
@@ -1,210 +0,0 @@
-// TODO: Ian 2018-10-09 figure out what belongs in LiquidsSidebar vs IngredientsList after #2427
-import { useState } from 'react'
-import { useTranslation } from 'react-i18next'
-import { useDispatch, useSelector } from 'react-redux'
-import { IconButton, SidePanel, truncateString } from '@opentrons/components'
-import { sortWells } from '@opentrons/shared-data'
-import * as wellSelectionSelectors from '../../top-selectors/well-contents'
-import { removeWellsContents } from '../../labware-ingred/actions'
-import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
-import { PDTitledList, PDListItem } from '../lists'
-import { TitledListNotes } from '../TitledListNotes'
-import { swatchColors } from '../swatchColors'
-import { LabwareDetailsCard } from './LabwareDetailsCard/LabwareDetailsCard'
-import styles from './IngredientsList.module.css'
-
-import type { SingleLabwareLiquidState } from '@opentrons/step-generation'
-import type { LiquidGroup } from '../../labware-ingred/types'
-import type { ThunkDispatch } from '../../types'
-
-type RemoveWellsContents = (args: {
- liquidGroupId: string
- wells: string[]
-}) => unknown
-
-// Props used by both IngredientsList and LiquidGroupCard
-export interface CommonProps {
- removeWellsContents: RemoveWellsContents
- selected?: boolean
-}
-
-type LiquidGroupCardProps = CommonProps & {
- groupId: string
- ingredGroup: LiquidGroup
- labwareWellContents: SingleLabwareLiquidState
-}
-
-const LiquidGroupCard = (props: LiquidGroupCardProps): JSX.Element | null => {
- const {
- ingredGroup,
- removeWellsContents,
- selected,
- groupId,
- labwareWellContents,
- } = props
- const { t } = useTranslation(['card', 'application'])
- const showName = ingredGroup.serialize
-
- const [expanded, setExpanded] = useState(true)
-
- const toggleAccordion = (): void => {
- setExpanded(!expanded)
- }
-
- const wellsWithIngred = Object.keys(labwareWellContents)
- .sort(sortWells)
- .filter(well => labwareWellContents[well][groupId])
- const liquidDisplayColors = useSelector(
- labwareIngredSelectors.getLiquidDisplayColors
- )
-
- if (wellsWithIngred.length < 1) {
- // do not show liquid card if it has no instances for this labware
- return null
- }
- const truncatedName =
- ingredGroup.name != null ? truncateString(ingredGroup.name, 25) : null
- return (
- }
- >
-
- {t('well')}
- {t('application:units.microliter')}
- {showName && {t('name')} }
-
-
-
- {wellsWithIngred.map((well, i) => {
- const wellIngredForCard = labwareWellContents[well][groupId]
- const volume =
- wellIngredForCard != null ? wellIngredForCard.volume : null
-
- if (volume == null) {
- console.warn(
- `Got null-ish volume for well: ${well}, ingred: ${groupId}`
- )
- return null
- }
-
- return (
-
- )
- })}
-
- )
-}
-
-interface IndividProps {
- name?: string | null
- wellName: string
- volume: number
- // concentration?: string,
- canDelete: boolean
- groupId: string
- removeWellsContents: RemoveWellsContents
-}
-
-function IngredIndividual(props: IndividProps): JSX.Element {
- const {
- name,
- wellName,
- volume,
- // concentration, // TODO LATER Ian 2018-02-22: concentration is removed from MVP. Remove all traces of it, or add it back in
- canDelete,
- groupId,
- removeWellsContents,
- } = props
- const { t } = useTranslation('application')
- return (
-
- {wellName}
-
- {Boolean(volume) ? volume + ` ${t('units.microliter')}` : '-'}
-
- {name != null ? {name} : null}
- {canDelete && (
- {
- if (
- window.confirm(
- t('are_you_sure_delete_well', { well: wellName }) as string
- )
- )
- removeWellsContents({ liquidGroupId: groupId, wells: [wellName] })
- }}
- />
- )}
-
- )
-}
-
-export function IngredientsList(): JSX.Element {
- const selectedLabwareId = useSelector(
- labwareIngredSelectors.getSelectedLabwareId
- )
- const allLabwareWellContents = useSelector(
- labwareIngredSelectors.getLiquidsByLabwareId
- )
-
- const liquidGroupsById = useSelector(
- labwareIngredSelectors.getLiquidGroupsById
- )
- const selectedIngredientGroupId = useSelector(
- wellSelectionSelectors.getSelectedWellsCommonIngredId
- )
- const { t } = useTranslation('nav')
- const dispatch = useDispatch>()
-
- const labwareWellContents =
- (selectedLabwareId != null
- ? allLabwareWellContents[selectedLabwareId]
- : null) ?? {}
-
- return (
-
-
-
- {Object.keys(liquidGroupsById).map(groupIdForCard => (
- {
- if (selectedLabwareId != null) {
- dispatch(
- removeWellsContents({
- labwareId: selectedLabwareId,
- liquidGroupId,
- wells,
- })
- )
- }
- }}
- labwareWellContents={labwareWellContents}
- ingredGroup={liquidGroupsById[groupIdForCard]}
- groupId={groupIdForCard}
- selected={selectedIngredientGroupId === groupIdForCard}
- />
- ))}
-
- )
-}
diff --git a/protocol-designer/src/components/KnowledgeBaseLink/index.tsx b/protocol-designer/src/components/KnowledgeBaseLink/index.tsx
deleted file mode 100644
index a21f8a0fc6d..00000000000
--- a/protocol-designer/src/components/KnowledgeBaseLink/index.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import type * as React from 'react'
-import { Link } from '@opentrons/components'
-
-export const KNOWLEDGEBASE_ROOT_URL =
- 'https://support.opentrons.com/s/protocol-designer'
-
-export const links = {
- airGap: `https://support.opentrons.com/en/articles/4398106-air-gap`,
- multiDispense: `https://support.opentrons.com/en/articles/4170341-paths`,
- protocolSteps: `https://support.opentrons.com/s/protocol-designer?tabset-92ba3=2`,
- customLabware: `https://support.opentrons.com/en/articles/3136504-creating-custom-labware-definitions`,
- recommendedLabware:
- 'https://support.opentrons.com/s/article/What-labware-can-I-use-with-my-modules',
- pipetteGen1MultiModuleCollision:
- 'https://support.opentrons.com/en/articles/4168741-module-placement',
- betaReleases: `https://support.opentrons.com/en/articles/3854833-opentrons-beta-software-releases`,
- magneticModuleGenerations:
- 'http://support.opentrons.com/en/articles/1820112-magnetic-module',
-} as const
-
-interface Props {
- to: keyof typeof links
- children: React.ReactNode
- className?: string
-}
-
-/** Link which opens a page on the knowledge base to a new tab/window */
-export function KnowledgeBaseLink(props: Props): JSX.Element {
- return (
-
- {props.children}
-
- )
-}
diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwareItem.tsx b/protocol-designer/src/components/LabwareSelectionModal/LabwareItem.tsx
deleted file mode 100644
index 33ba3393765..00000000000
--- a/protocol-designer/src/components/LabwareSelectionModal/LabwareItem.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import { useTranslation } from 'react-i18next'
-import cx from 'classnames'
-import { Icon } from '@opentrons/components'
-import { PDListItem } from '../lists'
-import styles from './styles.module.css'
-import {
- getLabwareDefURI,
- getLabwareDefIsStandard,
- getLabwareDisplayName,
-} from '@opentrons/shared-data'
-import type { LabwareDefinition2 } from '@opentrons/shared-data'
-import type { IconName } from '@opentrons/components'
-
-interface Props {
- disabled?: boolean | null
- icon?: IconName | null
- labwareDef: LabwareDefinition2
- onMouseEnter: () => any
- onMouseLeave: () => any
- selectLabware: (labwareLoadName: string) => unknown
-}
-
-const LABWARE_LIBRARY_PAGE_PATH = 'https://labware.opentrons.com'
-
-export function LabwareItem(props: Props): JSX.Element {
- const {
- disabled,
- icon,
- labwareDef,
- onMouseLeave,
- onMouseEnter,
- selectLabware,
- } = props
- const { t } = useTranslation('modal')
- const displayName = getLabwareDisplayName(labwareDef)
- const labwareURI = getLabwareDefURI(labwareDef)
- const labwareLoadName = labwareDef.parameters.loadName
-
- return (
- {
- if (!disabled) {
- selectLabware(labwareURI)
- }
- }}
- onMouseEnter={onMouseEnter}
- onMouseLeave={onMouseLeave}
- >
- {icon ? : null}
-
- {displayName}
-
- {getLabwareDefIsStandard(labwareDef) ? (
- {
- e.stopPropagation()
- }}
- >
- {t('labware_selection.view_measurements')}
-
- ) : null}
-
- )
-}
diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwarePreview.tsx b/protocol-designer/src/components/LabwareSelectionModal/LabwarePreview.tsx
deleted file mode 100644
index 5d82ec73191..00000000000
--- a/protocol-designer/src/components/LabwareSelectionModal/LabwarePreview.tsx
+++ /dev/null
@@ -1,87 +0,0 @@
-import reduce from 'lodash/reduce'
-import { useTranslation } from 'react-i18next'
-import {
- Icon,
- LabwareRender,
- LabeledValue,
- RobotWorkSpace,
-} from '@opentrons/components'
-import {
- getLabwareDisplayName,
- getLabwareDefIsStandard,
-} from '@opentrons/shared-data'
-import styles from './styles.module.css'
-import type { LabwareDefinition2 } from '@opentrons/shared-data'
-
-interface Props {
- labwareDef?: LabwareDefinition2 | null
- moduleCompatibility?:
- | 'recommended'
- | 'potentiallyCompatible'
- | 'notCompatible'
- | null
-}
-
-export const LabwarePreview = (props: Props): JSX.Element | null => {
- const { labwareDef, moduleCompatibility } = props
- const { t } = useTranslation(['modal', 'application'])
- if (!labwareDef) return null
- const maxVolumes = reduce(
- labwareDef.wells,
- (acc, well) => acc.add(well.totalLiquidVolume),
- new Set()
- )
- const formattedVolumes = Array.from(maxVolumes)
- .map(vol => `${vol}${t('application:units.microliter')}`)
- .join(', ')
-
- // NOTE: this is a temporary magic value that positions the preview component
- // in a fixed place relative to the labware dropdown, while still letting
- // it overflow the sidebar nav if necessary
- const leftValue = (global.innerWidth - 365) / 2 - 260
-
- return (
-
-
-
- {props.labwareDef ? getLabwareDisplayName(props.labwareDef) : ''}
-
- {moduleCompatibility != null ? (
-
- {moduleCompatibility === 'recommended' ? (
-
- ) : null}
- {t(`labware_selection.module_compatibility.${moduleCompatibility}`)}
-
- ) : null}
-
-
-
- {() => }
-
-
-
- {getLabwareDefIsStandard(labwareDef) && (
-
- )}
-
-
-
-
-
-
-
-
- )
-}
diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx b/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx
deleted file mode 100644
index 81941119f45..00000000000
--- a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx
+++ /dev/null
@@ -1,601 +0,0 @@
-import * as React from 'react'
-import { createPortal } from 'react-dom'
-import { useDispatch, useSelector } from 'react-redux'
-import { useTranslation } from 'react-i18next'
-import startCase from 'lodash/startCase'
-import reduce from 'lodash/reduce'
-import {
- useOnClickOutside,
- DeprecatedCheckboxField,
- Icon,
- OutlineButton,
-} from '@opentrons/components'
-import {
- getLabwareDefURI,
- getLabwareDefIsStandard,
- getIsLabwareAboveHeight,
- TEMPERATURE_MODULE_TYPE,
- MAGNETIC_MODULE_TYPE,
- THERMOCYCLER_MODULE_TYPE,
- HEATERSHAKER_MODULE_TYPE,
- MAGNETIC_BLOCK_TYPE,
- MAX_LABWARE_HEIGHT_EAST_WEST_HEATER_SHAKER_MM,
- getModuleType,
- THERMOCYCLER_MODULE_V2,
- getAreSlotsHorizontallyAdjacent,
- ABSORBANCE_READER_TYPE,
-} from '@opentrons/shared-data'
-import {
- closeLabwareSelector,
- createContainer,
-} from '../../labware-ingred/actions'
-import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
-import {
- actions as labwareDefActions,
- selectors as labwareDefSelectors,
-} from '../../labware-defs'
-import { selectors as stepFormSelectors } from '../../step-forms'
-import { SPAN7_8_10_11_SLOT } from '../../constants'
-import {
- getLabwareIsCompatible as _getLabwareIsCompatible,
- getLabwareCompatibleWithAdapter,
- ADAPTER_96_CHANNEL,
-} from '../../utils/labwareModuleCompatibility'
-import { getPipetteEntities } from '../../step-forms/selectors'
-import { getHas96Channel } from '../../utils'
-import { getOnlyLatestDefs } from '../../labware-defs/utils'
-import { getTopPortalEl } from '../portals/TopPortal'
-import { PDTitledList } from '../lists'
-import { useBlockingHint } from '../Hints/useBlockingHint'
-import { KnowledgeBaseLink } from '../KnowledgeBaseLink'
-import { LabwareItem } from './LabwareItem'
-import { LabwarePreview } from './LabwarePreview'
-import styles from './styles.module.css'
-
-import type {
- LabwareDefinition2,
- ModuleType,
- ModuleModel,
-} from '@opentrons/shared-data'
-import type { DeckSlot, ThunkDispatch } from '../../types'
-import type { LabwareDefByDefURI } from '../../labware-defs'
-import type { ModuleOnDeck } from '../../step-forms'
-
-export interface Props {
- onClose: (e?: any) => unknown
- onUploadLabware: (event: React.ChangeEvent) => unknown
- selectLabware: (containerType: string) => unknown
- customLabwareDefs: LabwareDefByDefURI
- /** the slot you're literally adding labware to (may be a module slot) */
- slot?: DeckSlot | null
- /** if adding to a module, the slot of the parent (for display) */
- parentSlot?: DeckSlot | null
- /** if adding to a module, the module's model */
- moduleModel?: ModuleModel | null
- /** tipracks that may be added to deck (depends on pipette<>tiprack assignment) */
- permittedTipracks: string[]
- isNextToHeaterShaker: boolean
- has96Channel: boolean
- adapterLoadName?: string
-}
-
-const LABWARE_CREATOR_URL = 'https://labware.opentrons.com/create'
-const CUSTOM_CATEGORY = 'custom'
-const adapterCompatibleLabware = 'adapterCompatibleLabware'
-
-const orderedCategories: string[] = [
- 'tipRack',
- 'tubeRack',
- 'wellPlate',
- 'reservoir',
- 'aluminumBlock',
- 'adapter',
- // 'trash', // NOTE: trash intentionally hidden
-]
-
-const RECOMMENDED_LABWARE_BY_MODULE: { [K in ModuleType]: string[] } = {
- [TEMPERATURE_MODULE_TYPE]: [
- 'opentrons_24_aluminumblock_generic_2ml_screwcap',
- 'opentrons_96_well_aluminum_block',
- 'opentrons_96_aluminumblock_generic_pcr_strip_200ul',
- 'opentrons_24_aluminumblock_nest_1.5ml_screwcap',
- 'opentrons_24_aluminumblock_nest_1.5ml_snapcap',
- 'opentrons_24_aluminumblock_nest_2ml_screwcap',
- 'opentrons_24_aluminumblock_nest_2ml_snapcap',
- 'opentrons_24_aluminumblock_nest_0.5ml_screwcap',
- 'opentrons_aluminum_flat_bottom_plate',
- 'opentrons_96_deep_well_temp_mod_adapter',
- ],
- [MAGNETIC_MODULE_TYPE]: [
- 'nest_96_wellplate_100ul_pcr_full_skirt',
- 'nest_96_wellplate_2ml_deep',
- 'opentrons_96_wellplate_200ul_pcr_full_skirt',
- ],
- [THERMOCYCLER_MODULE_TYPE]: [
- 'nest_96_wellplate_100ul_pcr_full_skirt',
- 'opentrons_96_wellplate_200ul_pcr_full_skirt',
- ],
- [HEATERSHAKER_MODULE_TYPE]: [
- 'opentrons_96_deep_well_adapter',
- 'opentrons_96_flat_bottom_adapter',
- 'opentrons_96_pcr_adapter',
- 'opentrons_universal_flat_adapter',
- ],
- [MAGNETIC_BLOCK_TYPE]: [
- 'nest_96_wellplate_100ul_pcr_full_skirt',
- 'nest_96_wellplate_2ml_deep',
- 'opentrons_96_wellplate_200ul_pcr_full_skirt',
- ],
- [ABSORBANCE_READER_TYPE]: [],
-}
-
-export const getLabwareIsRecommended = (
- def: LabwareDefinition2,
- moduleModel?: ModuleModel | null
-): boolean => {
- // special-casing the thermocycler module V2 recommended labware
- // since its different from V1
- const moduleType = moduleModel != null ? getModuleType(moduleModel) : null
- if (moduleModel === THERMOCYCLER_MODULE_V2) {
- return (
- def.parameters.loadName === 'opentrons_96_wellplate_200ul_pcr_full_skirt'
- )
- } else {
- return moduleType != null
- ? RECOMMENDED_LABWARE_BY_MODULE[moduleType].includes(
- def.parameters.loadName
- )
- : false
- }
-}
-export function LabwareSelectionModal(): JSX.Element | null {
- const { t } = useTranslation(['modules', 'modal', 'button', 'alert'])
- const dispatch = useDispatch>()
- const selectedLabwareSlot = useSelector(
- labwareIngredSelectors.selectedAddLabwareSlot
- )
- const pipetteEntities = useSelector(getPipetteEntities)
- const permittedTipracks = useSelector(stepFormSelectors.getPermittedTipracks)
- const customLabwareDefs = useSelector(
- labwareDefSelectors.getCustomLabwareDefsByURI
- )
- const deckSetup = useSelector(stepFormSelectors.getInitialDeckSetup)
- const has96Channel = getHas96Channel(pipetteEntities)
- const modulesById = deckSetup.modules
- const labwareById = deckSetup.labware
- const slot = selectedLabwareSlot === false ? null : selectedLabwareSlot
-
- const onClose = (): void => {
- dispatch(closeLabwareSelector())
- }
- const selectLabware = (labwareDefURI: string): void => {
- if (slot) {
- dispatch(
- createContainer({
- slot: slot,
- labwareDefURI,
- })
- )
- }
- }
-
- const onUploadLabware = (
- fileChangeEvent: React.ChangeEvent
- ): void => {
- dispatch(labwareDefActions.createCustomLabwareDef(fileChangeEvent))
- }
-
- const initialModules: ModuleOnDeck[] = Object.keys(modulesById).map(
- moduleId => modulesById[moduleId]
- )
- const parentModule =
- (slot != null &&
- initialModules.find(moduleOnDeck => moduleOnDeck.id === slot)) ||
- null
- const parentSlot = parentModule != null ? parentModule.slot : null
- const moduleModel = parentModule != null ? parentModule.model : null
- const isNextToHeaterShaker = initialModules.some(
- hardwareModule =>
- hardwareModule.type === HEATERSHAKER_MODULE_TYPE &&
- getAreSlotsHorizontallyAdjacent(hardwareModule.slot, parentSlot ?? slot)
- )
- const adapterLoadName = Object.values(labwareById)
- .filter(labwareOnDeck => slot === labwareOnDeck.id)
- .map(labwareOnDeck => labwareOnDeck.def.parameters.loadName)[0]
-
- const defs = getOnlyLatestDefs()
- const moduleType = moduleModel != null ? getModuleType(moduleModel) : null
- const URIs = Object.keys(defs)
- const [selectedCategory, setSelectedCategory] = React.useState(
- null
- )
- const [previewedLabware, setPreviewedLabware] = React.useState<
- LabwareDefinition2 | null | undefined
- >(null)
- const [filterRecommended, setFilterRecommended] = React.useState(
- false
- )
-
- const [filterHeight, setFilterHeight] = React.useState(false)
- const [enqueuedLabwareType, setEnqueuedLabwareType] = React.useState<
- string | null
- >(null)
-
- const blockingCustomLabwareHint = useBlockingHint({
- enabled: enqueuedLabwareType !== null,
- hintKey: 'custom_labware_with_modules',
- content: {t(`alert:hint.custom_labware_with_modules.body`)}
,
- handleCancel: () => {
- setEnqueuedLabwareType(null)
- },
- handleContinue: () => {
- setEnqueuedLabwareType(null)
- if (enqueuedLabwareType !== null) {
- // NOTE: this needs to be wrapped for Flow, IRL we know enqueuedLabwareType is not null
- // because `enabled` prop above ensures it's !== null.
- selectLabware(enqueuedLabwareType)
- } else {
- console.error(
- 'could not select labware because enqueuedLabwareType is null. This should not happen'
- )
- }
- },
- })
-
- const handleSelectCustomLabware = React.useCallback(
- (containerType: string) => {
- if (moduleType == null) {
- selectLabware(containerType)
- } else {
- // show the BlockingHint
- setEnqueuedLabwareType(containerType)
- }
- },
- [moduleType, selectLabware, setEnqueuedLabwareType]
- )
-
- // if you're adding labware to a module, check the recommended filter by default
- React.useEffect(() => {
- setFilterRecommended(moduleType != null)
- setFilterHeight(isNextToHeaterShaker)
- }, [moduleType, isNextToHeaterShaker])
-
- const getLabwareCompatible = React.useCallback(
- (def: LabwareDefinition2) => {
- // assume that custom (non-standard) labware is (potentially) compatible
- if (moduleType == null || !getLabwareDefIsStandard(def)) {
- return true
- }
- return _getLabwareIsCompatible(def, moduleType)
- },
- [moduleType]
- )
-
- const getIsLabwareFiltered = React.useCallback(
- (labwareDef: LabwareDefinition2) => {
- const { dimensions, parameters } = labwareDef
- const { xDimension, yDimension } = dimensions
-
- const isSmallXDimension = xDimension < 127.75
- const isSmallYDimension = yDimension < 85.48
- const isIrregularSize = isSmallXDimension && isSmallYDimension
-
- const isAdapter = labwareDef.allowedRoles?.includes('adapter')
- const isAdapter96Channel = parameters.loadName === ADAPTER_96_CHANNEL
-
- return (
- (filterRecommended &&
- !getLabwareIsRecommended(labwareDef, moduleModel)) ||
- (filterHeight &&
- getIsLabwareAboveHeight(
- labwareDef,
- MAX_LABWARE_HEIGHT_EAST_WEST_HEATER_SHAKER_MM
- )) ||
- !getLabwareCompatible(labwareDef) ||
- (isAdapter &&
- isIrregularSize &&
- !slot?.includes(HEATERSHAKER_MODULE_TYPE)) ||
- (isAdapter96Channel && !has96Channel) ||
- (slot === 'offDeck' && isAdapter)
- )
- },
- [filterRecommended, filterHeight, getLabwareCompatible, moduleType, slot]
- )
- const getTitleText = (): string => {
- if (isNextToHeaterShaker) {
- return `Slot ${slot}, Labware to the side of ${t(
- `module_long_names.heaterShakerModuleType`
- )}`
- }
- if (adapterLoadName != null) {
- const adapterDisplayName =
- Object.values(defs).find(
- def => def.parameters.loadName === adapterLoadName
- )?.metadata.displayName ?? ''
- return `Labware on top of the ${adapterDisplayName}`
- }
- if (parentSlot != null && moduleType != null) {
- return `Slot ${parentSlot === SPAN7_8_10_11_SLOT ? '7' : parentSlot}, ${t(
- `module_long_names.${moduleType}`
- )} Labware`
- }
- return `Slot ${slot} Labware`
- }
-
- const getLabwareAdapterItem = (
- index: number,
- labwareDefUri?: string
- ): JSX.Element | null => {
- const labwareDef = labwareDefUri != null ? defs[labwareDefUri] : null
- return labwareDef != null ? (
- {
- setPreviewedLabware(labwareDef)
- }}
- onMouseLeave={() => {
- // @ts-expect-error(sa, 2021-6-22): setPreviewedLabware expects an argument (even if nullsy)
- setPreviewedLabware()
- }}
- />
- ) : null
- }
-
- const customLabwareURIs: string[] = React.useMemo(
- () => Object.keys(customLabwareDefs),
- [customLabwareDefs]
- )
-
- const labwareByCategory = React.useMemo(() => {
- return reduce<
- LabwareDefByDefURI,
- { [category: string]: LabwareDefinition2[] }
- >(
- defs,
- (acc, def: typeof defs[keyof typeof defs]) => {
- const category: string = def.metadata.displayCategory
- // filter out non-permitted tipracks
- if (
- category === 'tipRack' &&
- !permittedTipracks.includes(getLabwareDefURI(def))
- ) {
- return acc
- }
-
- return {
- ...acc,
- [category]: [...(acc[category] || []), def],
- }
- },
- {}
- )
- }, [permittedTipracks])
-
- const populatedCategories: { [category: string]: boolean } = React.useMemo(
- () =>
- orderedCategories.reduce(
- (acc, category) =>
- labwareByCategory[category]
- ? {
- ...acc,
- [category]: labwareByCategory[category].some(
- def => !getIsLabwareFiltered(def)
- ),
- }
- : acc,
- {}
- ),
- [labwareByCategory, getIsLabwareFiltered]
- )
-
- const wrapperRef: React.RefObject = useOnClickOutside({
- onClickOutside: () => {
- // don't close when clicking on the custom labware hint
- if (!enqueuedLabwareType) {
- onClose()
- }
- },
- })
-
- // do not render without a slot
- if (!slot) return null
-
- const makeToggleCategory = (category: string) => () => {
- setSelectedCategory(selectedCategory === category ? null : category)
- }
-
- const getFilterCheckbox = (): JSX.Element | null => {
- if (isNextToHeaterShaker || moduleType != null) {
- return (
-
-
Filters
-
- ) => {
- isNextToHeaterShaker
- ? setFilterHeight(e.currentTarget.checked)
- : setFilterRecommended(e.currentTarget.checked)
- }}
- value={isNextToHeaterShaker ? filterHeight : filterRecommended}
- />
- {isNextToHeaterShaker && (
-
- )}
-
- {t(
- isNextToHeaterShaker
- ? 'modal:labware_selection.heater_shaker_labware_filter'
- : 'modal:labware_selection.recommended_labware_filter'
- )}{' '}
-
- here
-
- .
-
-
-
- )
- }
- return null
- }
-
- let moduleCompatibility: React.ComponentProps<
- typeof LabwarePreview
- >['moduleCompatibility'] = null
- if (previewedLabware && moduleType) {
- if (getLabwareIsRecommended(previewedLabware, moduleModel)) {
- moduleCompatibility = 'recommended'
- } else if (getLabwareCompatible(previewedLabware)) {
- moduleCompatibility = 'potentiallyCompatible'
- } else {
- moduleCompatibility = 'notCompatible'
- }
- }
-
- return (
- <>
- {createPortal(
- ,
- getTopPortalEl()
- )}
- {blockingCustomLabwareHint}
-
-
{getTitleText()}
- {getFilterCheckbox()}
-
- {customLabwareURIs.length > 0 ? (
-
- {customLabwareURIs.map((labwareURI, index) => (
- {
- setPreviewedLabware(customLabwareDefs[labwareURI])
- }}
- onMouseLeave={() => {
- // @ts-expect-error(sa, 2021-6-22): need to pass in a nullsy value
- setPreviewedLabware()
- }}
- />
- ))}
-
- ) : null}
- {adapterLoadName == null ? (
- orderedCategories.map(category => {
- const isPopulated = populatedCategories[category]
- if (isPopulated) {
- return (
-
- {labwareByCategory[category]?.map((labwareDef, index) => {
- const isFiltered = getIsLabwareFiltered(labwareDef)
- if (!isFiltered) {
- return (
- {
- setPreviewedLabware(labwareDef)
- }}
- onMouseLeave={() => {
- // @ts-expect-error(sa, 2021-6-22): setPreviewedLabware expects an argument (even if nullsy)
- setPreviewedLabware()
- }}
- />
- )
- }
- })}
-
- )
- }
- })
- ) : (
-
- {has96Channel && adapterLoadName === ADAPTER_96_CHANNEL
- ? permittedTipracks.map((tiprackDefUri, index) => {
- const labwareDefUri = URIs.find(
- defUri => defUri === tiprackDefUri
- )
- return getLabwareAdapterItem(index, labwareDefUri)
- })
- : getLabwareCompatibleWithAdapter(adapterLoadName).map(
- (adapterDefUri, index) => {
- const labwareDefUri = URIs.find(
- defUri => defUri === adapterDefUri
- )
- return getLabwareAdapterItem(index, labwareDefUri)
- }
- )}
-
- )}
-
-
-
- {t('button:upload_custom_labware')}
- {
- onUploadLabware(e)
- setSelectedCategory(CUSTOM_CATEGORY)
- }}
- />
-
-
- {t('modal:labware_selection.creating_labware_defs')}{' '}
- {/* TODO: Ian 2019-10-15 use LinkOut component once it's in components library, see Opentrons/opentrons#4229 */}
-
- here
-
- .
-
-
-
{t('button:close')}
-
- >
- )
-}
diff --git a/protocol-designer/src/components/LabwareSelectionModal/__tests__/LabwareSelectionModal.test.tsx b/protocol-designer/src/components/LabwareSelectionModal/__tests__/LabwareSelectionModal.test.tsx
deleted file mode 100644
index ab56ace5c46..00000000000
--- a/protocol-designer/src/components/LabwareSelectionModal/__tests__/LabwareSelectionModal.test.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import { vi, describe, it, expect, beforeEach } from 'vitest'
-import { fireEvent, screen } from '@testing-library/react'
-import {
- renderWithProviders,
- nestedTextMatcher,
-} from '../../../__testing-utils__'
-import {
- getIsLabwareAboveHeight,
- MAX_LABWARE_HEIGHT_EAST_WEST_HEATER_SHAKER_MM,
-} from '@opentrons/shared-data'
-import { selectors as labwareIngredSelectors } from '../../../labware-ingred/selectors'
-import {
- ADAPTER_96_CHANNEL,
- getLabwareCompatibleWithAdapter,
-} from '../../../utils/labwareModuleCompatibility'
-import { i18n } from '../../../assets/localization'
-import { LabwareSelectionModal } from '../LabwareSelectionModal'
-import {
- getInitialDeckSetup,
- getPermittedTipracks,
- getPipetteEntities,
-} from '../../../step-forms/selectors'
-import { getHas96Channel } from '../../../utils'
-import { getCustomLabwareDefsByURI } from '../../../labware-defs/selectors'
-import type * as SharedData from '@opentrons/shared-data'
-
-vi.mock('../../../utils/labwareModuleCompatibility')
-vi.mock('../../../step-forms/selectors')
-vi.mock('../../../labware-defs/selectors')
-vi.mock('../../Hints/useBlockingHint')
-vi.mock('../../../utils')
-vi.mock('../../../labware-ingred/selectors')
-vi.mock('@opentrons/shared-data', async importOriginal => {
- const actual = await importOriginal()
- return {
- ...actual,
- getIsLabwareAboveHeight: vi.fn(),
- }
-})
-
-const render = () => {
- return renderWithProviders( , {
- i18nInstance: i18n,
- })[0]
-}
-
-const mockTipUri = 'fixture/fixture_tiprack_1000_ul/1'
-const mockPermittedTipracks = [mockTipUri]
-
-describe('LabwareSelectionModal', () => {
- beforeEach(() => {
- vi.mocked(getLabwareCompatibleWithAdapter).mockReturnValue([])
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- labware: {},
- modules: {},
- pipettes: {},
- additionalEquipmentOnDeck: {},
- })
- vi.mocked(labwareIngredSelectors.selectedAddLabwareSlot).mockReturnValue(
- '2'
- )
- vi.mocked(getHas96Channel).mockReturnValue(false)
- vi.mocked(getPermittedTipracks).mockReturnValue(mockPermittedTipracks)
- vi.mocked(getPipetteEntities).mockReturnValue({
- mockPip: {
- tiprackLabwareDef: {} as any,
- spec: {} as any,
- name: 'p1000_single',
- id: 'mockId',
- tiprackDefURI: [mockTipUri],
- },
- })
- vi.mocked(getCustomLabwareDefsByURI).mockReturnValue({})
- })
- it('should NOT filter out labware above 57 mm when the slot is NOT next to a heater shaker', () => {
- render()
- expect(vi.mocked(getIsLabwareAboveHeight)).not.toHaveBeenCalled()
- })
- it('should filter out labware above 57 mm when the slot is next to a heater shaker', () => {
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- labware: {},
- modules: {
- heaterShaker: {
- id: 'mockId',
- type: 'heaterShakerModuleType',
- model: 'heaterShakerModuleV1',
- moduleState: {} as any,
- slot: '1',
- } as any,
- },
- pipettes: {},
- additionalEquipmentOnDeck: {},
- })
- render()
- expect(vi.mocked(getIsLabwareAboveHeight)).toHaveBeenCalledWith(
- expect.any(Object),
- MAX_LABWARE_HEIGHT_EAST_WEST_HEATER_SHAKER_MM
- )
- })
- it.only('should display only permitted tipracks if the 96-channel is attached', () => {
- vi.mocked(getHas96Channel).mockReturnValue(true)
- vi.mocked(labwareIngredSelectors.selectedAddLabwareSlot).mockReturnValue(
- 'adapter'
- )
- vi.mocked(getInitialDeckSetup).mockReturnValue({
- labware: {
- adapter: {
- id: 'adapter',
- labwareDefURI: `opentrons/${ADAPTER_96_CHANNEL}/1`,
- slot: 'A2',
- def: { parameters: { loadName: ADAPTER_96_CHANNEL } } as any,
- },
- },
- modules: {},
- pipettes: {},
- additionalEquipmentOnDeck: {},
- })
- render()
- fireEvent.click(
- screen.getByText(nestedTextMatcher('Adapter Compatible Labware'))
- )
- screen.getByText('Opentrons GEB 1000uL Tiprack')
- })
-})
diff --git a/protocol-designer/src/components/LabwareSelectionModal/styles.module.css b/protocol-designer/src/components/LabwareSelectionModal/styles.module.css
deleted file mode 100644
index 27097e62ee8..00000000000
--- a/protocol-designer/src/components/LabwareSelectionModal/styles.module.css
+++ /dev/null
@@ -1,181 +0,0 @@
-@import '@opentrons/components/styles';
-
-.title {
- font-size: var(--fs-header); /* from legacy --font-header-dark */
- font-weight: var(--fw-semibold); /* from legacy --font-header-dark */
- color: var(--c-font-dark); /* from legacy --font-header-dark */
- padding-bottom: 1rem;
-}
-
-.labware_dropdown {
- position: absolute;
- background-color: var(--c-white);
- box-shadow: var(--shadow-lvl-2);
- left: 0;
- right: 0;
- top: 12%;
- max-width: 28rem;
- margin: auto;
- padding: 1rem 2rem;
- user-select: none;
- z-index: 1;
-
- & button {
- margin-top: 2rem;
- float: right;
- }
-}
-
-/* ----- */
-
-.view_measurements_link,
-.labware_name {
- padding: 1rem 0.5rem;
-}
-
-.view_measurements_link {
- flex: 0.6;
- text-transform: uppercase;
- text-align: center;
- cursor: pointer;
- text-decoration: none;
- color: inherit;
-
- &:hover {
- background-color: var(--c-bg-hover);
- }
-}
-
-.labware_list_item {
- display: flex;
- padding: 0;
-
- & .view_measurements_link {
- display: none;
- }
-
- &:hover .view_measurements_link {
- display: inherit;
- }
-}
-
-.labware_preview_wrapper {
- position: absolute;
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
- z-index: 10;
-}
-
-.labware_preview {
- width: 25.25rem;
- height: 12.8125rem;
- background-color: var(--c-white);
- box-shadow: var(--shadow-lvl-2);
- padding: 1rem;
- z-index: 100;
- display: flex;
- justify-content: space-between;
- flex-direction: column;
-}
-
-.labware_preview_header {
- font-size: var(--fs-header); /* from legacy --font-header-dark */
- font-weight: var(--fw-semibold); /* from legacy --font-header-dark */
- color: var(--c-font-dark); /* from legacy --font-header-dark */
-}
-
-.labware_preview_module_compat {
- font-size: var(--fs-body-2); /* from legacy --font-body-2-dark */
- font-weight: var(--fw-regular); /* from legacy --font-body-2-dark */
- color: var(--c-font-dark); /* from legacy --font-body-2-dark */
- display: flex;
- align-items: center;
-}
-
-.labware_render_wrapper {
- height: 7.125rem;
- width: 10.75rem;
-}
-
-.labware_detail_row {
- display: flex;
- justify-content: space-between;
- flex-direction: row;
-}
-
-.labware_detail_column {
- display: flex;
- justify-content: space-between;
- flex-direction: column;
- flex: 1;
- padding: 0.25rem 1rem;
-}
-
-.labware_name {
- text-align: left;
-}
-
-/* TODO: Ian 2019-08-05 copied from FileSidebar.css, consider merging as new component */
-.upload_button {
- margin: 0.75rem 0;
- width: 100%;
-}
-
-.upload_button input {
- position: fixed;
- clip: rect(1px 1px 1px 1px);
-}
-
-.upload_helper_copy {
- font-size: var(--fs-body-1); /* from legacy --font-body-1-dark */
- font-weight: var(--fw-regular); /* from legacy --font-body-1-dark */
- color: var(--c-font-dark); /* from legacy --font-body-1-dark */
-}
-
-/* TODO: Ian 2019-09-03 similar styles for links exist in multiple projects */
-.link {
- color: var(--c-blue);
- text-decoration: none;
- cursor: pointer;
-}
-
-.labware_item_icon {
- flex: 0 1 auto;
- margin-left: 0.5rem;
-}
-
-.icon,
-.labware_item_icon {
- height: 1.25rem;
- fill: var(--c-near-black);
-}
-
-.filters_heading {
- font-size: var(--fs-body-2); /* from legacy --font-body-2-dark */
- color: var(--c-font-dark); /* from legacy --font-body-2-dark */
- font-weight: var(--fw-semibold);
-}
-
-.filter_checkbox {
- display: inline-block;
- padding-right: 0.75rem;
-}
-
-.filters_section {
- display: flex;
- align-items: center;
- margin: 0.25rem 0;
-}
-
-.filters_section_copy {
- font-size: var(--fs-body-1); /* from legacy --font-body-1-dark */
- font-weight: var(--fw-regular); /* from legacy --font-body-1-dark */
- color: var(--c-font-dark); /* from legacy --font-body-1-dark */
- padding-left: 0.15rem;
-}
-
-.disabled {
- color: var(--c-font-disabled);
-}
diff --git a/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.module.css b/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.module.css
deleted file mode 100644
index 16d370b63e5..00000000000
--- a/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.module.css
+++ /dev/null
@@ -1,30 +0,0 @@
-@import '@opentrons/components/styles';
-
-/* fields */
-
-.field_row {
- lost-utility: clearfix;
- margin-bottom: 2rem;
-}
-
-.liquid_field {
- lost-column: 8/16;
-}
-
-.volume_field {
- lost-column: 3/16;
-}
-
-/* buttons */
-
-.button_row {
- lost-utility: clearfix;
-
- & > * {
- lost-column: 4/16;
- }
-
- & > *:nth-child(2) {
- lost-offset: 4/16;
- }
-}
diff --git a/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.tsx b/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.tsx
deleted file mode 100644
index 1221d479448..00000000000
--- a/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.tsx
+++ /dev/null
@@ -1,260 +0,0 @@
-import type * as React from 'react'
-import { Controller, useForm } from 'react-hook-form'
-import isEmpty from 'lodash/isEmpty'
-import { useTranslation } from 'react-i18next'
-import { useSelector, useDispatch } from 'react-redux'
-
-import * as wellContentsSelectors from '../../top-selectors/well-contents'
-import * as fieldProcessors from '../../steplist/fieldLevel/processing'
-import {
- DropdownField,
- FormGroup,
- OutlineButton,
- DeprecatedPrimaryButton,
- LegacyInputField,
-} from '@opentrons/components'
-import styles from './LiquidPlacementForm.module.css'
-import formStyles from '../forms/forms.module.css'
-import stepEditFormStyles from '../StepEditForm/StepEditForm.module.css'
-import { deselectAllWells } from '../../well-selection/actions'
-import {
- removeWellsContents,
- setWellContents,
-} from '../../labware-ingred/actions'
-import { getSelectedWells } from '../../well-selection/selectors'
-
-import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
-
-interface ValidFormValues {
- selectedLiquidId: string
- volume: string
-}
-interface LiquidPlacementFormValues {
- selectedLiquidId?: string | null
- volume?: string | null
-}
-
-export const LiquidPlacementForm = (): JSX.Element | null => {
- const { t } = useTranslation(['form', 'button', 'application'])
- const selectedWellGroups = useSelector(getSelectedWells)
- const selectedWells = Object.keys(selectedWellGroups)
- const showForm = !isEmpty(selectedWellGroups)
- const dispatch = useDispatch()
- const labwareId = useSelector(labwareIngredSelectors.getSelectedLabwareId)
- const liquidLocations = useSelector(
- labwareIngredSelectors.getLiquidsByLabwareId
- )
- const commonSelectedLiquidId = useSelector(
- wellContentsSelectors.getSelectedWellsCommonIngredId
- )
- const commonSelectedVolume = useSelector(
- wellContentsSelectors.getSelectedWellsCommonVolume
- )
- const selectedWellsMaxVolume = useSelector(
- wellContentsSelectors.getSelectedWellsMaxVolume
- )
- const liquidSelectionOptions = useSelector(
- labwareIngredSelectors.getLiquidSelectionOptions
- )
-
- const selectionHasLiquids = Boolean(
- labwareId != null &&
- liquidLocations[labwareId] != null &&
- Object.keys(selectedWellGroups).some(
- well => liquidLocations[labwareId][well]
- )
- )
-
- const getInitialValues: () => ValidFormValues = () => {
- return {
- selectedLiquidId: commonSelectedLiquidId ?? '',
- volume:
- commonSelectedVolume != null ? commonSelectedVolume.toString() : '',
- }
- }
-
- const {
- handleSubmit,
- watch,
- control,
- setValue,
- formState: { errors, touchedFields },
- } = useForm({
- defaultValues: getInitialValues(),
- })
-
- const selectedLiquidId = watch('selectedLiquidId')
- const volume = watch('volume')
-
- const handleCancelForm = (): void => {
- dispatch(deselectAllWells())
- }
-
- const handleClearWells: () => void = () => {
- if (labwareId != null && selectedWells != null && selectionHasLiquids) {
- if (global.confirm(t('application:are_you_sure') as string)) {
- dispatch(
- removeWellsContents({
- labwareId,
- wells: selectedWells,
- })
- )
- }
- }
- }
-
- const handleChangeVolume: (
- e: React.ChangeEvent
- ) => void = e => {
- const value: string | null | undefined = e.currentTarget.value
- const masked = fieldProcessors.composeMaskers(
- fieldProcessors.maskToFloat,
- fieldProcessors.onlyPositiveNumbers,
- fieldProcessors.trimDecimals(1)
- )(value) as string
- setValue('volume', masked)
- }
-
- const handleSaveForm = (values: LiquidPlacementFormValues): void => {
- const volume = Number(values.volume)
- const { selectedLiquidId } = values
- console.assert(
- labwareId != null,
- 'when saving liquid placement form, expected a selected labware ID'
- )
- console.assert(
- selectedWells != null && selectedWells.length > 0,
- `when saving liquid placement form, expected selected wells to be array with length > 0 but got ${String(
- selectedWells
- )}`
- )
- console.assert(
- selectedLiquidId != null,
- `when saving liquid placement form, expected selectedLiquidId to be non-nullsy but got ${String(
- selectedLiquidId
- )}`
- )
- console.assert(
- volume > 0,
- `when saving liquid placement form, expected volume > 0, got ${volume}`
- )
-
- if (labwareId != null && selectedLiquidId != null) {
- dispatch(
- setWellContents({
- liquidGroupId: selectedLiquidId,
- labwareId,
- wells: selectedWells ?? [],
- volume: Number(values.volume),
- })
- )
- }
- }
-
- const handleSaveSubmit: (
- values: LiquidPlacementFormValues
- ) => void = values => {
- handleSaveForm(values)
- }
-
- if (!showForm) return null
-
- let volumeErrors: string | null = null
- if (Boolean(touchedFields.volume)) {
- if (volume == null || volume === '0') {
- volumeErrors = t('generic.error.more_than_zero')
- } else if (parseInt(volume) > selectedWellsMaxVolume) {
- volumeErrors = t('liquid_placement.volume_exceeded', {
- volume: selectedWellsMaxVolume,
- })
- }
- }
-
- return (
-
- )
-}
diff --git a/protocol-designer/src/components/LiquidPlacementModal.module.css b/protocol-designer/src/components/LiquidPlacementModal.module.css
deleted file mode 100644
index c63a9946758..00000000000
--- a/protocol-designer/src/components/LiquidPlacementModal.module.css
+++ /dev/null
@@ -1,34 +0,0 @@
-@import '@opentrons/components/styles';
-
-.labware {
- margin: 2rem auto;
- max-width: 50rem;
-}
-
-.liquid_placement_modal {
- position: absolute;
-
- /* from legacy --absolute-fill */
- top: 0;
-
- /* from legacy --absolute-fill */
- right: 0;
-
- /* from legacy --absolute-fill */
- bottom: 0;
-
- /* from legacy --absolute-fill */
- left: 0;
-
- /* from legacy --absolute-fill */
-
- background-color: rgba(0, 0, 0, 0.9);
- z-index: 4;
-
- /* make up lost space for overlay */
- height: 103%;
-
- &.expanded {
- height: 127%;
- }
-}
diff --git a/protocol-designer/src/components/LiquidPlacementModal.tsx b/protocol-designer/src/components/LiquidPlacementModal.tsx
deleted file mode 100644
index 307255ae846..00000000000
--- a/protocol-designer/src/components/LiquidPlacementModal.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import { useState } from 'react'
-
-import { useDispatch, useSelector } from 'react-redux'
-import cx from 'classnames'
-import isEmpty from 'lodash/isEmpty'
-import { WELL_LABEL_OPTIONS } from '@opentrons/components'
-
-import {
- wellFillFromWellContents,
- SelectableLabware,
-} from '../components/labware'
-import { selectors } from '../labware-ingred/selectors'
-import { selectors as stepFormSelectors } from '../step-forms'
-import * as wellContentsSelectors from '../top-selectors/well-contents'
-import { getSelectedWells } from '../well-selection/selectors'
-import { selectWells, deselectWells } from '../well-selection/actions'
-import { LiquidPlacementForm } from './LiquidPlacementForm/LiquidPlacementForm'
-import { WellSelectionInstructions } from './WellSelectionInstructions'
-
-import styles from './LiquidPlacementModal.module.css'
-import type { WellGroup } from '@opentrons/components'
-
-export function LiquidPlacementModal(): JSX.Element | null {
- const [highlightedWells, setHighlightedWells] = useState({})
- const labwareId = useSelector(selectors.getSelectedLabwareId)
- const selectedWells = useSelector(getSelectedWells)
- const dispatch = useDispatch()
- const labwareEntities = useSelector(stepFormSelectors.getLabwareEntities)
- const allWellContents = useSelector(
- wellContentsSelectors.getWellContentsAllLabware
- )
- const liquidNamesById = useSelector(selectors.getLiquidNamesById)
- const liquidDisplayColors = useSelector(selectors.getLiquidDisplayColors)
- if (labwareId == null) {
- console.assert(
- false,
- 'LiquidPlacementModal: No labware is selected, and no labwareId was given to LiquidPlacementModal'
- )
- return null
- }
-
- const labwareDef = labwareEntities[labwareId]?.def
- const wellContents = allWellContents[labwareId]
-
- return (
-
-
-
- {labwareDef && (
-
- dispatch(selectWells(wells))}
- deselectWells={(wells: WellGroup) => dispatch(deselectWells(wells))}
- updateHighlightedWells={(wells: WellGroup) => {
- setHighlightedWells(wells)
- }}
- ingredNames={liquidNamesById}
- wellContents={wellContents}
- nozzleType={null}
- />
-
- )}
-
-
-
- )
-}
diff --git a/protocol-designer/src/components/LiquidsPage/LiquidEditForm.module.css b/protocol-designer/src/components/LiquidsPage/LiquidEditForm.module.css
deleted file mode 100644
index d89e24f154e..00000000000
--- a/protocol-designer/src/components/LiquidsPage/LiquidEditForm.module.css
+++ /dev/null
@@ -1,26 +0,0 @@
-@import '@opentrons/components/styles';
-
-.form_card {
- margin: 1rem;
- padding: 1rem;
-}
-
-.section {
- padding-bottom: 2rem;
-}
-
-.info_text {
- padding-bottom: 1.5rem;
-}
-
-.button_row {
- lost-utility: clearfix;
-
- & > * {
- lost-column: 1/6;
- }
-
- & > *:nth-child(2) {
- lost-offset: 3/6;
- }
-}
diff --git a/protocol-designer/src/components/LiquidsPage/LiquidEditForm.tsx b/protocol-designer/src/components/LiquidsPage/LiquidEditForm.tsx
deleted file mode 100644
index f7697dc2add..00000000000
--- a/protocol-designer/src/components/LiquidsPage/LiquidEditForm.tsx
+++ /dev/null
@@ -1,236 +0,0 @@
-import type * as React from 'react'
-import { useTranslation } from 'react-i18next'
-import { Controller, useForm } from 'react-hook-form'
-import { yupResolver } from '@hookform/resolvers/yup'
-import { useSelector } from 'react-redux'
-import * as Yup from 'yup'
-import {
- Card,
- DeprecatedCheckboxField,
- DeprecatedPrimaryButton,
- Flex,
- FormGroup,
- JUSTIFY_END,
- LegacyInputField,
- OutlineButton,
- TYPOGRAPHY,
-} from '@opentrons/components'
-import { DEPRECATED_WHALE_GREY } from '@opentrons/shared-data'
-import { selectors } from '../../labware-ingred/selectors'
-import { swatchColors } from '../swatchColors'
-import { ColorPicker } from '../ColorPicker'
-import styles from './LiquidEditForm.module.css'
-import formStyles from '../forms/forms.module.css'
-
-import type { ColorResult } from 'react-color'
-import type { LiquidGroup } from '../../labware-ingred/types'
-
-interface LiquidEditFormProps {
- serialize: boolean
- canDelete: boolean
- deleteLiquidGroup: () => void
- cancelForm: () => void
- saveForm: (liquidGroup: LiquidGroup) => void
- displayColor?: string
- name?: string | null
- description?: string | null
-}
-
-interface LiquidEditFormValues {
- name: string
- displayColor: string
- description?: string | null
- serialize?: boolean
- [key: string]: unknown
-}
-
-function checkColor(hex: string): boolean {
- const cleanHex = hex.replace('#', '')
- const red = parseInt(cleanHex.slice(0, 2), 16)
- const green = parseInt(cleanHex.slice(2, 4), 16)
- const blue = parseInt(cleanHex.slice(4, 6), 16)
- const luminance = (0.299 * red + 0.587 * green + 0.114 * blue) / 255
- return luminance < 0.1 || luminance > 0.9
-}
-
-const INVALID_DISPLAY_COLORS = ['#000000', '#ffffff', DEPRECATED_WHALE_GREY]
-
-const liquidEditFormSchema: any = Yup.object().shape({
- name: Yup.string().required('liquid name is required'),
- displayColor: Yup.string().test(
- 'disallowed-color',
- 'Invalid display color',
- value => {
- if (value == null) {
- return true
- }
- return !INVALID_DISPLAY_COLORS.includes(value)
- ? !checkColor(value)
- : false
- }
- ),
- description: Yup.string(),
- serialize: Yup.boolean(),
-})
-
-export function LiquidEditForm(props: LiquidEditFormProps): JSX.Element {
- const {
- deleteLiquidGroup,
- cancelForm,
- canDelete,
- saveForm,
- displayColor,
- name: propName,
- description: propDescription,
- serialize,
- } = props
- const selectedLiquid = useSelector(selectors.getSelectedLiquidGroupState)
- const nextGroupId = useSelector(selectors.getNextLiquidGroupId)
- const liquidId = selectedLiquid.liquidGroupId ?? nextGroupId
- const { t } = useTranslation(['form', 'button'])
- const initialValues: LiquidEditFormValues = {
- name: propName ?? '',
- displayColor: displayColor ?? swatchColors(liquidId),
- description: propDescription ?? '',
- serialize: serialize || false,
- }
-
- const {
- handleSubmit,
- formState: { errors, touchedFields, isDirty },
- control,
- watch,
- setValue,
- } = useForm({
- defaultValues: initialValues,
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
- resolver: yupResolver(liquidEditFormSchema),
- })
- const name = watch('name')
- const description = watch('description')
- const color = watch('displayColor')
-
- const handleLiquidEdits = (values: LiquidEditFormValues): void => {
- saveForm({
- name: values.name,
- displayColor: values.displayColor,
- description: values.description ?? null,
- serialize: values.serialize ?? false,
- })
- }
-
- return (
-
-
-
- )
-}
diff --git a/protocol-designer/src/components/LiquidsPage/LiquidsPageInfo.module.css b/protocol-designer/src/components/LiquidsPage/LiquidsPageInfo.module.css
deleted file mode 100644
index 2da07d1398f..00000000000
--- a/protocol-designer/src/components/LiquidsPage/LiquidsPageInfo.module.css
+++ /dev/null
@@ -1,27 +0,0 @@
-@import '@opentrons/components/styles';
-
-.info_wrapper {
- font-size: var(--fs-body-2); /* from legacy --font-body-2-dark */
- font-weight: var(--fw-regular); /* from legacy --font-body-2-dark */
- color: var(--c-font-dark); /* from legacy --font-body-2-dark */
- text-align: center;
- max-width: 38rem;
- margin: 2rem auto;
-}
-
-.header {
- font-size: var(--fs-header); /* from legacy --font-header-dark */
- font-weight: var(--fw-semibold); /* from legacy --font-header-dark */
- color: var(--c-font-dark); /* from legacy --font-header-dark */
-}
-
-.instruction {
- margin: 2rem 0;
- line-height: 1.5;
-}
-
-.inline_icon {
- color: var(--c-font-dark);
- height: 1.5em;
- padding: 0 0.25em;
-}
diff --git a/protocol-designer/src/components/LiquidsPage/LiquidsPageInfo.tsx b/protocol-designer/src/components/LiquidsPage/LiquidsPageInfo.tsx
deleted file mode 100644
index 22f73b55db3..00000000000
--- a/protocol-designer/src/components/LiquidsPage/LiquidsPageInfo.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Icon } from '@opentrons/components'
-import styles from './LiquidsPageInfo.module.css'
-
-export function LiquidsPageInfo(): JSX.Element {
- return (
-
-
Define your liquids
-
-
- This is your inventory of the reagents and samples your protocol uses.
- Use the New Liquid button in the sidebar to start defining liquids.
-
-
-
- {"After you've added your liquids, continue to the"}
-
- tab where you can specify where labware and liquids start on your deck.
-
-
- )
-}
diff --git a/protocol-designer/src/components/LiquidsPage/index.tsx b/protocol-designer/src/components/LiquidsPage/index.tsx
deleted file mode 100644
index 761b4ef5d73..00000000000
--- a/protocol-designer/src/components/LiquidsPage/index.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { useDispatch, useSelector } from 'react-redux'
-
-import * as labwareIngredActions from '../../labware-ingred/actions'
-import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
-import { LiquidEditForm } from './LiquidEditForm'
-import { LiquidsPageInfo } from './LiquidsPageInfo'
-
-import type { LiquidGroup } from '../../labware-ingred/types'
-import type { ThunkDispatch } from '../../types'
-
-export function LiquidsPage(): JSX.Element {
- const dispatch = useDispatch>()
- const selectedLiquidGroupState = useSelector(
- labwareIngredSelectors.getSelectedLiquidGroupState
- )
- const allIngredientGroupFields = useSelector(
- labwareIngredSelectors.allIngredientGroupFields
- )
-
- const liquidGroupId =
- selectedLiquidGroupState && selectedLiquidGroupState.liquidGroupId
- const selectedIngredFields =
- liquidGroupId != null ? allIngredientGroupFields[liquidGroupId] : null
- const showForm = Boolean(
- selectedLiquidGroupState.liquidGroupId ||
- selectedLiquidGroupState.newLiquidGroup
- )
- const formKey = liquidGroupId || '__new_form__'
-
- const deleteLiquidGroup = (): void => {
- if (liquidGroupId != null)
- dispatch(labwareIngredActions.deleteLiquidGroup(liquidGroupId))
- }
- const cancelForm = (): void => {
- dispatch(labwareIngredActions.deselectLiquidGroup())
- }
-
- const saveForm = (formData: LiquidGroup): void => {
- dispatch(
- labwareIngredActions.editLiquidGroup({
- ...formData,
- liquidGroupId: liquidGroupId,
- })
- )
- }
-
- return showForm ? (
-
- ) : (
-
- )
-}
diff --git a/protocol-designer/src/components/LiquidsSidebar/index.tsx b/protocol-designer/src/components/LiquidsSidebar/index.tsx
deleted file mode 100644
index 174422b1878..00000000000
--- a/protocol-designer/src/components/LiquidsSidebar/index.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { useTranslation } from 'react-i18next'
-import { useDispatch, useSelector } from 'react-redux'
-import {
- DeprecatedPrimaryButton,
- SidePanel,
- truncateString,
-} from '@opentrons/components'
-import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
-import * as labwareIngredActions from '../../labware-ingred/actions'
-import { PDTitledList } from '../lists'
-import { swatchColors } from '../swatchColors'
-import listButtonStyles from '../listButtons.module.css'
-import styles from './styles.module.css'
-
-import type { ThunkDispatch } from '../../types'
-
-export function LiquidsSidebar(): JSX.Element {
- const { t } = useTranslation('button')
- const selectedLiquidGroup = useSelector(
- labwareIngredSelectors.getSelectedLiquidGroupState
- )
- const liquids = useSelector(labwareIngredSelectors.allIngredientNamesIds)
- const dispatch: ThunkDispatch = useDispatch()
-
- const selectLiquid = (liquidGroupId: string): void => {
- dispatch(labwareIngredActions.selectLiquidGroup(liquidGroupId))
- }
- const selectedLiquid =
- selectedLiquidGroup && selectedLiquidGroup.liquidGroupId
- return (
-
- {liquids.map(({ ingredientId, name, displayColor }) => (
- {
- selectLiquid(ingredientId)
- }}
- iconName="circle"
- iconProps={{
- style: {
- fill: displayColor ?? swatchColors(ingredientId),
- },
- ...{
- className: styles.liquid_icon_container,
- },
- }}
- title={
- truncateString(name ?? '', 25) ??
- `Unnamed Ingredient ${ingredientId}`
- } // fallback, should not happen
- />
- ))}
-
- dispatch(labwareIngredActions.createNewLiquidGroup())}
- >
- {t('new_liquid')}
-
-
-
- )
-}
diff --git a/protocol-designer/src/components/LiquidsSidebar/styles.module.css b/protocol-designer/src/components/LiquidsSidebar/styles.module.css
deleted file mode 100644
index 7f805134826..00000000000
--- a/protocol-designer/src/components/LiquidsSidebar/styles.module.css
+++ /dev/null
@@ -1,11 +0,0 @@
-@import '@opentrons/components/styles';
-
-.liquid_icon_container {
- border-style: solid;
- border-width: 1px;
- border-color: #e3e3e3;
- border-radius: 4px;
- background-color: var(--c-white);
- height: 2.25rem;
- padding: 0.5rem;
-}
diff --git a/protocol-designer/src/components/OffDeckLabwareButton.tsx b/protocol-designer/src/components/OffDeckLabwareButton.tsx
deleted file mode 100644
index 585cf6aca12..00000000000
--- a/protocol-designer/src/components/OffDeckLabwareButton.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { useState } from 'react'
-import { useSelector } from 'react-redux'
-import { useTranslation } from 'react-i18next'
-import {
- DeprecatedPrimaryButton,
- Flex,
- POSITION_ABSOLUTE,
- POSITION_RELATIVE,
- SPACING,
-} from '@opentrons/components'
-import { getSelectedTerminalItemId } from '../ui/steps'
-import { OffDeckLabwareSlideout } from './OffDeckLabwareSlideout'
-
-export const OffDeckLabwareButton = (): JSX.Element => {
- const selectedTerminalItemId = useSelector(getSelectedTerminalItemId)
- const { t } = useTranslation('button')
- const [showSlideout, setShowSlideout] = useState(false)
-
- return (
-
-
- {
- setShowSlideout(true)
- }}
- >
- {t('edit_off_deck')}
-
-
- {showSlideout ? (
- {
- setShowSlideout(false)
- }}
- initialSetupTerminalItemId={
- selectedTerminalItemId === '__initial_setup__'
- }
- />
- ) : null}
-
- )
-}
diff --git a/protocol-designer/src/components/OffDeckLabwareSlideout.tsx b/protocol-designer/src/components/OffDeckLabwareSlideout.tsx
deleted file mode 100644
index 1fd8be9814c..00000000000
--- a/protocol-designer/src/components/OffDeckLabwareSlideout.tsx
+++ /dev/null
@@ -1,181 +0,0 @@
-import { useDispatch, useSelector } from 'react-redux'
-import { css } from 'styled-components'
-import { useTranslation } from 'react-i18next'
-import {
- LegacyTooltip,
- DeprecatedPrimaryButton,
- useHoverTooltip,
- Flex,
- COLORS,
- Icon,
- SPACING,
- Text,
- DIRECTION_COLUMN,
- BORDERS,
- LabwareRender,
- RobotWorkSpace,
- LabwareNameOverlay,
- RobotCoordsForeignDiv,
- ALIGN_CENTER,
- JUSTIFY_CENTER,
- TYPOGRAPHY,
- truncateString,
- POSITION_ABSOLUTE,
-} from '@opentrons/components'
-import { getLabwareDisplayName } from '@opentrons/shared-data'
-import { openAddLabwareModal } from '../labware-ingred/actions'
-import { getLabwareEntities } from '../step-forms/selectors'
-import { selectors } from '../labware-ingred/selectors'
-import { getAllWellContentsForActiveItem } from '../top-selectors/well-contents'
-import { getRobotStateAtActiveItem } from '../top-selectors/labware-locations'
-import { getLabwareNicknamesById } from '../ui/labware/selectors'
-import { EditLabwareOffDeck } from './DeckSetup/LabwareOverlays/EditLabwareOffDeck'
-import { BrowseLabware } from './DeckSetup/LabwareOverlays/BrowseLabware'
-import { Slideout } from './Slideout'
-import { wellFillFromWellContents } from './labware'
-
-interface OffDeckLabwareSlideoutProps {
- initialSetupTerminalItemId: boolean
- isExpanded: boolean
- onCloseClick: () => void
-}
-
-export const OffDeckLabwareSlideout = (
- props: OffDeckLabwareSlideoutProps
-): JSX.Element => {
- const { t } = useTranslation(['deck', 'button', 'tooltip'])
- const [targetProps, tooltipProps] = useHoverTooltip()
- const dispatch = useDispatch()
- const disabled = props.initialSetupTerminalItemId === false
- const robotState = useSelector(getRobotStateAtActiveItem)
- const labwareEntities = useSelector(getLabwareEntities)
- const allWellContentsForActiveItem = useSelector(
- getAllWellContentsForActiveItem
- )
- const liquidDisplayColors = useSelector(selectors.getLiquidDisplayColors)
- const labwareNickNames = useSelector(getLabwareNicknamesById)
-
- const offDeckEntries =
- robotState?.labware != null
- ? Object.entries(robotState?.labware).filter(
- ([key, value]) => value.slot === 'offDeck'
- )
- : null
- const offDeck =
- offDeckEntries != null && offDeckEntries.length > 0
- ? Object.fromEntries(offDeckEntries)
- : null
-
- return (
-
- dispatch(openAddLabwareModal({ slot: 'offDeck' }))}
- marginTop={SPACING.spacing16}
- marginRight={SPACING.spacing16}
- disabled={disabled}
- >
- {t('button:add_off_deck')}
-
- {disabled ? (
-
- {t(`tooltip:disabled_off_deck`)}
-
- ) : null}
-
- }
- >
- {offDeck == null ? (
-