Jon/sky 6560 enrich browser session creation via UI and place inside main layout (#3560)
This commit is contained in:
@@ -41,7 +41,7 @@ const DrawerContent = React.forwardRef<
|
|||||||
<DrawerPrimitive.Content
|
<DrawerPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
|
"fixed bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import {
|
import { GlobeIcon, PlusIcon, ReloadIcon } from "@radix-ui/react-icons";
|
||||||
ExternalLinkIcon,
|
import { useState } from "react";
|
||||||
GlobeIcon,
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||||
PlusIcon,
|
|
||||||
ReloadIcon,
|
|
||||||
} from "@radix-ui/react-icons";
|
|
||||||
import { useSearchParams } from "react-router-dom";
|
|
||||||
|
|
||||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
import { ProxyLocation } from "@/api/types";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Drawer,
|
||||||
|
DrawerContent,
|
||||||
|
DrawerDescription,
|
||||||
|
DrawerHeader,
|
||||||
|
DrawerTitle,
|
||||||
|
} from "@/components/ui/drawer";
|
||||||
|
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
import {
|
import {
|
||||||
Pagination,
|
Pagination,
|
||||||
PaginationContent,
|
PaginationContent,
|
||||||
@@ -16,6 +22,7 @@ import {
|
|||||||
PaginationNext,
|
PaginationNext,
|
||||||
PaginationPrevious,
|
PaginationPrevious,
|
||||||
} from "@/components/ui/pagination";
|
} from "@/components/ui/pagination";
|
||||||
|
import { ProxySelector } from "@/components/ProxySelector";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -57,7 +64,16 @@ function sessionIsOpen(browserSession: BrowserSession): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function BrowserSessions() {
|
function BrowserSessions() {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||||
|
const [sessionOptions, setSessionOptions] = useState<{
|
||||||
|
proxyLocation: ProxyLocation;
|
||||||
|
timeoutMinutes: number;
|
||||||
|
}>({
|
||||||
|
proxyLocation: ProxyLocation.Residential,
|
||||||
|
timeoutMinutes: 60,
|
||||||
|
});
|
||||||
|
|
||||||
const page = searchParams.get("page") ? Number(searchParams.get("page")) : 1;
|
const page = searchParams.get("page") ? Number(searchParams.get("page")) : 1;
|
||||||
const itemsPerPage = searchParams.get("page_size")
|
const itemsPerPage = searchParams.get("page_size")
|
||||||
@@ -97,12 +113,19 @@ function BrowserSessions() {
|
|||||||
!nextPageBrowserSessions ||
|
!nextPageBrowserSessions ||
|
||||||
nextPageBrowserSessions.length === 0;
|
nextPageBrowserSessions.length === 0;
|
||||||
|
|
||||||
function handleRowClick(browserSessionId: string) {
|
function handleRowClick(
|
||||||
window.open(
|
e: React.MouseEvent<HTMLTableRowElement>,
|
||||||
window.location.origin + `/browser-session/${browserSessionId}`,
|
browserSessionId: string,
|
||||||
"_blank",
|
) {
|
||||||
"noopener,noreferrer",
|
if (e.ctrlKey || e.metaKey) {
|
||||||
);
|
window.open(
|
||||||
|
window.location.origin + `/browser-session/${browserSessionId}`,
|
||||||
|
"_blank",
|
||||||
|
"noopener,noreferrer",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
navigate(`/browser-session/${browserSessionId}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -126,10 +149,7 @@ function BrowserSessions() {
|
|||||||
<Button
|
<Button
|
||||||
disabled={createBrowserSessionMutation.isPending}
|
disabled={createBrowserSessionMutation.isPending}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
createBrowserSessionMutation.mutate({
|
setIsDrawerOpen(true);
|
||||||
proxyLocation: null,
|
|
||||||
timeout: null,
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{createBrowserSessionMutation.isPending ? (
|
{createBrowserSessionMutation.isPending ? (
|
||||||
@@ -167,7 +187,6 @@ function BrowserSessions() {
|
|||||||
<TableHead className="w-1/2 truncate text-slate-400">
|
<TableHead className="w-1/2 truncate text-slate-400">
|
||||||
CDP Url
|
CDP Url
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableHead className="w-[2.5rem] rounded-tr-lg"></TableHead>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@@ -196,10 +215,16 @@ function BrowserSessions() {
|
|||||||
"wss://session-staging.skyvern.com/pbs_442960015326262218/devtools/browser/f01f27e1-182b-4a33-9017-4c1146d3eb3e";
|
"wss://session-staging.skyvern.com/pbs_442960015326262218/devtools/browser/f01f27e1-182b-4a33-9017-4c1146d3eb3e";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow key={browserSession.browser_session_id}>
|
<TableRow
|
||||||
|
key={browserSession.browser_session_id}
|
||||||
|
className="cursor-pointer hover:bg-slate-elevation2"
|
||||||
|
onClick={(e) => {
|
||||||
|
handleRowClick(e, browserSession.browser_session_id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center font-mono text-sm">
|
||||||
<div className="flex-1 truncate opacity-75">
|
<div className="truncate opacity-75">
|
||||||
{browserSession.browser_session_id}
|
{browserSession.browser_session_id}
|
||||||
</div>
|
</div>
|
||||||
<CopyText
|
<CopyText
|
||||||
@@ -237,10 +262,8 @@ function BrowserSessions() {
|
|||||||
: "-"}
|
: "-"}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center font-mono text-sm">
|
||||||
<div className="flex-1 truncate opacity-75">
|
<div className="truncate opacity-75">{cdpUrl}</div>
|
||||||
{cdpUrl}
|
|
||||||
</div>
|
|
||||||
{cdpUrl !== "-" ? (
|
{cdpUrl !== "-" ? (
|
||||||
<CopyText
|
<CopyText
|
||||||
className="opacity-75 hover:opacity-100"
|
className="opacity-75 hover:opacity-100"
|
||||||
@@ -249,14 +272,6 @@ function BrowserSessions() {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() => {
|
|
||||||
handleRowClick(browserSession.browser_session_id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ExternalLinkIcon className="inline size-4" />
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -317,6 +332,80 @@ function BrowserSessions() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* create new session options */}
|
||||||
|
<Drawer
|
||||||
|
direction="right"
|
||||||
|
open={isDrawerOpen}
|
||||||
|
onOpenChange={setIsDrawerOpen}
|
||||||
|
>
|
||||||
|
<DrawerContent className="bottom-2 right-0 top-2 mt-0 h-full w-96 rounded border-0 p-6">
|
||||||
|
<DrawerHeader>
|
||||||
|
<DrawerTitle>Create Browser Session</DrawerTitle>
|
||||||
|
<DrawerDescription>
|
||||||
|
Create a new browser session to interact with websites, or run
|
||||||
|
workflows in.
|
||||||
|
<div className="mt-8 flex flex-col gap-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Label>Proxy Location</Label>
|
||||||
|
<HelpTooltip content="Route Skyvern through one of our available proxies." />
|
||||||
|
</div>
|
||||||
|
<ProxySelector
|
||||||
|
value={sessionOptions.proxyLocation}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSessionOptions({
|
||||||
|
...sessionOptions,
|
||||||
|
proxyLocation: value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Label>Timeout (Minutes)</Label>
|
||||||
|
<HelpTooltip content="Duration to keep the browser session open. Automatically extends as it is used." />
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
value={sessionOptions.timeoutMinutes}
|
||||||
|
placeholder="timeout (minutes)"
|
||||||
|
onChange={(event) => {
|
||||||
|
const value =
|
||||||
|
event.target.value === ""
|
||||||
|
? null
|
||||||
|
: Number(event.target.value);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
setSessionOptions({
|
||||||
|
...sessionOptions,
|
||||||
|
timeoutMinutes: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
disabled={createBrowserSessionMutation.isPending}
|
||||||
|
className="mt-6 w-full"
|
||||||
|
onClick={() => {
|
||||||
|
createBrowserSessionMutation.mutate({
|
||||||
|
proxyLocation: sessionOptions.proxyLocation,
|
||||||
|
timeout: sessionOptions.timeoutMinutes,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{createBrowserSessionMutation.isPending ? (
|
||||||
|
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<PlusIcon className="mr-2 h-4 w-4" />
|
||||||
|
)}
|
||||||
|
Create
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DrawerDescription>
|
||||||
|
</DrawerHeader>
|
||||||
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user