Skip to content

Commit

Permalink
fix(app): flip modules on deck map when in slots 3, 6, or 9 (#6383)
Browse files Browse the repository at this point in the history
This patches a visual bug that rendered modules in slots 3, 6, and 9 with their plugs towards the
center of the deck. This doesn't match the physical arrangement and occludes other information in
the visualization. Any module in those right-most slots will now render in the correct orientation.

Closes #4422
  • Loading branch information
b-cooper authored Aug 20, 2020
1 parent 973ee18 commit d0347da
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 31 deletions.
1 change: 1 addition & 0 deletions app/src/components/DeckMap/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ function DeckMapComponent(props: Props) {
<ModuleItem
model={moduleInSlot.model}
mode={moduleInSlot.mode || 'default'}
slot={slot}
/>
</g>
)}
Expand Down
8 changes: 8 additions & 0 deletions components/src/deck/Module.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,11 @@
font-weight: var(--fw-semibold);
text-transform: uppercase;
}

.flipped {
transform: rotate(180deg);
}

.right_icon {
margin: 0 0 0 1rem;
}
59 changes: 33 additions & 26 deletions components/src/deck/Module.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,37 @@ import cx from 'classnames'
import {
getModuleDisplayName,
type ModuleModel,
type DeckSlot,
MAGNETIC_MODULE_V1,
MAGNETIC_MODULE_V2,
TEMPERATURE_MODULE_V1,
TEMPERATURE_MODULE_V2,
THERMOCYCLER_MODULE_V1,
} from '@opentrons/shared-data'
import { getDeckDefinitions } from '@opentrons/components/src/deck/getDeckDefinitions'

import { Icon } from '../icons'
import { RobotCoordsForeignDiv } from './RobotCoordsForeignDiv'
import styles from './Module.css'

const FLIPPED_SLOTS = ['3', '6', '9']
export type ModuleProps = {|
/** module model */
model: ModuleModel,
/** display mode: 'default', 'present', 'missing', or 'info' */
mode: 'default' | 'present' | 'missing' | 'info',
/** slot details of the location of this module */
slot: DeckSlot,
|}

export function Module(props: ModuleProps): React.Node {
// TODO: BC 2019-7-23 get these from shared data, once absolute
// dimensions are added to data
const deckDef = React.useMemo(() => getDeckDefinitions()['ot2_standard'], [])
const { model, slot } = props
let x = 0
let y = 0
let {
xDimension: width,
yDimension: height,
// TODO(mc, 2020-06-01): is optional chaining necessary here? If so, type defs need updateding
} = deckDef?.locations?.orderedSlots[0]?.boundingBox
let { xDimension: width, yDimension: height } = slot.boundingBox
const shouldFlip = FLIPPED_SLOTS.includes(slot.id)

switch (props.model) {
// TODO: BC 2019-7-23 get these from shared-data module defs, once available
switch (model) {
case MAGNETIC_MODULE_V1:
case MAGNETIC_MODULE_V2: {
width = 137
Expand Down Expand Up @@ -69,15 +68,20 @@ export function Module(props: ModuleProps): React.Node {
x={x}
y={y - height}
transformWithSVG
innerDivProps={{ className: styles.module }}
extraTransform={`rotate(${shouldFlip ? 180 : 0}, ${slot.boundingBox
.xDimension / 2}, ${slot.boundingBox.yDimension / -2})`}
innerDivProps={{
className: cx(styles.module, { [styles.flipped]: shouldFlip }),
}}
>
<ModuleItemContents {...props} />
<ModuleItemContents {...props} shouldFlip={shouldFlip} />
</RobotCoordsForeignDiv>
)
}

function ModuleItemContents(props: ModuleProps) {
const { mode, model } = props
type ModuleItemContentsProps = {| ...ModuleProps, shouldFlip: boolean |}
function ModuleItemContents(props: ModuleItemContentsProps) {
const { mode, model, shouldFlip } = props
const displayName = getModuleDisplayName(model)

const message =
Expand All @@ -103,6 +107,7 @@ function ModuleItemContents(props: ModuleProps) {
const iconClassName = cx(styles.module_review_icon, {
[styles.module_review_icon_missing]: mode === 'missing',
[styles.module_review_icon_present]: mode === 'present',
[styles.right_icon]: shouldFlip,
})

const iconNameByMode = {
Expand All @@ -112,16 +117,18 @@ function ModuleItemContents(props: ModuleProps) {
default: 'usb',
}

return (
<>
<Icon
className={iconClassName}
x="8"
y="0"
svgWidth="16"
name={iconNameByMode[mode] || 'usb'}
/>
<div className={styles.module_text_wrapper}>{message}</div>
</>
)
const contents = [
<Icon
key="icon"
className={iconClassName}
x="8"
y="0"
svgWidth="16"
name={iconNameByMode[mode] || 'usb'}
/>,
<div key="label" className={styles.module_text_wrapper}>
{message}
</div>,
]
return <>{shouldFlip ? contents.reverse() : contents}</>
}
9 changes: 5 additions & 4 deletions components/src/deck/RobotCoordsForeignDiv.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type RobotCoordsForeignDivProps = {|
className?: string,
innerDivProps?: React.ElementProps<'div'>,
transformWithSVG?: boolean,
extraTransform?: string,
|}

export const RobotCoordsForeignDiv = (
Expand All @@ -24,18 +25,18 @@ export const RobotCoordsForeignDiv = (
className,
innerDivProps,
transformWithSVG = false,
extraTransform = '',
} = props

const transform = `scale(1, -1) ${extraTransform}`
return (
<foreignObject
{...{ x, y, height, width, className }}
transform={transformWithSVG ? 'scale(1, -1)' : null}
transform={transformWithSVG ? transform : extraTransform}
>
<div
{...innerDivProps}
style={{
transform: transformWithSVG ? 'none' : 'scale(1, -1)',
}}
style={transformWithSVG ? {} : { transform }}
xmlns="http://www.w3.org/1999/xhtml"
>
{children}
Expand Down
2 changes: 1 addition & 1 deletion protocol-library-kludge/src/URLDeck.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class URLDeck extends React.Component<{||}> {
slot.position[1]
})`}
>
<Module model={moduleModel} mode={'default'} />
<Module model={moduleModel} mode={'default'} slot={slot} />
</g>
)}
{labware && (
Expand Down

0 comments on commit d0347da

Please sign in to comment.