Skip to content

Commit

Permalink
Merge branch 'chore_release-7.3.0' into fix_app-restore-values-disabl…
Browse files Browse the repository at this point in the history
…ed-tooltip
  • Loading branch information
ncdiehl11 authored May 3, 2024
2 parents 4f4bdd6 + d6472ae commit 76643e7
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 8 deletions.
1 change: 1 addition & 0 deletions app/src/assets/localization/en/module_wizard_flows.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"location_occupied": "A {{fixture}} is currently specified here on the deck configuration",
"module_calibrating": "Stand back, {{moduleName}} is calibrating",
"module_calibration": "Module calibration",
"module_heating_or_cooling": "Module calibration cannot proceed while heating or cooling",
"module_secured": "The module must be fully secured in its caddy and secured in the deck slot.",
"module_too_hot": "Module is too hot to proceed to module calibration",
"move_gantry_to_front": "Move gantry to front",
Expand Down
10 changes: 8 additions & 2 deletions app/src/atoms/InputField/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react'
import { css } from 'styled-components'
import styled, { css } from 'styled-components'

import {
ALIGN_CENTER,
Expand Down Expand Up @@ -276,7 +276,7 @@ function Input(props: InputFieldProps): JSX.Element {
}
}}
>
<input
<StyledInput
{...inputProps}
data-testid={props.id}
value={value}
Expand Down Expand Up @@ -314,3 +314,9 @@ function Input(props: InputFieldProps): JSX.Element {
</Flex>
)
}

const StyledInput = styled.input`
&::placeholder {
color: ${COLORS.grey40};
}
`
5 changes: 4 additions & 1 deletion app/src/organisms/ChooseProtocolSlideout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export function ChooseProtocolSlideoutComponent(
] = React.useState<RunTimeParameter[]>([])
const [currentPage, setCurrentPage] = React.useState<number>(1)
const [hasParamError, setHasParamError] = React.useState<boolean>(false)
const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)

