diff --git a/app/src/organisms/ChooseRobotSlideout/AvailableRobotOption.tsx b/app/src/organisms/ChooseRobotSlideout/AvailableRobotOption.tsx index abcdc5b903d..7953a0cd353 100644 --- a/app/src/organisms/ChooseRobotSlideout/AvailableRobotOption.tsx +++ b/app/src/organisms/ChooseRobotSlideout/AvailableRobotOption.tsx @@ -22,7 +22,7 @@ import { getNetworkInterfaces, fetchStatus } from '../../redux/networking' import { appShellRequestor } from '../../redux/shell/remote' import OT2_PNG from '../../assets/images/OT2-R_HERO.png' import FLEX_PNG from '../../assets/images/FLEX.png' -import { useNotifyAllRunsQuery } from '../../resources/runs' +import { useCurrentRunId, useNotifyRunQuery } from '../../resources/runs' import type { IconName } from '@opentrons/components' import type { Runs } from '@opentrons/api-client' @@ -59,14 +59,15 @@ export function AvailableRobotOption( getRobotModelByName(state, robotName) ) - const { data: runsData } = useNotifyAllRunsQuery( - { pageLength: 0 }, + const [isBusy, setIsBusy] = React.useState(true) + + const currentRunId = useCurrentRunId( { onSuccess: data => { - if ((data as Runs)?.links?.current != null) - registerRobotBusyStatus({ type: 'robotIsBusy', robotName }) - else { + const definitelyIdle = (data as Runs)?.links?.current == null + if (definitelyIdle) { registerRobotBusyStatus({ type: 'robotIsIdle', robotName }) + setIsBusy(false) } }, }, @@ -75,7 +76,28 @@ export function AvailableRobotOption( requestor: ip === OPENTRONS_USB ? appShellRequestor : undefined, } ) - const robotHasCurrentRun = runsData?.links?.current != null + + useNotifyRunQuery( + currentRunId, + { + onSuccess: data => { + const busy = data?.data != null && data.data.completedAt == null + registerRobotBusyStatus({ + type: busy ? 'robotIsBusy' : 'robotIsIdle', + robotName, + }) + setIsBusy(busy) + }, + onError: () => { + registerRobotBusyStatus({ type: 'robotIsIdle', robotName }) + setIsBusy(false) + }, + }, + { + hostname: ip, + requestor: ip === OPENTRONS_USB ? appShellRequestor : undefined, + } + ) const { ethernet, wifi } = useSelector((state: State) => getNetworkInterfaces(state, robotName) @@ -95,7 +117,7 @@ export function AvailableRobotOption( // eslint-disable-next-line react-hooks/exhaustive-deps }, []) - return showIdleOnly && robotHasCurrentRun ? null : ( + return showIdleOnly && isBusy ? null : ( <> @@ -88,7 +89,7 @@ describe('ChooseRobotToRunProtocolSlideout', () => { isClosingCurrentRun: false, closeCurrentRun: mockCloseCurrentRun, }) - vi.mocked(useCurrentRunId).mockReturnValue(null) + provideNullCurrentRunIdFor(mockConnectableRobot.ip) vi.mocked(useCurrentRunStatus).mockReturnValue(null) when(vi.mocked(useCreateRunFromProtocol)) .calledWith( @@ -191,6 +192,7 @@ describe('ChooseRobotToRunProtocolSlideout', () => { { ...mockConnectableRobot, name: 'otherRobot', ip: 'otherIp' }, mockConnectableRobot, ]) + provideNullCurrentRunIdFor('otherIp') render({ storedProtocolData: storedProtocolDataFixture, onCloseClick: vi.fn(), @@ -372,6 +374,7 @@ describe('ChooseRobotToRunProtocolSlideout', () => { mockConnectableRobot, { ...mockConnectableRobot, name: 'otherRobot', ip: 'otherIp' }, ]) + provideNullCurrentRunIdFor('otherIp') render({ storedProtocolData: storedProtocolDataFixture, onCloseClick: vi.fn(), @@ -387,7 +390,7 @@ describe('ChooseRobotToRunProtocolSlideout', () => { fireEvent.click(proceedButton) fireEvent.click(screen.getByRole('button', { name: 'Confirm values' })) expect(vi.mocked(useCreateRunFromProtocol)).nthCalledWith( - 2, + 3, expect.any(Object), { hostname: '127.0.0.1' }, [ @@ -450,3 +453,21 @@ describe('ChooseRobotToRunProtocolSlideout', () => { ) }) }) + +const provideNullCurrentRunIdFor = (hostname: string): void => { + let once = true + when(vi.mocked(useCurrentRunId)) + .calledWith(expect.any(Object), { + hostname, + requestor: undefined, + }) + .thenDo(options => { + void (options?.onSuccess != null && once + ? options.onSuccess(({ + links: { current: null }, + } as unknown) as UseAllRunsQueryOptions) + : {}) + once = false + return null + }) +}