From 02eb9fc0ee725a6e867aebfcb4b5730e4b518247 Mon Sep 17 00:00:00 2001 From: Rhyann Clarke Date: Mon, 17 Nov 2025 16:48:26 -0500 Subject: [PATCH 1/3] refactor(app): remove start run disablement and replace with toast --- .../assets/localization/en/run_details.json | 5 ++ .../hooks/useActionBtnDisabledUtils.ts | 61 ++++++++++++++----- .../hooks/useActionButtonProperties.ts | 36 +++++++++++ .../RunHeaderContent/ActionButton/index.tsx | 26 +------- 4 files changed, 89 insertions(+), 39 deletions(-) diff --git a/app/src/assets/localization/en/run_details.json b/app/src/assets/localization/en/run_details.json index 20d99f2defa..cb4d86fb66b 100644 --- a/app/src/assets/localization/en/run_details.json +++ b/app/src/assets/localization/en/run_details.json @@ -68,6 +68,7 @@ "error_type": "Error: {{errorType}}", "failed_step": "Failed step", "final_step": "Final Step", + "fixture_mismatch": "Deck configuration does not match protocol needs.", "ignore_stored_data": "Ignore stored data", "image_at_step_at_timestamp": "Image at {{step}} at {{timestamp}}", "image_capture": "Image capture", @@ -77,6 +78,7 @@ "image_loading": "Image loading", "images": "Images", "images_available_download": "Image files associated with the run are available on the robot’s Recent Runs screen and Camera tab.", + "instrument_calibration_incomplete": "Instrument calibration is incomplete.", "labware": "labware", "labware_offset_data": "labware offset data", "left": "Left", @@ -91,7 +93,9 @@ "loading_data": "Loading data...", "loading_protocol": "Loading Protocol", "location": "location", + "module_calibration_incomplete": "Module calibration is incomplete.", "module_controls": "Module Controls", + "modules_missing": "Modules are missing.", "module_slot_number": "Slot {{slot_number}}", "move_labware": "Move Labware", "na": "N/A", @@ -141,6 +145,7 @@ "robot_was_recalibrated": "This robot was recalibrated after this Labware Offset data was stored.", "run": "Run", "run_again": "Run again", + "run_again_disabled": "Run again is disabled for this protocol", "run_canceled": "Run canceled.", "run_canceled_splash": "Run canceled", "run_canceled_with_errors": "Run canceled with errors.", diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts index 0b737137d33..00e1234558c 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts @@ -2,6 +2,13 @@ import { useTranslation } from 'react-i18next' import { RUN_STATUS_BLOCKED_BY_OPEN_DOOR } from '@opentrons/api-client' +import { + useCurrentRunId, + useModuleCalibrationStatus, + useRunCalibrationStatus, + useUnmatchedModulesForProtocol, +} from '/app/resources/runs' + import { useIsDoorOpen } from '../../../hooks' import { isCancellableStatus, @@ -14,7 +21,8 @@ import type { BaseActionButtonProps } from '..' import type { DoorResult } from '../../../../../../../DoorOpenControl/useIsDoorOpen' interface UseActionButtonDisabledUtilsProps extends BaseActionButtonProps { - isCurrentRun: boolean + robotName: string + runId: string isValidRunAgain: boolean isSetupComplete: boolean isOtherRunCurrent: boolean @@ -25,7 +33,7 @@ interface UseActionButtonDisabledUtilsProps extends BaseActionButtonProps { } type UseActionButtonDisabledUtilsResult = - | { isDisabled: true; disabledReason: string | null } + | { isDisabled: true; disabledReason: string } | { isDisabled: false; disabledReason: null } // Manages the various reasons the ActionButton may be disabled, returning the disabled state and user-facing disabled @@ -34,7 +42,6 @@ export function useActionBtnDisabledUtils( props: UseActionButtonDisabledUtilsProps ): UseActionButtonDisabledUtilsResult { const { - isCurrentRun, isSetupComplete, isOtherRunCurrent, isProtocolNotReady, @@ -52,9 +59,21 @@ export function useActionBtnDisabledUtils( const doorStatus = useIsDoorOpen(robotName) const isFixtureMismatch = useIsFixtureMismatch(runId, robotName) const isResetRunLoading = isResetRunLoadingRef.current + const isCurrentRun = useCurrentRunId() === runId + const isCalibrationComplete = !useRunCalibrationStatus(robotName, runId) + .complete + const isModuleCalibrationComplete = !useModuleCalibrationStatus( + robotName, + runId + ).complete + const { missingModuleIds } = useUnmatchedModulesForProtocol(robotName, runId) + const isMissingModules = missingModuleIds.length > 0 const isDisabled = (isCurrentRun && !isSetupComplete) || + isMissingModules || + isModuleCalibrationComplete || + isCalibrationComplete || isPlayRunActionLoading || isPauseRunActionLoading || isResetRunLoading || @@ -69,10 +88,13 @@ export function useActionBtnDisabledUtils( isCancellableStatus(runStatus)) const disabledReason = useDisabledReason({ - ...props, - doorStatus, isFixtureMismatch, + doorStatus, isResetRunLoading, + isMissingModules, + isModuleCalibrationComplete, + isCalibrationComplete, + ...props, }) return isDisabled @@ -85,12 +107,13 @@ type UseDisabledReasonProps = UseActionButtonDisabledUtilsProps & { isFixtureMismatch: boolean isResetRunLoading: boolean isClosingCurrentRun: boolean + isModuleCalibrationComplete: boolean + isMissingModules: boolean + isCalibrationComplete: boolean } // The user-facing disabled explanation for why the ActionButton is disabled, if any. function useDisabledReason({ - isCurrentRun, - isSetupComplete, isFixtureMismatch, isValidRunAgain, isOtherRunCurrent, @@ -100,17 +123,23 @@ function useDisabledReason({ isResetRunLoading, isClosingCurrentRun, isCameraReadyToRun, -}: UseDisabledReasonProps): string | null { + isMissingModules, + isModuleCalibrationComplete, + isCalibrationComplete, +}: UseDisabledReasonProps): string { const { t } = useTranslation(['run_details', 'shared']) - if (!isCameraReadyToRun) { return t('enable_camera') - } else if ( - isCurrentRun && - (!isSetupComplete || isFixtureMismatch) && - !isValidRunAgain - ) { - return t('setup_incomplete') + } else if (isCalibrationComplete) { + return t('instrument_calibration_incomplete') + } else if (isModuleCalibrationComplete) { + return t('module_calibration_incomplete') + } else if (isMissingModules) { + return t('modules_missing') + } else if (isFixtureMismatch) { + return t('fixture_mismatch') + } else if (isValidRunAgain) { + return t('run_again_disabled') } else if (isOtherRunCurrent && !isResetRunLoading) { return t('shared:robot_is_busy') } else if (isRobotOnWrongVersionOfSoftware) { @@ -126,6 +155,6 @@ function useDisabledReason({ } else if (isClosingCurrentRun) { return t('shared:robot_is_busy') } else { - return null + return t('run_cta_disabled') } } diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts index 7e86794a393..0b75289b5b8 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts @@ -10,6 +10,7 @@ import { import { useAddCameraSettingsToRunMutation } from '@opentrons/react-api-client' import { useIsHeaterShakerInProtocol } from '/app/organisms/ModuleCard/hooks' +import { useToaster } from '/app/organisms/ToasterOven' import { useTrackProtocolRunEvent } from '/app/redux-resources/analytics' import { SOURCE_RUN_RECORD, @@ -32,6 +33,7 @@ import { isRunAgainStatus, isStartRunStatus, } from '../../../utils' +import { useActionBtnDisabledUtils } from './useActionBtnDisabledUtils' import type { IconName } from '@opentrons/components' import type { StepKey } from '/app/redux/protocol-runs' @@ -59,8 +61,12 @@ export function useActionButtonProperties({ robotName, runId, currentRunId, + isOtherRunCurrent, + isRobotOnWrongVersionOfSoftware, confirmAttachment, confirmMissingSteps, + makeHandleJumpToStep, + runRecord, robotAnalyticsData, robotSerialNumber, protocolRunControls, @@ -69,6 +75,8 @@ export function useActionButtonProperties({ isResetRunLoadingRef, isClosingCurrentRun, areCameraPreferencesConfirmed, + isValidRunAgain, + protocolRunHeaderRef, }: UseButtonPropertiesProps): { buttonText: string handleButtonClick: () => void @@ -116,6 +124,30 @@ export function useActionButtonProperties({ recoveryCaptureEnabled: recoveryEnabled, }) } + const isSetupComplete = !missingSetupSteps || missingSetupSteps.length === 0 + const { makeSnackbar } = useToaster() + const isCameraReadyToRun = + missingSetupSteps.length === 0 || + !missingSetupSteps.includes('camera_setup_step') + const { isDisabled, disabledReason } = useActionBtnDisabledUtils({ + robotName, + runId, + isValidRunAgain, + isSetupComplete, + isOtherRunCurrent, + isProtocolNotReady, + isRobotOnWrongVersionOfSoftware, + isClosingCurrentRun, + isCameraReadyToRun, + makeHandleJumpToStep, + runRecord, + runStatus, + isResetRunLoadingRef, + protocolRunHeaderRef, + attachedModules, + protocolRunControls, + runHeaderModalContainerUtils, + }) if (isProtocolNotReady) { buttonIconName = 'ot-spinner' @@ -138,6 +170,10 @@ export function useActionButtonProperties({ buttonText = runStatus === RUN_STATUS_IDLE ? t('start_run') : t('resume_run') handleButtonClick = () => { + if (isDisabled) { + makeSnackbar(disabledReason) + return + } if (isHeaterShakerShaking && isHeaterShakerInProtocol) { runHeaderModalContainerUtils.HSRunningModalUtils.toggleModal?.() } else if ( diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx index b6b57f4ed90..cec5535eb4b 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx @@ -12,8 +12,6 @@ import { SIZE_1, SPACING, StyledText, - Tooltip, - useHoverTooltip, } from '@opentrons/components' import { useRobotAnalyticsData } from '/app/redux-resources/analytics' @@ -37,7 +35,7 @@ import { } from '../../utils' import { useActionBtnDisabledUtils, useActionButtonProperties } from './hooks' -import type { MutableRefObject } from 'react' +import type { MutableRefObject, RefObject } from 'react' import type { State } from '/app/redux/types' import type { RunHeaderContentProps } from '..' @@ -46,6 +44,7 @@ export type BaseActionButtonProps = RunHeaderContentProps interface ActionButtonProps extends BaseActionButtonProps { isResetRunLoadingRef: MutableRefObject isClosingCurrentRun: boolean + protocolRunHeaderRef: RefObject | null } export function ActionButton(props: ActionButtonProps): JSX.Element { @@ -60,9 +59,7 @@ export function ActionButton(props: ActionButtonProps): JSX.Element { } = props const { missingStepsModalUtils, HSConfirmationModalUtils } = runHeaderModalContainerUtils - const isFlex = useIsFlex(robotName) - const [targetProps, tooltipProps] = useHoverTooltip() const { isProtocolAnalyzing, protocolData } = useProtocolDetailsForRun(runId) const { missingModuleIds } = useUnmatchedModulesForProtocol(robotName, runId) const { complete: isCalibrationComplete } = useRunCalibrationStatus( @@ -99,13 +96,10 @@ export function ActionButton(props: ActionButtonProps): JSX.Element { ? isSetupComplete && !isRequiredOffsetMissing : isSetupComplete - const isCurrentRun = currentRunId === runId const isOtherRunCurrent = currentRunId != null && currentRunId !== runId const isProtocolNotReady = protocolData == null || !!isProtocolAnalyzing const isValidRunAgain = isValidRunAgainStatus(runStatus, isClosingCurrentRun) - - const { isDisabled, disabledReason } = useActionBtnDisabledUtils({ - isCurrentRun, + useActionBtnDisabledUtils({ isSetupComplete: isRobotTypeSetupComplete, isOtherRunCurrent, isProtocolNotReady, @@ -119,9 +113,6 @@ export function ActionButton(props: ActionButtonProps): JSX.Element { const robotSerialNumber = getFallbackRobotSerialNumber(robot) const robotAnalyticsData = useRobotAnalyticsData(robotName) - const validRunAgainButRequiresSetup = - isValidRunAgain && !isRobotTypeSetupComplete - const { buttonText, handleButtonClick, buttonIconName } = useActionButtonProperties({ isProtocolNotReady, @@ -138,7 +129,6 @@ export function ActionButton(props: ActionButtonProps): JSX.Element { areCameraPreferencesConfirmed, ...props, }) - return ( <> {buttonIconName != null ? ( - {disabledReason && ( - - {disabledReason} - - )} ) } From 759f44b551937b5a2995a28107ccc344ac512c71 Mon Sep 17 00:00:00 2001 From: Rhyann Clarke Date: Tue, 18 Nov 2025 13:18:28 -0500 Subject: [PATCH 2/3] copy changes and correct camera enablement error --- .../assets/localization/en/run_details.json | 8 +++---- .../hooks/useActionBtnDisabledUtils.ts | 21 +++++++++++-------- .../hooks/useActionButtonProperties.ts | 11 +++++----- .../RunHeaderContent/ActionButton/index.tsx | 1 + 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/app/src/assets/localization/en/run_details.json b/app/src/assets/localization/en/run_details.json index cb4d86fb66b..5e41e36f266 100644 --- a/app/src/assets/localization/en/run_details.json +++ b/app/src/assets/localization/en/run_details.json @@ -68,7 +68,7 @@ "error_type": "Error: {{errorType}}", "failed_step": "Failed step", "final_step": "Final Step", - "fixture_mismatch": "Deck configuration does not match protocol needs.", + "fixture_mismatch": "Deck configuration does not match protocol requirements", "ignore_stored_data": "Ignore stored data", "image_at_step_at_timestamp": "Image at {{step}} at {{timestamp}}", "image_capture": "Image capture", @@ -78,7 +78,7 @@ "image_loading": "Image loading", "images": "Images", "images_available_download": "Image files associated with the run are available on the robot’s Recent Runs screen and Camera tab.", - "instrument_calibration_incomplete": "Instrument calibration is incomplete.", + "instrument_calibration_incomplete": "Instrument calibration is incomplete", "labware": "labware", "labware_offset_data": "labware offset data", "left": "Left", @@ -93,9 +93,9 @@ "loading_data": "Loading data...", "loading_protocol": "Loading Protocol", "location": "location", - "module_calibration_incomplete": "Module calibration is incomplete.", + "module_calibration_incomplete": "Module calibration is incomplete", "module_controls": "Module Controls", - "modules_missing": "Modules are missing.", + "modules_missing": "Modules are missing from deck hardware", "module_slot_number": "Slot {{slot_number}}", "move_labware": "Move Labware", "na": "N/A", diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts index 00e1234558c..c0559e3af7e 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts @@ -33,7 +33,7 @@ interface UseActionButtonDisabledUtilsProps extends BaseActionButtonProps { } type UseActionButtonDisabledUtilsResult = - | { isDisabled: true; disabledReason: string } + | { isDisabled: true; disabledReason: string | null } | { isDisabled: false; disabledReason: null } // Manages the various reasons the ActionButton may be disabled, returning the disabled state and user-facing disabled @@ -52,6 +52,7 @@ export function useActionBtnDisabledUtils( runId, isResetRunLoadingRef, isClosingCurrentRun, + isCameraReadyToRun, } = props const { isPlayRunActionLoading, isPauseRunActionLoading } = @@ -82,6 +83,7 @@ export function useActionBtnDisabledUtils( isProtocolNotReady || isFixtureMismatch || isDisabledStatus(runStatus) || + !isCameraReadyToRun || isRobotOnWrongVersionOfSoftware || (doorStatus.isDoorOpen && runStatus !== RUN_STATUS_BLOCKED_BY_OPEN_DOOR && @@ -110,6 +112,7 @@ type UseDisabledReasonProps = UseActionButtonDisabledUtilsProps & { isModuleCalibrationComplete: boolean isMissingModules: boolean isCalibrationComplete: boolean + isCameraReadyToRun: boolean } // The user-facing disabled explanation for why the ActionButton is disabled, if any. @@ -122,20 +125,18 @@ function useDisabledReason({ runStatus, isResetRunLoading, isClosingCurrentRun, - isCameraReadyToRun, isMissingModules, isModuleCalibrationComplete, isCalibrationComplete, -}: UseDisabledReasonProps): string { + isCameraReadyToRun, +}: UseDisabledReasonProps): string | null { const { t } = useTranslation(['run_details', 'shared']) - if (!isCameraReadyToRun) { - return t('enable_camera') - } else if (isCalibrationComplete) { + if (isCalibrationComplete) { return t('instrument_calibration_incomplete') - } else if (isModuleCalibrationComplete) { - return t('module_calibration_incomplete') } else if (isMissingModules) { return t('modules_missing') + } else if (isModuleCalibrationComplete) { + return t('module_calibration_incomplete') } else if (isFixtureMismatch) { return t('fixture_mismatch') } else if (isValidRunAgain) { @@ -154,7 +155,9 @@ function useDisabledReason({ return t('close_door') } else if (isClosingCurrentRun) { return t('shared:robot_is_busy') + } else if (!isCameraReadyToRun) { + return t('enable_camera') } else { - return t('run_cta_disabled') + return null } } diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts index 0b75289b5b8..466163b3ee0 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionButtonProperties.ts @@ -50,8 +50,9 @@ interface UseButtonPropertiesProps extends BaseActionButtonProps { isValidRunAgain: boolean isOtherRunCurrent: boolean isRobotOnWrongVersionOfSoftware: boolean - isClosingCurrentRun: boolean areCameraPreferencesConfirmed: boolean + isClosingCurrentRun: boolean + isCameraReadyToRun: boolean } // Returns ActionButton properties. @@ -77,6 +78,7 @@ export function useActionButtonProperties({ areCameraPreferencesConfirmed, isValidRunAgain, protocolRunHeaderRef, + isCameraReadyToRun, }: UseButtonPropertiesProps): { buttonText: string handleButtonClick: () => void @@ -126,9 +128,6 @@ export function useActionButtonProperties({ } const isSetupComplete = !missingSetupSteps || missingSetupSteps.length === 0 const { makeSnackbar } = useToaster() - const isCameraReadyToRun = - missingSetupSteps.length === 0 || - !missingSetupSteps.includes('camera_setup_step') const { isDisabled, disabledReason } = useActionBtnDisabledUtils({ robotName, runId, @@ -138,7 +137,6 @@ export function useActionButtonProperties({ isProtocolNotReady, isRobotOnWrongVersionOfSoftware, isClosingCurrentRun, - isCameraReadyToRun, makeHandleJumpToStep, runRecord, runStatus, @@ -147,6 +145,7 @@ export function useActionButtonProperties({ attachedModules, protocolRunControls, runHeaderModalContainerUtils, + isCameraReadyToRun, }) if (isProtocolNotReady) { @@ -170,7 +169,7 @@ export function useActionButtonProperties({ buttonText = runStatus === RUN_STATUS_IDLE ? t('start_run') : t('resume_run') handleButtonClick = () => { - if (isDisabled) { + if (isDisabled && disabledReason) { makeSnackbar(disabledReason) return } diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx index cec5535eb4b..b589d4d8429 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx @@ -127,6 +127,7 @@ export function ActionButton(props: ActionButtonProps): JSX.Element { isOtherRunCurrent, isRobotOnWrongVersionOfSoftware, areCameraPreferencesConfirmed, + isCameraReadyToRun, ...props, }) return ( From 4ef2f58273ca99846376a9c61397028f642844ac Mon Sep 17 00:00:00 2001 From: Rhyann Clarke Date: Wed, 19 Nov 2025 17:11:09 -0500 Subject: [PATCH 3/3] change ordering of notifications to be on app vs in person --- .../hooks/useActionBtnDisabledUtils.ts | 26 +++++----- .../RunHeaderContent/ActionButton/index.tsx | 52 ++----------------- 2 files changed, 18 insertions(+), 60 deletions(-) diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts index c0559e3af7e..e68d92f4210 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/hooks/useActionBtnDisabledUtils.ts @@ -131,20 +131,24 @@ function useDisabledReason({ isCameraReadyToRun, }: UseDisabledReasonProps): string | null { const { t } = useTranslation(['run_details', 'shared']) - if (isCalibrationComplete) { - return t('instrument_calibration_incomplete') - } else if (isMissingModules) { - return t('modules_missing') - } else if (isModuleCalibrationComplete) { - return t('module_calibration_incomplete') + if (isRobotOnWrongVersionOfSoftware) { + return t('shared:a_software_update_is_available') + } else if (isClosingCurrentRun) { + return t('shared:robot_is_busy') + } else if (!isCameraReadyToRun) { + return t('enable_camera') } else if (isFixtureMismatch) { return t('fixture_mismatch') - } else if (isValidRunAgain) { + } else if (!isValidRunAgain) { return t('run_again_disabled') } else if (isOtherRunCurrent && !isResetRunLoading) { return t('shared:robot_is_busy') - } else if (isRobotOnWrongVersionOfSoftware) { - return t('shared:a_software_update_is_available') + } else if (!isCalibrationComplete) { + return t('instrument_calibration_incomplete') + } else if (isMissingModules) { + return t('modules_missing') + } else if (!isModuleCalibrationComplete) { + return t('module_calibration_incomplete') } else if ( doorStatus.isDoorOpen && doorStatus.moduleDoorLocation !== null && @@ -153,10 +157,6 @@ function useDisabledReason({ return t('close_stacker_door') } else if (doorStatus.isDoorOpen && isStartRunStatus(runStatus)) { return t('close_door') - } else if (isClosingCurrentRun) { - return t('shared:robot_is_busy') - } else if (!isCameraReadyToRun) { - return t('enable_camera') } else { return null } diff --git a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx index b589d4d8429..e87a66b5cb3 100644 --- a/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx +++ b/app/src/organisms/Desktop/Devices/ProtocolRun/ProtocolRunHeader/RunHeaderContent/ActionButton/index.tsx @@ -15,27 +15,18 @@ import { } from '@opentrons/components' import { useRobotAnalyticsData } from '/app/redux-resources/analytics' -import { useIsFlex, useRobot } from '/app/redux-resources/robots' -import { - getCameraUsageState, - selectIsAnyNecessaryDefaultOffsetMissing, -} from '/app/redux/protocol-runs' +import { useRobot } from '/app/redux-resources/robots' +import { getCameraUsageState } from '/app/redux/protocol-runs' import { useIsRobotOnWrongVersionOfSoftware } from '/app/redux/robot-update' -import { - useCurrentRunId, - useModuleCalibrationStatus, - useProtocolDetailsForRun, - useRunCalibrationStatus, - useUnmatchedModulesForProtocol, -} from '/app/resources/runs' +import { useCurrentRunId, useProtocolDetailsForRun } from '/app/resources/runs' import { getFallbackRobotSerialNumber, isValidRunAgainStatus, } from '../../utils' -import { useActionBtnDisabledUtils, useActionButtonProperties } from './hooks' +import { useActionButtonProperties } from './hooks' -import type { MutableRefObject, RefObject } from 'react' +import type { MutableRefObject } from 'react' import type { State } from '/app/redux/types' import type { RunHeaderContentProps } from '..' @@ -44,7 +35,6 @@ export type BaseActionButtonProps = RunHeaderContentProps interface ActionButtonProps extends BaseActionButtonProps { isResetRunLoadingRef: MutableRefObject isClosingCurrentRun: boolean - protocolRunHeaderRef: RefObject | null } export function ActionButton(props: ActionButtonProps): JSX.Element { @@ -59,24 +49,10 @@ export function ActionButton(props: ActionButtonProps): JSX.Element { } = props const { missingStepsModalUtils, HSConfirmationModalUtils } = runHeaderModalContainerUtils - const isFlex = useIsFlex(robotName) const { isProtocolAnalyzing, protocolData } = useProtocolDetailsForRun(runId) - const { missingModuleIds } = useUnmatchedModulesForProtocol(robotName, runId) - const { complete: isCalibrationComplete } = useRunCalibrationStatus( - robotName, - runId - ) - const { complete: isModuleCalibrationComplete } = useModuleCalibrationStatus( - robotName, - runId - ) const isRobotOnWrongVersionOfSoftware = useIsRobotOnWrongVersionOfSoftware(robotName) const currentRunId = useCurrentRunId() - const isRequiredOffsetMissing = useSelector( - selectIsAnyNecessaryDefaultOffsetMissing(runId) - ) - const { enabled: isCameraEnabled } = useSelector((state: State) => getCameraUsageState(state, runId) ) @@ -87,27 +63,9 @@ export function ActionButton(props: ActionButtonProps): JSX.Element { const isCameraReadyToRun = isCameraRequiredForRun ? isCameraEnabled : true const areCameraPreferencesConfirmed = runRecord?.data.cameraSettings != null - const isSetupComplete = - isCalibrationComplete && - isModuleCalibrationComplete && - missingModuleIds.length === 0 && - isCameraReadyToRun - const isRobotTypeSetupComplete = isFlex - ? isSetupComplete && !isRequiredOffsetMissing - : isSetupComplete - const isOtherRunCurrent = currentRunId != null && currentRunId !== runId const isProtocolNotReady = protocolData == null || !!isProtocolAnalyzing const isValidRunAgain = isValidRunAgainStatus(runStatus, isClosingCurrentRun) - useActionBtnDisabledUtils({ - isSetupComplete: isRobotTypeSetupComplete, - isOtherRunCurrent, - isProtocolNotReady, - isRobotOnWrongVersionOfSoftware, - isValidRunAgain, - isCameraReadyToRun, - ...props, - }) const robot = useRobot(robotName) const robotSerialNumber = getFallbackRobotSerialNumber(robot)