diff --git a/app/src/components/CalibrateLabware/ConfirmModal.js b/app/src/components/CalibrateLabware/ConfirmModal.js
index 85777271c90..6efb40130c5 100644
--- a/app/src/components/CalibrateLabware/ConfirmModal.js
+++ b/app/src/components/CalibrateLabware/ConfirmModal.js
@@ -12,7 +12,7 @@ import styles from './styles.css'
type Props = {
labware: Labware,
calibrateToBottom: boolean,
- onBackClick: () => void,
+ onBackClick: () => mixed,
}
export default function ConfirmModal (props: Props) {
diff --git a/app/src/components/ConnectModulesModal/Prompt.js b/app/src/components/ConnectModulesModal/Prompt.js
new file mode 100644
index 00000000000..882f513c05d
--- /dev/null
+++ b/app/src/components/ConnectModulesModal/Prompt.js
@@ -0,0 +1,48 @@
+// @flow
+// prompt for ReviewModulesModal of labware calibration page
+import * as React from 'react'
+
+import {OutlineButton, AlertItem} from '@opentrons/components'
+
+import styles from './styles.css'
+
+type Props = {
+ modulesMissing: boolean,
+ onClick: () => mixed,
+}
+
+const missingAlertProps = {
+ type: 'warning',
+ title: 'Module Missing',
+ className: styles.alert
+}
+
+const connectedAlertProps = {
+ type: 'success',
+ title: 'Module succesfully detected.',
+ className: styles.alert
+}
+
+export default function Prompt (props: Props) {
+ const {modulesMissing, onClick} = props
+ const alert = modulesMissing
+ ?
+ :
+ const message = modulesMissing
+ ? 'Plug in and power up the required module via USB to your robot.'
+ : 'Module succesfully detected.'
+ const buttonText = modulesMissing
+ ? 'try searching for missing module'
+ : 'continue to labware setup'
+ return (
+
+ {alert}
+
+ {message}
+
+
+ {buttonText}
+
+
+ )
+}
diff --git a/app/src/components/ConnectModulesModal/index.js b/app/src/components/ConnectModulesModal/index.js
new file mode 100644
index 00000000000..80db82c9003
--- /dev/null
+++ b/app/src/components/ConnectModulesModal/index.js
@@ -0,0 +1,17 @@
+// @flow
+import * as React from 'react'
+import {Modal} from '../modals'
+import Prompt from './Prompt'
+
+type Props = {
+ modulesMissing: boolean,
+ onClick: () => mixed,
+}
+
+export default function ConnectModulesModal (props: Props) {
+ return (
+
+
+
+ )
+}
diff --git a/app/src/components/ConnectModulesModal/styles.css b/app/src/components/ConnectModulesModal/styles.css
new file mode 100644
index 00000000000..aa8ebda7282
--- /dev/null
+++ b/app/src/components/ConnectModulesModal/styles.css
@@ -0,0 +1,28 @@
+@import '@opentrons/components';
+
+.alert {
+ position: absolute;
+ top: 3rem;
+ left: 0;
+ right: 0;
+}
+
+.prompt {
+ padding-top: 2rem;
+}
+
+.prompt_text {
+ @apply --font-header-light;
+
+ font-weight: normal;
+ margin-bottom: 1rem;
+ text-align: center;
+}
+
+.prompt_button {
+ display: block;
+ width: auto;
+ margin: 1rem auto;
+ padding-left: 3rem;
+ padding-right: 3rem;
+}
diff --git a/app/src/components/InstrumentSettings/AttachedModulesCard.js b/app/src/components/InstrumentSettings/AttachedModulesCard.js
index 9bdf432c772..467560b41af 100644
--- a/app/src/components/InstrumentSettings/AttachedModulesCard.js
+++ b/app/src/components/InstrumentSettings/AttachedModulesCard.js
@@ -16,7 +16,7 @@ type OP = Robot
type SP = {
modulesFlag: ?boolean,
- modules: Array,
+ modules: ?Array,
refreshing: boolean
}
@@ -26,24 +26,26 @@ type Props = OP & SP & DP
const TITLE = 'Modules'
-const STUBBED_MODULE_DATA = [
- {
- name: 'temp_deck',
- model: 'temp_deck',
- serial: '123123124',
- fwVersion: '1.2.13',
- status: '86',
- displayName: 'Temperature Module'
- },
- {
- name: 'mag_deck',
- model: 'mag_deck',
- serial: '123123124',
- fwVersion: '1.2.13',
- status: 'disengaged',
- displayName: 'Magnetic Bead Module'
- }
-]
+// TODO(mc, 2018-07-19): remove this testing code when API returns modules
+// const STUBBED_MODULE_DATA = [
+// {
+// name: 'tempdeck',
+// model: 'temp_deck',
+// serial: '123123124',
+// fwVersion: '1.2.13',
+// status: '86',
+// displayName: 'Temperature Module'
+// },
+// {
+// name: 'magdeck',
+// model: 'mag_deck',
+// serial: '123123124',
+// fwVersion: '1.2.13',
+// status: 'disengaged',
+// displayName: 'Magnetic Bead Module'
+// }
+// ]
+
export default connect(makeSTP, DTP)(AttachedModulesCard)
// TODO (ka 2018-6-29): change this to a refresh card once we have endpoints
@@ -74,7 +76,7 @@ function makeSTP (): (state: State, ownProps: OP) => SP {
return {
modulesFlag: getModulesOn(state),
- modules: modules || STUBBED_MODULE_DATA,
+ modules: modules /* || STUBBED_MODULE_DATA */,
refreshing: modulesCall.inProgress
}
}
diff --git a/app/src/components/InstrumentSettings/ModulesCardContents.js b/app/src/components/InstrumentSettings/ModulesCardContents.js
index c088ecd7a30..26f68046390 100644
--- a/app/src/components/InstrumentSettings/ModulesCardContents.js
+++ b/app/src/components/InstrumentSettings/ModulesCardContents.js
@@ -4,13 +4,11 @@ import type {Module} from '../../http-api-client'
import ModuleItem, {NoModulesMessage} from '../ModuleItem'
type Props = {
- modules: Array,
+ modules: ?Array,
}
export default function ModulesCardContents (props: Props) {
- const modulesFound = props.modules[0]
-
- if (!modulesFound) return ()
+ if (!props.modules || !props.modules[0]) return ()
return (
diff --git a/app/src/components/ReviewDeckModal/index.js b/app/src/components/ReviewDeckModal/index.js
index 9a954e08b26..36898c2e55b 100644
--- a/app/src/components/ReviewDeckModal/index.js
+++ b/app/src/components/ReviewDeckModal/index.js
@@ -11,7 +11,7 @@ import {
type Labware
} from '../../robot'
-import Modal from './Modal'
+import {Modal} from '../modals'
import Prompt from './Prompt'
import Deck from './Deck'
diff --git a/app/src/components/ReviewDeckModal/styles.css b/app/src/components/ReviewDeckModal/styles.css
index 5e0de7f504f..745b7a7dfbb 100644
--- a/app/src/components/ReviewDeckModal/styles.css
+++ b/app/src/components/ReviewDeckModal/styles.css
@@ -1,16 +1,5 @@
@import '@opentrons/components';
-.modal {
- @apply --modal;
-
- flex-direction: column;
- padding: 2rem;
-}
-
-.modal * {
- z-index: 1;
-}
-
.prompt {
max-width: 32rem;
margin: 0 0 0.5rem;
diff --git a/app/src/components/ReviewDeckModal/Modal.js b/app/src/components/modals/Modal.js
similarity index 59%
rename from app/src/components/ReviewDeckModal/Modal.js
rename to app/src/components/modals/Modal.js
index 4ef9706d0da..16fca6a3021 100644
--- a/app/src/components/ReviewDeckModal/Modal.js
+++ b/app/src/components/modals/Modal.js
@@ -2,7 +2,8 @@
// modal component for ReviewDeckModal of labware calibration page
import * as React from 'react'
-import {Overlay} from '@opentrons/components'
+import {Overlay, TitleBar} from '@opentrons/components'
+import SessionHeader from '../SessionHeader'
import styles from './styles.css'
@@ -10,10 +11,16 @@ type Props = {
children: React.Node
}
+const titleBarProps = {
+ title: (),
+ className: styles.title_bar
+}
+
export default function Modal (props: Props) {
return (
+
{props.children}
)
diff --git a/app/src/components/modals/index.js b/app/src/components/modals/index.js
index 44a8acddad3..e7fa0c06559 100644
--- a/app/src/components/modals/index.js
+++ b/app/src/components/modals/index.js
@@ -1,6 +1,6 @@
// @flow
// app specific modals
-
+import Modal from './Modal'
import ErrorModal from './ErrorModal'
-export {ErrorModal}
+export {Modal, ErrorModal}
diff --git a/app/src/components/modals/styles.css b/app/src/components/modals/styles.css
index 38fd84dc069..b5b95dfd68b 100644
--- a/app/src/components/modals/styles.css
+++ b/app/src/components/modals/styles.css
@@ -1,3 +1,24 @@
+@import '@opentrons/components';
+
+.modal {
+ @apply --modal;
+
+ flex-direction: column;
+ justify-content: flex-start;
+ padding: 4rem 2rem 2rem;
+}
+
+.modal * {
+ z-index: 1;
+}
+
.error_modal_message {
font-style: italic;
}
+
+.title_bar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+}
diff --git a/app/src/http-api-client/modules.js b/app/src/http-api-client/modules.js
index fe77ac8479c..7f50cfcb664 100644
--- a/app/src/http-api-client/modules.js
+++ b/app/src/http-api-client/modules.js
@@ -12,7 +12,7 @@ import {getRobotApiState} from './reducer'
import client from './client'
export type Module = {
- name: string,
+ name: 'magdeck' | 'tempdeck',
model: string,
serial: string,
fwVersion: string,
diff --git a/app/src/pages/Calibrate/Labware.js b/app/src/pages/Calibrate/Labware.js
index 17a06139a2d..7d224fcaaed 100644
--- a/app/src/pages/Calibrate/Labware.js
+++ b/app/src/pages/Calibrate/Labware.js
@@ -1,12 +1,17 @@
// @flow
-// setup instruments page
+// setup labware page
import * as React from 'react'
import {connect} from 'react-redux'
import {Route, Redirect, withRouter, type Match} from 'react-router'
import {push} from 'react-router-redux'
+import countBy from 'lodash/countBy'
+
import type {State, Dispatch} from '../../types'
-import type {Labware, Robot, StateModule} from '../../robot'
-import {selectors as robotSelectors} from '../../robot'
+import type {Labware, Robot, SessionModule} from '../../robot'
+import {
+ selectors as robotSelectors,
+ actions as robotActions
+} from '../../robot'
import {getModulesOn} from '../../config'
import type {Module} from '../../http-api-client'
import {makeGetRobotSettings, makeGetRobotModules, fetchModules} from '../../http-api-client'
@@ -15,7 +20,7 @@ import CalibrateLabware from '../../components/CalibrateLabware'
import SessionHeader from '../../components/SessionHeader'
import ReviewDeckModal from '../../components/ReviewDeckModal'
import ConfirmModal from '../../components/CalibrateLabware/ConfirmModal'
-
+import ConnectModulesModal from '../../components/ConnectModulesModal'
type OP = {
match: Match
}
@@ -24,19 +29,17 @@ type SP = {
deckPopulated: boolean,
labware: ?Labware,
calibrateToBottom: boolean,
- robot: Robot,
- modulesFlag: ?boolean,
- modules: Array,
- actualModules: ?Array,
+ _robot: ?Robot,
+ modulesMissing: boolean,
+ reviewModules: ?boolean,
}
-type DP = {
- dispatch: Dispatch
-}
+type DP = {dispatch: Dispatch}
type Props = SP & OP & {
- onBackClick: () => void,
+ onBackClick: () => mixed,
fetchModules: () => mixed,
+ onReviewPromptClick: () => mixed,
}
export default withRouter(connect(makeMapStateToProps, null, mergeProps)(SetupDeckPage))
@@ -46,8 +49,11 @@ function SetupDeckPage (props: Props) {
calibrateToBottom,
labware,
deckPopulated,
+ modulesMissing,
+ reviewModules,
onBackClick,
fetchModules,
+ onReviewPromptClick,
match: {url, params: {slot}}
} = props
@@ -60,7 +66,13 @@ function SetupDeckPage (props: Props) {
>
- {!deckPopulated && (
+ {reviewModules && (
+
+ )}
+ {(!deckPopulated && !reviewModules) && (
)}
{
@@ -87,7 +99,7 @@ function makeMapStateToProps (): (state: State, ownProps: OP) => SP {
const labware = robotSelectors.getLabware(state)
const currentLabware = labware.find((lw) => lw.slot === slot)
const name = robotSelectors.getConnectedRobotName(state)
- const robot = robotSelectors.getConnectedRobot(state)
+ const _robot = robotSelectors.getConnectedRobot(state)
const settingsResponse = getRobotSettings(state, {name}).response
const settings = settingsResponse && settingsResponse.settings
@@ -95,20 +107,26 @@ function makeMapStateToProps (): (state: State, ownProps: OP) => SP {
const calibrateToBottom = !!flag && flag.value
const modules = robotSelectors.getModules(state)
- const modulesCall = getRobotModules(state, robot)
- const modulesResponse = modulesCall.response
+
+ const modulesCall = _robot && getRobotModules(state, _robot)
+ const modulesResponse = modulesCall && modulesCall.response
const actualModules = modulesResponse && modulesResponse.modules
+ const modulesReviewed = robotSelectors.getModulesReviewed(state)
+ const modulesFlag = getModulesOn(state)
+ const modulesRequired = modules[0]
+
+ const reviewModules = modulesFlag && !modulesReviewed && !!modulesRequired
+
return {
- deckPopulated: !!robotSelectors.getDeckPopulated(state),
- labware: currentLabware,
slot,
url,
calibrateToBottom,
- robot,
- modulesFlag: getModulesOn(state),
- modules,
- actualModules
+ reviewModules,
+ _robot,
+ modulesMissing: checkModules(modules, actualModules),
+ deckPopulated: !!robotSelectors.getDeckPopulated(state),
+ labware: currentLabware
}
}
}
@@ -116,13 +134,29 @@ function makeMapStateToProps (): (state: State, ownProps: OP) => SP {
function mergeProps (stateProps: SP, dispatchProps: DP, ownProps: OP): Props {
const {match: {url}} = ownProps
const {dispatch} = dispatchProps
- const {robot} = stateProps
+ const {_robot, modulesMissing} = stateProps
+
+ const fetchMods = () => _robot && dispatch(fetchModules(_robot))
+ const onReviewPromptClick = modulesMissing
+ ? fetchMods
+ : () => dispatch(robotActions.setModulesReviewed(true))
+
return {
...stateProps,
...ownProps,
- onBackClick: () => { dispatch(push(url)) },
- fetchModules: () => {
- dispatch(fetchModules(robot))
- }
+ onReviewPromptClick,
+ fetchModules: fetchMods,
+ onBackClick: () => dispatch(push(url))
}
}
+
+function checkModules (
+ required: Array,
+ actual: ?Array
+): boolean {
+ const requiredNames = countBy(required, 'name')
+ const actualNames = countBy(actual, 'name')
+
+ return Object.keys(requiredNames)
+ .some(n => requiredNames[n] !== actualNames[n])
+}
diff --git a/app/src/pages/Calibrate/Pipettes.js b/app/src/pages/Calibrate/Pipettes.js
index 7fd3891fe8e..1bcb70940b5 100644
--- a/app/src/pages/Calibrate/Pipettes.js
+++ b/app/src/pages/Calibrate/Pipettes.js
@@ -19,18 +19,14 @@ import SessionHeader from '../../components/SessionHeader'
type SP = {
pipettes: Array,
currentPipette: ?Pipette,
- robot: Robot,
+ _robot: ?Robot,
}
type DP = {dispatch: Dispatch}
-type OP = {
- match: Match
-}
+type OP = {match: Match}
-type Props = SP & OP & {
- fetchPipettes: () => mixed
-}
+type Props = SP & OP & {fetchPipettes: () => mixed}
export default connect(makeMapStateToProps, null, mergeProps)(CalibratePipettesPage)
@@ -82,12 +78,12 @@ function makeMapStateToProps (): (State, OP) => SP {
return (state, props) => {
const name = robotSelectors.getConnectedRobotName(state)
- const robot = robotSelectors.getConnectedRobot(state)
+ const _robot = robotSelectors.getConnectedRobot(state)
const pipettesResponse = getAttachedPipettes(state, {name})
return {
name,
- robot,
+ _robot,
pipettes: robotSelectors.getPipettes(state),
currentPipette: getCurrentPipette(state, props),
actualPipettes: pipettesResponse.response
@@ -97,10 +93,11 @@ function makeMapStateToProps (): (State, OP) => SP {
function mergeProps (stateProps: SP, dispatchProps: DP, ownProps: OP): Props {
const {dispatch} = dispatchProps
- const {robot} = stateProps
+ const {_robot} = stateProps
+
return {
...stateProps,
...ownProps,
- fetchPipettes: () => { dispatch(fetchPipettes(robot)) }
+ fetchPipettes: () => _robot && dispatch(fetchPipettes(_robot))
}
}
diff --git a/app/src/robot/actions.js b/app/src/robot/actions.js
index 129c330a7c0..29ee8000a0a 100755
--- a/app/src/robot/actions.js
+++ b/app/src/robot/actions.js
@@ -168,6 +168,11 @@ export type CalibrationResponseAction =
| CalibrationSuccessAction
| CalibrationFailureAction
+export type SetModulesReviewedAction = {
+ type: 'robot:SET_MODULES_REVIEWED',
+ payload: boolean
+}
+
// TODO(mc, 2018-01-23): refactor to use type above
// DO NOT ADD NEW ACTIONS HERE
export const actionTypes = {
@@ -220,6 +225,7 @@ export type Action =
| SetJogDistanceAction
| SessionUpdateAction
| RefreshSessionAction
+ | SetModulesReviewedAction
export const actions = {
discover (): DiscoverAction {
@@ -293,6 +299,10 @@ export const actions = {
}
},
+ setModulesReviewed (payload: boolean) {
+ return {type: 'robot:SET_MODULES_REVIEWED', payload}
+ },
+
setDeckPopulated (payload: boolean) {
return {type: actionTypes.SET_DECK_POPULATED, payload}
},
diff --git a/app/src/robot/reducer/calibration.js b/app/src/robot/reducer/calibration.js
index 0d2a1631ba4..7ea7fb614a0 100755
--- a/app/src/robot/reducer/calibration.js
+++ b/app/src/robot/reducer/calibration.js
@@ -12,7 +12,8 @@ import type {
PipetteCalibrationAction,
LabwareCalibrationAction,
CalibrationSuccessAction,
- CalibrationFailureAction
+ CalibrationFailureAction,
+ SetModulesReviewedAction
} from '../actions'
// calibration request types
@@ -28,6 +29,7 @@ type CalibrationRequestType =
| 'DROP_TIP_AND_HOME'
| 'CONFIRM_TIPRACK'
| 'UPDATE_OFFSET'
+ | 'SET_MODULES_REVIEWED'
type CalibrationRequest = {
type: CalibrationRequestType,
@@ -39,6 +41,7 @@ type CalibrationRequest = {
export type State = {
+deckPopulated: ?boolean,
+ +modulesReviewed: ?boolean,
+probedByMount: {[Mount]: boolean},
+tipOnByMount: {[Mount]: boolean},
@@ -61,6 +64,7 @@ const {
const INITIAL_STATE: State = {
deckPopulated: null,
+ modulesReviewed: null,
// TODO(mc, 2018-01-22): combine these into subreducer
probedByMount: {},
@@ -139,6 +143,9 @@ export default function calibrationReducer (
case 'robot:REFRESH_SESSION':
return handleSession(state, action)
+ case 'robot:SET_MODULES_REVIEWED':
+ return handleSetModulesReviewed(state, action)
+
// TODO(mc, 20187-01-26): caution - not covered by flow yet
case SESSION: return handleSession(state, action)
case SET_DECK_POPULATED: return handleSetDeckPopulated(state, action)
@@ -167,6 +174,13 @@ function handleSetDeckPopulated (state: State, action: any): State {
return {...state, deckPopulated: action.payload}
}
+function handleSetModulesReviewed (
+ state: State,
+ action: SetModulesReviewedAction
+): State {
+ return {...state, modulesReviewed: action.payload}
+}
+
function handleMoveToFront (state: State, action: any): State {
if (!action.payload || !action.payload.mount) return state
@@ -175,6 +189,7 @@ function handleMoveToFront (state: State, action: any): State {
return {
...state,
deckPopulated: false,
+ modulesReviewed: false,
calibrationRequest: {
type: 'MOVE_TO_FRONT',
inProgress: true,
@@ -251,6 +266,7 @@ function handleMoveTo (state: State, action: LabwareCalibrationAction): State {
return {
...state,
deckPopulated: true,
+ modulesReviewed: true,
calibrationRequest: {
type: 'MOVE_TO',
inProgress: true,
@@ -306,6 +322,7 @@ function handlePickupAndHome (
return {
...state,
deckPopulated: true,
+ modulesReviewed: true,
calibrationRequest: {
type: 'PICKUP_AND_HOME',
inProgress: true,
diff --git a/app/src/robot/reducer/session.js b/app/src/robot/reducer/session.js
index 9853f9d7da9..88571e84bd5 100644
--- a/app/src/robot/reducer/session.js
+++ b/app/src/robot/reducer/session.js
@@ -4,7 +4,7 @@ import type {
Command,
StatePipette,
StateLabware,
- StateModule,
+ SessionModule,
Mount,
Slot,
SessionStatus
@@ -41,7 +41,7 @@ export type State = {
[Slot]: StateLabware,
},
modulesBySlot: {
- [Slot]: StateModule,
+ [Slot]: SessionModule,
},
runRequest: Request,
pauseRequest: Request,
diff --git a/app/src/robot/selectors.js b/app/src/robot/selectors.js
index 9830bba6769..ad00b09f42f 100644
--- a/app/src/robot/selectors.js
+++ b/app/src/robot/selectors.js
@@ -2,13 +2,14 @@
// robot selectors
import padStart from 'lodash/padStart'
import sortBy from 'lodash/sortBy'
-import {createSelector} from 'reselect'
+import {createSelector, type Selector} from 'reselect'
import type {ContextRouter} from 'react-router'
import type {State} from '../types'
import type {
Mount,
+ Slot,
Pipette,
PipetteCalibrationStatus,
Labware,
@@ -16,7 +17,7 @@ import type {
LabwareType,
Robot,
SessionStatus,
- StateModule
+ SessionModule
} from './types'
import {
@@ -76,11 +77,11 @@ export function getConnectRequest (state: State) {
return connection(state).connectRequest
}
-export function getConnectedRobotName (state: State) {
+export function getConnectedRobotName (state: State): string {
return connection(state).connectedTo
}
-export const getConnectedRobot = createSelector(
+export const getConnectedRobot: Selector = createSelector(
getDiscovered,
(discovered) => discovered.find((r) => r.isConnected)
)
@@ -314,21 +315,18 @@ export const getPipettesCalibrated = createSelector(
)
)
-export function getModulesBySlot (state: State) {
+export function getModulesBySlot (state: State): {[Slot]: ?SessionModule} {
return session(state).modulesBySlot
}
-export const getModules = createSelector(
- getModulesBySlot,
- (modules): ?StateModule[] => {
- return Object.keys(modules)
- .filter(isSlot)
- .map((slot) => {
- const module = modules[slot]
- return {...module}
- })
- }
-)
+export const getModules: Selector> =
+ createSelector(
+ getModulesBySlot,
+ modulesBySlot => Object
+ .keys(modulesBySlot)
+ .map(slot => modulesBySlot[slot])
+ .filter(Boolean)
+ )
export function getLabwareBySlot (state: State) {
return session(state).labwareBySlot
@@ -393,6 +391,10 @@ export const getLabware = createSelector(
}
)
+export function getModulesReviewed (state: State) {
+ return calibration(state).modulesReviewed
+}
+
export function getDeckPopulated (state: State) {
return calibration(state).deckPopulated
}
diff --git a/app/src/robot/test/actions.test.js b/app/src/robot/test/actions.test.js
index 58453316662..7fe8995e412 100644
--- a/app/src/robot/test/actions.test.js
+++ b/app/src/robot/test/actions.test.js
@@ -125,6 +125,18 @@ describe('robot actions', () => {
expect(actions.sessionUpdate(update)).toEqual(expected)
})
+ test('set modules reviewed action', () => {
+ expect(actions.setModulesReviewed(false)).toEqual({
+ type: 'robot:SET_MODULES_REVIEWED',
+ payload: false
+ })
+
+ expect(actions.setModulesReviewed(true)).toEqual({
+ type: 'robot:SET_MODULES_REVIEWED',
+ payload: true
+ })
+ })
+
test('set deck populated action', () => {
expect(actions.setDeckPopulated(false)).toEqual({
type: actionTypes.SET_DECK_POPULATED,
diff --git a/app/src/robot/test/calibration-reducer.test.js b/app/src/robot/test/calibration-reducer.test.js
index 4ec57931ec5..5348cbe930b 100644
--- a/app/src/robot/test/calibration-reducer.test.js
+++ b/app/src/robot/test/calibration-reducer.test.js
@@ -3,6 +3,7 @@ import {reducer, actionTypes} from '../'
const EXPECTED_INITIAL_STATE = {
deckPopulated: null,
+ modulesReviewed: null,
// intrument probed + basic tip-tracking flags
// TODO(mc, 2018-01-22): combine these into subreducer
@@ -48,6 +49,21 @@ describe('robot reducer - calibration', () => {
expect(reducer(state, action).calibration).toEqual(expected)
})
+ test('handles SET_MODULES_REVIEWED action', () => {
+ const setToTrue = {type: 'robot:SET_MODULES_REVIEWED', payload: true}
+ const setToFalse = {type: 'robot:SET_MODULES_REVIEWED', payload: false}
+
+ let state = {calibration: {modulesReviewed: false}}
+ expect(reducer(state, setToTrue).calibration).toEqual({
+ modulesReviewed: true
+ })
+
+ state = {calibration: {modulesReviewed: true}}
+ expect(reducer(state, setToFalse).calibration).toEqual({
+ modulesReviewed: false
+ })
+ })
+
test('handles SET_DECK_POPULATED action', () => {
const setToTrue = {type: actionTypes.SET_DECK_POPULATED, payload: true}
const setToFalse = {type: actionTypes.SET_DECK_POPULATED, payload: false}
@@ -67,6 +83,7 @@ describe('robot reducer - calibration', () => {
const state = {
calibration: {
deckPopulated: false,
+ modulesReviewed: false,
calibrationRequest: {
type: '',
inProgress: false,
@@ -81,6 +98,7 @@ describe('robot reducer - calibration', () => {
}
expect(reducer(state, action).calibration).toEqual({
deckPopulated: true,
+ modulesReviewed: true,
calibrationRequest: {
type: 'PICKUP_AND_HOME',
mount: 'left',
@@ -296,6 +314,7 @@ describe('robot reducer - calibration', () => {
const state = {
calibration: {
deckPopulated: true,
+ modulesReviewed: true,
calibrationRequest: {
type: '',
mount: '',
@@ -311,6 +330,7 @@ describe('robot reducer - calibration', () => {
expect(reducer(state, action).calibration).toEqual({
deckPopulated: false,
+ modulesReviewed: false,
calibrationRequest: {
type: 'MOVE_TO_FRONT',
mount: 'left',
@@ -444,6 +464,7 @@ describe('robot reducer - calibration', () => {
const state = {
calibration: {
deckPopulated: false,
+ modulesReviewed: false,
calibrationRequest: {
type: '',
inProgress: false,
@@ -458,6 +479,7 @@ describe('robot reducer - calibration', () => {
expect(reducer(state, action).calibration).toEqual({
deckPopulated: true,
+ modulesReviewed: true,
calibrationRequest: {
type: 'MOVE_TO',
inProgress: true,
diff --git a/app/src/robot/types.js b/app/src/robot/types.js
index 3b9e5e54412..6076a56eef9 100644
--- a/app/src/robot/types.js
+++ b/app/src/robot/types.js
@@ -132,13 +132,15 @@ export type Labware = StateLabware & {
export type LabwareType = 'tiprack' | 'labware'
-export type StateModule = {
+export type ModuleType = 'magdeck' | 'tempdeck'
+
+export type SessionModule = {
// resource ID
_id: number,
// slot module is installed in
slot: Slot,
// name identifier of the module
- type: 'magdeck' | 'tempdeck',
+ name: ModuleType
}
export type SessionStatus =