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 =