Add proxy location to task form advanced settings (#1171)

This commit is contained in:
Shuchang Zheng
2024-11-11 09:50:18 -08:00
committed by GitHub
parent 3b2a7dcffc
commit a149a4675b
7 changed files with 128 additions and 44 deletions

View 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 };

View File

@@ -1,5 +1,9 @@
import { getClient } from "@/api/AxiosClient"; 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 { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
@@ -33,6 +37,7 @@ import {
createNewTaskFormSchema, createNewTaskFormSchema,
CreateNewTaskFormValues, CreateNewTaskFormValues,
} from "./taskFormTypes"; } from "./taskFormTypes";
import { ProxySelector } from "@/components/ProxySelector";
type Props = { type Props = {
initialValues: CreateNewTaskFormValues; initialValues: CreateNewTaskFormValues;
@@ -70,7 +75,7 @@ function createTaskRequestObject(
webhook_callback_url: transform(formValues.webhookCallbackUrl), webhook_callback_url: transform(formValues.webhookCallbackUrl),
navigation_goal: transform(formValues.navigationGoal), navigation_goal: transform(formValues.navigationGoal),
data_extraction_goal: transform(formValues.dataExtractionGoal), data_extraction_goal: transform(formValues.dataExtractionGoal),
proxy_location: "RESIDENTIAL", proxy_location: formValues.proxyLocation ?? ProxyLocation.Residential,
navigation_payload: transform(formValues.navigationPayload), navigation_payload: transform(formValues.navigationPayload),
extracted_information_schema: extractedInformationSchema, extracted_information_schema: extractedInformationSchema,
totp_verification_url: transform(formValues.totpVerificationUrl), totp_verification_url: transform(formValues.totpVerificationUrl),
@@ -105,10 +110,10 @@ function CreateNewTaskForm({ initialValues }: Props) {
const form = useForm<CreateNewTaskFormValues>({ const form = useForm<CreateNewTaskFormValues>({
resolver: zodResolver(createNewTaskFormSchema), resolver: zodResolver(createNewTaskFormSchema),
defaultValues: initialValues, defaultValues: {
values: {
...initialValues, ...initialValues,
maxStepsOverride: null, maxStepsOverride: initialValues.maxStepsOverride ?? null,
proxyLocation: initialValues.proxyLocation ?? ProxyLocation.Residential,
}, },
}); });
const { errors } = useFormState({ control: form.control }); const { errors } = useFormState({ control: form.control });
@@ -486,6 +491,38 @@ function CreateNewTaskForm({ initialValues }: Props) {
</FormItem> </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 /> <Separator />
<FormField <FormField
control={form.control} control={form.control}

View File

@@ -60,6 +60,7 @@ function CreateNewTaskFormPage() {
totpIdentifier: null, totpIdentifier: null,
totpVerificationUrl: null, totpVerificationUrl: null,
webhookCallbackUrl: null, webhookCallbackUrl: null,
proxyLocation: null,
}} }}
/> />
</div> </div>

View File

@@ -31,7 +31,8 @@ import { stringify as convertToYAML } from "yaml";
import { MAX_STEPS_DEFAULT } from "../constants"; import { MAX_STEPS_DEFAULT } from "../constants";
import { TaskFormSection } from "./TaskFormSection"; import { TaskFormSection } from "./TaskFormSection";
import { savedTaskFormSchema, SavedTaskFormValues } from "./taskFormTypes"; import { savedTaskFormSchema, SavedTaskFormValues } from "./taskFormTypes";
import { OrganizationApiResponse } from "@/api/types"; import { OrganizationApiResponse, ProxyLocation } from "@/api/types";
import { ProxySelector } from "@/components/ProxySelector";
type Props = { type Props = {
initialValues: SavedTaskFormValues; initialValues: SavedTaskFormValues;
@@ -157,10 +158,10 @@ function SavedTaskForm({ initialValues }: Props) {
const form = useForm<SavedTaskFormValues>({ const form = useForm<SavedTaskFormValues>({
resolver: zodResolver(savedTaskFormSchema), resolver: zodResolver(savedTaskFormSchema),
defaultValues: initialValues, defaultValues: {
values: {
...initialValues, ...initialValues,
maxStepsOverride: initialValues.maxStepsOverride ?? null, maxStepsOverride: initialValues.maxStepsOverride ?? null,
proxyLocation: initialValues.proxyLocation ?? ProxyLocation.Residential,
}, },
}); });
@@ -662,6 +663,38 @@ function SavedTaskForm({ initialValues }: Props) {
</FormItem> </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 /> <Separator />
<FormField <FormField
control={form.control} control={form.control}

View File

@@ -42,6 +42,7 @@ function RetryTask() {
errorCodeMapping: task.request.error_code_mapping errorCodeMapping: task.request.error_code_mapping
? JSON.stringify(task.request.error_code_mapping, null, 2) ? JSON.stringify(task.request.error_code_mapping, null, 2)
: "", : "",
proxyLocation: task.request.proxy_location,
}} }}
/> />
</div> </div>

View File

@@ -1,3 +1,4 @@
import { ProxyLocation } from "@/api/types";
import { z } from "zod"; import { z } from "zod";
const createNewTaskFormSchemaBase = z.object({ const createNewTaskFormSchemaBase = z.object({
@@ -13,12 +14,12 @@ const createNewTaskFormSchemaBase = z.object({
totpVerificationUrl: z.string().or(z.null()), totpVerificationUrl: z.string().or(z.null()),
totpIdentifier: z.string().or(z.null()), totpIdentifier: z.string().or(z.null()),
errorCodeMapping: z.string().or(z.null()), errorCodeMapping: z.string().or(z.null()),
proxyLocation: z.nativeEnum(ProxyLocation).or(z.null()),
}); });
const savedTaskFormSchemaBase = createNewTaskFormSchemaBase.extend({ const savedTaskFormSchemaBase = createNewTaskFormSchemaBase.extend({
title: z.string().min(1, "Title is required"), title: z.string().min(1, "Title is required"),
description: z.string(), description: z.string(),
proxyLocation: z.string().or(z.null()),
}); });
function refineTaskFormValues( function refineTaskFormValues(

View File

@@ -24,13 +24,7 @@ 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 { ProxyLocation } from "@/api/types";
import { import { ProxySelector } from "@/components/ProxySelector";
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
type Props = { type Props = {
workflowParameters: Array<WorkflowParameter>; workflowParameters: Array<WorkflowParameter>;
@@ -316,34 +310,10 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
</FormLabel> </FormLabel>
<div className="w-full space-y-2"> <div className="w-full space-y-2">
<FormControl> <FormControl>
<Select <ProxySelector
value={field.value ?? ""} value={field.value}
onValueChange={field.onChange} onChange={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> </FormControl>
<FormMessage /> <FormMessage />
</div> </div>