Skip to content

Commit

Permalink
refactor: use deckmap in error recovery
Browse files Browse the repository at this point in the history
Two places in error recovery, refactoring as we go.

One big change was that there was a bunch of stuff called RecoveryMap as
in recovery (deck) map, but recovery also has the Recovery Map, the big
data structure that holds how all the steps of error recovery flow
together. This is very confusing, so now what used to be
RecoveryMap (component, utils) is now DeckMap.
  • Loading branch information
sfoster1 committed Jul 3, 2024
1 parent 6793319 commit 12b4a70
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ import {
RecoveryFooterButtons,
RecoverySingleColumnContent,
LeftColumnLabwareInfo,
RecoveryMap,
TwoColTextAndFailedStepNextStep,
} from '../shared'
import { TwoColumn } from '../../../molecules/InterventionModal'
import { TwoColumn, DeckMapContent } from '../../../molecules/InterventionModal'
import { SelectRecoveryOption } from './SelectRecoveryOption'

import type { RecoveryContentProps } from '../types'
Expand Down Expand Up @@ -45,7 +44,12 @@ export function FillWellAndSkip(props: RecoveryContentProps): JSX.Element {
}

export function FillWell(props: RecoveryContentProps): JSX.Element | null {
const { isOnDevice, routeUpdateActions, failedLabwareUtils } = props
const {
isOnDevice,
routeUpdateActions,
failedLabwareUtils,
deckMapUtils,
} = props
const { t } = useTranslation('error_recovery')
const { goBackPrevStep, proceedNextStep } = routeUpdateActions

Expand All @@ -63,7 +67,7 @@ export function FillWell(props: RecoveryContentProps): JSX.Element | null {
/>
</Flex>
<Flex marginTop="1.742rem">
<RecoveryMap {...props} />
<DeckMapContent {...deckMapUtils} />
</Flex>
</TwoColumn>
<RecoveryFooterButtons
Expand Down
2 changes: 1 addition & 1 deletion app/src/organisms/ErrorRecoveryFlows/__fixtures__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const mockRecoveryContentProps: RecoveryContentProps = {
currentRecoveryOptionUtils: {} as any,
failedLabwareUtils: { pickUpTipLabware: mockPickUpTipLabware } as any,
failedPipetteInfo: {} as any,
recoveryMapUtils: {} as any,
deckMapUtils: {} as any,
stepCounts: {} as any,
protocolAnalysis: { commands: [mockFailedCommand] } as any,
trackExternalMap: () => null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as React from 'react'
import { describe, it, expect, beforeEach, vi } from 'vitest'

import {
Expand All @@ -17,8 +16,7 @@ import {
getRunCurrentModulesInfo,
getRunCurrentLabwareOnDeck,
getRunCurrentModulesOnDeck,
} from '../useRecoveryMapUtils'
import { LabwareHighlight } from '../../shared'
} from '../useDeckMapUtils'

import type { LabwareDefinition2 } from '@opentrons/shared-data'

Expand Down Expand Up @@ -78,13 +76,11 @@ describe('getRunCurrentModulesOnDeck', () => {
moduleLocation: { slotName: 'A1' },
innerProps: {},
nestedLabwareDef: mockLabwareDef,
moduleChildren: (
<LabwareHighlight highlight={true} definition={mockLabwareDef} />
),
highlight: 'MOCK_MODULE_ID',
},
])
})
it('should set moduleChildren to null if getIsLabwareMatch returns false', () => {
it('should set highlight to null if getIsLabwareMatch returns false', () => {
const result = getRunCurrentModulesOnDeck({
failedLabwareUtils: mockFailedLabwareUtils,
currentModulesInfo: [
Expand All @@ -95,18 +91,18 @@ describe('getRunCurrentModulesOnDeck', () => {
],
})

expect(result[0].moduleChildren).toBeNull()
expect(result[0].highlight).toBeNull()
})

it('should set moduleChildren to null if nestedLabwareDef is null', () => {
it('should set highlight to null if nestedLabwareDef is null', () => {
const result = getRunCurrentModulesOnDeck({
failedLabwareUtils: mockFailedLabwareUtils,
currentModulesInfo: [
{ ...mockCurrentModulesInfo[0], nestedLabwareDef: null },
],
})

expect(result[0].moduleChildren).toBeNull()
expect(result[0].highlight).toBeNull()
})
})

Expand Down Expand Up @@ -139,14 +135,12 @@ describe('getRunCurrentLabwareOnDeck', () => {
{
labwareLocation: { slotName: 'A1' },
definition: mockLabwareDef,
labwareChildren: (
<LabwareHighlight highlight={true} definition={mockLabwareDef} />
),
highlight: 'A1',
},
])
})

it('should set labwareChildren to null if getIsLabwareMatch returns false', () => {
it('should set highlight to null if getIsLabwareMatch returns false', () => {
const result = getRunCurrentLabwareOnDeck({
failedLabwareUtils: {
...mockFailedLabwareUtils,
Expand All @@ -158,7 +152,7 @@ describe('getRunCurrentLabwareOnDeck', () => {
currentLabwareInfo: [mockCurrentLabwareInfo],
})

expect(result[0].labwareChildren).toBeNull()
expect(result[0].highlight).toBeNull()
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import {
THERMOCYCLER_MODULE_V1,
} from '@opentrons/shared-data'

import { LabwareHighlight } from '../shared'

import type { Run } from '@opentrons/api-client'
import type {
DeckDefinition,
Expand All @@ -21,29 +19,33 @@ import type {
LabwareLocation,
CutoutConfigProtocolSpec,
LoadedLabware,
RobotType,
} from '@opentrons/shared-data'
import type { ErrorRecoveryFlowsProps } from '..'
import type { UseFailedLabwareUtilsResult } from './useFailedLabwareUtils'

interface UseRecoveryMapUtilsProps {
interface UseDeckMapUtilsProps {
runId: ErrorRecoveryFlowsProps['runId']
protocolAnalysis: ErrorRecoveryFlowsProps['protocolAnalysis']
failedLabwareUtils: UseFailedLabwareUtilsResult
runRecord?: Run
}

export interface UseRecoveryMapUtilsResult {
export interface UseDeckMapUtilsResult {
deckConfig: CutoutConfigProtocolSpec[]
runCurrentModules: RunCurrentModulesOnDeck[]
runCurrentLabware: RunCurrentLabwareOnDeck[]
modulesOnDeck: RunCurrentModulesOnDeck[]
labwareOnDeck: RunCurrentLabwareOnDeck[]
highlightLabwareEventuallyIn: string[]
kind: 'intervention'
robotType: RobotType
}
// Returns the utilities needed by the Recovery Deck Map.
export function useRecoveryMapUtils({
export function useDeckMapUtils({
protocolAnalysis,
runRecord,
runId,
failedLabwareUtils,
}: UseRecoveryMapUtilsProps): UseRecoveryMapUtilsResult {
}: UseDeckMapUtilsProps): UseDeckMapUtilsResult {
const robotType = protocolAnalysis?.robotType ?? OT2_ROBOT_TYPE
const deckConfig = getSimplestDeckConfigForProtocol(protocolAnalysis)
const deckDef = getDeckDefFromRobotType(robotType)
Expand Down Expand Up @@ -83,8 +85,23 @@ export function useRecoveryMapUtils({

return {
deckConfig,
runCurrentModules,
runCurrentLabware,
modulesOnDeck: runCurrentModules.map(
({ moduleModel, moduleLocation, innerProps, nestedLabwareDef }) => ({
moduleModel,
moduleLocation,
innerProps,
nestedLabwareDef,
})
),
labwareOnDeck: runCurrentLabware.map(({ labwareLocation, definition }) => ({
labwareLocation,
definition,
})),
highlightLabwareEventuallyIn: [...runCurrentModules, ...runCurrentLabware]
.map(el => el.highlight)
.filter(maybeSlot => maybeSlot != null) as string[],
kind: 'intervention',
robotType,
}
}

Expand All @@ -101,70 +118,56 @@ interface RunCurrentModulesOnDeck {
lidMotorState?: undefined
}
nestedLabwareDef: LabwareDefinition2 | null
moduleChildren: JSX.Element | null
}

// Builds the necessary module object expected by BaseDeck.
export function getRunCurrentModulesOnDeck({
failedLabwareUtils,
currentModulesInfo,
}: {
failedLabwareUtils: UseRecoveryMapUtilsProps['failedLabwareUtils']
failedLabwareUtils: UseDeckMapUtilsProps['failedLabwareUtils']
currentModulesInfo: RunCurrentModuleInfo[]
}): RunCurrentModulesOnDeck[] {
}): Array<RunCurrentModulesOnDeck & { highlight: string | null }> {
const { failedLabware } = failedLabwareUtils

return currentModulesInfo.map(
({ moduleDef, slotName, nestedLabwareDef, nestedLabwareSlotName }) => {
const isLabwareMatch = getIsLabwareMatch(
nestedLabwareSlotName,
failedLabware
)

return {
moduleModel: moduleDef.model,
moduleLocation: { slotName },
innerProps:
moduleDef.model === THERMOCYCLER_MODULE_V1
? { lidMotorState: 'open' }
: {},

nestedLabwareDef,
moduleChildren:
isLabwareMatch && nestedLabwareDef != null ? (
<LabwareHighlight highlight={true} definition={nestedLabwareDef} />
) : null,
}
}
({ moduleDef, slotName, nestedLabwareDef, nestedLabwareSlotName }) => ({
moduleModel: moduleDef.model,
moduleLocation: { slotName },
innerProps:
moduleDef.model === THERMOCYCLER_MODULE_V1
? { lidMotorState: 'open' }
: {},

nestedLabwareDef,
highlight: getIsLabwareMatch(nestedLabwareSlotName, failedLabware)
? nestedLabwareSlotName
: null,
})
)
}

interface RunCurrentLabwareOnDeck {
labwareLocation: LabwareLocation
definition: LabwareDefinition2
labwareChildren: JSX.Element | null
}
// Builds the necessary labware object expected by BaseDeck.
export function getRunCurrentLabwareOnDeck({
currentLabwareInfo,
failedLabwareUtils,
}: {
failedLabwareUtils: UseRecoveryMapUtilsProps['failedLabwareUtils']
failedLabwareUtils: UseDeckMapUtilsProps['failedLabwareUtils']
currentLabwareInfo: RunCurrentLabwareInfo[]
}): RunCurrentLabwareOnDeck[] {
}): Array<RunCurrentLabwareOnDeck & { highlight: string | null }> {
const { failedLabware } = failedLabwareUtils

return currentLabwareInfo.map(({ slotName, labwareDef, labwareLocation }) => {
const isLabwareMatch = getIsLabwareMatch(slotName, failedLabware)

return {
return currentLabwareInfo.map(
({ slotName, labwareDef, labwareLocation }) => ({
labwareLocation,
definition: labwareDef,
labwareChildren: isLabwareMatch ? (
<LabwareHighlight highlight={true} definition={labwareDef} />
) : null,
}
})
highlight: getIsLabwareMatch(slotName, failedLabware) ? slotName : null,
})
)
}

interface RunCurrentModuleInfo {
Expand All @@ -181,8 +184,8 @@ export const getRunCurrentModulesInfo = ({
deckDef,
protocolAnalysis,
}: {
protocolAnalysis: UseRecoveryMapUtilsProps['protocolAnalysis']
runRecord: UseRecoveryMapUtilsProps['runRecord']
protocolAnalysis: UseDeckMapUtilsProps['protocolAnalysis']
runRecord: UseDeckMapUtilsProps['runRecord']
deckDef: DeckDefinition
}): RunCurrentModuleInfo[] => {
if (runRecord == null || protocolAnalysis == null) {
Expand Down Expand Up @@ -248,8 +251,8 @@ export function getRunCurrentLabwareInfo({
runRecord,
protocolAnalysis,
}: {
runRecord: UseRecoveryMapUtilsProps['runRecord']
protocolAnalysis: UseRecoveryMapUtilsProps['protocolAnalysis']
runRecord: UseDeckMapUtilsProps['runRecord']
protocolAnalysis: UseDeckMapUtilsProps['protocolAnalysis']
}): RunCurrentLabwareInfo[] {
if (runRecord == null || protocolAnalysis == null) {
return []
Expand Down
10 changes: 5 additions & 5 deletions app/src/organisms/ErrorRecoveryFlows/hooks/useERUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useRecoveryTipStatus } from './useRecoveryTipStatus'
import { useRecoveryRouting } from './useRecoveryRouting'
import { useFailedLabwareUtils } from './useFailedLabwareUtils'
import { getFailedCommandPipetteInfo, getNextStep } from '../utils'
import { useRecoveryMapUtils } from './useRecoveryMapUtils'
import { useDeckMapUtils } from './useDeckMapUtils'
import {
useNotifyAllCommandsQuery,
useNotifyRunQuery,
Expand All @@ -21,7 +21,7 @@ import type { UseRouteUpdateActionsResult } from './useRouteUpdateActions'
import type { UseRecoveryCommandsResult } from './useRecoveryCommands'
import type { RecoveryTipStatusUtils } from './useRecoveryTipStatus'
import type { UseFailedLabwareUtilsResult } from './useFailedLabwareUtils'
import type { UseRecoveryMapUtilsResult } from './useRecoveryMapUtils'
import type { UseDeckMapUtilsResult } from './useDeckMapUtils'
import type { CurrentRecoveryOptionUtils } from './useRecoveryRouting'
import type { StepCounts } from '../../../resources/protocols/hooks'

Expand All @@ -37,7 +37,7 @@ export interface ERUtilsResults {
recoveryCommands: UseRecoveryCommandsResult
tipStatusUtils: RecoveryTipStatusUtils
failedLabwareUtils: UseFailedLabwareUtilsResult
recoveryMapUtils: UseRecoveryMapUtilsResult
deckMapUtils: UseDeckMapUtilsResult
getRecoveryOptionCopy: ReturnType<typeof useRecoveryOptionCopy>
failedPipetteInfo: PipetteData | null
hasLaunchedRecovery: boolean
Expand Down Expand Up @@ -109,7 +109,7 @@ export function useERUtils({
routeUpdateActions,
})

const recoveryMapUtils = useRecoveryMapUtils({
const deckMapUtils = useDeckMapUtils({
runId,
runRecord,
protocolAnalysis,
Expand All @@ -133,7 +133,7 @@ export function useERUtils({
tipStatusUtils,
failedLabwareUtils,
failedPipetteInfo,
recoveryMapUtils,
deckMapUtils,
getRecoveryOptionCopy,
stepCounts,
commandAfterFailedCommand,
Expand Down
Loading

0 comments on commit 12b4a70

Please sign in to comment.