From d8175ba22e2b945bae04862227823cdec3d9d285 Mon Sep 17 00:00:00 2001 From: Kerem Yilmaz Date: Mon, 20 May 2024 13:50:21 -0700 Subject: [PATCH] Salih/fix both goals empty bug (#348) --- skyvern-frontend/src/api/types.ts | 4 +- .../routes/tasks/create/CreateNewTaskForm.tsx | 58 +++++++--- .../src/routes/tasks/create/SavedTaskForm.tsx | 102 +++++++++++++----- .../src/routes/tasks/data/sampleTaskData.ts | 63 ++++------- .../src/routes/tasks/detail/TaskDetails.tsx | 2 +- skyvern-frontend/src/types.ts | 3 + 6 files changed, 140 insertions(+), 92 deletions(-) create mode 100644 skyvern-frontend/src/types.ts diff --git a/skyvern-frontend/src/api/types.ts b/skyvern-frontend/src/api/types.ts index 373db475..81c1fc4e 100644 --- a/skyvern-frontend/src/api/types.ts +++ b/skyvern-frontend/src/api/types.ts @@ -60,8 +60,8 @@ export type TaskApiResponse = { title: string | null; url: string; webhook_callback_url: string; - navigation_goal: string; - data_extraction_goal: string; + navigation_goal: string | null; + data_extraction_goal: string | null; navigation_payload: string | object; // stringified JSON error_code_mapping: null; proxy_location: string; diff --git a/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx b/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx index ca7804fe..ba5eb64b 100644 --- a/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx +++ b/skyvern-frontend/src/routes/tasks/create/CreateNewTaskForm.tsx @@ -37,16 +37,34 @@ import { apiBaseUrl } from "@/util/env"; import { useCredentialGetter } from "@/hooks/useCredentialGetter"; import { useApiCredential } from "@/hooks/useApiCredential"; -const createNewTaskFormSchema = z.object({ - url: z.string().url({ - message: "Invalid URL", - }), - webhookCallbackUrl: z.string().or(z.null()).optional(), // url maybe, but shouldn't be validated as one - navigationGoal: z.string().or(z.null()).optional(), - dataExtractionGoal: z.string().or(z.null()).optional(), - navigationPayload: z.string().or(z.null()).optional(), - extractedInformationSchema: z.string().or(z.null()).optional(), -}); +const createNewTaskFormSchema = z + .object({ + url: z.string().url({ + message: "Invalid URL", + }), + webhookCallbackUrl: z.string().or(z.null()).optional(), // url maybe, but shouldn't be validated as one + navigationGoal: z.string().or(z.null()).optional(), + dataExtractionGoal: z.string().or(z.null()).optional(), + navigationPayload: z.string().or(z.null()).optional(), + extractedInformationSchema: z.string().or(z.null()).optional(), + }) + .superRefine(({ navigationGoal, dataExtractionGoal }, ctx) => { + if (!navigationGoal && !dataExtractionGoal) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + "At least one of navigation goal or data extraction goal must be provided", + path: ["navigationGoal"], + }); + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + "At least one of navigation goal or data extraction goal must be provided", + path: ["dataExtractionGoal"], + }); + return z.NEVER; + } + }); export type CreateNewTaskFormValues = z.infer; @@ -54,16 +72,22 @@ type Props = { initialValues: CreateNewTaskFormValues; }; +function transform(value: unknown) { + return value === "" ? null : value; +} + function createTaskRequestObject(formValues: CreateNewTaskFormValues) { return { url: formValues.url, - webhook_callback_url: formValues.webhookCallbackUrl ?? "", - navigation_goal: formValues.navigationGoal ?? "", - data_extraction_goal: formValues.dataExtractionGoal ?? "", + webhook_callback_url: transform(formValues.webhookCallbackUrl), + navigation_goal: transform(formValues.navigationGoal), + data_extraction_goal: transform(formValues.dataExtractionGoal), proxy_location: "NONE", error_code_mapping: null, - navigation_payload: formValues.navigationPayload, - extracted_information_schema: formValues.extractedInformationSchema, + navigation_payload: transform(formValues.navigationPayload), + extracted_information_schema: transform( + formValues.extractedInformationSchema, + ), }; } @@ -266,7 +290,7 @@ function CreateNewTaskForm({ initialValues }: Props) { rows={5} placeholder="Navigation Payload" {...field} - value={field.value ?? ""} + value={field.value === null ? "" : field.value} /> @@ -298,7 +322,7 @@ function CreateNewTaskForm({ initialValues }: Props) { placeholder="Extracted Information Schema" rows={5} {...field} - value={field.value ?? ""} + value={field.value === null ? "" : field.value} /> diff --git a/skyvern-frontend/src/routes/tasks/create/SavedTaskForm.tsx b/skyvern-frontend/src/routes/tasks/create/SavedTaskForm.tsx index 16da9d88..a0074b2e 100644 --- a/skyvern-frontend/src/routes/tasks/create/SavedTaskForm.tsx +++ b/skyvern-frontend/src/routes/tasks/create/SavedTaskForm.tsx @@ -37,20 +37,39 @@ import { urlDescription, webhookCallbackUrlDescription, } from "../data/descriptionHelperContent"; +import { SubmitEvent } from "@/types"; -const savedTaskFormSchema = z.object({ - title: z.string().min(1, "Title is required"), - description: z.string(), - url: z.string().url({ - message: "Invalid URL", - }), - proxyLocation: z.string().or(z.null()).optional(), - webhookCallbackUrl: z.string().or(z.null()).optional(), // url maybe, but shouldn't be validated as one - navigationGoal: z.string().or(z.null()).optional(), - dataExtractionGoal: z.string().or(z.null()).optional(), - navigationPayload: z.string().or(z.null()).optional(), - extractedInformationSchema: z.string().or(z.null()).optional(), -}); +const savedTaskFormSchema = z + .object({ + title: z.string().min(1, "Title is required"), + description: z.string(), + url: z.string().url({ + message: "Invalid URL", + }), + proxyLocation: z.string().or(z.null()).optional(), + webhookCallbackUrl: z.string().or(z.null()).optional(), // url maybe, but shouldn't be validated as one + navigationGoal: z.string().or(z.null()).optional(), + dataExtractionGoal: z.string().or(z.null()).optional(), + navigationPayload: z.string().or(z.null()).optional(), + extractedInformationSchema: z.string().or(z.null()).optional(), + }) + .superRefine(({ navigationGoal, dataExtractionGoal }, ctx) => { + if (!navigationGoal && !dataExtractionGoal) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + "At least one of navigation goal or data extraction goal must be provided", + path: ["navigationGoal"], + }); + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + "At least one of navigation goal or data extraction goal must be provided", + path: ["dataExtractionGoal"], + }); + return z.NEVER; + } + }); export type SavedTaskFormValues = z.infer; @@ -58,16 +77,22 @@ type Props = { initialValues: SavedTaskFormValues; }; +function transform(value: unknown) { + return value === "" ? null : value; +} + function createTaskRequestObject(formValues: SavedTaskFormValues) { return { url: formValues.url, - webhook_callback_url: formValues.webhookCallbackUrl ?? "", - navigation_goal: formValues.navigationGoal ?? "", - data_extraction_goal: formValues.dataExtractionGoal ?? "", - proxy_location: formValues.proxyLocation, + webhook_callback_url: transform(formValues.webhookCallbackUrl), + navigation_goal: transform(formValues.navigationGoal), + data_extraction_goal: transform(formValues.dataExtractionGoal), + proxy_location: transform(formValues.proxyLocation), error_code_mapping: null, - navigation_payload: formValues.navigationPayload, - extracted_information_schema: formValues.extractedInformationSchema, + navigation_payload: transform(formValues.navigationPayload), + extracted_information_schema: transform( + formValues.extractedInformationSchema, + ), }; } @@ -179,13 +204,30 @@ function SavedTaskForm({ initialValues }: Props) { }, }); - function onSubmit(values: SavedTaskFormValues) { + function handleCreate(values: SavedTaskFormValues) { createTaskMutation.mutate(values); } + function handleSave(values: SavedTaskFormValues) { + saveTaskMutation.mutate(values); + } + return (
- + { + const submitter = ( + (event.nativeEvent as SubmitEvent).submitter as HTMLButtonElement + ).value; + if (submitter === "save") { + form.handleSubmit(handleSave)(event); + } + if (submitter === "create") { + form.handleSubmit(handleCreate)(event); + } + }} + className="space-y-8" + > @@ -391,7 +433,7 @@ function SavedTaskForm({ initialValues }: Props) { placeholder="Extracted Information Schema" rows={5} {...field} - value={field.value ?? ""} + value={field.value === null ? "" : field.value} /> @@ -423,11 +465,10 @@ function SavedTaskForm({ initialValues }: Props) { {isDirty && ( )} -