fix(frontend): surface session mutation failures via toast; doResume only activates on success

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-29 13:30:46 +02:00
co-authored by Claude Sonnet 4.6
parent aa378291f9
commit 2c21e4659f
2 changed files with 57 additions and 13 deletions
@@ -62,3 +62,13 @@ test("Resume from the panel activates the session and closes the panel", async (
await waitFor(() => expect(resumed).toBe("s1"));
await waitFor(() => expect(screen.queryByText("Domanda originale")).not.toBeInTheDocument()); // panel closed
});
test("a failed resume keeps the panel open and does not activate the session", async () => {
server.use(http.post("http://localhost:8787/sessions/:id/resume", () => new HttpResponse(null, { status: 409 })));
wrap();
await userEvent.click(await screen.findByText("Attiva uno"));
await screen.findByText("Domanda originale"); // panel open
await userEvent.click(screen.getByRole("button", { name: /resume/i }));
// panel stays open (document still visible) after the failed resume
await waitFor(() => expect(screen.getByText("Domanda originale")).toBeInTheDocument());
});
+47 -13
View File
@@ -11,6 +11,7 @@ import { SteerInput, ComposerFooter } from "./SteerInput";
import { WorkflowBar } from "./WorkflowBar";
import { Button } from "../components/ui/button";
import { Toaster } from "../components/ui/sonner";
import { toast } from "sonner";
import {
closeSession, listSessions, resumeSession,
renameSession, setSessionGroup, archiveSession, unarchiveSession, deleteSession,
@@ -52,19 +53,39 @@ export function AppShell() {
if (s) setPanelSession(s);
}
async function doResume(id: string) {
await resumeSession(id);
setPanelSession(null);
setActiveSessionId(id);
try {
await resumeSession(id);
setPanelSession(null);
setActiveSessionId(id);
} catch {
toast.error("Failed to resume session.");
}
}
async function move(s: SessionSummary, group: string) {
try {
await setSessionGroup(s.id, group); refresh();
} catch {
toast.error("Failed to move session.");
}
}
async function move(s: SessionSummary, group: string) { await setSessionGroup(s.id, group); refresh(); }
async function newGroup(s: SessionSummary) {
const name = window.prompt("New group:");
if (name && name.trim()) { await setSessionGroup(s.id, name.trim()); refresh(); }
if (name && name.trim()) {
try {
await setSessionGroup(s.id, name.trim()); refresh();
} catch {
toast.error("Failed to update group.");
}
}
}
async function toggleArchive(s: SessionSummary) {
await (s.archived ? unarchiveSession(s.id) : archiveSession(s.id));
if (panelSession?.id === s.id) setPanelSession(null);
refresh();
try {
await (s.archived ? unarchiveSession(s.id) : archiveSession(s.id));
if (panelSession?.id === s.id) setPanelSession(null);
refresh();
} catch {
toast.error(s.archived ? "Failed to restore session." : "Failed to archive session.");
}
}
function menuFor(s: SessionSummary) {
@@ -244,7 +265,15 @@ export function AppShell() {
open
initial={renameTarget.name ?? ""}
onOpenChange={(o) => { if (!o) setRenameTarget(null); }}
onSubmit={async (name) => { await renameSession(renameTarget.id, name); setRenameTarget(null); refresh(); }}
onSubmit={async (name) => {
try {
await renameSession(renameTarget.id, name);
setRenameTarget(null);
refresh();
} catch {
toast.error("Failed to rename session.");
}
}}
/>
)}
{deleteTarget && (
@@ -253,10 +282,15 @@ export function AppShell() {
label={deleteTarget.name || deleteTarget.question}
onOpenChange={(o) => { if (!o) setDeleteTarget(null); }}
onConfirm={async () => {
await deleteSession(deleteTarget.id);
if (panelSession?.id === deleteTarget.id) setPanelSession(null);
if (activeSessionId === deleteTarget.id) { resetSession(); setActiveSessionId(null); }
setDeleteTarget(null); refresh();
try {
await deleteSession(deleteTarget.id);
if (panelSession?.id === deleteTarget.id) setPanelSession(null);
if (activeSessionId === deleteTarget.id) { resetSession(); setActiveSessionId(null); }
setDeleteTarget(null);
refresh();
} catch {
toast.error("Failed to delete session.");
}
}}
/>
)}