Skip to content

Commit

Permalink
chore: Merge chore_release-7.3.0 into edge (#15117)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjhuff authored May 7, 2024
1 parent 80cfe7e commit 1dede8b
Show file tree
Hide file tree
Showing 30 changed files with 431 additions and 67 deletions.
2 changes: 1 addition & 1 deletion api/src/opentrons/util/change_notifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ def notify(self) -> None:

async def wait(self) -> None:
"""Wait until the next state change notification."""
self._event.clear()
await self._event.wait()
self._event.clear()


class ChangeNotifier_ts(ChangeNotifier):
Expand Down
27 changes: 27 additions & 0 deletions api/tests/opentrons/util/test_change_notifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,30 @@ async def _do_task_3() -> None:
await asyncio.gather(task_1, task_2, task_3)

assert results == [1, 2, 3]


async def test_notify_while_busy() -> None:
"""Test that waiters process a new notify() after they are done being busy."""
subject = ChangeNotifier()
results = []

async def _do_task() -> None:
results.append("TEST")
await asyncio.sleep(0.2) # Simulate being busy

async def do_task() -> None:
while True:
await subject.wait()
await _do_task()

task = asyncio.create_task(do_task())

subject.notify()
await asyncio.sleep(0.0)

subject.notify()
await asyncio.sleep(0.5)

assert results == ["TEST", "TEST"]

task.cancel()
6 changes: 3 additions & 3 deletions app/src/assets/localization/en/drop_tip_wizard.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
"remove_the_tips_from_pipette": "You may want to remove the tips from the pipette before using it again in a protocol.",
"remove_the_tips_manually": "Remove the tips manually. Then home the gantry. Homing with tips attached could pull liquid into the pipette and damage it.",
"remove_tips": "Remove tips",
"select_blowout_slot": "<block>You can blow out liquid into a labware or dispose of it.</block><block>Select the slot where you want to blow out the liquid on the deck map to the right. Once confirmed, the gantry will move to the chosen slot.</block>",
"select_blowout_slot_odd": "<block>You can blow out liquid into a labware or dispose of it.</block><br/><block>After the gantry moves to the chosen slot, use the jog controls to move the pipette to the exact position for blowing out.</block>",
"select_blowout_slot": "<block>You can blow out liquid into a labware.</block><block>Select the slot where you want to blow out the liquid on the deck map to the right. Once confirmed, the gantry will move to the chosen slot.</block>",
"select_blowout_slot_odd": "<block>You can blow out liquid into a labware.</block><br/><block>After the gantry moves to the chosen slot, use the jog controls to move the pipette to the exact position for blowing out.</block>",
"select_drop_tip_slot": "<block>You can return tips to a tip rack or dispose of them.</block><block>Select the slot where you want to drop the tips on the deck map to the right. Once confirmed, the gantry will move to the chosen slot.</block>",
"select_drop_tip_slot_odd": "<block>You can blow out liquid into a labware or dispose of it.</block><br/><block>After the gantry moves to the chosen slot, use the jog controls to move the pipette to the exact position for dropping tips.</block>",
"select_drop_tip_slot_odd": "<block>You can return tips to a tip rack or dispose of them.</block><br/><block>After the gantry moves to the chosen slot, use the jog controls to move the pipette to the exact position for dropping tips.</block>",
"skip": "Skip",
"stand_back_blowing_out": "Stand back, robot is blowing out liquid",
"stand_back_dropping_tips": "Stand back, robot is dropping tips",
Expand Down
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
11 changes: 8 additions & 3 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 @@ -172,7 +172,6 @@ function Input(props: InputFieldProps): JSX.Element {
@media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} {
height: ${size === 'small' ? '4.25rem' : '5rem'};
box-shadow: ${hasError ? BORDERS.shadowBig : 'none'};
font-size: ${TYPOGRAPHY.fontSize28};
padding: ${SPACING.spacing16} ${SPACING.spacing24};
border: 2px ${BORDERS.styleSolid}
Expand Down Expand Up @@ -277,7 +276,7 @@ function Input(props: InputFieldProps): JSX.Element {
}
}}
>
<input
<StyledInput
{...inputProps}
data-testid={props.id}
value={value}
Expand Down Expand Up @@ -315,3 +314,9 @@ function Input(props: InputFieldProps): JSX.Element {
</Flex>
)
}

