From 90fbe5057917c4a5fd9821607e1034e53752e0a0 Mon Sep 17 00:00:00 2001 From: Salih Altun Date: Wed, 24 Apr 2024 17:11:12 +0300 Subject: [PATCH] Remove accordion, add cards, change layout of task page (#225) --- skyvern-frontend/package-lock.json | 24 ++ skyvern-frontend/package.json | 1 + .../src/components/ui/separator.tsx | 29 ++ .../src/routes/tasks/detail/StepArtifacts.tsx | 16 +- .../tasks/detail/StepArtifactsLayout.tsx | 5 - .../routes/tasks/detail/StepNavigation.tsx | 14 +- .../src/routes/tasks/detail/TaskDetails.tsx | 277 ++++++++++-------- 7 files changed, 224 insertions(+), 142 deletions(-) create mode 100644 skyvern-frontend/src/components/ui/separator.tsx diff --git a/skyvern-frontend/package-lock.json b/skyvern-frontend/package-lock.json index f2bf390a..ae3af56c 100644 --- a/skyvern-frontend/package-lock.json +++ b/skyvern-frontend/package-lock.json @@ -17,6 +17,7 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", @@ -1451,6 +1452,29 @@ } } }, + "node_modules/@radix-ui/react-separator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz", + "integrity": "sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", diff --git a/skyvern-frontend/package.json b/skyvern-frontend/package.json index 5ccb2f7a..c90b1876 100644 --- a/skyvern-frontend/package.json +++ b/skyvern-frontend/package.json @@ -23,6 +23,7 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", diff --git a/skyvern-frontend/src/components/ui/separator.tsx b/skyvern-frontend/src/components/ui/separator.tsx new file mode 100644 index 00000000..52dc942d --- /dev/null +++ b/skyvern-frontend/src/components/ui/separator.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import * as SeparatorPrimitive from "@radix-ui/react-separator"; + +import { cn } from "@/util/utils"; + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref, + ) => ( + + ), +); +Separator.displayName = SeparatorPrimitive.Root.displayName; + +export { Separator }; diff --git a/skyvern-frontend/src/routes/tasks/detail/StepArtifacts.tsx b/skyvern-frontend/src/routes/tasks/detail/StepArtifacts.tsx index 784da2c8..88574493 100644 --- a/skyvern-frontend/src/routes/tasks/detail/StepArtifacts.tsx +++ b/skyvern-frontend/src/routes/tasks/detail/StepArtifacts.tsx @@ -14,6 +14,8 @@ import { Skeleton } from "@/components/ui/skeleton"; import { JSONArtifact } from "./JSONArtifact"; import { TextArtifact } from "./TextArtifact"; import { getImageURL } from "./artifactUtils"; +import { Input } from "@/components/ui/input"; +import { basicTimeFormat } from "@/util/timeFormat"; type Props = { id: string; @@ -81,7 +83,7 @@ function StepArtifacts({ id, stepProps }: Props) { Info - LLM Screenshots + Page Screenshots Action Screenshots Element Tree @@ -96,17 +98,17 @@ function StepArtifacts({ id, stepProps }: Props) { HTML (Raw) -
+
- + {isFetching ? ( ) : ( - {stepProps?.step_id} + )}
- + {isFetching ? ( ) : stepProps ? ( @@ -114,11 +116,11 @@ function StepArtifacts({ id, stepProps }: Props) { ) : null}
- + {isFetching ? ( ) : stepProps ? ( - {stepProps.created_at} + ) : null}
diff --git a/skyvern-frontend/src/routes/tasks/detail/StepArtifactsLayout.tsx b/skyvern-frontend/src/routes/tasks/detail/StepArtifactsLayout.tsx index 02d0d972..2d31f928 100644 --- a/skyvern-frontend/src/routes/tasks/detail/StepArtifactsLayout.tsx +++ b/skyvern-frontend/src/routes/tasks/detail/StepArtifactsLayout.tsx @@ -12,7 +12,6 @@ function StepArtifactsLayout() { const { data: steps, - isFetching, isError, error, } = useQuery>({ @@ -24,10 +23,6 @@ function StepArtifactsLayout() { }, }); - if (isFetching) { - return
Loading...
; - } - if (isError) { return
Error: {error?.message}
; } diff --git a/skyvern-frontend/src/routes/tasks/detail/StepNavigation.tsx b/skyvern-frontend/src/routes/tasks/detail/StepNavigation.tsx index 4ae7225c..a1307fee 100644 --- a/skyvern-frontend/src/routes/tasks/detail/StepNavigation.tsx +++ b/skyvern-frontend/src/routes/tasks/detail/StepNavigation.tsx @@ -4,6 +4,7 @@ import { cn } from "@/util/utils"; import { useQuery } from "@tanstack/react-query"; import { useParams, useSearchParams } from "react-router-dom"; import { PAGE_SIZE } from "../constants"; +import { CheckboxIcon, CrossCircledIcon } from "@radix-ui/react-icons"; type Props = { activeIndex: number; @@ -17,7 +18,6 @@ function StepNavigation({ activeIndex, onActiveIndexChange }: Props) { const { data: steps, - isFetching, isError, error, } = useQuery>({ @@ -34,10 +34,6 @@ function StepNavigation({ activeIndex, onActiveIndexChange }: Props) { }, }); - if (isFetching) { - return
Loading...
; - } - if (isError) { return
Error: {error?.message}
; } @@ -53,7 +49,7 @@ function StepNavigation({ activeIndex, onActiveIndexChange }: Props) { return (
+ {step.status === "completed" && ( + + )} + {step.status === "failed" && ( + + )} {step.retry_index > 0 ? `Step ${step.order + 1} ( Retry ${step.retry_index} )` diff --git a/skyvern-frontend/src/routes/tasks/detail/TaskDetails.tsx b/skyvern-frontend/src/routes/tasks/detail/TaskDetails.tsx index 6f9d5d4c..5c94bd0e 100644 --- a/skyvern-frontend/src/routes/tasks/detail/TaskDetails.tsx +++ b/skyvern-frontend/src/routes/tasks/detail/TaskDetails.tsx @@ -2,23 +2,24 @@ import { client } from "@/api/AxiosClient"; import { Status, TaskApiResponse } from "@/api/types"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; -import { useQuery } from "@tanstack/react-query"; +import { keepPreviousData, useQuery } from "@tanstack/react-query"; import { useParams } from "react-router-dom"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from "@/components/ui/accordion"; import { StatusBadge } from "@/components/StatusBadge"; -import { Button } from "@/components/ui/button"; -import { ReloadIcon } from "@radix-ui/react-icons"; import { basicTimeFormat } from "@/util/timeFormat"; import { StepArtifactsLayout } from "./StepArtifactsLayout"; -import Zoom from "react-medium-image-zoom"; -import { AspectRatio } from "@/components/ui/aspect-ratio"; import { getRecordingURL, getScreenshotURL } from "./artifactUtils"; import { Skeleton } from "@/components/ui/skeleton"; +import { Input } from "@/components/ui/input"; +import { ZoomableImage } from "@/components/ZoomableImage"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Separator } from "@/components/ui/separator"; function TaskDetails() { const { taskId } = useParams(); @@ -28,12 +29,21 @@ function TaskDetails() { isFetching: isTaskFetching, isError: isTaskError, error: taskError, - refetch, } = useQuery({ queryKey: ["task", taskId, "details"], queryFn: async () => { return client.get(`/tasks/${taskId}`).then((response) => response.data); }, + refetchInterval: (query) => { + if ( + query.state.data?.status === Status.Running || + query.state.data?.status === Status.Queued + ) { + return 3000; + } + return false; + }, + placeholderData: keepPreviousData, }); if (isTaskError) { @@ -41,124 +51,143 @@ function TaskDetails() { } return ( -
-
- - {task?.recording_url ? ( -
- -
- ) : null} -
- - {isTaskFetching ? ( - - ) : task ? ( - - ) : null} -
- {task?.status === Status.Completed ? ( -
- -