Add copy as curl button to run workflow form (#839)
This commit is contained in:
@@ -8,7 +8,7 @@ import { Link, useParams } from "react-router-dom";
|
|||||||
import { WorkflowParameterInput } from "./WorkflowParameterInput";
|
import { WorkflowParameterInput } from "./WorkflowParameterInput";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { toast } from "@/components/ui/use-toast";
|
import { toast } from "@/components/ui/use-toast";
|
||||||
import { PlayIcon, ReloadIcon } from "@radix-ui/react-icons";
|
import { CopyIcon, PlayIcon, ReloadIcon } from "@radix-ui/react-icons";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -18,12 +18,47 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { ToastAction } from "@radix-ui/react-toast";
|
import { ToastAction } from "@radix-ui/react-toast";
|
||||||
|
import fetchToCurl from "fetch-to-curl";
|
||||||
|
import { apiBaseUrl } from "@/util/env";
|
||||||
|
import { useApiCredential } from "@/hooks/useApiCredential";
|
||||||
|
import { copyText } from "@/util/copyText";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
workflowParameters: Array<WorkflowParameter>;
|
workflowParameters: Array<WorkflowParameter>;
|
||||||
initialValues: Record<string, unknown>;
|
initialValues: Record<string, unknown>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function parseValuesForWorkflowRun(
|
||||||
|
values: Record<string, unknown>,
|
||||||
|
workflowParameters: Array<WorkflowParameter>,
|
||||||
|
): Record<string, unknown> {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(values).map(([key, value]) => {
|
||||||
|
const parameter = workflowParameters?.find(
|
||||||
|
(parameter) => parameter.key === key,
|
||||||
|
);
|
||||||
|
if (parameter?.workflow_parameter_type === "json") {
|
||||||
|
try {
|
||||||
|
return [key, JSON.parse(value as string)];
|
||||||
|
} catch {
|
||||||
|
console.error("Invalid JSON"); // this should never happen, it should fall to form error
|
||||||
|
return [key, value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// can improve this via the type system maybe
|
||||||
|
if (
|
||||||
|
parameter?.workflow_parameter_type === "file_url" &&
|
||||||
|
value !== null &&
|
||||||
|
typeof value === "object" &&
|
||||||
|
"s3uri" in value
|
||||||
|
) {
|
||||||
|
return [key, value.s3uri];
|
||||||
|
}
|
||||||
|
return [key, value];
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
||||||
const { workflowPermanentId } = useParams();
|
const { workflowPermanentId } = useParams();
|
||||||
const credentialGetter = useCredentialGetter();
|
const credentialGetter = useCredentialGetter();
|
||||||
@@ -31,6 +66,7 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
const form = useForm({
|
const form = useForm({
|
||||||
defaultValues: initialValues,
|
defaultValues: initialValues,
|
||||||
});
|
});
|
||||||
|
const apiCredential = useApiCredential();
|
||||||
|
|
||||||
const runWorkflowMutation = useMutation({
|
const runWorkflowMutation = useMutation({
|
||||||
mutationFn: async (values: Record<string, unknown>) => {
|
mutationFn: async (values: Record<string, unknown>) => {
|
||||||
@@ -74,31 +110,7 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function onSubmit(values: Record<string, unknown>) {
|
function onSubmit(values: Record<string, unknown>) {
|
||||||
const parsedValues = Object.fromEntries(
|
const parsedValues = parseValuesForWorkflowRun(values, workflowParameters);
|
||||||
Object.entries(values).map(([key, value]) => {
|
|
||||||
const parameter = workflowParameters?.find(
|
|
||||||
(parameter) => parameter.key === key,
|
|
||||||
);
|
|
||||||
if (parameter?.workflow_parameter_type === "json") {
|
|
||||||
try {
|
|
||||||
return [key, JSON.parse(value as string)];
|
|
||||||
} catch {
|
|
||||||
console.error("Invalid JSON"); // this should never happen, it should fall to form error
|
|
||||||
return [key, value];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// can improve this via the type system maybe
|
|
||||||
if (
|
|
||||||
parameter?.workflow_parameter_type === "file_url" &&
|
|
||||||
value !== null &&
|
|
||||||
typeof value === "object" &&
|
|
||||||
"s3uri" in value
|
|
||||||
) {
|
|
||||||
return [key, value.s3uri];
|
|
||||||
}
|
|
||||||
return [key, value];
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
runWorkflowMutation.mutate(parsedValues);
|
runWorkflowMutation.mutate(parsedValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +192,40 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
})}
|
})}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end gap-2">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
const parsedValues = parseValuesForWorkflowRun(
|
||||||
|
form.getValues(),
|
||||||
|
workflowParameters,
|
||||||
|
);
|
||||||
|
const curl = fetchToCurl({
|
||||||
|
method: "POST",
|
||||||
|
url: `${apiBaseUrl}/workflows/${workflowPermanentId}/run`,
|
||||||
|
body: {
|
||||||
|
data: parsedValues,
|
||||||
|
proxy_location: "RESIDENTIAL",
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
copyText(curl).then(() => {
|
||||||
|
toast({
|
||||||
|
variant: "success",
|
||||||
|
title: "Copied to Clipboard",
|
||||||
|
description:
|
||||||
|
"The cURL command has been copied to your clipboard.",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CopyIcon className="mr-2 h-4 w-4" />
|
||||||
|
Copy as cURL
|
||||||
|
</Button>
|
||||||
<Button type="submit" disabled={runWorkflowMutation.isPending}>
|
<Button type="submit" disabled={runWorkflowMutation.isPending}>
|
||||||
{runWorkflowMutation.isPending && (
|
{runWorkflowMutation.isPending && (
|
||||||
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
||||||
|
|||||||
Reference in New Issue
Block a user