Add cancel workflow functionality (#1193)
Co-authored-by: Muhammed Salih Altun <muhammedsalihaltun@gmail.com>
This commit is contained in:
@@ -43,9 +43,11 @@ import {
|
|||||||
Pencil2Icon,
|
Pencil2Icon,
|
||||||
PlayIcon,
|
PlayIcon,
|
||||||
ReaderIcon,
|
ReaderIcon,
|
||||||
|
ReloadIcon,
|
||||||
} from "@radix-ui/react-icons";
|
} from "@radix-ui/react-icons";
|
||||||
import {
|
import {
|
||||||
keepPreviousData,
|
keepPreviousData,
|
||||||
|
useMutation,
|
||||||
useQuery,
|
useQuery,
|
||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
@@ -59,9 +61,23 @@ import {
|
|||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
import { TaskActions } from "../tasks/list/TaskActions";
|
import { TaskActions } from "../tasks/list/TaskActions";
|
||||||
import { TaskListSkeletonRows } from "../tasks/list/TaskListSkeletonRows";
|
import { TaskListSkeletonRows } from "../tasks/list/TaskListSkeletonRows";
|
||||||
import { statusIsNotFinalized, statusIsRunningOrQueued } from "../tasks/types";
|
import {
|
||||||
|
statusIsFinalized,
|
||||||
|
statusIsNotFinalized,
|
||||||
|
statusIsRunningOrQueued,
|
||||||
|
} from "../tasks/types";
|
||||||
import { CodeEditor } from "./components/CodeEditor";
|
import { CodeEditor } from "./components/CodeEditor";
|
||||||
import { useWorkflowQuery } from "./hooks/useWorkflowQuery";
|
import { useWorkflowQuery } from "./hooks/useWorkflowQuery";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
|
||||||
type StreamMessage = {
|
type StreamMessage = {
|
||||||
task_id: string;
|
task_id: string;
|
||||||
@@ -144,6 +160,35 @@ function WorkflowRun() {
|
|||||||
workflowRun?.status === Status.Running ? "always" : false,
|
workflowRun?.status === Status.Running ? "always" : false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cancelWorkflowMutation = useMutation({
|
||||||
|
mutationFn: async () => {
|
||||||
|
const client = await getClient(credentialGetter);
|
||||||
|
return client
|
||||||
|
.post(`/workflows/runs/${workflowRunId}/cancel`)
|
||||||
|
.then((response) => response.data);
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ["workflowRun", workflowRunId],
|
||||||
|
});
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ["workflowRun", workflowPermanentId, workflowRunId],
|
||||||
|
});
|
||||||
|
toast({
|
||||||
|
variant: "success",
|
||||||
|
title: "Workflow Canceled",
|
||||||
|
description: "The workflow has been successfully canceled.",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast({
|
||||||
|
variant: "destructive",
|
||||||
|
title: "Error",
|
||||||
|
description: error.message,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const currentRunningTask = workflowTasks?.find(
|
const currentRunningTask = workflowTasks?.find(
|
||||||
(task) => task.status === Status.Running,
|
(task) => task.status === Status.Running,
|
||||||
);
|
);
|
||||||
@@ -151,6 +196,8 @@ function WorkflowRun() {
|
|||||||
const workflowRunIsRunningOrQueued =
|
const workflowRunIsRunningOrQueued =
|
||||||
workflowRun && statusIsRunningOrQueued(workflowRun);
|
workflowRun && statusIsRunningOrQueued(workflowRun);
|
||||||
|
|
||||||
|
const workflowRunIsFinalized = workflowRun && statusIsFinalized(workflowRun);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!workflowRunIsRunningOrQueued) {
|
if (!workflowRunIsRunningOrQueued) {
|
||||||
return;
|
return;
|
||||||
@@ -347,17 +394,51 @@ function WorkflowRun() {
|
|||||||
Edit
|
Edit
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button asChild>
|
{workflowRunIsRunningOrQueued && (
|
||||||
<Link
|
<Dialog>
|
||||||
to={`/workflows/${workflowPermanentId}/run`}
|
<DialogTrigger asChild>
|
||||||
state={{
|
<Button variant="destructive">Cancel</Button>
|
||||||
data: parameters,
|
</DialogTrigger>
|
||||||
}}
|
<DialogContent>
|
||||||
>
|
<DialogHeader>
|
||||||
<PlayIcon className="mr-2 h-4 w-4" />
|
<DialogTitle>Are you sure?</DialogTitle>
|
||||||
Rerun
|
<DialogDescription>
|
||||||
</Link>
|
Are you sure you want to cancel this workflow run?
|
||||||
</Button>
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button variant="secondary">Back</Button>
|
||||||
|
</DialogClose>
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
onClick={() => {
|
||||||
|
cancelWorkflowMutation.mutate();
|
||||||
|
}}
|
||||||
|
disabled={cancelWorkflowMutation.isPending}
|
||||||
|
>
|
||||||
|
{cancelWorkflowMutation.isPending && (
|
||||||
|
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
||||||
|
)}
|
||||||
|
Cancel Workflow Run
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)}
|
||||||
|
{workflowRunIsFinalized && (
|
||||||
|
<Button asChild>
|
||||||
|
<Link
|
||||||
|
to={`/workflows/${workflowPermanentId}/run`}
|
||||||
|
state={{
|
||||||
|
data: parameters,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlayIcon className="mr-2 h-4 w-4" />
|
||||||
|
Rerun
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
{workflowRun && statusIsNotFinalized(workflowRun) && (
|
{workflowRun && statusIsNotFinalized(workflowRun) && (
|
||||||
|
|||||||
Reference in New Issue
Block a user