diff --git a/skyvern-frontend/src/routes/workflows/WorkflowRun.tsx b/skyvern-frontend/src/routes/workflows/WorkflowRun.tsx
index 01a73be4..be390690 100644
--- a/skyvern-frontend/src/routes/workflows/WorkflowRun.tsx
+++ b/skyvern-frontend/src/routes/workflows/WorkflowRun.tsx
@@ -43,9 +43,11 @@ import {
Pencil2Icon,
PlayIcon,
ReaderIcon,
+ ReloadIcon,
} from "@radix-ui/react-icons";
import {
keepPreviousData,
+ useMutation,
useQuery,
useQueryClient,
} from "@tanstack/react-query";
@@ -59,9 +61,23 @@ import {
} from "react-router-dom";
import { TaskActions } from "../tasks/list/TaskActions";
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 { useWorkflowQuery } from "./hooks/useWorkflowQuery";
+import {
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/components/ui/dialog";
type StreamMessage = {
task_id: string;
@@ -144,6 +160,35 @@ function WorkflowRun() {
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(
(task) => task.status === Status.Running,
);
@@ -151,6 +196,8 @@ function WorkflowRun() {
const workflowRunIsRunningOrQueued =
workflowRun && statusIsRunningOrQueued(workflowRun);
+ const workflowRunIsFinalized = workflowRun && statusIsFinalized(workflowRun);
+
useEffect(() => {
if (!workflowRunIsRunningOrQueued) {
return;
@@ -347,17 +394,51 @@ function WorkflowRun() {
Edit
-
+ {workflowRunIsRunningOrQueued && (
+
+ )}
+ {workflowRunIsFinalized && (
+
+ )}
{workflowRun && statusIsNotFinalized(workflowRun) && (