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:
@@ -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(resumed).toBe("s1"));
|
||||||
await waitFor(() => expect(screen.queryByText("Domanda originale")).not.toBeInTheDocument()); // panel closed
|
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());
|
||||||
|
});
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { SteerInput, ComposerFooter } from "./SteerInput";
|
|||||||
import { WorkflowBar } from "./WorkflowBar";
|
import { WorkflowBar } from "./WorkflowBar";
|
||||||
import { Button } from "../components/ui/button";
|
import { Button } from "../components/ui/button";
|
||||||
import { Toaster } from "../components/ui/sonner";
|
import { Toaster } from "../components/ui/sonner";
|
||||||
|
import { toast } from "sonner";
|
||||||
import {
|
import {
|
||||||
closeSession, listSessions, resumeSession,
|
closeSession, listSessions, resumeSession,
|
||||||
renameSession, setSessionGroup, archiveSession, unarchiveSession, deleteSession,
|
renameSession, setSessionGroup, archiveSession, unarchiveSession, deleteSession,
|
||||||
@@ -52,19 +53,39 @@ export function AppShell() {
|
|||||||
if (s) setPanelSession(s);
|
if (s) setPanelSession(s);
|
||||||
}
|
}
|
||||||
async function doResume(id: string) {
|
async function doResume(id: string) {
|
||||||
await resumeSession(id);
|
try {
|
||||||
setPanelSession(null);
|
await resumeSession(id);
|
||||||
setActiveSessionId(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) {
|
async function newGroup(s: SessionSummary) {
|
||||||
const name = window.prompt("New group:");
|
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) {
|
async function toggleArchive(s: SessionSummary) {
|
||||||
await (s.archived ? unarchiveSession(s.id) : archiveSession(s.id));
|
try {
|
||||||
if (panelSession?.id === s.id) setPanelSession(null);
|
await (s.archived ? unarchiveSession(s.id) : archiveSession(s.id));
|
||||||
refresh();
|
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) {
|
function menuFor(s: SessionSummary) {
|
||||||
@@ -244,7 +265,15 @@ export function AppShell() {
|
|||||||
open
|
open
|
||||||
initial={renameTarget.name ?? ""}
|
initial={renameTarget.name ?? ""}
|
||||||
onOpenChange={(o) => { if (!o) setRenameTarget(null); }}
|
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 && (
|
{deleteTarget && (
|
||||||
@@ -253,10 +282,15 @@ export function AppShell() {
|
|||||||
label={deleteTarget.name || deleteTarget.question}
|
label={deleteTarget.name || deleteTarget.question}
|
||||||
onOpenChange={(o) => { if (!o) setDeleteTarget(null); }}
|
onOpenChange={(o) => { if (!o) setDeleteTarget(null); }}
|
||||||
onConfirm={async () => {
|
onConfirm={async () => {
|
||||||
await deleteSession(deleteTarget.id);
|
try {
|
||||||
if (panelSession?.id === deleteTarget.id) setPanelSession(null);
|
await deleteSession(deleteTarget.id);
|
||||||
if (activeSessionId === deleteTarget.id) { resetSession(); setActiveSessionId(null); }
|
if (panelSession?.id === deleteTarget.id) setPanelSession(null);
|
||||||
setDeleteTarget(null); refresh();
|
if (activeSessionId === deleteTarget.id) { resetSession(); setActiveSessionId(null); }
|
||||||
|
setDeleteTarget(null);
|
||||||
|
refresh();
|
||||||
|
} catch {
|
||||||
|
toast.error("Failed to delete session.");
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user