From 49c1fe93243cb4b610361281a0f4ef27cd34087f Mon Sep 17 00:00:00 2001 From: Katie Adee Date: Wed, 13 Mar 2019 18:03:18 -0400 Subject: [PATCH] feat(app): Enable pipette config modal and form (#3202) closes #3112 --- .../components/ConfigurePipette/ConfigForm.js | 33 ++++++++++++++++--- app/src/components/ConfigurePipette/index.js | 6 +++- .../AttachedPipettesCard.js | 8 ----- .../InstrumentSettings/InstrumentInfo.js | 3 +- app/src/config/index.js | 2 +- 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/app/src/components/ConfigurePipette/ConfigForm.js b/app/src/components/ConfigurePipette/ConfigForm.js index ca192c7660c..0981905d8c1 100644 --- a/app/src/components/ConfigurePipette/ConfigForm.js +++ b/app/src/components/ConfigurePipette/ConfigForm.js @@ -5,9 +5,11 @@ import {Formik, Form} from 'formik' import startCase from 'lodash/startCase' import mapValues from 'lodash/mapValues' +import forOwn from 'lodash/forOwn' +import keys from 'lodash/keys' import pick from 'lodash/pick' +import omit from 'lodash/omit' import set from 'lodash/set' -import forOwn from 'lodash/forOwn' import isEmpty from 'lodash/isEmpty' import FormButtonBar from './FormButtonBar' @@ -33,6 +35,7 @@ type Props = { pipette: Pipette, pipetteConfig: PipetteConfigResponse, updateConfig: (id: string, PipetteConfigRequest) => mixed, + showHiddenFields: boolean, } const PLUNGER_KEYS = ['top', 'bottom', 'blowout', 'dropTip'] @@ -57,6 +60,7 @@ export default class ConfigForm extends React.Component { } getVisibleFields = () => { + if (this.props.showHiddenFields) return this.props.pipetteConfig.fields return pick(this.props.pipetteConfig.fields, [ ...PLUNGER_KEYS, ...POWER_KEYS, @@ -64,6 +68,16 @@ export default class ConfigForm extends React.Component { ]) } + getUnknownKeys = () => { + return keys( + omit(this.props.pipetteConfig.fields, [ + ...PLUNGER_KEYS, + ...POWER_KEYS, + ...TIP_KEYS, + ]) + ) + } + handleSubmit = (values: FormValues) => { const params = mapValues(values, v => { return v === '' ? null : {value: Number(v)} @@ -89,14 +103,17 @@ export default class ConfigForm extends React.Component { // validate all visible fields with min and max forOwn(fields, (field, name) => { - const value = values[name] + const value = values[name].trim() const {min, max} = field - if (value !== '') { const parsed = Number(value) if (Number.isNaN(parsed)) { set(errors, name, `number required`) - } else if (min && max && (parsed < min || value > max)) { + } else if ( + typeof min === 'number' && + typeof max === 'number' && + (parsed < min || value > max) + ) { set(errors, name, `Min ${min} / Max ${max}`) } } @@ -118,12 +135,14 @@ export default class ConfigForm extends React.Component { render () { const {parentUrl} = this.props const fields = this.getVisibleFields() + const UNKNOWN_KEYS = this.getUnknownKeys() const initialValues = mapValues(fields, f => { return f.value !== f.default ? f.value.toString() : '' }) const plungerFields = this.getFieldsByKey(PLUNGER_KEYS, fields) const powerFields = this.getFieldsByKey(POWER_KEYS, fields) const tipFields = this.getFieldsByKey(TIP_KEYS, fields) + const devFields = this.getFieldsByKey(UNKNOWN_KEYS, fields) return ( { groupLabel="Tip Pickup / Drop " formFields={tipFields} /> + {this.props.showHiddenFields && ( + + )} )} @@ -93,10 +95,12 @@ function makeMapStateToProps (): (state: State, ownProps: OP) => SP { pipette && configResponse && configResponse[pipette.id] const configSetConfigCall = pipette && getPipetteRequestById(state, ownProps.robot, pipette.id) + const devInternal = getConfig(state).devInternal return { pipette, pipetteConfig, configError: configSetConfigCall && configSetConfigCall.error, + __featureEnabled: !!devInternal && !!devInternal.allPipetteConfig, } } } diff --git a/app/src/components/InstrumentSettings/AttachedPipettesCard.js b/app/src/components/InstrumentSettings/AttachedPipettesCard.js index fe24b9d6ab9..7f5f82432d4 100644 --- a/app/src/components/InstrumentSettings/AttachedPipettesCard.js +++ b/app/src/components/InstrumentSettings/AttachedPipettesCard.js @@ -2,7 +2,6 @@ // attached pipettes container card import * as React from 'react' import {connect} from 'react-redux' -import {getIn} from '@thi.ng/paths' import { makeGetRobotPipettes, @@ -20,7 +19,6 @@ import {Card, IntervalWrapper} from '@opentrons/components' import type {State} from '../../types' import type {Robot} from '../../discovery' import type {Pipette} from '../../http-api-client' -import {getConfig} from '../../config' type OP = Robot @@ -29,7 +27,6 @@ type SP = { left: ?Pipette, right: ?Pipette, showSettings: boolean, - __featureEnabled: boolean, } type DP = { @@ -39,8 +36,6 @@ type DP = { type Props = OP & SP & DP -const __FEATURE_FLAG = 'devInternal.newPipetteConfig' - const TITLE = 'Pipettes' export default connect( @@ -59,7 +54,6 @@ function AttachedPipettesCard (props: Props) { {...props.left} onChangeClick={props.clearMove} showSettings={props.showSettings} - __enableConfig={props.__featureEnabled} /> @@ -88,7 +81,6 @@ function makeMapStateToProps (): (state: State, ownProps: OP) => SP { left, right, showSettings: !!configCall.response, - __featureEnabled: !!getIn(getConfig(state), __FEATURE_FLAG), } } } diff --git a/app/src/components/InstrumentSettings/InstrumentInfo.js b/app/src/components/InstrumentSettings/InstrumentInfo.js index 9e2a1e9f350..98794d1bd36 100644 --- a/app/src/components/InstrumentSettings/InstrumentInfo.js +++ b/app/src/components/InstrumentSettings/InstrumentInfo.js @@ -18,7 +18,6 @@ type Props = { name: string, onChangeClick: () => mixed, showSettings: boolean, - __enableConfig: boolean, } // TODO(mc, 2018-03-30): volume and channels should come from the API @@ -54,7 +53,7 @@ export default function PipetteInfo (props: Props) { {direction} - {props.__enableConfig && model && showSettings && ( + {model && showSettings && ( settings diff --git a/app/src/config/index.js b/app/src/config/index.js index 6594aaeb4f4..8b2a083bc90 100644 --- a/app/src/config/index.js +++ b/app/src/config/index.js @@ -64,7 +64,7 @@ export type Config = { // internal development flags devInternal?: { - newPipetteConfig?: boolean, + allPipetteConfig?: boolean, manualIp?: boolean, }, }