Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(app): fix dqa ODD protocol setup deck config #14169

Merged
merged 8 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/assets/localization/en/protocol_setup.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
"modules": "Modules",
"mount_title": "{{mount}} MOUNT:",
"mount": "{{mount}} mount",
"multiple_fixtures_missing": "Missing {{count}} fixtures",
"multiple_fixtures_missing": "{{count}} fixtures missing",
"multiple_modules_example": "Your protocol has two Temperature Modules. The Temperature Module attached to the first port starting from the left will be related to the first Temperature Module in your protocol while the second Temperature Module loaded would be related to the Temperature Module connected to the next port to the right. If using a hub, follow the same logic with the port ordering.",
"multiple_modules_explanation": "To use more than one of the same module in a protocol, you first need to plug in the module that’s called first in your protocol to the lowest numbered USB port on the robot. Continue in the same manner with additional modules.",
"multiple_modules_help_link_title": "See How To Set Up Modules of the Same Type",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ import * as React from 'react'
import { when, resetAllWhenMocks } from 'jest-when'

import { renderWithProviders, BaseDeck } from '@opentrons/components'
import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client'
import {
useDeckConfigurationQuery,
useUpdateDeckConfigurationMutation,
} from '@opentrons/react-api-client'

import { i18n } from '../../../i18n'
import { useMostRecentCompletedAnalysis } from '../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
import { ProtocolSetupDeckConfiguration } from '..'

import type { CompletedProtocolAnalysis } from '@opentrons/shared-data'
import type { UseQueryResult } from 'react-query'
import type {
CompletedProtocolAnalysis,
DeckConfiguration,
} from '@opentrons/shared-data'

jest.mock('@opentrons/components/src/hardware-sim/BaseDeck/index')
jest.mock('@opentrons/react-api-client')
Expand All @@ -33,6 +40,9 @@ const mockUseUpdateDeckConfigurationMutation = useUpdateDeckConfigurationMutatio
typeof useUpdateDeckConfigurationMutation
>
const mockBaseDeck = BaseDeck as jest.MockedFunction<typeof BaseDeck>
const mockUseDeckConfigurationQuery = useDeckConfigurationQuery as jest.MockedFunction<
typeof useDeckConfigurationQuery
>

