Skip to content

Commit

Permalink
feat(protocol-designer): allow custom labware on modules on deck
Browse files Browse the repository at this point in the history
closes #4910
  • Loading branch information
Jenny committed Mar 9, 2020
1 parent ec1f8b8 commit 7f84cc3
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
20 changes: 17 additions & 3 deletions protocol-designer/src/components/DeckSetup/DeckSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
inferModuleOrientationFromSlot,
} from './getModuleVizDims'

import { selectors as labwareDefSelectors } from '../../labware-defs'
import { selectors as featureFlagSelectors } from '../../feature-flags'
import { getSlotsBlockedBySpanning, getSlotIsEmpty } from '../../step-forms'
import { BrowseLabwareModal } from '../labware'
Expand All @@ -36,6 +37,7 @@ import type {
LabwareOnDeck as LabwareOnDeckType,
ModuleOnDeck,
} from '../../step-forms'
import type { LabwareDefByDefURI } from '../../labware-defs'

import styles from './DeckSetup.css'

Expand Down Expand Up @@ -106,8 +108,9 @@ const getSwapBlocked = (args: {
hoveredLabware: ?LabwareOnDeckType,
draggedLabware: ?LabwareOnDeckType,
modulesById: $PropertyType<InitialDeckSetup, 'modules'>,
customLabwares: LabwareDefByDefURI,
}): boolean => {
const { hoveredLabware, draggedLabware, modulesById } = args
const { hoveredLabware, draggedLabware, modulesById, customLabwares } = args

if (!hoveredLabware || !draggedLabware) {
return false
Expand All @@ -118,11 +121,16 @@ const getSwapBlocked = (args: {
const destModuleType: ?ModuleRealType =
modulesById[hoveredLabware.slot]?.type || null

const draggedLabwareIsCustom = customLabwares[draggedLabware.labwareDefURI]
const hoveredLabwareIsCustom = customLabwares[hoveredLabware.labwareDefURI]
// dragging custom labware to module gives not compat error
const labwareSourceToDestBlocked = sourceModuleType
? !getLabwareIsCompatible(hoveredLabware.def, sourceModuleType)
? !getLabwareIsCompatible(hoveredLabware.def, sourceModuleType) &&
!hoveredLabwareIsCustom
: false
const labwareDestToSourceBlocked = destModuleType
? !getLabwareIsCompatible(draggedLabware.def, destModuleType)
? !getLabwareIsCompatible(draggedLabware.def, destModuleType) &&
!draggedLabwareIsCustom
: false

return labwareSourceToDestBlocked || labwareDestToSourceBlocked
Expand All @@ -145,12 +153,18 @@ const DeckSetupContents = (props: ContentsProps) => {
// 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] = useState<?LabwareOnDeckType>(null)
const [draggedLabware, setDraggedLabware] = useState<?LabwareOnDeckType>(null)

const customLabwares = useSelector(
labwareDefSelectors.getCustomLabwareDefsByURI
)
const swapBlocked = getSwapBlocked({
hoveredLabware,
draggedLabware,
modulesById: initialDeckSetup.modules,
customLabwares,
})
const handleHoverEmptySlot = useCallback(() => setHoveredLabware(null), [])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ import {
import { START_TERMINAL_ITEM_ID, type TerminalItemId } from '../../../steplist'
import { DND_TYPES } from './constants'

import type { DeckSlot, ThunkDispatch } from '../../../types'
import { selectors as labwareDefSelectors } from '../../../labware-defs'

import type { DeckSlot, ThunkDispatch, BaseState } from '../../../types'
import type { LabwareDefByDefURI } from '../../../labware-defs'
import type { LabwareOnDeck } from '../../../step-forms'
import type {
DeckSlot as DeckSlotDefinition,
ModuleRealType,
LabwareDefinition2,
} from '@opentrons/shared-data'
import styles from './LabwareOverlays.css'

type DNDP = {|
isOver: boolean,
connectDropTarget: Node => mixed,
draggedDef: ?LabwareDefinition2,
draggedItem: ?{ labwareOnDeck: LabwareOnDeck },
|}
type OP = {|
slot: {| ...DeckSlotDefinition, id: DeckSlot |}, // NOTE: Ian 2019-10-22 make slot `id` more restrictive when used in PD
Expand All @@ -39,7 +42,10 @@ type DP = {|
addLabware: (e: SyntheticEvent<*>) => mixed,
moveDeckItem: (DeckSlot, DeckSlot) => mixed,
|}
type Props = {| ...OP, ...DP, ...DNDP |}
type SP = {|
customLabwares: LabwareDefByDefURI,
|}
type Props = {| ...OP, ...DP, ...DNDP, ...SP |}

const SlotControlsComponent = (props: Props) => {
const {
Expand All @@ -49,16 +55,21 @@ const SlotControlsComponent = (props: Props) => {
isOver,
connectDropTarget,
moduleType,
draggedDef,
draggedItem,
customLabwares,
} = props
if (selectedTerminalItemId !== START_TERMINAL_ITEM_ID) return null

const draggedDef = draggedItem?.labwareOnDeck?.def
const isCustomLabware =
draggedItem && customLabwares[draggedItem.labwareOnDeck.labwareDefURI]

let slotBlocked: string | null = null
if (
isOver &&
moduleType != null &&
draggedDef != null &&
!getLabwareIsCompatible(draggedDef, moduleType)
(!getLabwareIsCompatible(draggedDef, moduleType) && !isCustomLabware)
) {
slotBlocked = 'Labware incompatible with this module'
}
Expand Down Expand Up @@ -98,6 +109,12 @@ const SlotControlsComponent = (props: Props) => {
)
}

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

const mapDispatchToProps = (dispatch: ThunkDispatch<*>, ownProps: OP): DP => ({
addLabware: () => dispatch(openAddLabwareModal({ slot: ownProps.slot.id })),
moveDeckItem: (sourceSlot, destSlot) =>
Expand All @@ -124,19 +141,22 @@ const slotTarget = {

if (moduleType != null && draggedDef != null) {
// this is a module slot, prevent drop if the dragged labware is not compatible
return getLabwareIsCompatible(draggedDef, moduleType)
const isCustomLabware =
props.customLabwares[draggedItem.labwareOnDeck.labwareDefURI]

return getLabwareIsCompatible(draggedDef, moduleType) || isCustomLabware
}
return true
},
}
const collectSlotTarget = (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
draggedDef: monitor.getItem()?.labwareOnDeck?.def || null,
draggedItem: monitor.getItem(),
})

export const SlotControls = connect<{| ...OP, ...DP |}, OP, _, DP, _, _>(
null,
export const SlotControls = connect<{| ...OP, ...DP, ...SP |}, OP, _, DP, _, _>(
mapStateToProps,
mapDispatchToProps
)(
DropTarget(DND_TYPES.LABWARE, slotTarget, collectSlotTarget)(
Expand Down

0 comments on commit 7f84cc3

Please sign in to comment.