Add tailwind plugin for prettier (#592)
This commit is contained in:
3
skyvern-frontend/.prettierrc
Normal file
3
skyvern-frontend/.prettierrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-tailwindcss"]
|
||||||
|
}
|
||||||
75
skyvern-frontend/package-lock.json
generated
75
skyvern-frontend/package-lock.json
generated
@@ -62,6 +62,7 @@
|
|||||||
"lint-staged": "^15.2.2",
|
"lint-staged": "^15.2.2",
|
||||||
"postcss": "^8.4.37",
|
"postcss": "^8.4.37",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"vite": "^5.1.6"
|
"vite": "^5.1.6"
|
||||||
@@ -5319,6 +5320,80 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prettier-plugin-tailwindcss": {
|
||||||
|
"version": "0.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.5.tgz",
|
||||||
|
"integrity": "sha512-axfeOArc/RiGHjOIy9HytehlC0ZLeMaqY09mm8YCkMzznKiDkwFzOpBvtuhuv3xG5qB73+Mj7OCe2j/L1ryfuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.21.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@ianvs/prettier-plugin-sort-imports": "*",
|
||||||
|
"@prettier/plugin-pug": "*",
|
||||||
|
"@shopify/prettier-plugin-liquid": "*",
|
||||||
|
"@trivago/prettier-plugin-sort-imports": "*",
|
||||||
|
"@zackad/prettier-plugin-twig-melody": "*",
|
||||||
|
"prettier": "^3.0",
|
||||||
|
"prettier-plugin-astro": "*",
|
||||||
|
"prettier-plugin-css-order": "*",
|
||||||
|
"prettier-plugin-import-sort": "*",
|
||||||
|
"prettier-plugin-jsdoc": "*",
|
||||||
|
"prettier-plugin-marko": "*",
|
||||||
|
"prettier-plugin-organize-attributes": "*",
|
||||||
|
"prettier-plugin-organize-imports": "*",
|
||||||
|
"prettier-plugin-sort-imports": "*",
|
||||||
|
"prettier-plugin-style-order": "*",
|
||||||
|
"prettier-plugin-svelte": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@ianvs/prettier-plugin-sort-imports": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@prettier/plugin-pug": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@shopify/prettier-plugin-liquid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@trivago/prettier-plugin-sort-imports": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@zackad/prettier-plugin-twig-melody": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-astro": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-css-order": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-import-sort": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-jsdoc": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-marko": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-organize-attributes": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-organize-imports": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-sort-imports": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-style-order": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"prettier-plugin-svelte": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/proxy-addr": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
"lint-staged": "^15.2.2",
|
"lint-staged": "^15.2.2",
|
||||||
"postcss": "^8.4.37",
|
"postcss": "^8.4.37",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"vite": "^5.1.6"
|
"vite": "^5.1.6"
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ function FileUpload({ value, onChange }: Props) {
|
|||||||
<Label
|
<Label
|
||||||
htmlFor={inputId}
|
htmlFor={inputId}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full cursor-pointer border border-dashed items-center justify-center py-8",
|
"flex w-full cursor-pointer items-center justify-center border border-dashed py-8",
|
||||||
{
|
{
|
||||||
"border-slate-500": highlight,
|
"border-slate-500": highlight,
|
||||||
},
|
},
|
||||||
@@ -144,7 +144,7 @@ function FileUpload({ value, onChange }: Props) {
|
|||||||
accept=".csv"
|
accept=".csv"
|
||||||
className="hidden"
|
className="hidden"
|
||||||
/>
|
/>
|
||||||
<div className="max-w-full truncate flex gap-2">
|
<div className="flex max-w-full gap-2 truncate">
|
||||||
{uploadFileMutation.isPending && (
|
{uploadFileMutation.isPending && (
|
||||||
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
||||||
)}
|
)}
|
||||||
@@ -156,7 +156,7 @@ function FileUpload({ value, onChange }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center justify-center before:flex before:content-[''] before:bg-slate-600">
|
<div className="flex flex-col items-center justify-center before:flex before:bg-slate-600 before:content-['']">
|
||||||
OR
|
OR
|
||||||
</div>
|
</div>
|
||||||
<div className="w-1/2">
|
<div className="w-1/2">
|
||||||
@@ -181,7 +181,7 @@ function FileUpload({ value, onChange }: Props) {
|
|||||||
|
|
||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex items-center gap-4">
|
||||||
<span>{value}</span>
|
<span>{value}</span>
|
||||||
<Button onClick={() => reset()}>Change</Button>
|
<Button onClick={() => reset()}>Change</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -190,7 +190,7 @@ function FileUpload({ value, onChange }: Props) {
|
|||||||
|
|
||||||
if (typeof value === "object" && file && "s3uri" in value) {
|
if (typeof value === "object" && file && "s3uri" in value) {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex items-center gap-4">
|
||||||
<a href={value.presignedUrl} className="underline">
|
<a href={value.presignedUrl} className="underline">
|
||||||
<span>{file.name}</span>
|
<span>{file.name}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function ZoomableImage(props: HTMLImageElementProps) {
|
|||||||
{modalOpen && (
|
{modalOpen && (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"fixed inset-0 z-50 flex justify-center bg-black bg-opacity-75 overflow-auto p-16",
|
"fixed inset-0 z-50 flex justify-center overflow-auto bg-black bg-opacity-75 p-16",
|
||||||
{
|
{
|
||||||
"items-center": !zoom,
|
"items-center": !zoom,
|
||||||
"items-baseline": zoom,
|
"items-baseline": zoom,
|
||||||
@@ -46,7 +46,7 @@ function ZoomableImage(props: HTMLImageElementProps) {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="absolute top-4 right-4 text-white text-4xl cursor-pointer"
|
className="absolute right-4 top-4 cursor-pointer text-4xl text-white"
|
||||||
onClick={closeModal}
|
onClick={closeModal}
|
||||||
>
|
>
|
||||||
×
|
×
|
||||||
@@ -55,9 +55,9 @@ function ZoomableImage(props: HTMLImageElementProps) {
|
|||||||
{...props}
|
{...props}
|
||||||
onClick={() => setZoom(!zoom)}
|
onClick={() => setZoom(!zoom)}
|
||||||
className={clsx({
|
className={clsx({
|
||||||
"min-h-full object-contain h-full w-full m-0 cursor-zoom-in max-h-full max-w-full":
|
"m-0 h-full max-h-full min-h-full w-full max-w-full cursor-zoom-in object-contain":
|
||||||
!zoom,
|
!zoom,
|
||||||
"min-h-full object-contain m-0 cursor-zoom-out max-w-none max-h-none mr-auto ml-auto":
|
"m-0 ml-auto mr-auto max-h-none min-h-full max-w-none cursor-zoom-out object-contain":
|
||||||
zoom,
|
zoom,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const CardHeader = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("flex flex-col space-y-1.5 p-4 bg-muted/40", className)}
|
className={cn("flex flex-col space-y-1.5 bg-muted/40 p-4", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function HiddenCopyableInput({ value }: Props) {
|
|||||||
return (
|
return (
|
||||||
<div className="relative w-full">
|
<div className="relative w-full">
|
||||||
<Input value={inputValue} className="h-10" readOnly />
|
<Input value={inputValue} className="h-10" readOnly />
|
||||||
<div className="absolute flex inset-y-0 items-center right-1">
|
<div className="absolute inset-y-0 right-1 flex items-center">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ type Props = {
|
|||||||
|
|
||||||
function Profile({ name }: Props) {
|
function Profile({ name }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center border-2 p-2 rounded-lg">
|
<div className="flex items-center rounded-lg border-2 p-2">
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex items-center gap-2">
|
||||||
<PersonIcon className="h-4 w-4" />
|
<PersonIcon className="h-4 w-4" />
|
||||||
<p className="w-40 overflow-hidden text-ellipsis">{name}</p>
|
<p className="w-40 overflow-hidden text-ellipsis">{name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ function RootLayout() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="w-full h-full px-4">
|
<div className="h-full w-full px-4">
|
||||||
<aside className="fixed w-72 px-6 shrink-0 min-h-screen border-r-2">
|
<aside className="fixed min-h-screen w-72 shrink-0 border-r-2 px-6">
|
||||||
<Link to={window.location.origin}>
|
<Link to={window.location.origin}>
|
||||||
<div className="h-24">
|
<div className="h-24">
|
||||||
<Logo />
|
<Logo />
|
||||||
@@ -22,18 +22,18 @@ function RootLayout() {
|
|||||||
</Link>
|
</Link>
|
||||||
<SideNav />
|
<SideNav />
|
||||||
{user ? (
|
{user ? (
|
||||||
<div className="absolute bottom-2 left-0 w-72 px-6 shrink-0">
|
<div className="absolute bottom-2 left-0 w-72 shrink-0 px-6">
|
||||||
<Profile name={user.name} />
|
<Profile name={user.name} />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</aside>
|
</aside>
|
||||||
<div className="pl-72 h-24 flex justify-end items-center px-6 gap-4">
|
<div className="flex h-24 items-center justify-end gap-4 px-6 pl-72">
|
||||||
<Link
|
<Link
|
||||||
to="https://discord.com/invite/fG2XXEuQX3"
|
to="https://discord.com/invite/fG2XXEuQX3"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<DiscordLogoIcon className="w-7 h-7" />
|
<DiscordLogoIcon className="h-7 w-7" />
|
||||||
</Link>
|
</Link>
|
||||||
<div className="h-7">
|
<div className="h-7">
|
||||||
<GitHubButton
|
<GitHubButton
|
||||||
@@ -47,7 +47,7 @@ function RootLayout() {
|
|||||||
</GitHubButton>
|
</GitHubButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<main className="pl-72 pb-4">
|
<main className="pb-4 pl-72">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,45 +13,45 @@ function SideNav() {
|
|||||||
<NavLink
|
<NavLink
|
||||||
to="create"
|
to="create"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn("flex items-center px-5 py-3 hover:bg-muted rounded-2xl", {
|
return cn("flex items-center rounded-2xl px-5 py-3 hover:bg-muted", {
|
||||||
"bg-muted": isActive,
|
"bg-muted": isActive,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PlusCircledIcon className="mr-4 w-6 h-6" />
|
<PlusCircledIcon className="mr-4 h-6 w-6" />
|
||||||
<span className="text-lg">Create</span>
|
<span className="text-lg">Create</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="tasks"
|
to="tasks"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn("flex items-center px-5 py-3 hover:bg-muted rounded-2xl", {
|
return cn("flex items-center rounded-2xl px-5 py-3 hover:bg-muted", {
|
||||||
"bg-muted": isActive,
|
"bg-muted": isActive,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ListBulletIcon className="mr-4 w-6 h-6" />
|
<ListBulletIcon className="mr-4 h-6 w-6" />
|
||||||
<span className="text-lg">Tasks</span>
|
<span className="text-lg">Tasks</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="workflows"
|
to="workflows"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn("flex items-center px-5 py-3 hover:bg-muted rounded-2xl", {
|
return cn("flex items-center rounded-2xl px-5 py-3 hover:bg-muted", {
|
||||||
"bg-muted": isActive,
|
"bg-muted": isActive,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<LightningBoltIcon className="mr-4 w-6 h-6" />
|
<LightningBoltIcon className="mr-4 h-6 w-6" />
|
||||||
<span className="text-lg">Workflows (Beta)</span>
|
<span className="text-lg">Workflows (Beta)</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="settings"
|
to="settings"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn("flex items-center px-5 py-3 hover:bg-muted rounded-2xl", {
|
return cn("flex items-center rounded-2xl px-5 py-3 hover:bg-muted", {
|
||||||
"bg-muted": isActive,
|
"bg-muted": isActive,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<GearIcon className="mr-4 w-6 h-6" />
|
<GearIcon className="mr-4 h-6 w-6" />
|
||||||
<span className="text-lg">Settings</span>
|
<span className="text-lg">Settings</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ function Settings() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="p-8">
|
<CardContent className="p-8">
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex items-center gap-4">
|
||||||
<Label className="whitespace-nowrap w-36">Environment</Label>
|
<Label className="w-36 whitespace-nowrap">Environment</Label>
|
||||||
<Select value={environment} onValueChange={setEnvironment}>
|
<Select value={environment} onValueChange={setEnvironment}>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Environment" />
|
<SelectValue placeholder="Environment" />
|
||||||
@@ -44,8 +44,8 @@ function Settings() {
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex items-center gap-4">
|
||||||
<Label className="whitespace-nowrap w-36">Organization</Label>
|
<Label className="w-36 whitespace-nowrap">Organization</Label>
|
||||||
<Select value={organization} onValueChange={setOrganization}>
|
<Select value={organization} onValueChange={setOrganization}>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Organization" />
|
<SelectValue placeholder="Organization" />
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ function CreateNewTaskFromPrompt() {
|
|||||||
return (
|
return (
|
||||||
<section className="space-y-8">
|
<section className="space-y-8">
|
||||||
<header className="flex flex-col gap-4">
|
<header className="flex flex-col gap-4">
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex items-center gap-4">
|
||||||
<MagicWandIcon className="w-6 h-6" />
|
<MagicWandIcon className="h-6 w-6" />
|
||||||
<h1 className="text-3xl font-bold">Create New Task</h1>
|
<h1 className="text-3xl font-bold">Create New Task</h1>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ function SavedTaskCard({ workflowId, title, url, description }: Props) {
|
|||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="flex justify-between items-center">
|
<CardTitle className="flex items-center justify-between">
|
||||||
<span className="overflow-hidden text-ellipsis whitespace-nowrap ">
|
<span className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
@@ -130,7 +130,7 @@ function SavedTaskCard({ workflowId, title, url, description }: Props) {
|
|||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent
|
<CardContent
|
||||||
className="h-48 overflow-scroll hover:bg-muted/40 cursor-pointer"
|
className="h-48 cursor-pointer overflow-scroll hover:bg-muted/40"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(workflowId);
|
navigate(workflowId);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -108,14 +108,14 @@ function SavedTasks() {
|
|||||||
>
|
>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>New Template</CardTitle>
|
<CardTitle>New Template</CardTitle>
|
||||||
<CardDescription className="whitespace-nowrap overflow-hidden text-ellipsis">
|
<CardDescription className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
Create your own template
|
Create your own template
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex h-48 justify-center items-center hover:bg-muted/40 cursor-pointer">
|
<CardContent className="flex h-48 cursor-pointer items-center justify-center hover:bg-muted/40">
|
||||||
{!mutation.isPending && <PlusIcon className="w-12 h-12" />}
|
{!mutation.isPending && <PlusIcon className="h-12 w-12" />}
|
||||||
{mutation.isPending && (
|
{mutation.isPending && (
|
||||||
<ReloadIcon className="animate-spin w-12 h-12" />
|
<ReloadIcon className="h-12 w-12 animate-spin" />
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ function TaskTemplates() {
|
|||||||
href="https://meetings.hubspot.com/suchintan"
|
href="https://meetings.hubspot.com/suchintan"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="underline underline-offset-2 ml-auto"
|
className="ml-auto underline underline-offset-2"
|
||||||
>
|
>
|
||||||
Book a demo {"->"}
|
Book a demo {"->"}
|
||||||
</a>
|
</a>
|
||||||
@@ -105,25 +105,25 @@ function TaskTemplates() {
|
|||||||
</Alert>
|
</Alert>
|
||||||
<section className="py-4">
|
<section className="py-4">
|
||||||
<header>
|
<header>
|
||||||
<h1 className="text-3xl mb-2">Try a prompt</h1>
|
<h1 className="mb-2 text-3xl">Try a prompt</h1>
|
||||||
</header>
|
</header>
|
||||||
<p className="text-sm">
|
<p className="text-sm">
|
||||||
We will generate a task for you automatically.
|
We will generate a task for you automatically.
|
||||||
</p>
|
</p>
|
||||||
<Separator className="mt-2 mb-8" />
|
<Separator className="mb-8 mt-2" />
|
||||||
<div className="flex border rounded-xl items-center pr-4 max-w-xl mx-auto">
|
<div className="mx-auto flex max-w-xl items-center rounded-xl border pr-4">
|
||||||
<Textarea
|
<Textarea
|
||||||
className="rounded-xl resize-none border-transparent hover:border-transparent focus-visible:ring-0 p-2 font-mono text-sm"
|
className="resize-none rounded-xl border-transparent p-2 font-mono text-sm hover:border-transparent focus-visible:ring-0"
|
||||||
value={prompt}
|
value={prompt}
|
||||||
onChange={(e) => setPrompt(e.target.value)}
|
onChange={(e) => setPrompt(e.target.value)}
|
||||||
placeholder="Enter your prompt..."
|
placeholder="Enter your prompt..."
|
||||||
/>
|
/>
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
{getTaskFromPromptMutation.isPending ? (
|
{getTaskFromPromptMutation.isPending ? (
|
||||||
<ReloadIcon className="w-6 h-6 animate-spin" />
|
<ReloadIcon className="h-6 w-6 animate-spin" />
|
||||||
) : (
|
) : (
|
||||||
<PaperPlaneIcon
|
<PaperPlaneIcon
|
||||||
className="w-6 h-6 cursor-pointer"
|
className="h-6 w-6 cursor-pointer"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
getTaskFromPromptMutation.mutate(prompt);
|
getTaskFromPromptMutation.mutate(prompt);
|
||||||
}}
|
}}
|
||||||
@@ -131,12 +131,12 @@ function TaskTemplates() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-4 mt-4 justify-center">
|
<div className="mt-4 flex flex-wrap justify-center gap-4">
|
||||||
{examplePrompts.map((examplePrompt) => {
|
{examplePrompts.map((examplePrompt) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={examplePrompt}
|
key={examplePrompt}
|
||||||
className="p-2 border rounded-xl cursor-pointer text-muted-foreground text-sm"
|
className="cursor-pointer rounded-xl border p-2 text-sm text-muted-foreground"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPrompt(examplePrompt);
|
setPrompt(examplePrompt);
|
||||||
}}
|
}}
|
||||||
@@ -151,18 +151,18 @@ function TaskTemplates() {
|
|||||||
<header>
|
<header>
|
||||||
<h1 className="text-3xl">Your Templates</h1>
|
<h1 className="text-3xl">Your Templates</h1>
|
||||||
</header>
|
</header>
|
||||||
<p className="text-sm mt-1">Your saved task templates</p>
|
<p className="mt-1 text-sm">Your saved task templates</p>
|
||||||
<Separator className="mt-2 mb-8" />
|
<Separator className="mb-8 mt-2" />
|
||||||
<SavedTasks />
|
<SavedTasks />
|
||||||
</section>
|
</section>
|
||||||
<section className="py-4">
|
<section className="py-4">
|
||||||
<header>
|
<header>
|
||||||
<h1 className="text-3xl">Skyvern Templates</h1>
|
<h1 className="text-3xl">Skyvern Templates</h1>
|
||||||
</header>
|
</header>
|
||||||
<p className="text-sm mt-1">
|
<p className="mt-1 text-sm">
|
||||||
Sample tasks that showcase Skyvern's capabilities
|
Sample tasks that showcase Skyvern's capabilities
|
||||||
</p>
|
</p>
|
||||||
<Separator className="mt-2 mb-8" />
|
<Separator className="mb-8 mt-2" />
|
||||||
<div className="grid grid-cols-4 gap-4">
|
<div className="grid grid-cols-4 gap-4">
|
||||||
{Object.entries(templateSamples).map(([sampleKey, sample]) => {
|
{Object.entries(templateSamples).map(([sampleKey, sample]) => {
|
||||||
return (
|
return (
|
||||||
@@ -174,7 +174,7 @@ function TaskTemplates() {
|
|||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent
|
<CardContent
|
||||||
className="h-48 hover:bg-muted/40 cursor-pointer"
|
className="h-48 cursor-pointer hover:bg-muted/40"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(sampleKey);
|
navigate(sampleKey);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function ActionCard({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex p-4 rounded-lg shadow-md border hover:bg-muted cursor-pointer",
|
"flex cursor-pointer rounded-lg border p-4 shadow-md hover:bg-muted",
|
||||||
{
|
{
|
||||||
"bg-muted": selected,
|
"bg-muted": selected,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -34,15 +34,15 @@ function ActionScreenshot({ stepId, index }: Props) {
|
|||||||
|
|
||||||
if (isFetching) {
|
if (isFetching) {
|
||||||
return (
|
return (
|
||||||
<div className="max-h-[400px] flex flex-col mx-auto items-center gap-2 overflow-hidden">
|
<div className="mx-auto flex max-h-[400px] flex-col items-center gap-2 overflow-hidden">
|
||||||
<ReloadIcon className="animate-spin h-6 w-6" />
|
<ReloadIcon className="h-6 w-6 animate-spin" />
|
||||||
<div>Loading screenshot...</div>
|
<div>Loading screenshot...</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return screenshot ? (
|
return screenshot ? (
|
||||||
<figure className="max-w-full flex flex-col mx-auto items-center gap-2 overflow-hidden">
|
<figure className="mx-auto flex max-w-full flex-col items-center gap-2 overflow-hidden">
|
||||||
<ZoomableImage src={getImageURL(screenshot)} alt="llm-screenshot" />
|
<ZoomableImage src={getImageURL(screenshot)} alt="llm-screenshot" />
|
||||||
</figure>
|
</figure>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ type Props = {
|
|||||||
|
|
||||||
function InputReasoningCard({ input, reasoning, confidence }: Props) {
|
function InputReasoningCard({ input, reasoning, confidence }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className="flex p-4 gap-2 rounded-md shadow-md border items-start">
|
<div className="flex items-start gap-2 rounded-md border p-4 shadow-md">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<span className="font-bold">Agent Input:</span> {input}
|
<span className="font-bold">Agent Input:</span> {input}
|
||||||
@@ -15,7 +15,7 @@ function InputReasoningCard({ input, reasoning, confidence }: Props) {
|
|||||||
<span className="font-bold">Agent Reasoning:</span> {reasoning}
|
<span className="font-bold">Agent Reasoning:</span> {reasoning}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-center border p-2 rounded-lg bg-muted">
|
<div className="flex items-center justify-center rounded-lg border bg-muted p-2">
|
||||||
<span>Confidence: {confidence}</span>
|
<span>Confidence: {confidence}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function JSONArtifact({ artifact }: Props) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isFetching) {
|
if (isFetching) {
|
||||||
return <Skeleton className="w-full h-48" />;
|
return <Skeleton className="h-48 w-full" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ function ScrollableActionList({
|
|||||||
refs.current[actionIndex] = element;
|
refs.current[actionIndex] = element;
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex p-4 rounded-lg shadow-md border hover:border-slate-300 cursor-pointer",
|
"flex cursor-pointer rounded-lg border p-4 shadow-md hover:border-slate-300",
|
||||||
{
|
{
|
||||||
"border-slate-300": selected,
|
"border-slate-300": selected,
|
||||||
},
|
},
|
||||||
@@ -95,9 +95,9 @@ function ScrollableActionList({
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex-1 p-2 pt-0 space-y-2">
|
<div className="flex-1 space-y-2 p-2 pt-0">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex items-center gap-2">
|
||||||
<span>#{i + 1}</span>
|
<span>#{i + 1}</span>
|
||||||
<Badge>{ReadableActionTypes[action.type]}</Badge>
|
<Badge>{ReadableActionTypes[action.type]}</Badge>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,9 +113,9 @@ function ScrollableActionList({
|
|||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
)}
|
)}
|
||||||
{action.success ? (
|
{action.success ? (
|
||||||
<CheckCircledIcon className="w-6 h-6 text-success" />
|
<CheckCircledIcon className="h-6 w-6 text-success" />
|
||||||
) : (
|
) : (
|
||||||
<CrossCircledIcon className="w-6 h-6 text-destructive" />
|
<CrossCircledIcon className="h-6 w-6 text-destructive" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,7 +123,7 @@ function ScrollableActionList({
|
|||||||
<div className="text-sm">{action.reasoning}</div>
|
<div className="text-sm">{action.reasoning}</div>
|
||||||
{action.type === ActionTypes.InputText && (
|
{action.type === ActionTypes.InputText && (
|
||||||
<>
|
<>
|
||||||
<Separator className="bg-slate-50 block" />
|
<Separator className="block bg-slate-50" />
|
||||||
<div className="text-sm">Input: {action.input}</div>
|
<div className="text-sm">Input: {action.input}</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -138,8 +138,8 @@ function ScrollableActionList({
|
|||||||
typeof activeIndex === "number" ? data.length - activeIndex - 1 : "stream";
|
typeof activeIndex === "number" ? data.length - activeIndex - 1 : "stream";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-1/3 flex flex-col items-center border rounded h-[40rem]">
|
<div className="flex h-[40rem] w-1/3 flex-col items-center rounded border">
|
||||||
<div className="flex items-center text-sm p-4 gap-2">
|
<div className="flex items-center gap-2 p-4 text-sm">
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -155,7 +155,7 @@ function ScrollableActionList({
|
|||||||
<ArrowDownIcon />
|
<ArrowDownIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-y-scroll w-full px-4 pb-4 space-y-4">
|
<div className="w-full space-y-4 overflow-y-scroll px-4 pb-4">
|
||||||
{showStreamOption && (
|
{showStreamOption && (
|
||||||
<div
|
<div
|
||||||
key="stream"
|
key="stream"
|
||||||
@@ -163,15 +163,15 @@ function ScrollableActionList({
|
|||||||
refs.current[data.length] = element;
|
refs.current[data.length] = element;
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex p-4 rounded-lg shadow-md border hover:border-slate-300 cursor-pointer",
|
"flex cursor-pointer rounded-lg border p-4 shadow-md hover:border-slate-300",
|
||||||
{
|
{
|
||||||
"border-slate-300": activeIndex === "stream",
|
"border-slate-300": activeIndex === "stream",
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
onClick={() => onActiveIndexChange("stream")}
|
onClick={() => onActiveIndexChange("stream")}
|
||||||
>
|
>
|
||||||
<div className="text-lg flex gap-2 items-center">
|
<div className="flex items-center gap-2 text-lg">
|
||||||
<DotFilledIcon className="w-6 h-6 text-red-500" />
|
<DotFilledIcon className="h-6 w-6 text-red-500" />
|
||||||
Live
|
Live
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ function StepArtifacts({ id, stepProps }: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs defaultValue="info" className="w-full">
|
<Tabs defaultValue="info" className="w-full">
|
||||||
<TabsList className="grid w-full h-16 grid-cols-5">
|
<TabsList className="grid h-16 w-full grid-cols-5">
|
||||||
<TabsTrigger value="info">Info</TabsTrigger>
|
<TabsTrigger value="info">Info</TabsTrigger>
|
||||||
<TabsTrigger value="screenshot_llm">Annotated Screenshots</TabsTrigger>
|
<TabsTrigger value="screenshot_llm">Annotated Screenshots</TabsTrigger>
|
||||||
<TabsTrigger value="screenshot_action">Action Screenshots</TabsTrigger>
|
<TabsTrigger value="screenshot_action">Action Screenshots</TabsTrigger>
|
||||||
@@ -126,16 +126,16 @@ function StepArtifacts({ id, stepProps }: Props) {
|
|||||||
<ZoomableImage
|
<ZoomableImage
|
||||||
key={index}
|
key={index}
|
||||||
src={getImageURL(artifact)}
|
src={getImageURL(artifact)}
|
||||||
className="object-cover w-full h-full"
|
className="h-full w-full object-cover"
|
||||||
alt="action-screenshot"
|
alt="action-screenshot"
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : isFetching ? (
|
) : isFetching ? (
|
||||||
<div className="grid grid-cols-2 gap-4 p-4">
|
<div className="grid grid-cols-2 gap-4 p-4">
|
||||||
<Skeleton className="w-full h-full" />
|
<Skeleton className="h-full w-full" />
|
||||||
<Skeleton className="w-full h-full" />
|
<Skeleton className="h-full w-full" />
|
||||||
<Skeleton className="w-full h-full" />
|
<Skeleton className="h-full w-full" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>No screenshots found</div>
|
<div>No screenshots found</div>
|
||||||
@@ -148,16 +148,16 @@ function StepArtifacts({ id, stepProps }: Props) {
|
|||||||
<ZoomableImage
|
<ZoomableImage
|
||||||
key={index}
|
key={index}
|
||||||
src={getImageURL(artifact)}
|
src={getImageURL(artifact)}
|
||||||
className="object-cover w-full h-full"
|
className="h-full w-full object-cover"
|
||||||
alt="action-screenshot"
|
alt="action-screenshot"
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : isFetching ? (
|
) : isFetching ? (
|
||||||
<div className="grid grid-cols-3 gap-4 p-4">
|
<div className="grid grid-cols-3 gap-4 p-4">
|
||||||
<Skeleton className="w-full h-full" />
|
<Skeleton className="h-full w-full" />
|
||||||
<Skeleton className="w-full h-full" />
|
<Skeleton className="h-full w-full" />
|
||||||
<Skeleton className="w-full h-full" />
|
<Skeleton className="h-full w-full" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>No screenshots found</div>
|
<div>No screenshots found</div>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function StepArtifactsLayout() {
|
|||||||
onActiveIndexChange={setActiveIndex}
|
onActiveIndexChange={setActiveIndex}
|
||||||
/>
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
<main className="px-4 w-full">
|
<main className="w-full px-4">
|
||||||
{activeStep ? (
|
{activeStep ? (
|
||||||
<StepArtifacts id={activeStep.step_id} stepProps={activeStep} />
|
<StepArtifacts id={activeStep.step_id} stepProps={activeStep} />
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ function StepNavigation({ activeIndex, onActiveIndexChange }: Props) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center px-6 py-2 hover:bg-primary-foreground rounded-2xl cursor-pointer",
|
"flex cursor-pointer items-center rounded-2xl px-6 py-2 hover:bg-primary-foreground",
|
||||||
{
|
{
|
||||||
"bg-primary-foreground": isActive,
|
"bg-primary-foreground": isActive,
|
||||||
},
|
},
|
||||||
@@ -59,10 +59,10 @@ function StepNavigation({ activeIndex, onActiveIndexChange }: Props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{step.status === "completed" && (
|
{step.status === "completed" && (
|
||||||
<CheckboxIcon className="w-6 h-6 mr-2 text-green-500" />
|
<CheckboxIcon className="mr-2 h-6 w-6 text-green-500" />
|
||||||
)}
|
)}
|
||||||
{step.status === "failed" && (
|
{step.status === "failed" && (
|
||||||
<CrossCircledIcon className="w-6 h-6 mr-2 text-red-500" />
|
<CrossCircledIcon className="mr-2 h-6 w-6 text-red-500" />
|
||||||
)}
|
)}
|
||||||
<span>
|
<span>
|
||||||
{step.retry_index > 0
|
{step.retry_index > 0
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ function TaskActions() {
|
|||||||
function getStream() {
|
function getStream() {
|
||||||
if (task?.status === Status.Queued) {
|
if (task?.status === Status.Queued) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full flex flex-col gap-4 items-center justify-center text-lg bg-slate-900">
|
<div className="flex h-full w-full flex-col items-center justify-center gap-4 bg-slate-900 text-lg">
|
||||||
<span>Your task is queued. Typical queue time is 1-2 minutes.</span>
|
<span>Your task is queued. Typical queue time is 1-2 minutes.</span>
|
||||||
<span>Stream will start when the task is running.</span>
|
<span>Stream will start when the task is running.</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -209,7 +209,7 @@ function TaskActions() {
|
|||||||
|
|
||||||
if (task?.status === Status.Running && streamImgSrc.length === 0) {
|
if (task?.status === Status.Running && streamImgSrc.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full flex items-center justify-center text-lg bg-slate-900">
|
<div className="flex h-full w-full items-center justify-center bg-slate-900 text-lg">
|
||||||
Starting the stream...
|
Starting the stream...
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -217,7 +217,7 @@ function TaskActions() {
|
|||||||
|
|
||||||
if (task?.status === Status.Running && streamImgSrc.length > 0) {
|
if (task?.status === Status.Running && streamImgSrc.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full">
|
<div className="h-full w-full">
|
||||||
<img src={`data:image/png;base64,${streamImgSrc}`} />
|
<img src={`data:image/png;base64,${streamImgSrc}`} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -227,8 +227,8 @@ function TaskActions() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div className="w-2/3 border rounded">
|
<div className="w-2/3 rounded border">
|
||||||
<div className="p-4 w-full h-full">
|
<div className="h-full w-full p-4">
|
||||||
{selectedAction === "stream" ? getStream() : null}
|
{selectedAction === "stream" ? getStream() : null}
|
||||||
{typeof selectedAction === "number" && activeAction ? (
|
{typeof selectedAction === "number" && activeAction ? (
|
||||||
<ActionScreenshot
|
<ActionScreenshot
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ function TaskDetails() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span className="text-lg">{taskId}</span>
|
<span className="text-lg">{taskId}</span>
|
||||||
{taskId && <TaskInfo id={taskId} />}
|
{taskId && <TaskInfo id={taskId} />}
|
||||||
@@ -141,8 +141,8 @@ function TaskDetails() {
|
|||||||
</div>
|
</div>
|
||||||
{taskIsLoading ? (
|
{taskIsLoading ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Skeleton className="w-32 h-32" />
|
<Skeleton className="h-32 w-32" />
|
||||||
<Skeleton className="w-full h-32" />
|
<Skeleton className="h-32 w-full" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -150,13 +150,13 @@ function TaskDetails() {
|
|||||||
{failureReason}
|
{failureReason}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex items-center justify-center">
|
||||||
<div className="inline-flex border rounded bg-muted p-1">
|
<div className="inline-flex rounded border bg-muted p-1">
|
||||||
<NavLink
|
<NavLink
|
||||||
to="actions"
|
to="actions"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn(
|
return cn(
|
||||||
"cursor-pointer px-2 py-1 rounded-md text-muted-foreground",
|
"cursor-pointer rounded-md px-2 py-1 text-muted-foreground",
|
||||||
{
|
{
|
||||||
"bg-primary-foreground text-foreground": isActive,
|
"bg-primary-foreground text-foreground": isActive,
|
||||||
},
|
},
|
||||||
@@ -169,7 +169,7 @@ function TaskDetails() {
|
|||||||
to="recording"
|
to="recording"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn(
|
return cn(
|
||||||
"cursor-pointer px-2 py-1 rounded-md text-muted-foreground",
|
"cursor-pointer rounded-md px-2 py-1 text-muted-foreground",
|
||||||
{
|
{
|
||||||
"bg-primary-foreground text-foreground": isActive,
|
"bg-primary-foreground text-foreground": isActive,
|
||||||
},
|
},
|
||||||
@@ -182,7 +182,7 @@ function TaskDetails() {
|
|||||||
to="parameters"
|
to="parameters"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn(
|
return cn(
|
||||||
"cursor-pointer px-2 py-1 rounded-md text-muted-foreground",
|
"cursor-pointer rounded-md px-2 py-1 text-muted-foreground",
|
||||||
{
|
{
|
||||||
"bg-primary-foreground text-foreground": isActive,
|
"bg-primary-foreground text-foreground": isActive,
|
||||||
},
|
},
|
||||||
@@ -195,7 +195,7 @@ function TaskDetails() {
|
|||||||
to="diagnostics"
|
to="diagnostics"
|
||||||
className={({ isActive }) => {
|
className={({ isActive }) => {
|
||||||
return cn(
|
return cn(
|
||||||
"cursor-pointer px-2 py-1 rounded-md text-muted-foreground",
|
"cursor-pointer rounded-md px-2 py-1 text-muted-foreground",
|
||||||
{
|
{
|
||||||
"bg-primary-foreground text-foreground": isActive,
|
"bg-primary-foreground text-foreground": isActive,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ function TaskInfo({ id }: Props) {
|
|||||||
if (stepsIsLoading || taskIsLoading) {
|
if (stepsIsLoading || taskIsLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<Skeleton className="w-20 h-6" />
|
<Skeleton className="h-6 w-20" />
|
||||||
<Skeleton className="w-20 h-6" />
|
<Skeleton className="h-6 w-20" />
|
||||||
<Skeleton className="w-20 h-6" />
|
<Skeleton className="h-6 w-20" />
|
||||||
<Skeleton className="w-20 h-6" />
|
<Skeleton className="h-6 w-20" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ function TaskRecording() {
|
|||||||
|
|
||||||
if (taskIsFetching) {
|
if (taskIsFetching) {
|
||||||
return (
|
return (
|
||||||
<div className="flex mx-auto">
|
<div className="mx-auto flex">
|
||||||
<div className="w-[800px] h-[450px]">
|
<div className="h-[450px] w-[800px]">
|
||||||
<Skeleton className="h-full" />
|
<Skeleton className="h-full" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,7 +37,7 @@ function TaskRecording() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex mx-auto">
|
<div className="mx-auto flex">
|
||||||
{task.recording_url ? (
|
{task.recording_url ? (
|
||||||
<video width={800} height={450} src={getRecordingURL(task)} controls />
|
<video width={800} height={450} src={getRecordingURL(task)} controls />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function TextArtifact({ artifact }: Props) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isFetching) {
|
if (isFetching) {
|
||||||
return <Skeleton className="w-full h-48" />;
|
return <Skeleton className="h-48 w-full" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ function TaskHistory() {
|
|||||||
{task.task_id}
|
{task.task_id}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell
|
<TableCell
|
||||||
className="w-1/4 cursor-pointer max-w-64 overflow-hidden whitespace-nowrap overflow-ellipsis"
|
className="w-1/4 max-w-64 cursor-pointer overflow-hidden overflow-ellipsis whitespace-nowrap"
|
||||||
onClick={(event) => handleNavigate(event, task.task_id)}
|
onClick={(event) => handleNavigate(event, task.task_id)}
|
||||||
>
|
>
|
||||||
{task.request.url}
|
{task.request.url}
|
||||||
|
|||||||
@@ -8,16 +8,16 @@ function TaskListSkeletonRows() {
|
|||||||
return (
|
return (
|
||||||
<TableRow key={index}>
|
<TableRow key={index}>
|
||||||
<TableCell className="w-1/3">
|
<TableCell className="w-1/3">
|
||||||
<Skeleton className="w-full h-6" />
|
<Skeleton className="h-6 w-full" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-1/4">
|
<TableCell className="w-1/4">
|
||||||
<Skeleton className="w-full h-6" />
|
<Skeleton className="h-6 w-full" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-1/3">
|
<TableCell className="w-1/3">
|
||||||
<Skeleton className="w-full h-6" />
|
<Skeleton className="h-6 w-full" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-1/12">
|
<TableCell className="w-1/12">
|
||||||
<Skeleton className="w-full h-6" />
|
<Skeleton className="h-6 w-full" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ function LatestScreenshot({ id }: Props) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isFetching && !artifact) {
|
if (isFetching && !artifact) {
|
||||||
return <Skeleton className="w-full h-full" />;
|
return <Skeleton className="h-full w-full" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError || !artifact) {
|
if (isError || !artifact) {
|
||||||
@@ -75,7 +75,7 @@ function LatestScreenshot({ id }: Props) {
|
|||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
src={getImageURL(artifact)}
|
src={getImageURL(artifact)}
|
||||||
className="w-full h-full object-contain"
|
className="h-full w-full object-contain"
|
||||||
alt="Latest screenshot"
|
alt="Latest screenshot"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ function QueuedTasks() {
|
|||||||
onClick={(event) => handleNavigate(event, task.task_id)}
|
onClick={(event) => handleNavigate(event, task.task_id)}
|
||||||
>
|
>
|
||||||
<TableCell className="w-1/4">{task.task_id}</TableCell>
|
<TableCell className="w-1/4">{task.task_id}</TableCell>
|
||||||
<TableCell className="w-1/4 max-w-64 overflow-hidden whitespace-nowrap overflow-ellipsis">
|
<TableCell className="w-1/4 max-w-64 overflow-hidden overflow-ellipsis whitespace-nowrap">
|
||||||
{task.request.url}
|
{task.request.url}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-1/4">
|
<TableCell className="w-1/4">
|
||||||
|
|||||||
@@ -52,19 +52,19 @@ function RunningTasks() {
|
|||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
key={task.task_id}
|
key={task.task_id}
|
||||||
className="hover:bg-muted/50 cursor-pointer"
|
className="cursor-pointer hover:bg-muted/50"
|
||||||
onClick={(event) => handleNavigate(event, task.task_id)}
|
onClick={(event) => handleNavigate(event, task.task_id)}
|
||||||
>
|
>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="overflow-hidden text-ellipsis whitespace-nowrap">
|
<CardTitle className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
{task.task_id}
|
{task.task_id}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="whitespace-nowrap overflow-hidden text-ellipsis">
|
<CardDescription className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
{task.request.url}
|
{task.request.url}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex items-center justify-center">
|
<CardContent className="flex items-center justify-center">
|
||||||
<div className="w-40 h-40">
|
<div className="h-40 w-40">
|
||||||
<LatestScreenshot id={task.task_id} />
|
<LatestScreenshot id={task.task_id} />
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ function RunWorkflowForm({ workflowParameters, initialValues }: Props) {
|
|||||||
})}
|
})}
|
||||||
<Button type="submit" disabled={runWorkflowMutation.isPending}>
|
<Button type="submit" disabled={runWorkflowMutation.isPending}>
|
||||||
{runWorkflowMutation.isPending && (
|
{runWorkflowMutation.isPending && (
|
||||||
<ReloadIcon className="mr-2 w-4 h-4 animate-spin" />
|
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
||||||
)}
|
)}
|
||||||
Run workflow
|
Run workflow
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ function WorkflowRun() {
|
|||||||
<header className="flex gap-2">
|
<header className="flex gap-2">
|
||||||
<h1 className="text-lg font-semibold">{workflowRunId}</h1>
|
<h1 className="text-lg font-semibold">{workflowRunId}</h1>
|
||||||
{workflowRunIsLoading ? (
|
{workflowRunIsLoading ? (
|
||||||
<Skeleton className="w-28 h-8" />
|
<Skeleton className="h-8 w-28" />
|
||||||
) : workflowRun ? (
|
) : workflowRun ? (
|
||||||
<StatusBadge status={workflowRun?.status} />
|
<StatusBadge status={workflowRun?.status} />
|
||||||
) : null}
|
) : null}
|
||||||
@@ -105,7 +105,7 @@ function WorkflowRun() {
|
|||||||
{task.task_id}
|
{task.task_id}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell
|
<TableCell
|
||||||
className="w-1/4 cursor-pointer max-w-64 overflow-hidden whitespace-nowrap overflow-ellipsis"
|
className="w-1/4 max-w-64 cursor-pointer overflow-hidden overflow-ellipsis whitespace-nowrap"
|
||||||
onClick={(event) => handleNavigate(event, task.task_id)}
|
onClick={(event) => handleNavigate(event, task.task_id)}
|
||||||
>
|
>
|
||||||
{task.request.url}
|
{task.request.url}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ function WorkflowTitle({ workflowPermanentId }: Props) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <Skeleton className="w-full h-6" />;
|
return <Skeleton className="h-6 w-full" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError || !workflow) {
|
if (isError || !workflow) {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { Button } from "@/components/ui/button";
|
|||||||
|
|
||||||
function WorkflowsBetaAlertCard() {
|
function WorkflowsBetaAlertCard() {
|
||||||
return (
|
return (
|
||||||
<div className="shadow rounded-lg bg-slate-900 flex flex-col items-center p-4">
|
<div className="flex flex-col items-center rounded-lg bg-slate-900 p-4 shadow">
|
||||||
<header>
|
<header>
|
||||||
<h1 className="text-3xl py-4">Workflows (Beta)</h1>
|
<h1 className="py-4 text-3xl">Workflows (Beta)</h1>
|
||||||
</header>
|
</header>
|
||||||
<div>Workflows through UI are currently under construction.</div>
|
<div>Workflows through UI are currently under construction.</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user