feat(frontend): sessions list/create + steering + resume + selectors
- NavSessions: left nav listing sessions via listSessions (TanStack Query), clicking resumes via resumeSession and sets active; active item highlighted - NewSessionDialog: ShadCn dialog with question textarea, workspace native select (from listWorkspaces), graceful model field (dropdown when models list is non-empty, free-text input when empty per §9 degradation), optional thinking/provider fields; try/catch surfaces errors inline - SteerInput: text input + button POSTs to postSteer, clears on send, supports Enter key; only shown when a session is active - WorkflowBar: renders 8 phases (F1..F8) with data-active highlighting driven by useSessionStore.currentPhase (new store field + setPhase action) - AppShell: wires all four components; right artifact sidebar now collapsible via a toggle button (useState sidebarOpen); replaces old "Nuova domanda" button with NewSessionDialog trigger - f1-loop.test: updated to drive through the new dialog flow (open → fill question → submit → wait for SSE → respond) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
// frontend/src/shell/NavSessions.tsx
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { listSessions } from "../api/sessions";
|
||||
import { resumeSession } from "../api/sessions";
|
||||
import type { SessionSummary } from "../api/types";
|
||||
|
||||
interface Props {
|
||||
activeSessionId: string | null;
|
||||
onSessionSelect: (id: string) => void;
|
||||
}
|
||||
|
||||
export function NavSessions({ activeSessionId, onSessionSelect }: Props) {
|
||||
const { data: sessions = [] } = useQuery<SessionSummary[]>({
|
||||
queryKey: ["sessions"],
|
||||
queryFn: listSessions,
|
||||
refetchInterval: 10_000,
|
||||
});
|
||||
|
||||
async function handleClick(id: string) {
|
||||
await resumeSession(id);
|
||||
onSessionSelect(id);
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="flex flex-col gap-1">
|
||||
{sessions.map((s) => (
|
||||
<li key={s.id}>
|
||||
<button
|
||||
data-testid={`session-item-${s.id}`}
|
||||
data-active={s.id === activeSessionId ? "true" : "false"}
|
||||
onClick={() => handleClick(s.id)}
|
||||
className={[
|
||||
"w-full text-left rounded px-2 py-1 text-xs hover:bg-accent truncate",
|
||||
s.id === activeSessionId ? "bg-accent font-semibold" : "",
|
||||
].join(" ")}
|
||||
>
|
||||
<span className="block truncate">{s.question || s.id}</span>
|
||||
<span className="block text-muted-foreground text-[10px]">{s.status}</span>
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user