diff --git a/app/src/organisms/DropTipWizardFlows/hooks/useDropTipCommands.ts b/app/src/organisms/DropTipWizardFlows/hooks/useDropTipCommands.ts index c6921c5e203..c4036d04d1e 100644 --- a/app/src/organisms/DropTipWizardFlows/hooks/useDropTipCommands.ts +++ b/app/src/organisms/DropTipWizardFlows/hooks/useDropTipCommands.ts @@ -359,12 +359,13 @@ const buildMoveToAACommand = ( export const buildLoadPipetteCommand = ( pipetteName: PipetteModelSpecs['name'], - mount: PipetteData['mount'] + mount: PipetteData['mount'], + pipetteId?: string | null ): CreateCommand => { return { commandType: 'loadPipette', params: { - pipetteId: MANAGED_PIPETTE_ID, + pipetteId: pipetteId ?? MANAGED_PIPETTE_ID, mount, pipetteName, }, diff --git a/app/src/organisms/DropTipWizardFlows/hooks/useDropTipWithType.ts b/app/src/organisms/DropTipWizardFlows/hooks/useDropTipWithType.ts index 33ea2a116fd..951b29c6266 100644 --- a/app/src/organisms/DropTipWizardFlows/hooks/useDropTipWithType.ts +++ b/app/src/organisms/DropTipWizardFlows/hooks/useDropTipWithType.ts @@ -117,10 +117,15 @@ function useRegisterPipetteFixitType({ instrumentModelSpecs, issuedCommandsType, chainRunCommands, + fixitCommandTypeUtils, }: UseRegisterPipetteFixitType): void { React.useEffect(() => { if (issuedCommandsType === 'fixit') { - const command = buildLoadPipetteCommand(instrumentModelSpecs.name, mount) + const command = buildLoadPipetteCommand( + instrumentModelSpecs.name, + mount, + fixitCommandTypeUtils?.pipetteId + ) void chainRunCommands([command], true) } }, []) diff --git a/app/src/organisms/DropTipWizardFlows/types.ts b/app/src/organisms/DropTipWizardFlows/types.ts index 15a9e25cc9e..4238d9ac8a0 100644 --- a/app/src/organisms/DropTipWizardFlows/types.ts +++ b/app/src/organisms/DropTipWizardFlows/types.ts @@ -36,6 +36,7 @@ export interface DropTipWizardRouteOverride { export interface FixitCommandTypeUtils { runId: string failedCommandId: string + pipetteId: string | null copyOverrides: CopyOverrides errorOverrides: ErrorOverrides buttonOverrides: ButtonOverrides diff --git a/app/src/organisms/ErrorRecoveryFlows/RecoveryError.tsx b/app/src/organisms/ErrorRecoveryFlows/RecoveryError.tsx index 370b80174a6..4f2128b2253 100644 --- a/app/src/organisms/ErrorRecoveryFlows/RecoveryError.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/RecoveryError.tsx @@ -1,5 +1,6 @@ import * as React from 'react' import { useTranslation } from 'react-i18next' +import { css } from 'styled-components' import { COLORS, @@ -10,13 +11,21 @@ import { SPACING, ALIGN_CENTER, JUSTIFY_END, + PrimaryButton, + JUSTIFY_CENTER, + RESPONSIVENESS, } from '@opentrons/components' -import { RECOVERY_MAP } from './constants' +import { SmallButton } from '../../atoms/buttons' import { RecoverySingleColumnContentWrapper } from './shared' +import { + DESKTOP_ONLY, + ICON_SIZE_ALERT_INFO_STYLE, + ODD_ONLY, + RECOVERY_MAP, +} from './constants' import type { RecoveryContentProps } from './types' -import { SmallButton } from '../../atoms/buttons' export function RecoveryError(props: RecoveryContentProps): JSX.Element { const { recoveryMap } = props @@ -155,7 +164,6 @@ export function RecoveryDropTipFlowErrors({ } export function ErrorContent({ - isOnDevice, title, subTitle, btnText, @@ -169,19 +177,12 @@ export function ErrorContent({ }): JSX.Element | null { return ( - + - + + + {btnText} + ) } + +const CONTAINER_STYLE = css` + padding: ${SPACING.spacing40}; + grid-gap: ${SPACING.spacing16}; + flex-direction: ${DIRECTION_COLUMN}; + align-items: ${ALIGN_CENTER}; + justify-content: ${JUSTIFY_CENTER}; + flex: 1; + + @media (${RESPONSIVENESS.touchscreenMediaQuerySpecs}) { + grid-gap: ${SPACING.spacing24}; + } +` diff --git a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/ManageTips.tsx b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/ManageTips.tsx index 58999c0cabb..271c2f0f070 100644 --- a/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/ManageTips.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/RecoveryOptions/ManageTips.tsx @@ -301,9 +301,17 @@ export function useDropTipFlowUtils({ } } + const pipetteId = + failedCommand != null && + 'params' in failedCommand.byRunRecord && + 'pipetteId' in failedCommand.byRunRecord.params + ? failedCommand.byRunRecord.params.pipetteId + : null + return { runId, failedCommandId, + pipetteId, copyOverrides: buildCopyOverrides(), errorOverrides: buildErrorOverrides(), buttonOverrides: buildButtonOverrides(), diff --git a/app/src/organisms/ErrorRecoveryFlows/__tests__/RecoveryError.test.tsx b/app/src/organisms/ErrorRecoveryFlows/__tests__/RecoveryError.test.tsx index d3b0d4dd629..e77e3e280aa 100644 --- a/app/src/organisms/ErrorRecoveryFlows/__tests__/RecoveryError.test.tsx +++ b/app/src/organisms/ErrorRecoveryFlows/__tests__/RecoveryError.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable testing-library/prefer-presence-queries */ import * as React from 'react' import { describe, it, vi, expect, beforeEach } from 'vitest' import { screen, fireEvent } from '@testing-library/react' @@ -48,13 +49,13 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.RECOVERY_ACTION_FAILED render(props) - expect(screen.getByText('Retry step failed')).toBeInTheDocument() + expect(screen.queryAllByText('Retry step failed')[0]).toBeInTheDocument() expect( - screen.getByText( + screen.queryAllByText( 'Next, you can try another recovery action or cancel the run.' - ) + )[0] ).toBeInTheDocument() - expect(screen.getByText('Back to menu')).toBeInTheDocument() + expect(screen.queryAllByText('Back to menu')[0]).toBeInTheDocument() }) it(`renders RecoveryDropTipFlowErrors when step is ${ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_GENERAL_ERROR}`, () => { @@ -62,13 +63,13 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_GENERAL_ERROR render(props) - expect(screen.getByText('Retry step failed')).toBeInTheDocument() + expect(screen.queryAllByText('Retry step failed')[0]).toBeInTheDocument() expect( - screen.getByText( + screen.queryAllByText( 'Next, you can try another recovery action or cancel the run.' - ) + )[0] ).toBeInTheDocument() - expect(screen.getByText('Return to menu')).toBeInTheDocument() + expect(screen.queryAllByText('Return to menu')[0]).toBeInTheDocument() }) it(`renders RecoveryDropTipFlowErrors when step is ${ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_BLOWOUT_FAILED}`, () => { @@ -76,13 +77,13 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_BLOWOUT_FAILED render(props) - expect(screen.getByText('Blowout failed')).toBeInTheDocument() + expect(screen.queryAllByText('Blowout failed')[0]).toBeInTheDocument() expect( - screen.getByText( + screen.queryAllByText( 'You can still drop the attached tips before proceeding to tip selection.' - ) + )[0] ).toBeInTheDocument() - expect(screen.getByText('Continue to drop tip')).toBeInTheDocument() + expect(screen.queryAllByText('Continue to drop tip')[0]).toBeInTheDocument() }) it(`renders RecoveryDropTipFlowErrors when step is ${ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_TIP_DROP_FAILED}`, () => { @@ -90,13 +91,13 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_TIP_DROP_FAILED render(props) - expect(screen.getByText('Tip drop failed')).toBeInTheDocument() + expect(screen.queryAllByText('Tip drop failed')[0]).toBeInTheDocument() expect( - screen.getByText( + screen.queryAllByText( 'Next, you can try another recovery action or cancel the run.' - ) + )[0] ).toBeInTheDocument() - expect(screen.getByText('Return to menu')).toBeInTheDocument() + expect(screen.queryAllByText('Return to menu')[0]).toBeInTheDocument() }) it(`calls proceedToRouteAndStep with ${RECOVERY_MAP.OPTION_SELECTION.ROUTE} when the "Back to menu" button is clicked in ErrorRecoveryFlowError`, () => { @@ -104,7 +105,7 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.RECOVERY_ACTION_FAILED render(props) - fireEvent.click(screen.getByText('Back to menu')) + fireEvent.click(screen.queryAllByText('Back to menu')[0]) expect(proceedToRouteAndStepMock).toHaveBeenCalledWith( RECOVERY_MAP.OPTION_SELECTION.ROUTE @@ -116,7 +117,7 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_GENERAL_ERROR render(props) - fireEvent.click(screen.getByText('Return to menu')) + fireEvent.click(screen.queryAllByText('Return to menu')[0]) expect(proceedToRouteAndStepMock).toHaveBeenCalledWith( RECOVERY_MAP.OPTION_SELECTION.ROUTE @@ -128,7 +129,7 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_TIP_DROP_FAILED render(props) - fireEvent.click(screen.getByText('Return to menu')) + fireEvent.click(screen.queryAllByText('Return to menu')[0]) expect(proceedToRouteAndStepMock).toHaveBeenCalledWith( RECOVERY_MAP.OPTION_SELECTION.ROUTE @@ -140,7 +141,7 @@ describe('RecoveryError', () => { RECOVERY_MAP.ERROR_WHILE_RECOVERING.STEPS.DROP_TIP_BLOWOUT_FAILED render(props) - fireEvent.click(screen.getByText('Continue to drop tip')) + fireEvent.click(screen.queryAllByText('Continue to drop tip')[0]) expect(proceedToRouteAndStepMock).toHaveBeenCalledWith( RECOVERY_MAP.DROP_TIP_FLOWS.ROUTE,