Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol-designer): update React DnD from version 6.0.0 to 16.0.1 #14485

Merged
merged 17 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import type { DeckDefinition, DeckSlot } from '@opentrons/shared-data'

export interface RobotCoordinateSpaceWithDOMCoordsRenderProps {
deckSlotsById: { [slotId: string]: DeckSlot }
getRobotCoordsFromDOMCoords: (
domX: number,
domY: number
) => { x: number; y: number }
}

interface RobotCoordinateSpaceWithDOMCoordsProps
Expand All @@ -19,25 +15,12 @@ interface RobotCoordinateSpaceWithDOMCoordsProps
) => React.ReactNode
}

type GetRobotCoordsFromDOMCoords = RobotCoordinateSpaceWithDOMCoordsRenderProps['getRobotCoordsFromDOMCoords']

export function RobotCoordinateSpaceWithDOMCoords(
props: RobotCoordinateSpaceWithDOMCoordsProps
): JSX.Element | null {
const { children, deckDef, viewBox, ...restProps } = props
const wrapperRef = React.useRef<SVGSVGElement>(null)
const getRobotCoordsFromDOMCoords: GetRobotCoordsFromDOMCoords = (x, y) => {
if (wrapperRef.current == null) return { x: 0, y: 0 }

const cursorPoint = wrapperRef.current.createSVGPoint()

cursorPoint.x = x
cursorPoint.y = y

return cursorPoint.matrixTransform(
wrapperRef.current.getScreenCTM()?.inverse()
)
}
if (deckDef == null && viewBox == null) return null

let wholeDeckViewBox
Expand All @@ -59,7 +42,7 @@ export function RobotCoordinateSpaceWithDOMCoords(
transform="scale(1, -1)"
{...restProps}
>
{children?.({ deckSlotsById, getRobotCoordsFromDOMCoords })}
{children?.({ deckSlotsById })}
</Svg>
)
}
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-html5-backend": "16.0.1",
"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
Expand Up @@ -35,6 +35,7 @@ export function LabwareOnDeck(props: LabwareOnDeckProps): JSX.Element {
const missingTips = missingTipsByLabwareId
? missingTipsByLabwareId[labwareOnDeck.id]
: null

return (
<g transform={`translate(${x}, ${y})`} className={className}>
<LabwareRender
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,108 @@
moveDeckItem,
openAddLabwareModal,
} from '../../../labware-ingred/actions'
import {
LabwareDefByDefURI,
selectors as labwareDefSelectors,
} from '../../../labware-defs'
import { getDeckSetupForActiveItem } from '../../../top-selectors/labware-locations'
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 = (

Check warning on line 43 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L43

Added line #L43 was not covered by tests
props: AdapterControlsProps
): JSX.Element | null => {
const {
slotPosition,
slotBoundingBox,
addLabware,
selectedTerminalItemId,
isOver,
connectDropTarget,
draggedItem,
itemType,
deleteLabware,
labwareId,
customLabwareDefs,
onDeck,
handleDragHover,
allLabware,
} = props
const customLabwareDefs = useSelector(

Check warning on line 55 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L55

Added line #L55 was not covered by tests
labwareDefSelectors.getCustomLabwareDefsByURI
)
const activeDeckSetup = useSelector(getDeckSetupForActiveItem)
const labware = activeDeckSetup.labware
const ref = React.useRef(null)
const [newSlot, setSlot] = React.useState<string | null>(null)
const dispatch = useDispatch()

Check warning on line 62 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L58-L62

Added lines #L58 - L62 were not covered by tests

const adapterName =
allLabware.find(labware => labware.id === labwareId)?.def.metadata
.displayName ?? ''

const [{ itemType, draggedItem, isOver }, drop] = useDrop({

Check warning on line 68 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L68

Added line #L68 was not covered by tests
accept: DND_TYPES.LABWARE,
canDrop: (item: DroppedItem) => {
const draggedDef = item.labwareOnDeck?.def
assert(draggedDef, 'no labware def of dragged item, expected it on drop')

Check warning on line 72 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L71-L72

Added lines #L71 - L72 were not covered by tests

if (draggedDef != null) {
const isCustomLabware = getLabwareIsCustom(

Check warning on line 75 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L75

Added line #L75 was not covered by tests
customLabwareDefs,
item.labwareOnDeck
)
return (

Check warning on line 79 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L79

Added line #L79 was not covered by tests
getAdapterLabwareIsAMatch(
labwareId,
allLabware,
draggedDef.parameters.loadName
) || isCustomLabware
)
}
return true

Check warning on line 87 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L87

Added line #L87 was not covered by tests
},
drop: (item: DroppedItem) => {
const droppedLabware = item

Check warning on line 90 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L90

Added line #L90 was not covered by tests
if (newSlot != null) {
dispatch(moveDeckItem(newSlot, labwareId))

Check warning on line 92 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L92

Added line #L92 was not covered by tests
Comment on lines +91 to +92
Copy link
Collaborator Author

@jerader jerader Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the reason why i am checking for newSlot here (also in SlotControls) is because I can't get item from useDrag to update to the latest state. If you drag and drop the labware initially, it doesn't update to the new slot in item - this was causing a bug where you could only drag and drop the labware once. I tried to find documentation about how to fix this but i couldn't find anything so this was my workaround. Any refactor suggestions are welcome!

} else if (droppedLabware.labwareOnDeck != null) {
const droppedSlot = droppedLabware.labwareOnDeck.slot
dispatch(moveDeckItem(droppedSlot, labwareId))

Check warning on line 95 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L94-L95

Added lines #L94 - L95 were not covered by tests
}
},
hover: () => {
if (handleDragHover) {
handleDragHover()

Check warning on line 100 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L100

Added line #L100 was not covered by tests
}
},
collect: (monitor: DropTargetMonitor) => ({

Check warning on line 103 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L103

Added line #L103 was not covered by tests
itemType: monitor.getItemType(),
isOver: !!monitor.isOver(),
draggedItem: monitor.getItem() as DroppedItem,
}),
})

const draggedLabware = Object.values(labware).find(
l => l.id === draggedItem?.labwareOnDeck?.id

Check warning on line 111 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L110-L111

Added lines #L110 - L111 were not covered by tests
)

React.useEffect(() => {

Check warning on line 114 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L114

Added line #L114 was not covered by tests
if (draggedLabware != null) {
setSlot(draggedLabware.slot)

Check warning on line 116 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L116

Added line #L116 was not covered by tests
}
})

if (
selectedTerminalItemId !== START_TERMINAL_ITEM_ID ||
(itemType !== DND_TYPES.LABWARE && itemType !== null)
Expand All @@ -101,8 +143,10 @@
slotBlocked = 'Labware incompatible with this adapter'
}

return connectDropTarget(
<g>
drop(ref)

Check warning on line 146 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L146

Added line #L146 was not covered by tests

return (

Check warning on line 148 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L148

Added line #L148 was not covered by tests
<g ref={ref}>
{slotBlocked ? (
<BlockedSlot
x={slotPosition[0]}
Expand All @@ -124,11 +168,21 @@
onClick: isOver ? noop : undefined,
}}
>
<a className={styles.overlay_button} onClick={addLabware}>
<a
className={styles.overlay_button}
onClick={() => dispatch(openAddLabwareModal({ slot: labwareId }))}

Check warning on line 173 in protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/LabwareOverlays/AdapterControls.tsx#L173

Added line #L173 was not covered by tests
>
{!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 +191,3 @@
</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)
)

This file was deleted.

This file was deleted.

Loading
Loading