diff --git a/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx b/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx index 83b54db070..cc63f9c3a6 100644 --- a/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx +++ b/frontend/src/pages/projects/notebook/NotebookStatusToggle.tsx @@ -8,7 +8,7 @@ import { computeNotebooksTolerations } from '~/utilities/tolerations'; import { useAppContext } from '~/app/AppContext'; import { currentlyHasPipelines } from '~/concepts/pipelines/elyra/utils'; import { NotebookState } from './types'; -import useRefreshNotebookUntilStart from './useRefreshNotebookUntilStart'; +import useRefreshNotebookUntilStartOrStop from './useRefreshNotebookUntilStartOrStop'; import StopNotebookConfirmModal from './StopNotebookConfirmModal'; import useStopNotebookModalAvailability from './useStopNotebookModalAvailability'; import NotebookStatusText from './NotebookStatusText'; @@ -24,12 +24,12 @@ const NotebookStatusToggle: React.FC = ({ doListen, enablePipelines, }) => { - const { notebook, isStarting, isRunning, refresh } = notebookState; + const { notebook, isStarting, isRunning, isStopping, refresh } = notebookState; const gpuNumber = useNotebookGPUNumber(notebook); const { size } = useNotebookDeploymentSize(notebook); const [isOpenConfirm, setOpenConfirm] = React.useState(false); const [inProgress, setInProgress] = React.useState(false); - const listenToNotebookStart = useRefreshNotebookUntilStart(notebookState, doListen); + const listenToNotebookStart = useRefreshNotebookUntilStartOrStop(notebookState, doListen); const [dontShowModalValue] = useStopNotebookModalAvailability(); const { dashboardConfig } = useAppContext(); const notebookName = notebook.metadata.name; @@ -42,8 +42,8 @@ const NotebookStatusToggle: React.FC = ({ let label = ''; if (isStarting) { label = 'Starting...'; - } else if (inProgress) { - label = isChecked ? 'Starting...' : 'Stopping...'; + } else if (isStopping) { + label = 'Stopping...'; } else { label = isRunning ? 'Running' : 'Stopped'; } @@ -72,7 +72,7 @@ const NotebookStatusToggle: React.FC = ({ setInProgress(true); stopNotebook(notebookName, notebookNamespace).then(() => { refresh().then(() => setInProgress(false)); - listenToNotebookStart(false); + listenToNotebookStart(true, true); }); }, [notebookName, notebookNamespace, refresh, listenToNotebookStart, fireNotebookTrackingEvent]); @@ -82,7 +82,7 @@ const NotebookStatusToggle: React.FC = ({ { diff --git a/frontend/src/pages/projects/notebook/service.ts b/frontend/src/pages/projects/notebook/service.ts index 550b087a49..c7bb080223 100644 --- a/frontend/src/pages/projects/notebook/service.ts +++ b/frontend/src/pages/projects/notebook/service.ts @@ -34,6 +34,8 @@ export const getNotebooksStatus = async ( notebook: notebooks[i], isStarting: !isStopped && !podsReady, isRunning: !isStopped && podsReady, + isStopping: isStopped && podsReady, + isStopped: isStopped && !podsReady, runningPodUid: pods[0]?.metadata?.uid || '', }, ]; diff --git a/frontend/src/pages/projects/notebook/types.ts b/frontend/src/pages/projects/notebook/types.ts index 5046993f6b..d8d889905d 100644 --- a/frontend/src/pages/projects/notebook/types.ts +++ b/frontend/src/pages/projects/notebook/types.ts @@ -5,6 +5,8 @@ export type NotebookDataState = { notebook: NotebookKind; isStarting: boolean; isRunning: boolean; + isStopping: boolean; + isStopped: boolean; runningPodUid: string; }; diff --git a/frontend/src/pages/projects/notebook/useRefreshNotebookUntilStart.ts b/frontend/src/pages/projects/notebook/useRefreshNotebookUntilStartOrStop.ts similarity index 58% rename from frontend/src/pages/projects/notebook/useRefreshNotebookUntilStart.ts rename to frontend/src/pages/projects/notebook/useRefreshNotebookUntilStartOrStop.ts index 95ba86283f..17288d085c 100644 --- a/frontend/src/pages/projects/notebook/useRefreshNotebookUntilStart.ts +++ b/frontend/src/pages/projects/notebook/useRefreshNotebookUntilStartOrStop.ts @@ -2,11 +2,12 @@ import * as React from 'react'; import { FAST_POLL_INTERVAL } from '~/utilities/const'; import { NotebookState } from './types'; -const useRefreshNotebookUntilStart = ( +const useRefreshNotebookUntilStartOrStop = ( notebookState: NotebookState, doListen: boolean, -): ((listen: boolean) => void) => { +): ((listen: boolean, stop?: boolean) => void) => { const [watchingForNotebook, setWatchingForNotebook] = React.useState(false); + const [watchingForStop, setWatchingForStop] = React.useState(false); const lastNotebookState = React.useRef(notebookState); lastNotebookState.current = notebookState; @@ -14,8 +15,9 @@ const useRefreshNotebookUntilStart = ( let interval; if (watchingForNotebook && doListen) { interval = setInterval(() => { - const { isRunning, refresh } = lastNotebookState.current; - if (!isRunning) { + const { isRunning, isStopped, refresh } = lastNotebookState.current; + const condition = watchingForStop ? isStopped : isRunning; + if (!condition) { refresh().catch((e) => { /* eslint-disable-next-line no-console */ console.error('Error refreshing, stopping notebook refresh', e); @@ -30,11 +32,15 @@ const useRefreshNotebookUntilStart = ( return () => { clearInterval(interval); }; - }, [watchingForNotebook, doListen]); + }, [watchingForStop, watchingForNotebook, doListen]); - return React.useCallback((listen: boolean) => { + /** + * The second parameter allows listening for the notebook to be stopped. Default is to wait until started. + */ + return React.useCallback((listen: boolean, waitForStop = false) => { + setWatchingForStop(waitForStop); setWatchingForNotebook(listen); }, []); }; -export default useRefreshNotebookUntilStart; +export default useRefreshNotebookUntilStartOrStop; diff --git a/frontend/src/pages/projects/screens/detail/notebooks/NotebookTableRow.tsx b/frontend/src/pages/projects/screens/detail/notebooks/NotebookTableRow.tsx index c54bcede43..979a5c1e23 100644 --- a/frontend/src/pages/projects/screens/detail/notebooks/NotebookTableRow.tsx +++ b/frontend/src/pages/projects/screens/detail/notebooks/NotebookTableRow.tsx @@ -94,7 +94,7 @@ const NotebookTableRow: React.FC = ({ { navigate(