From 1453cf8d42b14372c1a5c1973510450d24ae4b5a Mon Sep 17 00:00:00 2001 From: yu zhao Date: Sun, 18 Feb 2024 10:39:34 -0500 Subject: [PATCH] feat(orchestrator): display a confirmation dialog before the user aborts a running workflow (#1215) * display a confirmation dialog before the user aborts a running workflow * Fix lint issue * Move dialog action component out of the parent component --- .../src/components/InfoDialog.tsx | 2 +- .../src/components/WorkflowInstancePage.tsx | 73 ++++++++++++++----- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/plugins/orchestrator/src/components/InfoDialog.tsx b/plugins/orchestrator/src/components/InfoDialog.tsx index 37a99c911c..3813b21679 100644 --- a/plugins/orchestrator/src/components/InfoDialog.tsx +++ b/plugins/orchestrator/src/components/InfoDialog.tsx @@ -17,7 +17,7 @@ export type InfoDialogProps = { open: boolean; onClose?: () => void; dialogActions?: React.ReactNode; - children: React.ReactNode; + children?: React.ReactNode; }; export type ParentComponentRef = HTMLElement; diff --git a/plugins/orchestrator/src/components/WorkflowInstancePage.tsx b/plugins/orchestrator/src/components/WorkflowInstancePage.tsx index 1d1c57e837..d498665f7a 100644 --- a/plugins/orchestrator/src/components/WorkflowInstancePage.tsx +++ b/plugins/orchestrator/src/components/WorkflowInstancePage.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { @@ -27,8 +27,29 @@ import { executeWorkflowRouteRef, workflowInstanceRouteRef } from '../routes'; import { isNonNullable } from '../utils/TypeGuards'; import { buildUrl } from '../utils/UrlUtils'; import { BaseOrchestratorPage } from './BaseOrchestratorPage'; +import { InfoDialog } from './InfoDialog'; import { WorkflowInstancePageContent } from './WorkflowInstancePageContent'; +export type AbortConfirmationDialogActionsProps = { + handleSubmit: () => void; + handleCancel: () => void; +}; + +const AbortConfirmationDialogContent = () => ( +
Are you sure you want to abort this workflow instance?
+); + +const AbortConfirmationDialogActions = ( + props: AbortConfirmationDialogActionsProps, +) => ( + <> + + + +); + export const WorkflowInstancePage = ({ instanceId, }: { @@ -40,6 +61,8 @@ export const WorkflowInstancePage = ({ const { instanceId: queryInstanceId } = useRouteRefParams( workflowInstanceRouteRef, ); + const [isAbortConfirmationDialogOpen, setIsAbortConfirmationDialogOpen] = + useState(false); const fetchInstance = React.useCallback(async () => { if (!instanceId && !queryInstanceId) { @@ -73,26 +96,24 @@ export const WorkflowInstancePage = ({ [value], ); + const toggleAbortConfirmationDialog = () => { + setIsAbortConfirmationDialogOpen(!isAbortConfirmationDialogOpen); + }; + const handleAbort = React.useCallback(async () => { if (value) { - // eslint-disable-next-line no-alert - const yes = window.confirm( - 'Are you sure you want to abort this instance?', - ); - - if (yes) { - try { - await orchestratorApi.abortWorkflow(value.instance.id); - restart(); - } catch (e) { - // eslint-disable-next-line no-alert - window.alert( - `The abort operation failed with the following error: ${ - (e as Error).message - }`, - ); - } + try { + await orchestratorApi.abortWorkflow(value.instance.id); + restart(); + } catch (e) { + // eslint-disable-next-line no-alert + window.alert( + `The abort operation failed with the following error: ${ + (e as Error).message + }`, + ); } + setIsAbortConfirmationDialogOpen(false); } }, [orchestratorApi, restart, value]); @@ -122,6 +143,18 @@ export const WorkflowInstancePage = ({ {!loading && isNonNullable(value) ? ( <> + + } + children={} + /> {!canRerun && ( @@ -129,7 +162,9 @@ export const WorkflowInstancePage = ({ variant="contained" color="secondary" disabled={!canAbort} - onClick={canAbort ? handleAbort : undefined} + onClick={ + canAbort ? toggleAbortConfirmationDialog : undefined + } > Abort