Skip to content

Commit

Permalink
feat(protocol-designer): Add missing labware hint to magnet step (#4592)
Browse files Browse the repository at this point in the history
closes #4303
  • Loading branch information
Kadee80 authored Dec 18, 2019
1 parent 09c7be6 commit a947a14
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 18 deletions.
6 changes: 6 additions & 0 deletions protocol-designer/src/components/Hints/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ class Hints extends React.Component<Props, State> {
<p>{i18n.t(`alert.hint.${hintKey}.body3`)}</p>
</>
)
case 'module_without_labware':
return (
<>
<p>{i18n.t(`alert.hint.${hintKey}.body`)}</p>
</>
)
default:
return null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,8 @@
.temperature_form_group {
margin: 1rem 0;
}

.module_labware_text {
font-size: var(--fs-body-1);
margin-top: 0.5rem;
}
14 changes: 14 additions & 0 deletions protocol-designer/src/components/StepEditForm/forms/MagnetForm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// @flow
import * as React from 'react'
import { useSelector } from 'react-redux'
import { selectors as uiModuleSelectors } from '../../../ui/modules'
import { FormGroup } from '@opentrons/components'
import i18n from '../../../localization'

Expand All @@ -11,6 +13,12 @@ import type { FocusHandlers } from '../types'
type MagnetFormProps = { focusHandlers: FocusHandlers }
function MagnetForm(props: MagnetFormProps): React.Element<'div'> {
const { focusHandlers } = props
const moduleLabwareOptions = useSelector(
uiModuleSelectors.getMagneticLabwareOptions
)
const moduleOption: ?string = moduleLabwareOptions[0]
? moduleLabwareOptions[0].name
: 'No magnetic module'

return (
<div className={styles.form_wrapper}>
Expand All @@ -21,6 +29,12 @@ function MagnetForm(props: MagnetFormProps): React.Element<'div'> {
</div>

<div className={styles.magnet_section_wrapper}>
<FormGroup
label={i18n.t('form.step_edit_form.field.moduleActionLabware.label')}
className={styles.magnet_form_group}
>
<p className={styles.module_labware_text}>{moduleOption}</p>
</FormGroup>
<FormGroup
label={i18n.t('form.step_edit_form.field.magnetAction.label')}
className={styles.magnet_form_group}
Expand Down
4 changes: 4 additions & 0 deletions protocol-designer/src/localization/en/alert.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
"custom_labware_with_modules": {
"title": "Cannot verify compatibility of custom labware",
"body": "The Protocol Designer cannot confirm whether or not custom labware is compatible with any module. Proceed if you are confident your custom labware will fit."
},
"module_without_labware": {
"title": "Your module has no labware",
"body": "Oops! It looks like your module is missing labware! Final copy TBD."
}
},
"timeline": {
Expand Down
2 changes: 1 addition & 1 deletion protocol-designer/src/localization/en/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"pipette": { "label": "pipette" },
"preWetTip": { "label": "pre-wet tip" },
"touchTip": { "label": "touch tip" },
"moduleActionLabware": { "label": "labware" },
"moduleActionLabware": { "label": "module" },
"moduleLabwarePrefix": {
"magdeck": "MAG",
"tempdeck": "TEMP",
Expand Down
1 change: 1 addition & 0 deletions protocol-designer/src/tutorial/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type HintKey =
// normal hints
| 'add_liquids_and_labware'
| 'deck_setup_explanation'
| 'module_without_labware'
// blocking hints
| 'custom_labware_with_modules'

Expand Down
3 changes: 2 additions & 1 deletion protocol-designer/src/ui/labware/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
getLabwareDisplayName,
getLabwareHasQuirk,
} from '@opentrons/shared-data'
import { selectors as stepFormSelectors } from '../../step-forms'
import * as stepFormSelectors from '../../step-forms/selectors'

import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'

import type { Options } from '@opentrons/components'
Expand Down
20 changes: 14 additions & 6 deletions protocol-designer/src/ui/modules/selectors.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// @flow
import { createSelector } from 'reselect'

import { selectors as stepFormSelectors } from '../../step-forms'
import { selectors as uiLabwareSelectors } from '../labware'
import { getModuleLabwareOptions } from './utils'
import * as stepFormSelectors from '../../step-forms/selectors'
import { getLabwareNicknamesById } from '../labware/selectors'
import { getModuleLabwareOptions, getModuleHasLabware } from './utils'
import type { Options } from '@opentrons/components'
import type { Selector } from '../../types'

/** Returns dropdown option for labware placed on magnetic module */
export const getMagneticLabwareOptions: Selector<Options> = createSelector(
stepFormSelectors.getInitialDeckSetup,
uiLabwareSelectors.getLabwareNicknamesById,
getLabwareNicknamesById,
(initialDeckSetup, nicknamesById) => {
return getModuleLabwareOptions(initialDeckSetup, nicknamesById, 'magdeck')
}
Expand All @@ -19,7 +19,7 @@ export const getMagneticLabwareOptions: Selector<Options> = createSelector(
/** Returns dropdown option for labware placed on temperature module */
export const getTemperatureLabwareOptions: Selector<Options> = createSelector(
stepFormSelectors.getInitialDeckSetup,
uiLabwareSelectors.getLabwareNicknamesById,
getLabwareNicknamesById,
(initialDeckSetup, nicknamesById) => {
return getModuleLabwareOptions(initialDeckSetup, nicknamesById, 'tempdeck')
}
Expand All @@ -28,7 +28,7 @@ export const getTemperatureLabwareOptions: Selector<Options> = createSelector(
/** Returns dropdown option for labware placed on thermocycler module */
export const getThermocyclerLabwareOptions: Selector<Options> = createSelector(
stepFormSelectors.getInitialDeckSetup,
uiLabwareSelectors.getLabwareNicknamesById,
getLabwareNicknamesById,
(initialDeckSetup, nicknamesById) => {
return getModuleLabwareOptions(
initialDeckSetup,
Expand All @@ -37,3 +37,11 @@ export const getThermocyclerLabwareOptions: Selector<Options> = createSelector(
)
}
)

/** Returns boolean if magnetic module has labware */
export const getMagnetModuleHasLabware: Selector<boolean> = createSelector(
stepFormSelectors.getInitialDeckSetup,
initialDeckSetup => {
return getModuleHasLabware(initialDeckSetup, 'magdeck')
}
)
37 changes: 28 additions & 9 deletions protocol-designer/src/ui/modules/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,33 @@ export function getModuleLabwareOptions(
const module = getModuleOnDeckByType(initialDeckSetup, type)
const labware = module && getLabwareOnModule(initialDeckSetup, module.id)
const prefix = i18n.t(`form.step_edit_form.field.moduleLabwarePrefix.${type}`)
const options =
module && labware
? [
{
name: `${prefix} ${nicknamesById[labware.id]}`,
value: module.id,
},
]
: []
let options = []
if (module) {
if (labware) {
options = [
{
name: `${prefix} ${nicknamesById[labware.id]}`,
value: module.id,
},
]
} else {
options = [
{
name: `${prefix} No labware on module`,
value: module.id,
},
]
}
}

return options
}

export function getModuleHasLabware(
initialDeckSetup: InitialDeckSetup,
type: ModuleType
): boolean {
const module = getModuleOnDeckByType(initialDeckSetup, type)
const labware = module && getLabwareOnModule(initialDeckSetup, module.id)
return Boolean(module) && Boolean(labware)
}
21 changes: 20 additions & 1 deletion protocol-designer/src/ui/steps/actions/thunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { selectors as labwareIngredsSelectors } from '../../../labware-ingred/se
import stepsSelectors from '../selectors'
import { selectStep } from './actions'
import { actions as tutorialActions } from '../../../tutorial'
import type { DuplicateStepAction, ReorderSelectedStepAction } from './types'

import * as uiModuleSelectors from '../../../ui/modules/selectors'
import type { DuplicateStepAction } from './types'

import type { StepType, StepIdType } from '../../../form-types'
import type { GetState, ThunkDispatch } from '../../../types'

Expand All @@ -24,14 +27,30 @@ export const addStep = (payload: { stepType: StepType }) => (
},
})
const deckHasLiquid = labwareIngredsSelectors.getDeckHasLiquid(state)
const magnetModuleHasLabware = uiModuleSelectors.getMagnetModuleHasLabware(
state
)

// TODO: Ian 2019-01-17 move out to centralized step info file - see #2926
const stepNeedsLiquid = ['mix', 'moveLiquid'].includes(payload.stepType)
const stepMagnetNeedsLabware = ['magnet'].includes(payload.stepType)
if (stepNeedsLiquid && !deckHasLiquid) {
dispatch(tutorialActions.addHint('add_liquids_and_labware'))
}
if (stepMagnetNeedsLabware && !magnetModuleHasLabware) {
dispatch(tutorialActions.addHint('module_without_labware'))
}
dispatch(selectStep(stepId, stepType))
}

export type ReorderSelectedStepAction = {
type: 'REORDER_SELECTED_STEP',
payload: {
delta: number,
stepId: StepIdType,
},
}

export const reorderSelectedStep = (delta: number) => (
dispatch: ThunkDispatch<ReorderSelectedStepAction>,
getState: GetState
Expand Down

0 comments on commit a947a14

Please sign in to comment.