diff --git a/ui/src/styles/components.css b/ui/src/styles/components.css index f4ef315ec..58965472e 100644 --- a/ui/src/styles/components.css +++ b/ui/src/styles/components.css @@ -454,6 +454,15 @@ background: rgba(0, 0, 0, 0.2); } +.session-link { + text-decoration: none; + color: var(--accent); +} + +.session-link:hover { + text-decoration: underline; +} + .log-stream { border: 1px solid var(--border); border-radius: 14px; diff --git a/ui/src/ui/app-render.ts b/ui/src/ui/app-render.ts index c19820d4e..873f99a93 100644 --- a/ui/src/ui/app-render.ts +++ b/ui/src/ui/app-render.ts @@ -358,6 +358,7 @@ export function renderApp(state: AppViewState) { limit: state.sessionsFilterLimit, includeGlobal: state.sessionsIncludeGlobal, includeUnknown: state.sessionsIncludeUnknown, + basePath: state.basePath, onFiltersChange: (next) => { state.sessionsFilterActive = next.activeMinutes; state.sessionsFilterLimit = next.limit; diff --git a/ui/src/ui/app.ts b/ui/src/ui/app.ts index 6e959494e..d1b0a954f 100644 --- a/ui/src/ui/app.ts +++ b/ui/src/ui/app.ts @@ -824,7 +824,9 @@ export class ClawdbotApp extends LitElement { const params = new URLSearchParams(window.location.search); const tokenRaw = params.get("token"); const passwordRaw = params.get("password"); + const sessionRaw = params.get("session"); let changed = false; + let shouldCleanUrl = false; if (tokenRaw != null) { const token = tokenRaw.trim(); @@ -833,6 +835,7 @@ export class ClawdbotApp extends LitElement { changed = true; } params.delete("token"); + shouldCleanUrl = true; } if (passwordRaw != null) { @@ -842,9 +845,20 @@ export class ClawdbotApp extends LitElement { changed = true; } params.delete("password"); + shouldCleanUrl = true; } - if (!changed && tokenRaw == null && passwordRaw == null) return; + if (sessionRaw != null) { + const session = sessionRaw.trim(); + if (session) { + this.sessionKey = session; + changed = true; + } + params.delete("session"); + shouldCleanUrl = true; + } + + if (!shouldCleanUrl) return; const url = new URL(window.location.href); url.search = params.toString(); window.history.replaceState({}, "", url.toString()); diff --git a/ui/src/ui/views/sessions.ts b/ui/src/ui/views/sessions.ts index c82526538..47e910750 100644 --- a/ui/src/ui/views/sessions.ts +++ b/ui/src/ui/views/sessions.ts @@ -2,6 +2,7 @@ import { html, nothing } from "lit"; import { formatAgo } from "../format"; import { formatSessionTokens } from "../presenter"; +import { pathForTab } from "../navigation"; import type { GatewaySessionRow, SessionsListResult } from "../types"; export type SessionsProps = { @@ -12,6 +13,7 @@ export type SessionsProps = { limit: string; includeGlobal: boolean; includeUnknown: boolean; + basePath: string; onFiltersChange: (next: { activeMinutes: string; limit: string; @@ -118,19 +120,27 @@ export function renderSessions(props: SessionsProps) { ${rows.length === 0 ? html`