React.useEffect(() => {
setRunTimeParametersOverrides(
Expand Down Expand Up @@ -235,7 +236,7 @@ export function ChooseProtocolSlideoutComponent(
const value = runtimeParam.value as number
const id = `InputField_${runtimeParam.variableName}_${index.toString()}`
const error =
Number.isNaN(value) ||
(Number.isNaN(value) && !isInputFocused) ||
value < runtimeParam.min ||
value > runtimeParam.max
? t(`protocol_details:value_out_of_range`, {
Expand Down Expand Up @@ -264,6 +265,8 @@ export function ChooseProtocolSlideoutComponent(
caption={`${runtimeParam.min}-${runtimeParam.max}`}
id={id}
error={error}
onBlur={() => setIsInputFocused(false)}
onFocus={() => setIsInputFocused(true)}
onChange={e => {
const clone = runTimeParametersOverrides.map((parameter, i) => {
if (i === index) {
Expand Down
4 changes: 3 additions & 1 deletion app/src/organisms/ChooseRobotSlideout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ export function ChooseRobotSlideout(
const value = runtimeParam.value as number
const id = `InputField_${runtimeParam.variableName}_${index.toString()}`
const error =
Number.isNaN(value) ||
(Number.isNaN(value) && !isInputFocused) ||

Check failure on line 392 in app/src/organisms/ChooseRobotSlideout/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

Cannot find name 'isInputFocused'.

Check failure on line 392 in app/src/organisms/ChooseRobotSlideout/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

Cannot find name 'isInputFocused'.
value < runtimeParam.min ||
value > runtimeParam.max
? t(`value_out_of_range`, {
Expand Down Expand Up @@ -424,6 +424,8 @@ export function ChooseRobotSlideout(
}
id={id}
error={error}
onBlur={() => setIsInputFocused(false)}

Check failure on line 427 in app/src/organisms/ChooseRobotSlideout/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

Cannot find name 'setIsInputFocused'.

Check failure on line 427 in app/src/organisms/ChooseRobotSlideout/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

Cannot find name 'setIsInputFocused'.
onFocus={() => setIsInputFocused(true)}

Check failure on line 428 in app/src/organisms/ChooseRobotSlideout/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

Cannot find name 'setIsInputFocused'.

Check failure on line 428 in app/src/organisms/ChooseRobotSlideout/index.tsx

View workflow job for this annotation

GitHub Actions / js checks

Cannot find name 'setIsInputFocused'.
onChange={e => {
const clone = runTimeParametersOverrides.map((parameter, i) => {
if (i === index) {
Expand Down
42 changes: 38 additions & 4 deletions app/src/organisms/ModuleCard/ModuleOverflowMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { useTranslation } from 'react-i18next'

import { Flex, POSITION_RELATIVE, useHoverTooltip } from '@opentrons/components'

import { MODULE_MODELS_OT2_ONLY } from '@opentrons/shared-data'
import {
HEATERSHAKER_MODULE_TYPE,
MODULE_MODELS_OT2_ONLY,
TEMPERATURE_MODULE_TYPE,
THERMOCYCLER_MODULE_TYPE,
} from '@opentrons/shared-data'
import { MenuList } from '../../atoms/MenuList'
import { Tooltip } from '../../atoms/Tooltip'
import { MenuItem } from '../../atoms/MenuList/MenuItem'
Expand Down Expand Up @@ -69,6 +74,23 @@ export const ModuleOverflowMenu = (
isDisabled = true
}

let isHeatingOrCooling
switch (module.moduleType) {
case TEMPERATURE_MODULE_TYPE:
isHeatingOrCooling = module.data.status !== 'idle'
break
case HEATERSHAKER_MODULE_TYPE:
isHeatingOrCooling = module.data.temperatureStatus !== 'idle'
break
case THERMOCYCLER_MODULE_TYPE:
isHeatingOrCooling =
module.data.lidTemperatureStatus !== 'idle' ||
module.data.status !== 'idle'
break
default:
isHeatingOrCooling = false
}

const { menuOverflowItemsByModuleType } = useModuleOverflowMenu(
module,
handleAboutClick,
Expand All @@ -79,6 +101,18 @@ export const ModuleOverflowMenu = (
isIncompatibleWithOT3
)

const isCalibrateDisabled = !isPipetteReady || isTooHot || isHeatingOrCooling
let calibrateDisabledReason
if (!isPipetteReady) {
calibrateDisabledReason = t('calibrate_pipette')
} else if (isTooHot) {
calibrateDisabledReason = t('module_too_hot')
} else if (isHeatingOrCooling) {
calibrateDisabledReason = t('module_heating_or_cooling')
} else {
calibrateDisabledReason = null
}

return (
<Flex position={POSITION_RELATIVE}>
<MenuList>
Expand All @@ -89,7 +123,7 @@ export const ModuleOverflowMenu = (
<>
<MenuItem
onClick={handleCalibrateClick}
disabled={!isPipetteReady || isTooHot}
disabled={isCalibrateDisabled}
{...targetProps}
>
{i18n.format(
Expand All @@ -99,9 +133,9 @@ export const ModuleOverflowMenu = (
'capitalize'
)}
</MenuItem>
{!isPipetteReady || isTooHot ? (
{isCalibrateDisabled ? (
<Tooltip tooltipProps={tooltipProps}>
{t(!isPipetteReady ? 'calibrate_pipette' : 'module_too_hot')}
{calibrateDisabledReason}
</Tooltip>
) : null}
</>
Expand Down
40 changes: 40 additions & 0 deletions app/src/organisms/ModuleCard/__tests__/ModuleOverflowMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
import { useCurrentRunId } from '../../ProtocolUpload/hooks'
import { ModuleOverflowMenu } from '../ModuleOverflowMenu'

import type { TemperatureStatus } from '@opentrons/api-client'

vi.mock('../../Devices/hooks')
vi.mock('../../RunTimeControl/hooks')
vi.mock('../../ProtocolUpload/hooks')
Expand Down Expand Up @@ -535,6 +537,44 @@ describe('ModuleOverflowMenu', () => {
expect(calibrate).toBeDisabled()
})

it('renders a disabled calibrate button if module is heating or cooling', () => {
vi.mocked(useIsFlex).mockReturnValue(true)
const mockHeatingModule = {
...mockHeaterShaker,
data: {
...mockHeaterShaker.data,
temperatureStatus: 'heating' as TemperatureStatus,
},
}
props = {
...props,
module: mockHeatingModule,
}
render(props)

const calibrate = screen.getByRole('button', { name: 'Calibrate' })
expect(calibrate).toBeDisabled()
})

it('renders a disabled calibrate button if module temperature status errors', () => {
vi.mocked(useIsFlex).mockReturnValue(true)
const mockHeatingModule = {
...mockHeaterShaker,
data: {
...mockHeaterShaker.data,
temperatureStatus: 'error' as TemperatureStatus,
},
}
props = {
...props,
module: mockHeatingModule,
}
render(props)

const calibrate = screen.getByRole('button', { name: 'Calibrate' })
expect(calibrate).toBeDisabled()
})

it('a mock function should be called when clicking Calibrate if pipette is ready', () => {
vi.mocked(useIsFlex).mockReturnValue(true)
props = {
Expand Down

0 comments on commit 76643e7

Please sign in to comment.