Skip to content

Commit

Permalink
refactor a bunch of components
Browse files Browse the repository at this point in the history
  • Loading branch information
jerader committed Feb 13, 2024
1 parent c142da1 commit 2018908
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 641 deletions.
4 changes: 2 additions & 2 deletions protocol-designer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"query-string": "6.2.0",
"react": "18.2.0",
"react-color": "2.19.3",
"react-dnd": "6.0.0",
"react-dnd-mouse-backend": "0.1.2",
"react-dnd": "16.0.1",
"react-dnd-mouse-backend": "1.0.0-rc.2",
"react-dom": "18.2.0",
"react-hook-form": "7.49.3",
"react-i18next": "14.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import assert from 'assert'
import * as React from 'react'
import { DropTarget, DropTargetConnector, DropTargetMonitor } from 'react-dnd'
import { useDispatch, useSelector } from 'react-redux'
import { DropTargetMonitor, useDrop } from 'react-dnd'
import cx from 'classnames'
import { connect } from 'react-redux'
import noop from 'lodash/noop'
import { Icon, RobotCoordsForeignDiv } from '@opentrons/components'
import { DND_TYPES } from '../../../constants'
Expand All @@ -15,66 +15,89 @@ import {
moveDeckItem,
openAddLabwareModal,
} from '../../../labware-ingred/actions'
import {
LabwareDefByDefURI,
selectors as labwareDefSelectors,
} from '../../../labware-defs'
import { selectors as labwareDefSelectors } from '../../../labware-defs'
import { START_TERMINAL_ITEM_ID, TerminalItemId } from '../../../steplist'
import { BlockedSlot } from './BlockedSlot'

import type { CoordinateTuple, Dimensions } from '@opentrons/shared-data'
import type { BaseState, DeckSlot, ThunkDispatch } from '../../../types'
import type { LabwareOnDeck } from '../../../step-forms'

import styles from './LabwareOverlays.css'

interface DNDP {
isOver: boolean
connectDropTarget: (val: React.ReactNode) => JSX.Element
draggedItem: { labwareOnDeck: LabwareOnDeck } | null
itemType: string
}

