Add proxy location to workflow run screen (#1158)
This commit is contained in:
@@ -12,6 +12,8 @@ export const ArtifactType = {
|
|||||||
HTMLScrape: "html_scrape",
|
HTMLScrape: "html_scrape",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export type ArtifactType = (typeof ArtifactType)[keyof typeof ArtifactType];
|
||||||
|
|
||||||
export const Status = {
|
export const Status = {
|
||||||
Created: "created",
|
Created: "created",
|
||||||
Running: "running",
|
Running: "running",
|
||||||
@@ -25,7 +27,16 @@ export const Status = {
|
|||||||
|
|
||||||
export type Status = (typeof Status)[keyof typeof Status];
|
export type Status = (typeof Status)[keyof typeof Status];
|
||||||
|
|
||||||
export type ArtifactType = (typeof ArtifactType)[keyof typeof ArtifactType];
|
export const ProxyLocation = {
|
||||||
|
Residential: "RESIDENTIAL",
|
||||||
|
ResidentialIE: "RESIDENTIAL_IE",
|
||||||
|
ResidentialES: "RESIDENTIAL_ES",
|
||||||
|
ResidentialIN: "RESIDENTIAL_IN",
|
||||||
|
ResidentialJP: "RESIDENTIAL_JP",
|
||||||
|
None: "NONE",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type ProxyLocation = (typeof ProxyLocation)[keyof typeof ProxyLocation];
|
||||||
|
|
||||||
export type ArtifactApiResponse = {
|
export type ArtifactApiResponse = {
|
||||||
created_at: string;
|
created_at: string;
|
||||||
@@ -90,7 +101,7 @@ export type CreateTaskRequest = {
|
|||||||
navigation_payload: Record<string, unknown> | string | null;
|
navigation_payload: Record<string, unknown> | string | null;
|
||||||
extracted_information_schema: Record<string, unknown> | string | null;
|
extracted_information_schema: Record<string, unknown> | string | null;
|
||||||
error_code_mapping: Record<string, string> | null;
|
error_code_mapping: Record<string, string> | null;
|
||||||
proxy_location: string | null;
|
proxy_location: ProxyLocation | null;
|
||||||
totp_verification_url: string | null;
|
totp_verification_url: string | null;
|
||||||
totp_identifier: string | null;
|
totp_identifier: string | null;
|
||||||
};
|
};
|
||||||
@@ -184,7 +195,7 @@ export type WorkflowApiResponse = {
|
|||||||
parameters: Array<WorkflowParameter>;
|
parameters: Array<WorkflowParameter>;
|
||||||
blocks: Array<WorkflowBlock>;
|
blocks: Array<WorkflowBlock>;
|
||||||
};
|
};
|
||||||
proxy_location: string;
|
proxy_location: ProxyLocation | null;
|
||||||
webhook_callback_url: string;
|
webhook_callback_url: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
modified_at: string;
|
modified_at: string;
|
||||||
@@ -248,7 +259,7 @@ export type WorkflowRunApiResponse = {
|
|||||||
workflow_run_id: string;
|
workflow_run_id: string;
|
||||||
workflow_id: string;
|
workflow_id: string;
|
||||||
status: Status;
|
status: Status;
|
||||||
proxy_location: string;
|
proxy_location: ProxyLocation | null;
|
||||||
webhook_callback_url: string;
|
webhook_callback_url: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
modified_at: string;
|
modified_at: string;
|
||||||
@@ -258,7 +269,7 @@ export type WorkflowRunStatusApiResponse = {
|
|||||||
workflow_id: string;
|
workflow_id: string;
|
||||||
workflow_run_id: string;
|
workflow_run_id: string;
|
||||||
status: Status;
|
status: Status;
|
||||||
proxy_location: string;
|
proxy_location: ProxyLocation | null;
|
||||||
webhook_callback_url: string | null;
|
webhook_callback_url: string | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
modified_at: string;
|
modified_at: string;
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ import { copyText } from "@/util/copyText";
|
|||||||
import { WorkflowParameter } from "./types/workflowTypes";
|
import { WorkflowParameter } from "./types/workflowTypes";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import { ProxyLocation } from "@/api/types";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
workflowParameters: Array<WorkflowParameter>;
|
workflowParameters: Array<WorkflowParameter>;
|
||||||
@@ -60,38 +68,61 @@ function parseValuesForWorkflowRun(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RunWorkflowRequestBody = {
|
||||||
|
data: Record<string, unknown>; // workflow parameters and values
|
||||||
|
proxy_location: ProxyLocation | null;
|
||||||
|
webhook_callback_url?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getRunWorkflowRequestBody(
|
||||||
|
values: RunWorkflowFormType,
|
||||||
|
workflowParameters: Array<WorkflowParameter>,
|
||||||
|
): RunWorkflowRequestBody {
|
||||||
|
const { webhookCallbackUrl, proxyLocation, ...parameters } = values;
|
||||||
|
|
||||||
|
const parsedParameters = parseValuesForWorkflowRun(
|
||||||
|
parameters,
|
||||||
|
workflowParameters,
|
||||||
|
);
|
||||||
|
|
||||||
|
const body: RunWorkflowRequestBody = {
|
||||||
|
data: parsedParameters,
|
||||||
|
proxy_location: proxyLocation,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (webhookCallbackUrl) {
|
||||||
|
body.webhook_callback_url = webhookCallbackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunWorkflowFormType = Record<string, unknown> & {
|
||||||
|
webhookCallbackUrl: string | null;
|
||||||
|
proxyLocation: ProxyLocation | null;
|
||||||
|
};
|
||||||
|
|
||||||
function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
||||||
const { workflowPermanentId } = useParams();
|
const { workflowPermanentId } = useParams();
|
||||||
const credentialGetter = useCredentialGetter();
|
const credentialGetter = useCredentialGetter();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const form = useForm<Record<string, unknown>>({
|
const form = useForm<RunWorkflowFormType>({
|
||||||
defaultValues: { ...initialValues, webhookCallbackUrl: null },
|
defaultValues: {
|
||||||
|
...initialValues,
|
||||||
|
webhookCallbackUrl: null,
|
||||||
|
proxyLocation: ProxyLocation.Residential,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const apiCredential = useApiCredential();
|
const apiCredential = useApiCredential();
|
||||||
|
|
||||||
const runWorkflowMutation = useMutation({
|
const runWorkflowMutation = useMutation({
|
||||||
mutationFn: async (values: Record<string, unknown>) => {
|
mutationFn: async (values: RunWorkflowFormType) => {
|
||||||
const client = await getClient(credentialGetter);
|
const client = await getClient(credentialGetter);
|
||||||
|
const body = getRunWorkflowRequestBody(values, workflowParameters);
|
||||||
const { webhookCallbackUrl, ...parameters } = values;
|
return client.post<
|
||||||
|
RunWorkflowRequestBody,
|
||||||
const body: {
|
{ data: { workflow_run_id: string } }
|
||||||
data: Record<string, unknown>;
|
>(`/workflows/${workflowPermanentId}/run`, body);
|
||||||
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`,
|
|
||||||
body,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
onSuccess: (response) => {
|
onSuccess: (response) => {
|
||||||
toast({
|
toast({
|
||||||
@@ -123,8 +154,8 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function onSubmit(values: Record<string, unknown>) {
|
function onSubmit(values: RunWorkflowFormType) {
|
||||||
const { webhookCallbackUrl, ...parameters } = values;
|
const { webhookCallbackUrl, proxyLocation, ...parameters } = values;
|
||||||
const parsedParameters = parseValuesForWorkflowRun(
|
const parsedParameters = parseValuesForWorkflowRun(
|
||||||
parameters,
|
parameters,
|
||||||
workflowParameters,
|
workflowParameters,
|
||||||
@@ -132,6 +163,7 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
runWorkflowMutation.mutate({
|
runWorkflowMutation.mutate({
|
||||||
...parsedParameters,
|
...parsedParameters,
|
||||||
webhookCallbackUrl,
|
webhookCallbackUrl,
|
||||||
|
proxyLocation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +248,7 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
<FormField
|
<FormField
|
||||||
key="webhookCallbackUrl"
|
key="webhookCallbackUrl"
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={"webhookCallbackUrl"}
|
name="webhookCallbackUrl"
|
||||||
rules={{
|
rules={{
|
||||||
validate: (value) => {
|
validate: (value) => {
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
@@ -264,6 +296,62 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
key="proxyLocation"
|
||||||
|
control={form.control}
|
||||||
|
name="proxyLocation"
|
||||||
|
render={({ field }) => {
|
||||||
|
return (
|
||||||
|
<FormItem>
|
||||||
|
<div className="flex gap-16">
|
||||||
|
<FormLabel>
|
||||||
|
<div className="w-72">
|
||||||
|
<div className="flex items-center gap-2 text-lg">
|
||||||
|
Proxy Location
|
||||||
|
</div>
|
||||||
|
<h2 className="text-sm text-slate-400">
|
||||||
|
Route Skyvern through one of our available proxies.
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</FormLabel>
|
||||||
|
<div className="w-full space-y-2">
|
||||||
|
<FormControl>
|
||||||
|
<Select
|
||||||
|
value={field.value ?? ""}
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-48">
|
||||||
|
<SelectValue placeholder="Proxy Location" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value={ProxyLocation.Residential}>
|
||||||
|
Residential
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value={ProxyLocation.ResidentialES}>
|
||||||
|
Residential (Spain)
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value={ProxyLocation.ResidentialIE}>
|
||||||
|
Residential (Ireland)
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value={ProxyLocation.ResidentialIN}>
|
||||||
|
Residential (India)
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value={ProxyLocation.ResidentialJP}>
|
||||||
|
Residential (Japan)
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value={ProxyLocation.None}>
|
||||||
|
None
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
@@ -272,22 +360,10 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const values = form.getValues();
|
const values = form.getValues();
|
||||||
const { webhookCallbackUrl, ...parameters } = values;
|
const body = getRunWorkflowRequestBody(
|
||||||
const parsedParameters = parseValuesForWorkflowRun(
|
values,
|
||||||
parameters,
|
|
||||||
workflowParameters,
|
workflowParameters,
|
||||||
);
|
);
|
||||||
const body: {
|
|
||||||
data: Record<string, unknown>;
|
|
||||||
proxy_location: string;
|
|
||||||
webhook_callback_url?: string;
|
|
||||||
} = {
|
|
||||||
data: parsedParameters,
|
|
||||||
proxy_location: "RESIDENTIAL",
|
|
||||||
};
|
|
||||||
if (webhookCallbackUrl) {
|
|
||||||
body.webhook_callback_url = webhookCallbackUrl as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const curl = fetchToCurl({
|
const curl = fetchToCurl({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -298,6 +374,7 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
"x-api-key": apiCredential ?? "<your-api-key>",
|
"x-api-key": apiCredential ?? "<your-api-key>",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
copyText(curl).then(() => {
|
copyText(curl).then(() => {
|
||||||
toast({
|
toast({
|
||||||
variant: "success",
|
variant: "success",
|
||||||
|
|||||||
Reference in New Issue
Block a user