const render = (
props: React.ComponentProps<typeof ProtocolSetupDeckConfiguration>
Expand All @@ -59,6 +69,9 @@ describe('ProtocolSetupDeckConfiguration', () => {
mockUseUpdateDeckConfigurationMutation.mockReturnValue({
updateDeckConfiguration: mockUpdateDeckConfiguration,
} as any)
mockUseDeckConfigurationQuery.mockReturnValue(({
data: [],
} as unknown) as UseQueryResult<DeckConfiguration>)
})

afterEach(() => {
Expand Down
23 changes: 19 additions & 4 deletions app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
FLEX_ROBOT_TYPE,
getSimplestDeckConfigForProtocol,
} from '@opentrons/shared-data'
import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client'
import {
useDeckConfigurationQuery,
useUpdateDeckConfigurationMutation,
} from '@opentrons/react-api-client'

import { ChildNavigation } from '../ChildNavigation'
import { AddFixtureModal } from '../DeviceDetailsDeckConfiguration/AddFixtureModal'
Expand Down Expand Up @@ -52,15 +55,26 @@ export function ProtocolSetupDeckConfiguration({
] = React.useState<boolean>(false)

const mostRecentAnalysis = useMostRecentCompletedAnalysis(runId)
const { data: deckConfig = [] } = useDeckConfigurationQuery()

const simplestDeckConfig = getSimplestDeckConfigForProtocol(
mostRecentAnalysis
).map(({ cutoutId, cutoutFixtureId }) => ({ cutoutId, cutoutFixtureId }))

const targetDeckConfig = simplestDeckConfig.find(
deck => deck.cutoutId === cutoutId
)

const mergedDeckConfig = deckConfig.map(config =>
targetDeckConfig != null && config.cutoutId === targetDeckConfig.cutoutId
? targetDeckConfig
: config
)

const [
currentDeckConfig,
setCurrentDeckConfig,
] = React.useState<DeckConfiguration>(simplestDeckConfig)
] = React.useState<DeckConfiguration>(mergedDeckConfig)

const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation()
const handleClickConfirm = (): void => {
Expand Down Expand Up @@ -94,12 +108,13 @@ export function ProtocolSetupDeckConfiguration({
onClickButton={handleClickConfirm}
/>
<Flex
koji marked this conversation as resolved.
Show resolved Hide resolved
marginTop="7.75rem"
marginTop="4rem"
paddingX={SPACING.spacing40}
justifyContent={JUSTIFY_CENTER}
height="28.4375rem"
>
<BaseDeck
deckConfig={simplestDeckConfig}
deckConfig={currentDeckConfig}
robotType={FLEX_ROBOT_TYPE}
/>
</Flex>
Expand Down
51 changes: 39 additions & 12 deletions app/src/pages/OnDeviceDisplay/ProtocolSetup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
getDeckDefFromRobotType,
getModuleDisplayName,
getFixtureDisplayName,
SINGLE_SLOT_FIXTURES,
} from '@opentrons/shared-data'

import { StyledText } from '../../../atoms/text'
Expand Down Expand Up @@ -80,6 +81,8 @@
import { ConfirmAttachedModal } from './ConfirmAttachedModal'
import { getLatestCurrentOffsets } from '../../../organisms/Devices/ProtocolRun/SetupLabwarePositionCheck/utils'
import { CloseButton, PlayButton } from './Buttons'
import { useDeckConfigurationCompatibility } from '../../../resources/deck_configuration/hooks'
import { getRequiredDeckConfig } from '../../../resources/deck_configuration/utils'

import type { CutoutFixtureId, CutoutId } from '@opentrons/shared-data'
import type { OnDeviceRouteParams } from '../../../App/types'
Expand Down Expand Up @@ -302,6 +305,14 @@
setShowConfirmCancelModal,
] = React.useState<boolean>(false)

const deckConfigCompatibility = useDeckConfigurationCompatibility(
robotType,
mostRecentAnalysis
)
const requiredDeckConfigCompatibility = getRequiredDeckConfig(
deckConfigCompatibility
)

// True if any server request is still pending.
const isLoading =
mostRecentAnalysis == null ||
Expand All @@ -314,24 +325,43 @@
(getProtocolUsesGripper(mostRecentAnalysis) ? 1 : 0)
: 0

const missingProtocolHardware = useMissingProtocolHardwareFromAnalysis(
const { missingProtocolHardware } = useMissingProtocolHardwareFromAnalysis(
robotType,
mostRecentAnalysis
)
const isLocationConflict = missingProtocolHardware.conflictedSlots.length > 0

const missingPipettes = missingProtocolHardware.missingProtocolHardware.filter(
const locationConflictSlots = requiredDeckConfigCompatibility.map(
fixtureCompatibility => {
const {
compatibleCutoutFixtureIds,
cutoutFixtureId,
} = fixtureCompatibility

Check warning on line 338 in app/src/pages/OnDeviceDisplay/ProtocolSetup/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/OnDeviceDisplay/ProtocolSetup/index.tsx#L338

Added line #L338 was not covered by tests
const isCurrentFixtureCompatible =
cutoutFixtureId != null &&
compatibleCutoutFixtureIds.includes(cutoutFixtureId)
return (

Check warning on line 342 in app/src/pages/OnDeviceDisplay/ProtocolSetup/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/OnDeviceDisplay/ProtocolSetup/index.tsx#L342

Added line #L342 was not covered by tests
!isCurrentFixtureCompatible &&
cutoutFixtureId != null &&
!SINGLE_SLOT_FIXTURES.includes(cutoutFixtureId)
)
}
)
const isLocationConflict = locationConflictSlots.some(
conflictSlot => conflictSlot

Check warning on line 350 in app/src/pages/OnDeviceDisplay/ProtocolSetup/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/OnDeviceDisplay/ProtocolSetup/index.tsx#L350

Added line #L350 was not covered by tests
)

const missingPipettes = missingProtocolHardware.filter(
hardware => hardware.hardwareType === 'pipette'
)

const missingGripper = missingProtocolHardware.missingProtocolHardware.filter(
const missingGripper = missingProtocolHardware.filter(
hardware => hardware.hardwareType === 'gripper'
)

const missingModules = missingProtocolHardware.missingProtocolHardware.filter(
const missingModules = missingProtocolHardware.filter(
hardware => hardware.hardwareType === 'module'
)
const missingFixtures = missingProtocolHardware.missingProtocolHardware.filter(
const missingFixtures = missingProtocolHardware.filter(
koji marked this conversation as resolved.
Show resolved Hide resolved
(hardware): hardware is ProtocolFixture =>
hardware.hardwareType === 'fixture'
)
Expand Down Expand Up @@ -374,11 +404,8 @@
? 'ready'
: 'not ready'

// TODO: (ND: 11/6/23) check for areFixturesReady once we removed stubbed fixtures in useRequiredProtocolHardwareFromAnalysis
// const isReadyToRun =
// incompleteInstrumentCount === 0 && areModulesReady && areFixturesReady

const isReadyToRun = incompleteInstrumentCount === 0 && areModulesReady
const isReadyToRun =
incompleteInstrumentCount === 0 && areModulesReady && areFixturesReady
const onPlay = (): void => {
if (isDoorOpen) {
makeSnackbar(t('shared:close_robot_door'))
Expand Down Expand Up @@ -748,7 +775,7 @@
padding={
setupScreen === 'prepare to run'
? `0 ${SPACING.spacing32} ${SPACING.spacing40}`
: `${SPACING.spacing32} ${SPACING.spacing40}`
: `${SPACING.spacing32} ${SPACING.spacing40} ${SPACING.spacing40}`
}
>
{setupComponentByScreen[setupScreen]}
Expand Down
Loading