const StyledInput = styled.input`
&::placeholder {
color: ${COLORS.grey40};
}
`
4 changes: 2 additions & 2 deletions app/src/atoms/MenuList/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element {
{currentOption.name}
</StyledText>
{showDropdownMenu ? (
<Icon size="1.2rem" name="menu-down" transform="rotate(180deg)" />
<Icon size="0.75rem" name="menu-down" transform="rotate(180deg)" />
) : (
<Icon size="1.2rem" name="menu-down" />
<Icon size="0.75rem" name="menu-down" />
)}
</Flex>
{showDropdownMenu && (
Expand Down
4 changes: 4 additions & 0 deletions app/src/molecules/ReleaseNotes/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@
& ol {
margin-left: 1.25rem;
margin-bottom: 0.25rem;
font-size: var(--fs-body-2);
color: var(--c-font-dark); /* from legacy --font-body-2-dark */
}

& li {
margin: 0.25rem 0;
font-size: var(--fs-body-2);
color: var(--c-font-dark); /* from legacy --font-body-2-dark */
}

& code {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,28 @@ describe('ChooseProtocolSlideout', () => {
screen.getByText('Restore default values')
})

it('shows tooltip when disabled Restore default values link is clicked', () => {
const protocolDataWithoutRunTimeParameter = {
...storedProtocolDataFixture,
}
vi.mocked(getStoredProtocols).mockReturnValue([
protocolDataWithoutRunTimeParameter,
])

render({
robot: mockConnectableRobot,
onCloseClick: vi.fn(),
showSlideout: true,
})
const proceedButton = screen.getByRole('button', {
name: 'Continue to parameters',
})
fireEvent.click(proceedButton)
const restoreValuesLink = screen.getByText('Restore default values')
fireEvent.click(restoreValuesLink)
screen.getByText('No custom values specified')
})

// ToDo (kk:04/18/2024) I will update test for RTP
/*
it('renders error state when there is a run creation error', () => {
Expand Down
53 changes: 42 additions & 11 deletions app/src/organisms/ChooseProtocolSlideout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
SecondaryButton,
StyledText,
TYPOGRAPHY,
useHoverTooltip,
useTooltip,
} from '@opentrons/components'
import { ApiHostProvider } from '@opentrons/react-api-client'

Expand Down Expand Up @@ -63,6 +63,8 @@ export const CARD_OUTLINE_BORDER_STYLE = css`
}
`

const TOOLTIP_DELAY_MS = 2000

const _getFileBaseName = (filePath: string): string => {
return filePath.split('/').reverse()[0]
}
Expand All @@ -78,7 +80,11 @@ export function ChooseProtocolSlideoutComponent(
const { t } = useTranslation(['device_details', 'shared'])
const history = useHistory()
const logger = useLogger(new URL('', import.meta.url).pathname)
const [targetProps, tooltipProps] = useHoverTooltip()
const [targetProps, tooltipProps] = useTooltip()
const [
showRestoreValuesTooltip,
setShowRestoreValuesTooltip,
] = React.useState<boolean>(false)

const { robot, showSlideout, onCloseClick } = props
const { name } = robot
Expand All @@ -93,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 @@ -229,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 @@ -258,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 Expand Up @@ -341,24 +350,42 @@ export function ChooseProtocolSlideoutComponent(
}

const pageTwoBody = (
<Flex flexDirection={DIRECTION_COLUMN}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing10}>
<Flex justifyContent={JUSTIFY_END}>
<LinkComponent
textAlign={TYPOGRAPHY.textAlignRight}
css={
isRestoreDefaultsLinkEnabled ? ENABLED_LINK_CSS : DISABLED_LINK_CSS
}
onClick={resetRunTimeParameters}
onClick={() => {
if (isRestoreDefaultsLinkEnabled) {
resetRunTimeParameters?.()
} else {
setShowRestoreValuesTooltip(true)
setTimeout(
() => setShowRestoreValuesTooltip(false),
TOOLTIP_DELAY_MS
)
}
}}
paddingBottom={SPACING.spacing10}
{...targetProps}
>
{t('protocol_details:restore_defaults')}
</LinkComponent>
{!isRestoreDefaultsLinkEnabled && (
<Tooltip tooltipProps={tooltipProps}>
{t('protocol_details:no_custom_values')}
</Tooltip>
)}
<Tooltip
tooltipProps={{
...tooltipProps,
visible: showRestoreValuesTooltip,
}}
css={css`
&:hover {
cursor: auto;
}
`}
>
{t('protocol_details:no_custom_values')}
</Tooltip>{' '}
</Flex>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing16}>
{runTimeParametersInputs}
Expand Down Expand Up @@ -525,7 +552,11 @@ function StoredProtocolList(props: StoredProtocolListProps): JSX.Element {
isWarning={missingAnalysisData}
onClick={() => handleSelectProtocol(storedProtocol)}
>
<Box display="grid" gridTemplateColumns="1fr 3fr">
<Box
display="grid"
gridTemplateColumns="1fr 3fr"
marginRight={SPACING.spacing16}
>
{!missingAnalysisData ? (
<Box
marginY={SPACING.spacingAuto}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,22 @@ describe('ChooseRobotSlideout', () => {
})
expect(mockSetSelectedRobot).toBeCalledWith(null)
})

it('shows tooltip when disabled Restore default values link is clicked', () => {
render({
onCloseClick: vi.fn(),
isExpanded: true,
isSelectedRobotOnDifferentSoftwareVersion: false,
selectedRobot: null,
setSelectedRobot: mockSetSelectedRobot,
title: 'choose robot slideout title',
robotType: OT2_ROBOT_TYPE,
multiSlideout: { currentPage: 2 },
runTimeParametersOverrides: mockRunTimeParameters,
})

const restoreValuesLink = screen.getByText('Restore default values')
fireEvent.click(restoreValuesLink)
screen.getByText('No custom values specified')
})
})
47 changes: 37 additions & 10 deletions app/src/organisms/ChooseRobotSlideout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
SPACING,
StyledText,
TYPOGRAPHY,
useHoverTooltip,
useTooltip,
} from '@opentrons/components'

import { FLEX_ROBOT_TYPE, OT2_ROBOT_TYPE } from '@opentrons/shared-data'
Expand Down Expand Up @@ -63,6 +63,8 @@ export const CARD_OUTLINE_BORDER_STYLE = css`
}
`

const TOOLTIP_DELAY_MS = 2000

interface RobotIsBusyAction {
type: 'robotIsBusy'
robotName: string
Expand Down Expand Up @@ -145,7 +147,12 @@ export function ChooseRobotSlideout(

const dispatch = useDispatch<Dispatch>()
const isScanning = useSelector((state: State) => getScanning(state))
const [targetProps, tooltipProps] = useHoverTooltip()
const [targetProps, tooltipProps] = useTooltip()
const [
showRestoreValuesTooltip,
setShowRestoreValuesTooltip,
] = React.useState<boolean>(false)
const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)

const unhealthyReachableRobots = useSelector((state: State) =>
getReachableRobots(state)
Expand Down Expand Up @@ -383,7 +390,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) ||
value < runtimeParam.min ||
value > runtimeParam.max
? t(`value_out_of_range`, {
Expand Down Expand Up @@ -418,6 +425,8 @@ export function ChooseRobotSlideout(
}
id={id}
error={error}
onBlur={() => setIsInputFocused(false)}
onFocus={() => setIsInputFocused(true)}
onChange={e => {
const clone = runTimeParametersOverrides.map((parameter, i) => {
if (i === index) {
Expand Down Expand Up @@ -500,7 +509,7 @@ export function ChooseRobotSlideout(

const pageTwoBody =
runTimeParametersOverrides != null ? (
<Flex flexDirection={DIRECTION_COLUMN}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing10}>
<Flex justifyContent={JUSTIFY_END}>
<Link
textAlign={TYPOGRAPHY.textAlignRight}
Expand All @@ -509,17 +518,35 @@ export function ChooseRobotSlideout(
? ENABLED_LINK_CSS
: DISABLED_LINK_CSS
}
onClick={() => resetRunTimeParameters?.()}
onClick={() => {
if (isRestoreDefaultsLinkEnabled) {
resetRunTimeParameters?.()
} else {
setShowRestoreValuesTooltip(true)
setTimeout(
() => setShowRestoreValuesTooltip(false),
TOOLTIP_DELAY_MS
)
}
}}
paddingBottom={SPACING.spacing10}
{...targetProps}
>
{t('restore_defaults')}
</Link>
{!isRestoreDefaultsLinkEnabled && (
<Tooltip tooltipProps={tooltipProps}>
{t('no_custom_values')}
</Tooltip>
)}
<Tooltip
tooltipProps={{
...tooltipProps,
visible: showRestoreValuesTooltip,
}}
css={css`
&:hover {
cursor: auto;
}
`}
>
{t('no_custom_values')}
</Tooltip>
</Flex>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing16}>
{runTimeParameters}
Expand Down
Loading

0 comments on commit 1dede8b

Please sign in to comment.