Add webhook callback url in run workflow form (#1035)
This commit is contained in:
@@ -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";
|
||||
@@ -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>;
|
||||
@@ -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) => {
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user