remove: session operations center and progress panel

The bottom-right progress panel duplicated feedback already shown by
toasts. Remove it and the operation-tracking state to simplify the UI:

- Delete state/session-operations.tsx and session-progress-panel.tsx.
- Remove SessionOperationsProvider/SessionProgressPanel from AppShell.
- Remove startOperation/completeOperation calls from useInstanceActions
  and ToolStarter.
- Remove SessionOperationsProvider wrapper from DashboardPage.test.tsx.
- Remove .session-progress-panel CSS rules.
- Format use-events.test.ts mock to match project lint rules.

Quality gates: npm run typecheck, npm run lint, npm test -- --run
(87 passed).
This commit is contained in:
Developer
2026-06-13 09:50:14 +00:00
parent 43d65840ea
commit 61f9c52455
8 changed files with 28 additions and 561 deletions
@@ -1,115 +0,0 @@
import { useEffect } from "react";
import {
useSessionOperations,
type Operation,
} from "../../../state/session-operations";
import { useEventContext } from "../../../state/events";
import { Icon } from "../../icon";
interface StepConfig {
label: string;
index: number;
}
const steps: StepConfig[] = [
{ label: "Created", index: 1 },
{ label: "Building", index: 2 },
{ label: "Starting", index: 3 },
{ label: "Ready", index: 4 },
];
function OperationItem({
operation,
onDismiss,
}: {
operation: Operation;
onDismiss: () => void;
}) {
const isDone = operation.status === "success" || operation.status === "error";
const isError = operation.status === "error";
return (
<div
className={`session-operation-item ${operation.status}`}
role="status"
aria-live="polite"
>
<div className="session-operation-header">
<div className="session-operation-title">
{isError ? (
<Icon name="error" size="sm" />
) : isDone ? (
<Icon name="success" size="sm" />
) : (
<Icon name="loading" size="sm" />
)}
<span className="session-operation-name">{operation.displayName}</span>
</div>
{isDone && (
<button
type="button"
className="session-operation-dismiss"
onClick={onDismiss}
aria-label="Dismiss"
>
<Icon name="close" size="sm" />
</button>
)}
</div>
<p className="session-operation-message">{operation.message}</p>
<div className="session-operation-steps">
{steps.map((step) => {
const active = operation.step >= step.index;
const current = operation.step === step.index && !isDone;
return (
<span
key={step.label}
className={`session-operation-step ${active ? "active" : ""} ${current ? "current" : ""}`}
>
{step.label}
</span>
);
})}
</div>
</div>
);
}
export function SessionProgressPanel() {
const { operations, updateOperationFromEvent, dismissOperation } =
useSessionOperations();
const { events } = useEventContext();
useEffect(() => {
if (events.length === 0) return;
const latestEvent = events[events.length - 1];
updateOperationFromEvent(latestEvent);
}, [events, updateOperationFromEvent]);
const visibleOperations = operations.filter(
(op) =>
op.status === "pending" ||
op.status === "active" ||
(op.status === "success" && Date.now() - op.createdAt < 5000) ||
op.status === "error",
);
if (visibleOperations.length === 0) return null;
return (
<div className="session-progress-panel" role="region" aria-label="Session operations">
<div className="session-progress-panel-header">
<span className="session-progress-panel-title">Operations</span>
</div>
<div className="session-progress-panel-list">
{visibleOperations.map((operation) => (
<OperationItem
key={operation.id}
operation={operation}
onDismiss={() => dismissOperation(operation.id)}
/>
))}
</div>
</div>
);
}
@@ -9,7 +9,6 @@ import {
} from "../../../api/config-profiles";
import { listSSHKeys, type SSHKey } from "../../../api/ssh-keys";
import { useSessions } from "../../../state/sessions";
import { useSessionOperations } from "../../../state/session-operations";
import type { Workspace } from "../../../types/workspace";
import type { ToolInstance } from "../../../api/sessions";
@@ -25,7 +24,6 @@ export function ToolStarter({
onCancel,
}: ToolStarterProps) {
const { addOrUpdateSession } = useSessions();
const { startOperation } = useSessionOperations();
const [toolTypes, setToolTypes] = useState<ToolType[]>([]);
const [toolTypesLoading, setToolTypesLoading] = useState(true);
const [toolTypesError, setToolTypesError] = useState<string | null>(null);
@@ -156,7 +154,6 @@ export function ToolStarter({
status: instance.status || "pending",
url: instance.url || null,
});
startOperation("create", instance.id, instance.display_name);
onStarted(instance);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to start tool");
@@ -171,7 +168,6 @@ export function ToolStarter({
onStarted,
toolTypes,
addOrUpdateSession,
startOperation,
]);
return (