Skip to content

Commit

Permalink
feat(app): Add opt-in modal for new p10s (#2816)
Browse files Browse the repository at this point in the history
Closes #2793
  • Loading branch information
Kadee80 authored and mcous committed Dec 13, 2018
1 parent 8546ea4 commit cd69e19
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 11 deletions.
6 changes: 3 additions & 3 deletions app-shell/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ import type {Config} from '@opentrons/app/src/config'

// make sure all arguments are included in production
// $FlowFixMe: process.defaultApp exists in electron
const argv = process.defaultApp
? process.argv.slice(2)
: process.argv.slice(1)
const argv = process.defaultApp ? process.argv.slice(2) : process.argv.slice(1)

const PARSE_ARGS_OPTS = {
envPrefix: 'OT_APP',
Expand Down Expand Up @@ -63,6 +61,8 @@ const DEFAULTS: Config = {
seenOptIn: false,
},

p10WarningSeen: {},

// user support (intercom)
support: {
userId: uuid(),
Expand Down
66 changes: 58 additions & 8 deletions app/src/components/RobotSettings/AdvancedSettingsCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@
import * as React from 'react'
import {connect} from 'react-redux'
import {Link} from 'react-router-dom'
import get from 'lodash/get'
import reduce from 'lodash/reduce'

import {
fetchSettings,
setSettings,
makeGetRobotSettings,
} from '../../http-api-client'
import {getConfig, updateConfig} from '../../config'
import {CONNECTABLE} from '../../discovery'
import {downloadLogs} from '../../shell'
import {RefreshCard} from '@opentrons/components'
import {LabeledButton, LabeledToggle} from '../controls'
import OptInPipetteModal from './OptInPipetteModal'

import type {State, Dispatch} from '../../types'
import type {ViewableRobot} from '../../discovery'
Expand All @@ -23,12 +27,16 @@ type OP = {
resetUrl: string,
}

type SP = {|settings: Array<Setting>|}
type SP = {|
settings: Array<Setting>,
showP10Warning: boolean,
|}

type DP = {|
fetch: () => mixed,
set: (id: string, value: boolean) => mixed,
download: () => mixed,
setP10WarningSeen: () => mixed,
|}

type Props = {...$Exact<OP>, ...SP, ...DP}
Expand All @@ -42,6 +50,7 @@ type BooleanSettingProps = {
}

const TITLE = 'Advanced Settings'
const P10_OPT_IN_SETTING_ID = 'useNewP10Aspiration'

export default connect(
makeMapStateToProps,
Expand All @@ -65,11 +74,19 @@ class BooleanSettingToggle extends React.Component<BooleanSettingProps> {
}

function AdvancedSettingsCard (props: Props) {
const {settings, set, fetch, download, resetUrl} = props
const {
settings,
set,
fetch,
download,
resetUrl,
showP10Warning,
setP10WarningSeen,
} = props
const {name, health, status} = props.robot
const disabled = status !== CONNECTABLE
const logsAvailable = health && health.logs

const setP10Setting = () => set(P10_OPT_IN_SETTING_ID, true)
return (
<RefreshCard
watch={name}
Expand Down Expand Up @@ -99,31 +116,64 @@ function AdvancedSettingsCard (props: Props) {
>
<p>Restore robot to factory configuration</p>
</LabeledButton>
{settings.map(s => <BooleanSettingToggle {...s} key={s.id} set={set} />)}
{showP10Warning && (
<OptInPipetteModal
setP10Setting={setP10Setting}
setP10WarningSeen={setP10WarningSeen}
/>
)}
{settings.map(s => (
<BooleanSettingToggle {...s} key={s.id} set={set} />
))}
</RefreshCard>
)
}

const seenP10WarningConfigPath = (name: string) => `p10WarningSeen.${name}`

function makeMapStateToProps (): (state: State, ownProps: OP) => SP {
const getRobotSettings = makeGetRobotSettings()

return (state, ownProps) => {
const settingsRequest = getRobotSettings(state, ownProps.robot)
const {robot} = ownProps
const config = getConfig(state)
const settingsRequest = getRobotSettings(state, robot)
const settings =
settingsRequest &&
settingsRequest.response &&
settingsRequest.response.settings

return {settings: settings || []}
const p10OptedIn = reduce(
settings,
(result, setting) => {
if (setting.id === P10_OPT_IN_SETTING_ID) return setting.value
return result
},
null
)

const seenP10Warning = get(config, seenP10WarningConfigPath(robot.name))

return {
settings: settings || [],
showP10Warning: !seenP10Warning && p10OptedIn === false,
}
}
}

function mapDispatchToProps (dispatch: Dispatch, ownProps: OP): DP {
const {robot} = ownProps

const setP10WarningSeen = () =>
dispatch(updateConfig(seenP10WarningConfigPath(robot.name), true))
return {
fetch: () => dispatch(fetchSettings(robot)),
set: (id, value) => dispatch(setSettings(robot, {id, value})),
set: (id, value) => {
if (id === P10_OPT_IN_SETTING_ID) {
setP10WarningSeen()
}
dispatch(setSettings(robot, {id, value}))
},
download: () => dispatch(downloadLogs(robot)),
setP10WarningSeen,
}
}
55 changes: 55 additions & 0 deletions app/src/components/RobotSettings/OptInPipetteModal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// @flow
import * as React from 'react'
import {AlertModal} from '@opentrons/components'
import {Portal} from '../../portal'
import styles from './styles.css'
type Props = {
setP10Setting: () => mixed,
setP10WarningSeen: () => mixed,
}

export default function OptInModal (props: Props) {
const {setP10Setting, setP10WarningSeen} = props
const HEADING = 'Update available for P10 single-channel pipette'
const buttons = [
{onClick: setP10WarningSeen, children: 'not now'},
{
onClick: setP10Setting,
children: 'Update Pipette Function',
className: styles.width_auto,
},
]
return (
<Portal>
<AlertModal heading={HEADING} buttons={buttons} alertOverlay>
<p>
<strong>
There is an updated aspiration function available for the P10
single-channel pipette.
</strong>
</p>

<p>
This is a small but material change to the P10&apos;s pipetting
performance based on an expanded data set. In particular, it decreases
the low-volume µl-to-mm conversion factor to address under-aspiration
issues.
</p>

<p>
<strong>
We strongly recommend you update your pipette function
</strong>
, unless you are an advanced user who has manually modified your P10S
pipette&apos;s µl-to-mm conversion factor.
</p>

<p className={styles.footer}>
* This setting can be changed in your robot&apos;s &quot;Advanced
Settings&quot; menu. If you have any questions, please contact our
Support Team.
</p>
</AlertModal>
</Portal>
)
}
10 changes: 10 additions & 0 deletions app/src/components/RobotSettings/OptInPipetteModal/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@import '@opentrons/components';

.width_auto {
width: auto;
padding: 0.5rem 2rem;
}

.footer {
font-style: italic;
}
4 changes: 4 additions & 0 deletions app/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ export type Config = {
seenOptIn: boolean,
},

p10WarningSeen: {
[id: string]: ?boolean,
},

support: {
userId: string,
createdAt: number,
Expand Down

0 comments on commit cd69e19

Please sign in to comment.