Skip to content

Commit

Permalink
fix(app): fix ODD drop tip modal overflow not dismissing (#16263)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjhuff authored Sep 17, 2024
1 parent 5f868c7 commit 81770b3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 43 deletions.
38 changes: 15 additions & 23 deletions app/src/pages/InstrumentDetail/InstrumentDetailOverflowMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,13 @@ import {
import {
SINGLE_MOUNT_PIPETTES,
NINETY_SIX_CHANNEL,
FLEX_ROBOT_TYPE,
getPipetteModelSpecs,
} from '@opentrons/shared-data'
import { ApiHostProvider } from '@opentrons/react-api-client'

import { MenuList } from '../../atoms/MenuList'
import { MenuItem } from '../../atoms/MenuList/MenuItem'
import { PipetteWizardFlows } from '../../organisms/PipetteWizardFlows'
import { GripperWizardFlows } from '../../organisms/GripperWizardFlows'
import {
DropTipWizardFlows,
useDropTipWizardFlows,
} from '../../organisms/DropTipWizardFlows'
import { FLOWS } from '../../organisms/PipetteWizardFlows/constants'
import { GRIPPER_FLOW_TYPES } from '../../organisms/GripperWizardFlows/constants'

Expand All @@ -38,18 +32,24 @@ import type {
interface InstrumentDetailsOverflowMenuProps {
instrument: PipetteData | GripperData
host: HostConfig | null
toggleDTWiz: () => void
}

export const handleInstrumentDetailOverflowMenu = (
instrument: InstrumentDetailsOverflowMenuProps['instrument'],
host: InstrumentDetailsOverflowMenuProps['host']
host: InstrumentDetailsOverflowMenuProps['host'],
toggleDTWiz: () => void
): void => {
NiceModal.show(InstrumentDetailsOverflowMenu, { instrument, host })
NiceModal.show(InstrumentDetailsOverflowMenu, {
instrument,
host,
toggleDTWiz,
})
}

const InstrumentDetailsOverflowMenu = NiceModal.create(
(props: InstrumentDetailsOverflowMenuProps): JSX.Element => {
const { instrument, host } = props
const { instrument, host, toggleDTWiz } = props
const { t } = useTranslation('robot_controls')
const modal = useModal()
const [wizardProps, setWizardProps] = React.useState<
Expand All @@ -66,9 +66,6 @@ const InstrumentDetailsOverflowMenu = NiceModal.create(
modal.remove()
},
}
const { showDTWiz, toggleDTWiz } = useDropTipWizardFlows()
const pipetteModelSpecs =
getPipetteModelSpecs((instrument as PipetteData).instrumentModel) ?? null

const is96Channel =
instrument?.ok &&
Expand Down Expand Up @@ -97,6 +94,11 @@ const InstrumentDetailsOverflowMenu = NiceModal.create(
}
}

const handleDropTip = (): void => {
toggleDTWiz()
modal.remove()
}

return (
<ApiHostProvider {...host} hostname={host?.hostname ?? null}>
<MenuList onClick={modal.remove} isOnDevice={true}>
Expand All @@ -120,7 +122,7 @@ const InstrumentDetailsOverflowMenu = NiceModal.create(
</MenuItem>
) : null}
{instrument.mount !== 'extension' ? (
<MenuItem key="drop-tips" onClick={toggleDTWiz}>
<MenuItem key="drop-tips" onClick={handleDropTip}>
<Flex alignItems={ALIGN_CENTER}>
<Icon
name="reset-position"
Expand All @@ -144,16 +146,6 @@ const InstrumentDetailsOverflowMenu = NiceModal.create(
{wizardProps != null && !('mount' in wizardProps) ? (
<GripperWizardFlows {...wizardProps} />
) : null}
{showDTWiz &&
instrument.mount !== 'extension' &&
pipetteModelSpecs != null ? (
<DropTipWizardFlows
robotType={FLEX_ROBOT_TYPE}
mount={instrument.mount}
instrumentModelSpecs={pipetteModelSpecs}
closeFlow={modal.remove}
/>
) : null}
</ApiHostProvider>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,29 @@ import {
usePipetteModelSpecs,
} from '../../../resources/instruments/hooks'
import { useIsOEMMode } from '../../../resources/robot-settings/hooks'
import {
DropTipWizardFlows,
useDropTipWizardFlows,
} from '../../../organisms/DropTipWizardFlows'

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

import type * as SharedData from '@opentrons/shared-data'

vi.mock('@opentrons/shared-data', async importOriginal => {
const actual = await importOriginal<typeof SharedData>()
return {
...actual,
getPipetteModelSpecs: vi.fn(),
}
})
vi.mock('@opentrons/react-api-client')
vi.mock('react-router-dom', () => ({
useParams: vi.fn(),
useNavigate: vi.fn(),
}))
vi.mock('../../../resources/instruments/hooks')
vi.mock('../../../resources/robot-settings/hooks')
vi.mock('../../../organisms/DropTipWizardFlows')

const render = () => {
return renderWithProviders(<InstrumentDetail />, {
Expand Down Expand Up @@ -98,6 +111,11 @@ describe('InstrumentDetail', () => {
vi.mocked(useGripperDisplayName).mockReturnValue('mockGripper')
vi.mocked(useParams).mockReturnValue({ mount: 'left' })
vi.mocked(useIsOEMMode).mockReturnValue(false)
vi.mocked(useDropTipWizardFlows).mockReturnValue({
toggleDTWiz: () => null,
showDTWiz: false,
})
vi.mocked(DropTipWizardFlows).mockReturnValue(<div>MOCK_DROP_TIP_WIZ</div>)
})

afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import { handleInstrumentDetailOverflowMenu } from '../InstrumentDetailOverflowM
import { useNotifyCurrentMaintenanceRun } from '../../../resources/maintenance_runs'
import { PipetteWizardFlows } from '../../../organisms/PipetteWizardFlows'
import { GripperWizardFlows } from '../../../organisms/GripperWizardFlows'
import { useDropTipWizardFlows } from '../../../organisms/DropTipWizardFlows'

import type { Mock } from 'vitest'
import type {
PipetteData,
GripperData,
Expand All @@ -31,7 +29,6 @@ vi.mock('@opentrons/shared-data', async importOriginal => {
vi.mock('../../../resources/maintenance_runs')
vi.mock('../../../organisms/PipetteWizardFlows')
vi.mock('../../../organisms/GripperWizardFlows')
vi.mock('../../../organisms/DropTipWizardFlows')

const MOCK_PIPETTE = {
mount: 'left',
Expand Down Expand Up @@ -103,13 +100,18 @@ const MOCK_GRIPPER = {
} as GripperData

const MOCK_HOST: HostConfig = { hostname: 'TEST_HOST' }
const mockToggleDTWiz = vi.fn()

const render = (pipetteOrGripper: PipetteData | GripperData) => {
return renderWithProviders(
<NiceModal.Provider>
<button
onClick={() =>
handleInstrumentDetailOverflowMenu(pipetteOrGripper, MOCK_HOST)
handleInstrumentDetailOverflowMenu(
pipetteOrGripper,
MOCK_HOST,
mockToggleDTWiz
)
}
data-testid="testButton"
/>
Expand All @@ -120,11 +122,7 @@ const render = (pipetteOrGripper: PipetteData | GripperData) => {
)
}

let mockToggleDTWiz: Mock

describe('UpdateBuildroot', () => {
mockToggleDTWiz = vi.fn()

describe('InstrumentDetailOverFlowMenu', () => {
beforeEach(() => {
vi.mocked(getPipetteModelSpecs).mockReturnValue({
displayName: 'mockPipette',
Expand All @@ -136,10 +134,6 @@ describe('UpdateBuildroot', () => {
},
},
} as any)
vi.mocked(useDropTipWizardFlows).mockReturnValue({
showDTWiz: false,
toggleDTWiz: mockToggleDTWiz,
})
})

afterEach(() => {
Expand Down Expand Up @@ -181,13 +175,15 @@ describe('UpdateBuildroot', () => {
expect(vi.mocked(PipetteWizardFlows)).toHaveBeenCalled()
})

it('renders the drop tip wizard when Drop tips is clicked', () => {
it('toggles the drop tip wizard toggle when Drop tips is clicked', () => {
render(MOCK_PIPETTE)
const btn = screen.getByTestId('testButton')
fireEvent.click(btn)
fireEvent.click(screen.getByText('Drop tips'))

expect(vi.mocked(mockToggleDTWiz)).toHaveBeenCalled()
const dtBtn = screen.getByRole('button', { name: /Drop tips/ })
fireEvent.click(dtBtn)

expect(mockToggleDTWiz).toHaveBeenCalled()
})

it('renders the gripper calibration wizard when recalibrate is clicked', () => {
Expand Down
37 changes: 34 additions & 3 deletions app/src/pages/InstrumentDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react'
import { useParams } from 'react-router-dom'
import styled from 'styled-components'
import { createPortal } from 'react-dom'

import { useInstrumentsQuery, useHost } from '@opentrons/react-api-client'
import {
Expand All @@ -13,15 +14,21 @@ import {
DIRECTION_ROW,
JUSTIFY_SPACE_BETWEEN,
} from '@opentrons/components'
import { FLEX_ROBOT_TYPE, getPipetteModelSpecs } from '@opentrons/shared-data'

import { BackButton } from '../../atoms/buttons/BackButton'
import { BackButton } from '../../atoms/buttons'
import { ODD_FOCUS_VISIBLE } from '../../atoms/buttons/constants'
import { InstrumentInfo } from '../../organisms/InstrumentInfo'
import { handleInstrumentDetailOverflowMenu } from '../../pages/InstrumentDetail/InstrumentDetailOverflowMenu'
import { handleInstrumentDetailOverflowMenu } from './InstrumentDetailOverflowMenu'
import {
useGripperDisplayName,
usePipetteModelSpecs,
} from '../../resources/instruments/hooks'
import {
DropTipWizardFlows,
useDropTipWizardFlows,
} from '../../organisms/DropTipWizardFlows'
import { getTopPortalEl } from '../../App/portal'

import type { GripperData, PipetteData } from '@opentrons/api-client'
import type { GripperModel, PipetteModel } from '@opentrons/shared-data'
Expand All @@ -41,12 +48,32 @@ export const InstrumentDetail = (): JSX.Element => {
const gripperDisplayName = useGripperDisplayName(
instrument?.instrumentModel as GripperModel
)
const { showDTWiz, toggleDTWiz } = useDropTipWizardFlows()
const pipetteModelSpecs =
instrument != null
? getPipetteModelSpecs((instrument as PipetteData).instrumentModel) ??
null
: null

const displayName =
instrument?.mount !== 'extension' ? pipetteDisplayName : gripperDisplayName

return (
<>
{showDTWiz &&
instrument != null &&
instrument?.mount !== 'extension' &&
pipetteModelSpecs != null
? createPortal(
<DropTipWizardFlows
robotType={FLEX_ROBOT_TYPE}
mount={instrument.mount}
instrumentModelSpecs={pipetteModelSpecs}
closeFlow={toggleDTWiz}
/>,
getTopPortalEl()
)
: null}
<Flex
padding={`${SPACING.spacing32} ${SPACING.spacing40} ${SPACING.spacing40}`}
flexDirection={DIRECTION_COLUMN}
Expand All @@ -62,7 +89,11 @@ export const InstrumentDetail = (): JSX.Element => {
<IconButton
aria-label="overflow menu button"
onClick={() => {
handleInstrumentDetailOverflowMenu(instrument, host)
handleInstrumentDetailOverflowMenu(
instrument,
host,
toggleDTWiz
)
}}
>
<Icon
Expand Down

0 comments on commit 81770b3

Please sign in to comment.