diff --git a/api-client/src/runs/constants.ts b/api-client/src/runs/constants.ts new file mode 100644 index 00000000000..9f0d8293ef6 --- /dev/null +++ b/api-client/src/runs/constants.ts @@ -0,0 +1,11 @@ +import { + RUN_STATUS_FAILED, + RUN_STATUS_STOPPED, + RUN_STATUS_SUCCEEDED, +} from './types' + +export const RUN_STATUSES_TERMINAL = [ + RUN_STATUS_SUCCEEDED, + RUN_STATUS_FAILED, + RUN_STATUS_STOPPED, +] diff --git a/api-client/src/runs/index.ts b/api-client/src/runs/index.ts index fa38dade02f..1d62755d4c5 100644 --- a/api-client/src/runs/index.ts +++ b/api-client/src/runs/index.ts @@ -10,6 +10,6 @@ export { getCommands } from './commands/getCommands' export { createRunAction } from './createRunAction' export * from './createLabwareOffset' export * from './createLabwareDefinition' - +export * from './constants' export * from './types' export type { CreateRunData } from './createRun' diff --git a/api-client/src/runs/types.ts b/api-client/src/runs/types.ts index 7e6ec2b0ee7..36c5f9a3a20 100644 --- a/api-client/src/runs/types.ts +++ b/api-client/src/runs/types.ts @@ -4,6 +4,7 @@ import type { LoadedPipette, ModuleModel, RunTimeCommand, + RunTimeParameter, } from '@opentrons/shared-data' import type { ResourceLink, ErrorDetails } from '../types' export * from './commands/types' @@ -47,7 +48,7 @@ export interface LegacyGoodRunData { modules: LoadedModule[] protocolId?: string labwareOffsets?: LabwareOffset[] - runTimeParameterValues?: RunTimeParameterCreateData + runTimeParameters: RunTimeParameter[] } export interface KnownGoodRunData extends LegacyGoodRunData { diff --git a/app/src/assets/localization/en/protocol_setup.json b/app/src/assets/localization/en/protocol_setup.json index 3bb871d4e64..74fbf93d3c2 100644 --- a/app/src/assets/localization/en/protocol_setup.json +++ b/app/src/assets/localization/en/protocol_setup.json @@ -48,6 +48,7 @@ "confirm_values": "Confirm values", "connect_all_hardware": "Connect and calibrate all hardware first", "connect_all_mod": "Connect all modules first", + "connect_modules_for_controls": "Connect modules to see controls", "connection_info_not_available": "Connection info not available once run has started", "connection_status": "Connection Status", "currently_configured": "Currently configured", @@ -236,6 +237,7 @@ "run_disabled_modules_and_calibration_not_complete": "Make sure robot calibration is complete and all modules are connected before proceeding to run", "run_disabled_modules_not_connected": "Make sure all modules are connected before proceeding to run", "run_labware_position_check": "run labware position check", + "run_never_started": "Run was never started", "run": "Run", "secure_labware_instructions": "Secure labware instructions", "secure_labware_modal": "Securing labware to the {{name}}", diff --git a/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx b/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx index 0bfa08ce47b..53cdf10f46c 100644 --- a/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx +++ b/app/src/organisms/Devices/ProtocolRun/ProtocolRunHeader.tsx @@ -15,6 +15,7 @@ import { RUN_STATUS_SUCCEEDED, RUN_STATUS_BLOCKED_BY_OPEN_DOOR, RUN_STATUS_AWAITING_RECOVERY, + RUN_STATUSES_TERMINAL, } from '@opentrons/api-client' import { useModulesQuery, @@ -128,11 +129,6 @@ const CANCELLABLE_STATUSES = [ RUN_STATUS_IDLE, RUN_STATUS_AWAITING_RECOVERY, ] -const RUN_OVER_STATUSES: RunStatus[] = [ - RUN_STATUS_FAILED, - RUN_STATUS_STOPPED, - RUN_STATUS_SUCCEEDED, -] interface ProtocolRunHeaderProps { protocolRunHeaderRef: React.RefObject | null @@ -214,7 +210,11 @@ export function ProtocolRunHeader({ if (runStatus === RUN_STATUS_IDLE) { setShowDropTipBanner(true) setPipettesWithTip([]) - } else if (runStatus != null && RUN_OVER_STATUSES.includes(runStatus)) { + } else if ( + runStatus != null && + // @ts-expect-error runStatus expected to possibly not be terminal + RUN_STATUSES_TERMINAL.includes(runStatus) + ) { getPipettesWithTipAttached({ host, runId, diff --git a/app/src/organisms/Devices/ProtocolRun/ProtocolRunRunTimeParameters.tsx b/app/src/organisms/Devices/ProtocolRun/ProtocolRunRunTimeParameters.tsx index ea7ec478415..b7a253fdeca 100644 --- a/app/src/organisms/Devices/ProtocolRun/ProtocolRunRunTimeParameters.tsx +++ b/app/src/organisms/Devices/ProtocolRun/ProtocolRunRunTimeParameters.tsx @@ -1,6 +1,11 @@ import * as React from 'react' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' +import { + RUN_ACTION_TYPE_PLAY, + RUN_STATUS_STOPPED, + RUN_STATUSES_TERMINAL, +} from '@opentrons/api-client' import { formatRunTimeParameterValue } from '@opentrons/shared-data' import { ALIGN_CENTER, @@ -23,8 +28,11 @@ import { Banner } from '../../../atoms/Banner' import { Divider } from '../../../atoms/structure' import { Tooltip } from '../../../atoms/Tooltip' import { useMostRecentCompletedAnalysis } from '../../LabwarePositionCheck/useMostRecentCompletedAnalysis' +import { useRunStatus } from '../../RunTimeControl/hooks' +import { useNotifyRunQuery } from '../../../resources/runs' import type { RunTimeParameter } from '@opentrons/shared-data' +import type { RunStatus } from '@opentrons/api-client' interface ProtocolRunRuntimeParametersProps { runId: string @@ -34,13 +42,31 @@ export function ProtocolRunRuntimeParameters({ }: ProtocolRunRuntimeParametersProps): JSX.Element { const { t } = useTranslation('protocol_setup') const mostRecentAnalysis = useMostRecentCompletedAnalysis(runId) - const runTimeParameters = mostRecentAnalysis?.runTimeParameters ?? [] - const hasParameter = runTimeParameters.length > 0 - - const hasCustomValues = runTimeParameters.some( + const runStatus = useRunStatus(runId) + const isRunTerminal = + runStatus == null + ? false + : (RUN_STATUSES_TERMINAL as RunStatus[]).includes(runStatus) + // we access runTimeParameters from the run record rather than the most recent analysis + // because the most recent analysis may not reflect the selected run (e.g. cloning a run + // from a historical protocol run from the device details page) + const run = useNotifyRunQuery(runId).data + const runTimeParameters = + (isRunTerminal + ? run?.data?.runTimeParameters + : mostRecentAnalysis?.runTimeParameters) ?? [] + const hasRunTimeParameters = runTimeParameters.length > 0 + const hasCustomRunTimeParameterValues = runTimeParameters.some( parameter => parameter.value !== parameter.default ) + const runActions = run?.data.actions + const hasRunStarted = runActions?.some( + action => action.actionType === RUN_ACTION_TYPE_PLAY + ) + const isRunCancelledWithoutStarting = + !hasRunStarted && runStatus === RUN_STATUS_STOPPED + return ( <> {t('parameters')} - {hasParameter ? ( + {hasRunTimeParameters ? ( - {hasCustomValues ? t('custom_values') : t('default_values')} + {hasCustomRunTimeParameterValues + ? t('custom_values') + : t('default_values')} ) : null} - {hasParameter ? ( + {hasRunTimeParameters ? ( ) : null} - {!hasParameter ? ( + {!hasRunTimeParameters ? ( - + ) : ( <> diff --git a/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx b/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx index f683986c26b..4be025a491e 100644 --- a/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx +++ b/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx @@ -1,12 +1,17 @@ import * as React from 'react' +import { UseQueryResult } from 'react-query' import { describe, it, vi, beforeEach, afterEach, expect } from 'vitest' import { screen } from '@testing-library/react' import { when } from 'vitest-when' +import { Run } from '@opentrons/api-client' import { InfoScreen } from '@opentrons/components' import { renderWithProviders } from '../../../../__testing-utils__' import { i18n } from '../../../../i18n' import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis' +import { useRunStatus } from '../../../RunTimeControl/hooks' +import { useNotifyRunQuery } from '../../../../resources/runs' +import { mockSucceededRun } from '../../../RunTimeControl/__fixtures__' import { ProtocolRunRuntimeParameters } from '../ProtocolRunRunTimeParameters' @@ -23,6 +28,8 @@ vi.mock('@opentrons/components', async importOriginal => { } }) vi.mock('../../../LabwarePositionCheck/useMostRecentCompletedAnalysis') +vi.mock('../../../RunTimeControl/hooks') +vi.mock('../../../../resources/runs') const RUN_ID = 'mockId' @@ -100,13 +107,17 @@ describe('ProtocolRunRuntimeParameters', () => { .thenReturn({ runTimeParameters: mockRunTimeParameterData, } as CompletedProtocolAnalysis) + vi.mocked(useRunStatus).mockReturnValue('running') + vi.mocked(useNotifyRunQuery).mockReturnValue(({ + data: { data: mockSucceededRun }, + } as unknown) as UseQueryResult) }) afterEach(() => { vi.resetAllMocks() }) - it('should render title, and banner when RunTimeParameters are note empty and all values are default', () => { + it('should render title, and banner when RunTimeParameters are not empty and all values are default', () => { render(props) screen.getByText('Parameters') screen.getByText('Default values') @@ -116,7 +127,7 @@ describe('ProtocolRunRuntimeParameters', () => { screen.getByText('Value') }) - it('should render title, and banner when RunTimeParameters are note empty and some value is changed', () => { + it('should render title, and banner when RunTimeParameters are not empty and some value is changed', () => { vi.mocked(useMostRecentCompletedAnalysis).mockReturnValue({ runTimeParameters: [ ...mockRunTimeParameterData, @@ -139,7 +150,7 @@ describe('ProtocolRunRuntimeParameters', () => { screen.getByText('Value') }) - it('should render RunTimeParameters when RunTimeParameters are note empty', () => { + it('should render RunTimeParameters when RunTimeParameters are not empty', () => { render(props) screen.getByText('Dry Run') screen.getByText('Off') diff --git a/app/src/organisms/Devices/hooks/useRunStatuses.ts b/app/src/organisms/Devices/hooks/useRunStatuses.ts index bba83f76299..887de586f8e 100644 --- a/app/src/organisms/Devices/hooks/useRunStatuses.ts +++ b/app/src/organisms/Devices/hooks/useRunStatuses.ts @@ -1,15 +1,15 @@ import { + RUN_STATUSES_TERMINAL, RUN_STATUS_AWAITING_RECOVERY, - RUN_STATUS_FAILED, RUN_STATUS_IDLE, RUN_STATUS_PAUSED, RUN_STATUS_RUNNING, - RUN_STATUS_STOPPED, - RUN_STATUS_SUCCEEDED, } from '@opentrons/api-client' import { useCurrentRunId } from '../../ProtocolUpload/hooks' import { useRunStatus } from '../../RunTimeControl/hooks' +import type { RunStatus } from '@opentrons/api-client' + interface RunStatusesInfo { isRunStill: boolean isRunTerminal: boolean @@ -29,9 +29,9 @@ export function useRunStatuses(): RunStatusesInfo { runStatus === RUN_STATUS_RUNNING || runStatus === RUN_STATUS_AWAITING_RECOVERY const isRunTerminal = - runStatus === RUN_STATUS_SUCCEEDED || - runStatus === RUN_STATUS_STOPPED || - runStatus === RUN_STATUS_FAILED + runStatus != null + ? (RUN_STATUSES_TERMINAL as RunStatus[]).includes(runStatus) + : false const isRunStill = isRunTerminal || isRunIdle return { isRunStill, isRunTerminal, isRunIdle, isRunRunning } diff --git a/app/src/organisms/InterventionModal/__fixtures__/index.ts b/app/src/organisms/InterventionModal/__fixtures__/index.ts index b6d631f4c97..2611fe19b03 100644 --- a/app/src/organisms/InterventionModal/__fixtures__/index.ts +++ b/app/src/organisms/InterventionModal/__fixtures__/index.ts @@ -188,6 +188,7 @@ export const mockRunData: RunData = { pipettes: [], labware: [mockLabwareOnModule, mockLabwareOnSlot, mockLabwareOffDeck], modules: [mockModule], + runTimeParameters: [], } export const mockLabwareRenderInfo = [ diff --git a/app/src/organisms/OnDeviceDisplay/RobotDashboard/__tests__/RecentRunProtocolCarousel.test.tsx b/app/src/organisms/OnDeviceDisplay/RobotDashboard/__tests__/RecentRunProtocolCarousel.test.tsx index 85e956ed977..8bc3a481843 100644 --- a/app/src/organisms/OnDeviceDisplay/RobotDashboard/__tests__/RecentRunProtocolCarousel.test.tsx +++ b/app/src/organisms/OnDeviceDisplay/RobotDashboard/__tests__/RecentRunProtocolCarousel.test.tsx @@ -26,6 +26,7 @@ const mockRun = { pipettes: [], protocolId: 'mockSortedProtocolID', status: 'stopped', + runTimeParameters: [], } const render = ( diff --git a/app/src/organisms/ProtocolUpload/hooks/__tests__/useCloneRun.test.tsx b/app/src/organisms/ProtocolUpload/hooks/__tests__/useCloneRun.test.tsx index af388d30930..40726be91bf 100644 --- a/app/src/organisms/ProtocolUpload/hooks/__tests__/useCloneRun.test.tsx +++ b/app/src/organisms/ProtocolUpload/hooks/__tests__/useCloneRun.test.tsx @@ -4,7 +4,11 @@ import { renderHook } from '@testing-library/react' import { QueryClient, QueryClientProvider } from 'react-query' import { describe, it, beforeEach, afterEach, vi, expect } from 'vitest' -import { useHost, useCreateRunMutation } from '@opentrons/react-api-client' +import { + useHost, + useCreateRunMutation, + useCreateProtocolAnalysisMutation, +} from '@opentrons/react-api-client' import { useCloneRun } from '../useCloneRun' import { useNotifyRunQuery } from '../../../../resources/runs' @@ -30,13 +34,16 @@ describe('useCloneRun hook', () => { id: RUN_ID, protocolId: 'protocolId', labwareOffsets: 'someOffset', - runTimeParameterValues: 'someRtp', + runTimeParameters: [], }, }, } as any) when(vi.mocked(useCreateRunMutation)) .calledWith(expect.anything()) .thenReturn({ createRun: vi.fn() } as any) + vi.mocked(useCreateProtocolAnalysisMutation).mockReturnValue({ + createProtocolAnalysis: vi.fn(), + } as any) const queryClient = new QueryClient() const clientProvider: React.FunctionComponent<{ @@ -61,7 +68,7 @@ describe('useCloneRun hook', () => { expect(mockCreateRun).toHaveBeenCalledWith({ protocolId: 'protocolId', labwareOffsets: 'someOffset', - runTimeParameterValues: 'someRtp', + runTimeParameterValues: {}, }) }) }) diff --git a/app/src/organisms/ProtocolUpload/hooks/useCloneRun.ts b/app/src/organisms/ProtocolUpload/hooks/useCloneRun.ts index 0858544d93c..fe6e3ab3649 100644 --- a/app/src/organisms/ProtocolUpload/hooks/useCloneRun.ts +++ b/app/src/organisms/ProtocolUpload/hooks/useCloneRun.ts @@ -1,10 +1,13 @@ import { useQueryClient } from 'react-query' -import { useHost, useCreateRunMutation } from '@opentrons/react-api-client' - +import { + useHost, + useCreateRunMutation, + useCreateProtocolAnalysisMutation, +} from '@opentrons/react-api-client' import { useNotifyRunQuery } from '../../../resources/runs' -import type { Run } from '@opentrons/api-client' +import type { Run, RunTimeParameterCreateData } from '@opentrons/api-client' interface UseCloneRunResult { cloneRun: () => void @@ -13,28 +16,45 @@ interface UseCloneRunResult { export function useCloneRun( runId: string | null, - onSuccessCallback?: (createRunResponse: Run) => unknown + onSuccessCallback?: (createRunResponse: Run) => unknown, + triggerAnalysis: boolean = false ): UseCloneRunResult { const host = useHost() const queryClient = useQueryClient() const { data: runRecord } = useNotifyRunQuery(runId) + const protocolKey = runRecord?.data.protocolId ?? null + const { createRun, isLoading } = useCreateRunMutation({ onSuccess: response => { - queryClient - .invalidateQueries([host, 'runs']) - .catch((e: Error) => - console.error(`error invalidating runs query: ${e.message}`) - ) + const invalidateRuns = queryClient.invalidateQueries([host, 'runs']) + const invalidateProtocols = queryClient.invalidateQueries([ + host, + 'protocols', + protocolKey, + ]) + Promise.all([invalidateRuns, invalidateProtocols]).catch((e: Error) => + console.error(`error invalidating runs query: ${e.message}`) + ) if (onSuccessCallback != null) onSuccessCallback(response) }, }) + const { createProtocolAnalysis } = useCreateProtocolAnalysisMutation( + protocolKey, + host + ) const cloneRun = (): void => { if (runRecord != null) { - const { - protocolId, - labwareOffsets, - runTimeParameterValues, - } = runRecord.data + const { protocolId, labwareOffsets, runTimeParameters } = runRecord.data + const runTimeParameterValues = runTimeParameters.reduce( + (acc, param) => + param.value !== param.default + ? { ...acc, [param.variableName]: param.value } + : acc, + {} + ) + if (triggerAnalysis && protocolKey != null) { + createProtocolAnalysis({ protocolKey, runTimeParameterValues }) + } createRun({ protocolId, labwareOffsets, runTimeParameterValues }) } else { console.info('failed to clone run record, source run record not found') diff --git a/app/src/organisms/RunPreview/index.tsx b/app/src/organisms/RunPreview/index.tsx index a75257c1952..a7e4aa2591b 100644 --- a/app/src/organisms/RunPreview/index.tsx +++ b/app/src/organisms/RunPreview/index.tsx @@ -3,6 +3,8 @@ import { css } from 'styled-components' import { useTranslation } from 'react-i18next' import { ViewportList, ViewportListRef } from 'react-viewport-list' +import { RUN_STATUSES_TERMINAL } from '@opentrons/api-client' +import { useAllCommandsQuery } from '@opentrons/react-api-client' import { ALIGN_CENTER, BORDERS, @@ -24,6 +26,9 @@ import { CommandText } from '../CommandText' import { Divider } from '../../atoms/structure' import { NAV_BAR_WIDTH } from '../../App/constants' import { CommandIcon } from './CommandIcon' +import { useRunStatus } from '../RunTimeControl/hooks' + +import type { RunStatus } from '@opentrons/api-client' import type { RobotType } from '@opentrons/shared-data' const COLOR_FADE_MS = 500 @@ -41,6 +46,17 @@ export const RunPreviewComponent = ( ): JSX.Element | null => { const { t } = useTranslation('run_details') const robotSideAnalysis = useMostRecentCompletedAnalysis(runId) + const runStatus = useRunStatus(runId) + const isRunTerminal = + runStatus != null + ? (RUN_STATUSES_TERMINAL as RunStatus[]).includes(runStatus) + : false + // we only ever want one request done for terminal runs because this is a heavy request + const commandsFromQuery = useAllCommandsQuery(runId, null, { + staleTime: Infinity, + cacheTime: Infinity, + enabled: isRunTerminal, + }).data?.data const viewPortRef = React.useRef(null) const currentRunCommandKey = useNotifyLastRunCommandKey(runId, { refetchInterval: LIVE_RUN_COMMANDS_POLL_MS, @@ -50,7 +66,9 @@ export const RunPreviewComponent = ( setIsCurrentCommandVisible, ] = React.useState(true) if (robotSideAnalysis == null) return null - const currentRunCommandIndex = robotSideAnalysis.commands.findIndex( + const commands = + (isRunTerminal ? commandsFromQuery : robotSideAnalysis.commands) ?? [] + const currentRunCommandIndex = commands.findIndex( c => c.key === currentRunCommandKey ) @@ -69,7 +87,7 @@ export const RunPreviewComponent = ( {t('run_preview')} - {t('steps_total', { count: robotSideAnalysis.commands.length })} + {t('steps_total', { count: commands.length })} @@ -79,7 +97,7 @@ export const RunPreviewComponent = ( ) : null} - {currentRunCommandIndex === robotSideAnalysis.commands.length - 1 ? ( + {currentRunCommandIndex === commands.length - 1 ? ( {t('end_of_protocol')} diff --git a/app/src/organisms/RunTimeControl/__fixtures__/index.ts b/app/src/organisms/RunTimeControl/__fixtures__/index.ts index 1a18a9a6bcf..33f2e0c4393 100644 --- a/app/src/organisms/RunTimeControl/__fixtures__/index.ts +++ b/app/src/organisms/RunTimeControl/__fixtures__/index.ts @@ -41,6 +41,7 @@ export const mockPausedRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockPauseRequestedRun: RunData = { @@ -65,6 +66,7 @@ export const mockPauseRequestedRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockRunningRun: RunData = { @@ -94,6 +96,7 @@ export const mockRunningRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockFailedRun: RunData = { @@ -133,6 +136,7 @@ export const mockFailedRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockStopRequestedRun: RunData = { @@ -167,6 +171,7 @@ export const mockStopRequestedRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockStoppedRun: RunData = { @@ -201,6 +206,7 @@ export const mockStoppedRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockSucceededRun: RunData = { @@ -230,6 +236,7 @@ export const mockSucceededRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockIdleUnstartedRun: RunData = { @@ -243,6 +250,7 @@ export const mockIdleUnstartedRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockIdleStartedRun: RunData = { @@ -272,6 +280,7 @@ export const mockIdleStartedRun: RunData = { pipettes: [], labware: [], modules: [], + runTimeParameters: [], } export const mockCommand = { diff --git a/app/src/organisms/RunTimeControl/__tests__/hooks.test.tsx b/app/src/organisms/RunTimeControl/__tests__/hooks.test.tsx index 21adedbd165..a46bc37d865 100644 --- a/app/src/organisms/RunTimeControl/__tests__/hooks.test.tsx +++ b/app/src/organisms/RunTimeControl/__tests__/hooks.test.tsx @@ -61,7 +61,7 @@ describe('useRunControls hook', () => { isStopRunActionLoading: false, }) when(useCloneRun) - .calledWith(mockPausedRun.id, undefined) + .calledWith(mockPausedRun.id, undefined, true) .thenReturn({ cloneRun: mockCloneRun, isLoading: false }) const { result } = renderHook(() => useRunControls(mockPausedRun.id)) diff --git a/app/src/organisms/RunTimeControl/hooks.ts b/app/src/organisms/RunTimeControl/hooks.ts index db042a2ce65..d513fcbe118 100644 --- a/app/src/organisms/RunTimeControl/hooks.ts +++ b/app/src/organisms/RunTimeControl/hooks.ts @@ -12,6 +12,7 @@ import { RUN_STATUS_SUCCEEDED, RUN_ACTION_TYPE_STOP, RUN_STATUS_STOP_REQUESTED, + RUN_STATUSES_TERMINAL, } from '@opentrons/api-client' import { useRunActionMutations } from '@opentrons/react-api-client' @@ -52,7 +53,8 @@ export function useRunControls( const { cloneRun, isLoading: isResetRunLoading } = useCloneRun( runId ?? null, - onCloneRunSuccess + onCloneRunSuccess, + true ) return { @@ -78,11 +80,7 @@ export function useRunStatus( refetchInterval: DEFAULT_STATUS_REFETCH_INTERVAL, enabled: lastRunStatus.current == null || - !([ - RUN_STATUS_FAILED, - RUN_STATUS_SUCCEEDED, - RUN_STATUS_STOPPED, - ] as RunStatus[]).includes(lastRunStatus.current), + !(RUN_STATUSES_TERMINAL as RunStatus[]).includes(lastRunStatus.current), onSuccess: data => (lastRunStatus.current = data?.data?.status ?? null), ...options, }) diff --git a/components/src/molecules/ParametersTable/InfoScreen.tsx b/components/src/molecules/ParametersTable/InfoScreen.tsx index b9798f828e3..cd6db0d622b 100644 --- a/components/src/molecules/ParametersTable/InfoScreen.tsx +++ b/components/src/molecules/ParametersTable/InfoScreen.tsx @@ -8,14 +8,32 @@ import { Flex } from '../../primitives' import { ALIGN_CENTER, DIRECTION_COLUMN } from '../../styles' interface InfoScreenProps { - contentType: 'parameters' | 'moduleControls' + contentType: 'parameters' | 'moduleControls' | 'runNotStarted' + t?: any } -export function InfoScreen({ contentType }: InfoScreenProps): JSX.Element { - const bodyText = - contentType === 'parameters' - ? 'No parameters specified in this protocol' - : 'Connect modules to see controls' +export function InfoScreen({ contentType, t }: InfoScreenProps): JSX.Element { + let bodyText: string = '' + switch (contentType) { + case 'parameters': + bodyText = + t != null + ? t('no_parameters_specified_in_protocol') + : 'No parameters specified in this protocol' + break + case 'moduleControls': + bodyText = + t != null + ? t('connect_modules_for_controls') + : 'Connect modules to see controls' + break + case 'runNotStarted': + bodyText = t != null ? t('run_never_started') : 'Run was never started' + break + default: + bodyText = contentType + } + return ( ( runId: string | null, - params: GetCommandsParams = DEFAULT_PARAMS, + params?: GetCommandsParams | null, options: UseQueryOptions = {} ): UseQueryResult { const host = useHost() + const nullCheckedParams = params ?? DEFAULT_PARAMS + const allOptions: UseQueryOptions = { ...options, enabled: host !== null && runId != null && options.enabled !== false, } - const { cursor, pageLength } = params + const { cursor, pageLength } = nullCheckedParams const query = useQuery( [host, 'runs', runId, 'commands', cursor, pageLength], () => { - return getCommands(host as HostConfig, runId as string, params).then( - response => response.data - ) + return getCommands( + host as HostConfig, + runId as string, + nullCheckedParams + ).then(response => response.data) }, allOptions )