Files
Dorod-Sky/skyvern-frontend/src/routes/workflows/WorkflowBlockCollapsibleContent.tsx
Shuchang Zheng 6151527c26 fix issues in forms page, add prompt editing (#1342)
Co-authored-by: Muhammed Salih Altun <muhammedsalihaltun@gmail.com>
2024-12-06 22:06:05 +03:00

213 lines
7.1 KiB
TypeScript

import { Status, TaskApiResponse } from "@/api/types";
import { StatusBadge } from "@/components/StatusBadge";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { TableCell, TableRow } from "@/components/ui/table";
import { basicLocalTimeFormat, basicTimeFormat } from "@/util/timeFormat";
import { ChevronDownIcon, ChevronRightIcon } from "@radix-ui/react-icons";
import { useState } from "react";
import { cn } from "@/util/utils";
import { CodeEditor } from "./components/CodeEditor";
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
import { statusIsFinalized } from "../tasks/types";
type Props = {
task: TaskApiResponse;
onNavigate: (event: React.MouseEvent, id: string) => void;
};
function WorkflowBlockCollapsibleContent({ task, onNavigate }: Props) {
const [open, setOpen] = useState(false);
const [activeTab, setActiveTab] = useState<"output" | "goal" | "parameters">(
statusIsFinalized(task) ? "output" : "goal",
);
const showExtractedInformation = task?.status === Status.Completed;
const extractedInformation = showExtractedInformation ? (
<CodeEditor
language="json"
value={JSON.stringify(task.extracted_information, null, 2)}
readOnly
minHeight={"96px"}
maxHeight={"500px"}
className="w-full"
/>
) : null;
const isCanceled = task?.status === Status.Canceled;
const showFailureReason =
task?.status === Status.Failed ||
task?.status === Status.Terminated ||
task?.status === Status.TimedOut ||
task?.status === Status.Canceled;
const failureReason = showFailureReason ? (
<CodeEditor
language="json"
value={JSON.stringify(
task.failure_reason ?? (isCanceled && "This task was canceled."),
null,
2,
)}
readOnly
minHeight={"96px"}
maxHeight={"500px"}
className="w-full"
/>
) : null;
return (
<Collapsible key={task.task_id} asChild open={open} onOpenChange={setOpen}>
<>
<TableRow
className={cn("hover:bg-slate-elevation2", {
"border-b-0 bg-slate-elevation2": open,
})}
>
<TableCell>
<CollapsibleTrigger asChild>
<div className="w-10 cursor-pointer rounded-full p-2 hover:bg-muted">
{open ? (
<ChevronDownIcon className="size-6" />
) : (
<ChevronRightIcon className="size-6" />
)}
</div>
</CollapsibleTrigger>
</TableCell>
<TableCell
className="w-1/5 max-w-0 cursor-pointer truncate"
title={task.request.title ?? undefined}
onClick={(event) => {
onNavigate(event, task.task_id);
}}
>
{task.request.title}
</TableCell>
<TableCell
className="w-1/6 max-w-0 cursor-pointer truncate"
title={task.task_id}
onClick={(event) => {
onNavigate(event, task.task_id);
}}
>
{task.task_id}
</TableCell>
<TableCell
className="w-1/4 max-w-0 cursor-pointer truncate"
title={task.request.url}
onClick={(event) => onNavigate(event, task.task_id)}
>
{task.request.url}
</TableCell>
<TableCell
className="w-1/8 cursor-pointer"
onClick={(event) => onNavigate(event, task.task_id)}
>
<StatusBadge status={task.status} />
</TableCell>
<TableCell
className="w-1/5 max-w-0 cursor-pointer truncate"
onClick={(event) => onNavigate(event, task.task_id)}
title={basicTimeFormat(task.created_at)}
>
{basicLocalTimeFormat(task.created_at)}
</TableCell>
</TableRow>
<CollapsibleContent asChild>
<TableRow className="bg-slate-elevation2 hover:bg-slate-elevation2">
<TableCell colSpan={6} className="border-b">
<div className="space-y-2 px-6">
<div className="flex gap-1">
{statusIsFinalized(task) && (
<div
className={cn(
"cursor-pointer rounded-sm px-3 py-2 text-slate-400 hover:bg-slate-700",
{
"bg-slate-700 text-foreground":
activeTab === "output",
},
)}
onClick={() => {
setActiveTab("output");
}}
>
{showExtractedInformation
? "Extracted Information"
: showFailureReason
? "Failure Reason"
: ""}
</div>
)}
<div
className={cn(
"cursor-pointer rounded-sm px-3 py-2 text-slate-400 hover:bg-slate-700 hover:text-foreground",
{
"bg-slate-700 text-foreground": activeTab === "goal",
},
)}
onClick={() => {
setActiveTab("goal");
}}
>
Navigation Goal
</div>
<div
className={cn(
"cursor-pointer rounded-sm px-3 py-2 text-slate-400 hover:bg-slate-700 hover:text-foreground",
{
"bg-slate-700 text-foreground":
activeTab === "parameters",
},
)}
onClick={() => {
setActiveTab("parameters");
}}
>
Parameters
</div>
</div>
<div>
{activeTab === "output" &&
(showExtractedInformation
? extractedInformation
: showFailureReason
? failureReason
: null)}
{activeTab === "goal" && (
<AutoResizingTextarea
value={task.request.navigation_goal ?? ""}
readOnly
/>
)}
{activeTab === "parameters" && (
<CodeEditor
language="json"
value={JSON.stringify(
task.request.navigation_payload,
null,
2,
)}
minHeight={"96px"}
maxHeight={"500px"}
className="w-full"
readOnly
/>
)}
</div>
</div>
</TableCell>
</TableRow>
</CollapsibleContent>
</>
</Collapsible>
);
}
export { WorkflowBlockCollapsibleContent };