Add proxy location to task form advanced settings (#1171)
This commit is contained in:
41
skyvern-frontend/src/components/ProxySelector.tsx
Normal file
41
skyvern-frontend/src/components/ProxySelector.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { ProxyLocation } from "@/api/types";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "./ui/select";
|
||||
|
||||
type Props = {
|
||||
value: ProxyLocation | null;
|
||||
onChange: (value: ProxyLocation) => void;
|
||||
};
|
||||
|
||||
function ProxySelector({ value, onChange }: Props) {
|
||||
return (
|
||||
<Select value={value ?? ""} onValueChange={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>
|
||||
);
|
||||
}
|
||||
|
||||
export { ProxySelector };
|
||||
@@ -1,5 +1,9 @@
|
||||
import { getClient } from "@/api/AxiosClient";
|
||||
import { CreateTaskRequest, OrganizationApiResponse } from "@/api/types";
|
||||
import {
|
||||
CreateTaskRequest,
|
||||
OrganizationApiResponse,
|
||||
ProxyLocation,
|
||||
} from "@/api/types";
|
||||
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@@ -33,6 +37,7 @@ import {
|
||||
createNewTaskFormSchema,
|
||||
CreateNewTaskFormValues,
|
||||
} from "./taskFormTypes";
|
||||
import { ProxySelector } from "@/components/ProxySelector";
|
||||
|
||||
type Props = {
|
||||
initialValues: CreateNewTaskFormValues;
|
||||
@@ -70,7 +75,7 @@ function createTaskRequestObject(
|
||||
webhook_callback_url: transform(formValues.webhookCallbackUrl),
|
||||
navigation_goal: transform(formValues.navigationGoal),
|
||||
data_extraction_goal: transform(formValues.dataExtractionGoal),
|
||||
proxy_location: "RESIDENTIAL",
|
||||
proxy_location: formValues.proxyLocation ?? ProxyLocation.Residential,
|
||||
navigation_payload: transform(formValues.navigationPayload),
|
||||
extracted_information_schema: extractedInformationSchema,
|
||||
totp_verification_url: transform(formValues.totpVerificationUrl),
|
||||
@@ -105,10 +110,10 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
|
||||
const form = useForm<CreateNewTaskFormValues>({
|
||||
resolver: zodResolver(createNewTaskFormSchema),
|
||||
defaultValues: initialValues,
|
||||
values: {
|
||||
defaultValues: {
|
||||
...initialValues,
|
||||
maxStepsOverride: null,
|
||||
maxStepsOverride: initialValues.maxStepsOverride ?? null,
|
||||
proxyLocation: initialValues.proxyLocation ?? ProxyLocation.Residential,
|
||||
},
|
||||
});
|
||||
const { errors } = useFormState({ control: form.control });
|
||||
@@ -486,6 +491,38 @@ function CreateNewTaskForm({ initialValues }: Props) {
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
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>
|
||||
<ProxySelector
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
</div>
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Separator />
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
||||
@@ -60,6 +60,7 @@ function CreateNewTaskFormPage() {
|
||||
totpIdentifier: null,
|
||||
totpVerificationUrl: null,
|
||||
webhookCallbackUrl: null,
|
||||
proxyLocation: null,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,8 @@ import { stringify as convertToYAML } from "yaml";
|
||||
import { MAX_STEPS_DEFAULT } from "../constants";
|
||||
import { TaskFormSection } from "./TaskFormSection";
|
||||
import { savedTaskFormSchema, SavedTaskFormValues } from "./taskFormTypes";
|
||||
import { OrganizationApiResponse } from "@/api/types";
|
||||
import { OrganizationApiResponse, ProxyLocation } from "@/api/types";
|
||||
import { ProxySelector } from "@/components/ProxySelector";
|
||||
|
||||
type Props = {
|
||||
initialValues: SavedTaskFormValues;
|
||||
@@ -157,10 +158,10 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
|
||||
const form = useForm<SavedTaskFormValues>({
|
||||
resolver: zodResolver(savedTaskFormSchema),
|
||||
defaultValues: initialValues,
|
||||
values: {
|
||||
defaultValues: {
|
||||
...initialValues,
|
||||
maxStepsOverride: initialValues.maxStepsOverride ?? null,
|
||||
proxyLocation: initialValues.proxyLocation ?? ProxyLocation.Residential,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -662,6 +663,38 @@ function SavedTaskForm({ initialValues }: Props) {
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
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>
|
||||
<ProxySelector
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
</div>
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Separator />
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
||||
@@ -42,6 +42,7 @@ function RetryTask() {
|
||||
errorCodeMapping: task.request.error_code_mapping
|
||||
? JSON.stringify(task.request.error_code_mapping, null, 2)
|
||||
: "",
|
||||
proxyLocation: task.request.proxy_location,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ProxyLocation } from "@/api/types";
|
||||
import { z } from "zod";
|
||||
|
||||
const createNewTaskFormSchemaBase = z.object({
|
||||
@@ -13,12 +14,12 @@ const createNewTaskFormSchemaBase = z.object({
|
||||
totpVerificationUrl: z.string().or(z.null()),
|
||||
totpIdentifier: z.string().or(z.null()),
|
||||
errorCodeMapping: z.string().or(z.null()),
|
||||
proxyLocation: z.nativeEnum(ProxyLocation).or(z.null()),
|
||||
});
|
||||
|
||||
const savedTaskFormSchemaBase = createNewTaskFormSchemaBase.extend({
|
||||
title: z.string().min(1, "Title is required"),
|
||||
description: z.string(),
|
||||
proxyLocation: z.string().or(z.null()),
|
||||
});
|
||||
|
||||
function refineTaskFormValues(
|
||||
|
||||
@@ -24,13 +24,7 @@ import { WorkflowParameter } from "./types/workflowTypes";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { z } from "zod";
|
||||
import { ProxyLocation } from "@/api/types";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { ProxySelector } from "@/components/ProxySelector";
|
||||
|
||||
type Props = {
|
||||
workflowParameters: Array<WorkflowParameter>;
|
||||
@@ -316,34 +310,10 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
||||
</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>
|
||||
<ProxySelector
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user