feat(ui): link sessions to chat page
- Session names in the Sessions table are now clickable links - Clicking navigates to /chat?session=<key> with that session loaded - Global sessions excluded (not real conversations) - Added .session-link CSS styling (accent color, underline on hover) - Chat page reads 'session' query param and cleans URL after applying
This commit is contained in:
committed by
Peter Steinberger
parent
b3b84ffefa
commit
2e1dee197a
@@ -454,6 +454,15 @@
|
|||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.session-link {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.log-stream {
|
.log-stream {
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
|
|||||||
@@ -358,6 +358,7 @@ export function renderApp(state: AppViewState) {
|
|||||||
limit: state.sessionsFilterLimit,
|
limit: state.sessionsFilterLimit,
|
||||||
includeGlobal: state.sessionsIncludeGlobal,
|
includeGlobal: state.sessionsIncludeGlobal,
|
||||||
includeUnknown: state.sessionsIncludeUnknown,
|
includeUnknown: state.sessionsIncludeUnknown,
|
||||||
|
basePath: state.basePath,
|
||||||
onFiltersChange: (next) => {
|
onFiltersChange: (next) => {
|
||||||
state.sessionsFilterActive = next.activeMinutes;
|
state.sessionsFilterActive = next.activeMinutes;
|
||||||
state.sessionsFilterLimit = next.limit;
|
state.sessionsFilterLimit = next.limit;
|
||||||
|
|||||||
@@ -824,7 +824,9 @@ export class ClawdbotApp extends LitElement {
|
|||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const tokenRaw = params.get("token");
|
const tokenRaw = params.get("token");
|
||||||
const passwordRaw = params.get("password");
|
const passwordRaw = params.get("password");
|
||||||
|
const sessionRaw = params.get("session");
|
||||||
let changed = false;
|
let changed = false;
|
||||||
|
let shouldCleanUrl = false;
|
||||||
|
|
||||||
if (tokenRaw != null) {
|
if (tokenRaw != null) {
|
||||||
const token = tokenRaw.trim();
|
const token = tokenRaw.trim();
|
||||||
@@ -833,6 +835,7 @@ export class ClawdbotApp extends LitElement {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
params.delete("token");
|
params.delete("token");
|
||||||
|
shouldCleanUrl = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passwordRaw != null) {
|
if (passwordRaw != null) {
|
||||||
@@ -842,9 +845,20 @@ export class ClawdbotApp extends LitElement {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
params.delete("password");
|
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);
|
const url = new URL(window.location.href);
|
||||||
url.search = params.toString();
|
url.search = params.toString();
|
||||||
window.history.replaceState({}, "", url.toString());
|
window.history.replaceState({}, "", url.toString());
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { html, nothing } from "lit";
|
|||||||
|
|
||||||
import { formatAgo } from "../format";
|
import { formatAgo } from "../format";
|
||||||
import { formatSessionTokens } from "../presenter";
|
import { formatSessionTokens } from "../presenter";
|
||||||
|
import { pathForTab } from "../navigation";
|
||||||
import type { GatewaySessionRow, SessionsListResult } from "../types";
|
import type { GatewaySessionRow, SessionsListResult } from "../types";
|
||||||
|
|
||||||
export type SessionsProps = {
|
export type SessionsProps = {
|
||||||
@@ -12,6 +13,7 @@ export type SessionsProps = {
|
|||||||
limit: string;
|
limit: string;
|
||||||
includeGlobal: boolean;
|
includeGlobal: boolean;
|
||||||
includeUnknown: boolean;
|
includeUnknown: boolean;
|
||||||
|
basePath: string;
|
||||||
onFiltersChange: (next: {
|
onFiltersChange: (next: {
|
||||||
activeMinutes: string;
|
activeMinutes: string;
|
||||||
limit: string;
|
limit: string;
|
||||||
@@ -118,19 +120,27 @@ export function renderSessions(props: SessionsProps) {
|
|||||||
</div>
|
</div>
|
||||||
${rows.length === 0
|
${rows.length === 0
|
||||||
? html`<div class="muted">No sessions found.</div>`
|
? html`<div class="muted">No sessions found.</div>`
|
||||||
: rows.map((row) => renderRow(row, props.onPatch))}
|
: rows.map((row) => renderRow(row, props.basePath, props.onPatch))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRow(row: GatewaySessionRow, onPatch: SessionsProps["onPatch"]) {
|
function renderRow(row: GatewaySessionRow, basePath: string, onPatch: SessionsProps["onPatch"]) {
|
||||||
const updated = row.updatedAt ? formatAgo(row.updatedAt) : "n/a";
|
const updated = row.updatedAt ? formatAgo(row.updatedAt) : "n/a";
|
||||||
const thinking = row.thinkingLevel ?? "";
|
const thinking = row.thinkingLevel ?? "";
|
||||||
const verbose = row.verboseLevel ?? "";
|
const verbose = row.verboseLevel ?? "";
|
||||||
|
const displayName = row.displayName ?? row.key;
|
||||||
|
const canLink = row.kind !== "global";
|
||||||
|
const chatUrl = canLink
|
||||||
|
? `${pathForTab("chat", basePath)}?session=${encodeURIComponent(row.key)}`
|
||||||
|
: null;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="table-row">
|
<div class="table-row">
|
||||||
<div class="mono">${row.displayName ?? row.key}</div>
|
<div class="mono">${canLink
|
||||||
|
? html`<a href=${chatUrl} class="session-link">${displayName}</a>`
|
||||||
|
: displayName}</div>
|
||||||
<div>${row.kind}</div>
|
<div>${row.kind}</div>
|
||||||
<div>${updated}</div>
|
<div>${updated}</div>
|
||||||
<div>${formatSessionTokens(row)}</div>
|
<div>${formatSessionTokens(row)}</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user