interface OP {
interface AdapterControlsProps {
slotPosition: CoordinateTuple
slotBoundingBox: Dimensions
// labwareId is the adapter's labwareId
labwareId: string
allLabware: LabwareOnDeck[]
onDeck: boolean
selectedTerminalItemId?: TerminalItemId | null
handleDragHover?: () => unknown
}
interface DP {
addLabware: (e: React.MouseEvent<any>) => unknown
moveDeckItem: (item1: DeckSlot, item2: DeckSlot) => unknown
deleteLabware: () => void
handleDragHover?: () => void
}

interface SP {
customLabwareDefs: LabwareDefByDefURI
interface DroppedItem {
labwareOnDeck: LabwareOnDeck
}

export type SlotControlsProps = OP & DP & DNDP & SP

export const AdapterControlsComponents = (
props: SlotControlsProps
export const AdapterControls = (
props: AdapterControlsProps
): JSX.Element | null => {
const {
slotPosition,
slotBoundingBox,
addLabware,
selectedTerminalItemId,
isOver,
connectDropTarget,
draggedItem,
itemType,
deleteLabware,
labwareId,
customLabwareDefs,
onDeck,
handleDragHover,
allLabware,
} = props
const customLabwareDefs = useSelector(
labwareDefSelectors.getCustomLabwareDefsByURI
)

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
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) => {
if (item.labwareOnDeck) {
dispatch(moveDeckItem(item.labwareOnDeck.slot, labwareId))
}
},
hover: () => {
if (handleDragHover) {
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)
Expand All @@ -101,8 +124,8 @@ export const AdapterControlsComponents = (
slotBlocked = 'Labware incompatible with this adapter'
}

return connectDropTarget(
<g>
return (
<g ref={drop}>
{slotBlocked ? (
<BlockedSlot
x={slotPosition[0]}
Expand All @@ -124,11 +147,21 @@ export const AdapterControlsComponents = (
onClick: isOver ? noop : undefined,
}}
>
<a className={styles.overlay_button} onClick={addLabware}>
<a
className={styles.overlay_button}
onClick={() => dispatch(openAddLabwareModal({ slot: labwareId }))}
>
{!isOver && <Icon className={styles.overlay_icon} name="plus" />}
{isOver ? 'Place Here' : 'Add Labware'}
</a>
<a className={styles.overlay_button} onClick={deleteLabware}>
<a
className={styles.overlay_button}
onClick={() => {
window.confirm(
`"Are you sure you want to remove this ${adapterName}?`
) && dispatch(deleteContainer({ labwareId: labwareId }))
}}
>
{!isOver && <Icon className={styles.overlay_icon} name="close" />}
{'Delete'}
</a>
Expand All @@ -137,80 +170,3 @@ export const AdapterControlsComponents = (
</g>
)
}

const mapStateToProps = (state: BaseState): SP => {
return {
customLabwareDefs: labwareDefSelectors.getCustomLabwareDefsByURI(state),
}
}

const mapDispatchToProps = (dispatch: ThunkDispatch<any>, ownProps: OP): DP => {
const adapterName =
ownProps.allLabware.find(labware => labware.id === ownProps.labwareId)?.def
.metadata.displayName ?? ''
return {
addLabware: () =>
dispatch(openAddLabwareModal({ slot: ownProps.labwareId })),
moveDeckItem: (sourceSlot, destSlot) =>
dispatch(moveDeckItem(sourceSlot, destSlot)),
deleteLabware: () => {
window.confirm(`"Are you sure you want to remove this ${adapterName}?`) &&
dispatch(deleteContainer({ labwareId: ownProps.labwareId }))
},
}
}

const slotTarget = {
drop: (props: SlotControlsProps, monitor: DropTargetMonitor) => {
const draggedItem = monitor.getItem()
if (draggedItem) {
props.moveDeckItem(draggedItem.labwareOnDeck.slot, props.labwareId)
}
},
hover: (props: SlotControlsProps) => {
if (props.handleDragHover) {
props.handleDragHover()
}
},
canDrop: (props: SlotControlsProps, monitor: DropTargetMonitor) => {
const draggedItem = monitor.getItem()
const draggedDef = draggedItem?.labwareOnDeck?.def
assert(draggedDef, 'no labware def of dragged item, expected it on drop')

if (draggedDef != null) {
const isCustomLabware = getLabwareIsCustom(
props.customLabwareDefs,
draggedItem.labwareOnDeck
)
return (
getAdapterLabwareIsAMatch(
props.labwareId,
props.allLabware,
draggedDef.parameters.loadName
) || isCustomLabware
)
}
return true
},
}
const collectSlotTarget = (
connect: DropTargetConnector,
monitor: DropTargetMonitor
): React.ReactNode => ({
// @ts-expect-error(BC, 12-13-2023): react dnd needs to be updated or removed to include proper type
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
draggedItem: monitor.getItem(),
itemType: monitor.getItemType(),
})

export const AdapterControls = connect(
mapStateToProps,
mapDispatchToProps
)(
DropTarget(
DND_TYPES.LABWARE,
slotTarget,
collectSlotTarget
)(AdapterControlsComponents)
)
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import * as React from 'react'
import { DragLayer } from 'react-dnd'
import { useDragLayer, XYCoord } from 'react-dnd'
import { LabwareOnDeck } from '../LabwareOnDeck'
import { DND_TYPES } from '../../../constants'
import { LabwareOnDeck as LabwareOnDeckType } from '../../../step-forms'
import { RobotWorkSpaceRenderProps } from '@opentrons/components'
import styles from './DragPreview.css'

interface DragPreviewProps {
isDragging: boolean
currentOffset?: { x: number; y: number }
item: { labwareOnDeck: LabwareOnDeckType }
itemType: string
getRobotCoordsFromDOMCoords: RobotWorkSpaceRenderProps['getRobotCoordsFromDOMCoords']
}

const LabwareDragPreview = (props: DragPreviewProps): JSX.Element | null => {
const {
item,
itemType,
isDragging,
currentOffset,
getRobotCoordsFromDOMCoords,
} = props
if (itemType !== DND_TYPES.LABWARE || !isDragging || !currentOffset)
export const DragPreview = (props: DragPreviewProps): JSX.Element | null => {
const { getRobotCoordsFromDOMCoords } = props
const { item, itemType, isDragging, currentOffset } = useDragLayer(
monitor => ({
item: monitor.getItem(),
itemType: monitor.getItemType(),
isDragging: monitor.isDragging(),
currentOffset: monitor.getSourceClientOffset(),
})
)

if (!isDragging || !currentOffset || itemType !== DND_TYPES.LABWARE) {
return null
const { x, y } = currentOffset
}

const cursor = getRobotCoordsFromDOMCoords(x, y)
const { x, y } = currentOffset
const cursor: XYCoord = getRobotCoordsFromDOMCoords(x, y)

return (
<LabwareOnDeck
Expand All @@ -37,12 +36,3 @@ const LabwareDragPreview = (props: DragPreviewProps): JSX.Element | null => {
/>
)
}

export const DragPreview = DragLayer<
Omit<DragPreviewProps, 'currentOffset' | 'isDragging' | 'itemType' | 'item'>
>(monitor => ({
currentOffset: monitor.getSourceClientOffset(),
isDragging: monitor.isDragging(),
itemType: monitor.getItemType(),
item: monitor.getItem(),
}))(LabwareDragPreview)
Loading

0 comments on commit 2018908

Please sign in to comment.