Skip to content

Commit

Permalink
enhance: option to delete workflow triggers with workflow deletion (#…
Browse files Browse the repository at this point in the history
…1446)

* enhance: option to delete workflow triggers with workflow deletion

* delete-triggers in apiRoutes
  • Loading branch information
ivyjeong13 authored Jan 27, 2025
1 parent 19f6156 commit ae21a35
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 24 deletions.
6 changes: 5 additions & 1 deletion ui/admin/app/components/composed/ConfirmationDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type ConfirmationDialogProps = ComponentProps<typeof Dialog> & {
onConfirm: (e: React.MouseEvent<HTMLButtonElement>) => void;
onCancel?: (e: React.MouseEvent<HTMLButtonElement>) => void;
confirmProps?: Omit<Partial<ComponentProps<typeof Button>>, "onClick">;
cancelProps?: Omit<Partial<ComponentProps<typeof Button>>, "onClick">;
closeOnConfirm?: boolean;
};

Expand All @@ -31,6 +32,7 @@ export function ConfirmationDialog({
onConfirm,
onCancel,
confirmProps,
cancelProps,
closeOnConfirm = true,
...dialogProps
}: ConfirmationDialogProps) {
Expand All @@ -49,7 +51,9 @@ export function ConfirmationDialog({

<DialogFooter>
<DialogClose onClick={onCancel} asChild>
<Button variant="secondary">Cancel</Button>
<Button variant="secondary" {...cancelProps}>
{cancelProps?.children ?? "Cancel"}
</Button>
</DialogClose>

{closeOnConfirm ? (
Expand Down
92 changes: 75 additions & 17 deletions ui/admin/app/components/workflow/DeleteWorkflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import {
TooltipContent,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { useConfirmationDialog } from "~/hooks/component-helpers/useConfirmationDialog";
import { useAsync } from "~/hooks/useAsync";
import { useWorkflowTriggers } from "~/hooks/workflow-triggers/useWorkflowTriggers";

type DeleteWorkflowButtonProps = {
id: string;
Expand All @@ -22,35 +24,91 @@ export function DeleteWorkflowButton({
id,
onSuccess,
}: DeleteWorkflowButtonProps) {
const deleteAssociatedTriggersConfirm = useConfirmationDialog();
const deleteWorkflowConfirm = useConfirmationDialog();

const { workflowTriggers } = useWorkflowTriggers({ workflowId: id });

const handleSuccess = () => {
mutate(WorkflowService.getWorkflows.key());
toast.success("Workflow deleted");
onSuccess?.();
};

const deleteWorkflow = useAsync(WorkflowService.deleteWorkflow, {
onSuccess: () => {
mutate(WorkflowService.getWorkflows.key());
toast.success("Workflow deleted");
onSuccess?.();
},
onError: () => toast.error("Failed to delete workflow"),
onSuccess: handleSuccess,
});

const deleteWorkflowWithTriggers = useAsync(
WorkflowService.deleteWorkflowWithTriggers,
{
onSuccess: handleSuccess,
}
);

const handleDelete = async (deleteTriggers: boolean) => {
if (deleteTriggers) {
await deleteWorkflowWithTriggers.execute(id);
} else {
await deleteWorkflow.execute(id);
}
};

const handleConfirmDeleteWorkflow = () => {
const handleConfirm = async () => {
if (workflowTriggers.length > 0) {
deleteAssociatedTriggersConfirm.interceptAsync(
async () => handleDelete(true),
{
onCancel: async () => handleDelete(false),
}
);
} else {
await handleDelete(false);
}
};

deleteWorkflowConfirm.interceptAsync(handleConfirm);
};

return (
<Tooltip>
<ConfirmationDialog
title="Delete Workflow?"
onConfirm={() => deleteWorkflow.execute(id)}
confirmProps={{ variant: "destructive", children: "Delete" }}
description="This action cannot be undone."
>
<>
<Tooltip>
<TooltipTrigger onClick={(e) => e.stopPropagation()} asChild>
<Button
variant="ghost"
size="icon"
loading={deleteWorkflow.isLoading}
loading={
deleteWorkflow.isLoading || deleteWorkflowWithTriggers.isLoading
}
onClick={handleConfirmDeleteWorkflow}
>
<TrashIcon />
</Button>
</TooltipTrigger>
</ConfirmationDialog>

<TooltipContent>Delete Workflow</TooltipContent>
</Tooltip>
<TooltipContent>Delete Workflow</TooltipContent>
</Tooltip>
<ConfirmationDialog
{...deleteWorkflowConfirm.dialogProps}
title="Delete Workflow?"
confirmProps={{ variant: "destructive", children: "Delete" }}
description="This action cannot be undone."
/>
<ConfirmationDialog
{...deleteAssociatedTriggersConfirm.dialogProps}
title="Delete Associated Triggers?"
description="There are attached workflow triggers to this workflow. Would you like to delete them as well?"
confirmProps={{
variant: "destructive",
children: "Delete",
loading: deleteWorkflowWithTriggers.isLoading,
}}
cancelProps={{
children: "Keep",
loading: deleteWorkflow.isLoading,
}}
/>
</>
);
}
2 changes: 2 additions & 0 deletions ui/admin/app/lib/routers/apiRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ export const ApiRoutes = {
getById: (workflowId: string) => buildUrl(`/workflows/${workflowId}`),
authenticate: (workflowId: string) =>
buildUrl(`/workflows/${workflowId}/authenticate`),
deleteWithTriggers: (workflowId: string) =>
buildUrl(`/workflows/${workflowId}`, { "delete-triggers": "true" }),
},
toolAuthentication: {
authenticate: (namespace: AssistantNamespace, entityId: string) =>
Expand Down
9 changes: 9 additions & 0 deletions ui/admin/app/lib/service/api/workflowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ async function deleteWorkflow(id: string) {
});
}

async function deleteWorkflowWithTriggers(id: string) {
await request({
url: ApiRoutes.workflows.deleteWithTriggers(id).url,
method: "DELETE",
errorMessage: "Failed to delete workflow and triggers",
});
}

const revalidateWorkflows = () =>
revalidateWhere((url) => url.includes(ApiRoutes.workflows.base().path));

Expand Down Expand Up @@ -93,6 +101,7 @@ export const WorkflowService = {
createWorkflow,
updateWorkflow,
deleteWorkflow,
deleteWorkflowWithTriggers,
revalidateWorkflows,
authenticateWorkflow,
};
15 changes: 9 additions & 6 deletions ui/admin/app/routes/_auth.workflow-triggers._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,15 @@ export default function WorkflowTriggersPage() {
columnHelper.accessor((row) => row.type as string, {
header: "Type",
}),
columnHelper.accessor(
(row) => workflowMap[row.workflow]?.name ?? row.workflow,
{
header: "Workflow",
}
),
columnHelper.accessor((row) => workflowMap[row.workflow]?.name, {
header: "Workflow",
cell: ({ getValue }) =>
getValue() ?? (
<span className="text-muted-foreground">
Workflow Not Available
</span>
),
}),
columnHelper.display({
id: "actions",
cell: ({ row }) => (
Expand Down

0 comments on commit ae21a35

Please sign in to comment.