Skip to content

Commit

Permalink
Add webhook callback url in run workflow form (#1035)
Browse files Browse the repository at this point in the history
  • Loading branch information
wintonzheng authored Oct 23, 2024
1 parent 3f1a9b3 commit 2798c4c
Showing 1 changed file with 146 additions and 70 deletions.
216 changes: 146 additions & 70 deletions skyvern-frontend/src/routes/workflows/RunWorkflowForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { useCredentialGetter } from "@/hooks/useCredentialGetter";
import { useMutation, useQueryClient } from "@tanstack/react-query";
Expand All @@ -20,6 +21,8 @@ import { apiBaseUrl } from "@/util/env";
import { useApiCredential } from "@/hooks/useApiCredential";
import { copyText } from "@/util/copyText";
import { WorkflowParameter } from "./types/workflowTypes";
import { Input } from "@/components/ui/input";
import { z } from "zod";

type Props = {
workflowParameters: Array<WorkflowParameter>;
Expand Down Expand Up @@ -61,20 +64,33 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
const { workflowPermanentId } = useParams();
const credentialGetter = useCredentialGetter();
const queryClient = useQueryClient();
const form = useForm({
defaultValues: initialValues,
const form = useForm<Record<string, unknown>>({
defaultValues: { ...initialValues, webhookCallbackUrl: null },
});
const apiCredential = useApiCredential();

const runWorkflowMutation = useMutation({
mutationFn: async (values: Record<string, unknown>) => {
const client = await getClient(credentialGetter);

const { webhookCallbackUrl, ...parameters } = values;

const body: {
data: Record<string, unknown>;
proxy_location: string;
webhook_callback_url?: string;
} = {
data: parameters,
proxy_location: "RESIDENTIAL",
};

if (webhookCallbackUrl) {
body.webhook_callback_url = webhookCallbackUrl as string;
}

return client.post<unknown, { data: { workflow_run_id: string } }>(
`/workflows/${workflowPermanentId}/run`,
{
data: values,
proxy_location: "RESIDENTIAL",
},
body,
);
},
onSuccess: (response) => {
Expand Down Expand Up @@ -114,75 +130,135 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {

return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 rounded-lg bg-slate-elevation3 px-6 py-5"
>
{workflowParameters?.map((parameter) => {
return (
<FormField
key={parameter.key}
control={form.control}
name={parameter.key}
rules={{
validate: (value) => {
if (
parameter.workflow_parameter_type === "json" &&
typeof value === "string"
) {
try {
JSON.parse(value);
return true;
} catch (e) {
return "Invalid JSON";
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<div className="space-y-8 rounded-lg bg-slate-elevation3 px-6 py-5">
<header>
<h1 className="text-lg">Workflow Parameters</h1>
</header>
{workflowParameters?.map((parameter) => {
return (
<FormField
key={parameter.key}
control={form.control}
name={parameter.key}
rules={{
validate: (value) => {
if (
parameter.workflow_parameter_type === "json" &&
typeof value === "string"
) {
try {
JSON.parse(value);
return true;
} catch (e) {
return "Invalid JSON";
}
}
}
if (value === null) {
return "This field is required";
}
},
}}
render={({ field }) => {
return (
<FormItem>
<div className="flex gap-16">
<FormLabel>
<div className="w-72">
<div className="flex items-center gap-2 text-lg">
{parameter.key}
<span className="text-sm text-slate-400">
{parameter.workflow_parameter_type}
</span>
if (value === null) {
return "This field is required";
}
},
}}
render={({ field }) => {
return (
<FormItem>
<div className="flex gap-16">
<FormLabel>
<div className="w-72">
<div className="flex items-center gap-2 text-lg">
{parameter.key}
<span className="text-sm text-slate-400">
{parameter.workflow_parameter_type}
</span>
</div>
<h2 className="text-sm text-slate-400">
{parameter.description}
</h2>
</div>
<h2 className="text-sm text-slate-400">
{parameter.description}
</h2>
</FormLabel>
<div className="w-full space-y-2">
<FormControl>
<WorkflowParameterInput
type={parameter.workflow_parameter_type}
value={field.value}
onChange={field.onChange}
/>
</FormControl>
{form.formState.errors[parameter.key] && (
<div className="text-destructive">
{form.formState.errors[parameter.key]?.message}
</div>
)}
</div>
</FormLabel>
<div className="w-full space-y-2">
<FormControl>
<WorkflowParameterInput
type={parameter.workflow_parameter_type}
value={field.value}
onChange={field.onChange}
/>
</FormControl>
{form.formState.errors[parameter.key] && (
<div className="text-destructive">
{form.formState.errors[parameter.key]?.message}
</div>
)}
</div>
</FormItem>
);
}}
/>
);
})}
{workflowParameters.length === 0 && (
<div>No workflow parameters for this workflow.</div>
)}
</div>

<div className="space-y-8 rounded-lg bg-slate-elevation3 px-6 py-5">
<header>
<h1 className="text-lg">Advanced Settings</h1>
</header>
<FormField
key="webhookCallbackUrl"
control={form.control}
name={"webhookCallbackUrl"}
rules={{
validate: (value) => {
if (value === null) {
return;
}
if (typeof value !== "string") {
return "Invalid URL";
}
const urlSchema = z.string().url({ message: "Invalid URL" });
const { success } = urlSchema.safeParse(value);
if (!success) {
return "Invalid URL";
}
},
}}
render={({ field }) => {
return (
<FormItem>
<div className="flex gap-16">
<FormLabel>
<div className="w-72">
<div className="flex items-center gap-2 text-lg">
Webhook Callback URL
</div>
<h2 className="text-sm text-slate-400">
The URL of a webhook endpoint to send the details of
the workflow result.
</h2>
</div>
</FormLabel>
<div className="w-full space-y-2">
<FormControl>
<Input
{...field}
placeholder="https://"
value={
field.value === null ? "" : (field.value as string)
}
/>
</FormControl>
<FormMessage />
</div>
</FormItem>
);
}}
/>
);
})}
{workflowParameters.length === 0 && (
<div>No workflow parameters for this workflow.</div>
)}
</div>
</FormItem>
);
}}
/>
</div>

<div className="flex justify-end gap-2">
<Button
type="button"
Expand Down

0 comments on commit 2798c4c

Please sign in to comment.