feat(frontend): repliage par défaut des background tasks par agent (#87)
WebWorkspace replie désormais par défaut la liste des background tasks par agent dans le panneau Work ; QA a ajouté les cas de test associés dans WebWorkspaceLive.test.tsx (887 tests verts, tsc --noEmit clean). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@ -253,6 +253,28 @@ function LiveProjectPanel({ projectId, root }: { projectId: string; root: string
|
||||
const [openAgentId, setOpenAgentId] = useState<string | null>(null);
|
||||
const agents = vm.state?.agents ?? [];
|
||||
|
||||
// Per-agent background-tasks disclosure (collapsed by default). A live refresh
|
||||
// must never flip this — only drop an entry once its agent has no tasks left,
|
||||
// so state doesn't leak for agents that no longer have a background section.
|
||||
const [expandedBgAgents, setExpandedBgAgents] = useState<Set<string>>(new Set());
|
||||
useEffect(() => {
|
||||
const withTasks = new Set(
|
||||
agents.filter((a) => (a.backgroundTasks ?? []).length > 0).map((a) => a.agentId),
|
||||
);
|
||||
setExpandedBgAgents((cur) => {
|
||||
const next = new Set([...cur].filter((id) => withTasks.has(id)));
|
||||
return next.size === cur.size ? cur : next;
|
||||
});
|
||||
}, [agents]);
|
||||
const toggleBgExpanded = useCallback((agentId: string) => {
|
||||
setExpandedBgAgents((cur) => {
|
||||
const next = new Set(cur);
|
||||
if (next.has(agentId)) next.delete(agentId);
|
||||
else next.add(agentId);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Panel className="mt-2">
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
@ -284,6 +306,8 @@ function LiveProjectPanel({ projectId, root }: { projectId: string; root: string
|
||||
setOpenAgentId((cur) => (cur === a.agentId ? null : a.agentId))
|
||||
}
|
||||
onRefresh={vm.refresh}
|
||||
bgExpanded={expandedBgAgents.has(a.agentId)}
|
||||
onToggleBgExpanded={() => toggleBgExpanded(a.agentId)}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
@ -310,11 +334,15 @@ function AgentLiveRow({
|
||||
open,
|
||||
onToggleOpen,
|
||||
onRefresh,
|
||||
bgExpanded,
|
||||
onToggleBgExpanded,
|
||||
}: {
|
||||
agent: AgentWorkState;
|
||||
open: boolean;
|
||||
onToggleOpen: () => void;
|
||||
onRefresh: () => Promise<void>;
|
||||
bgExpanded: boolean;
|
||||
onToggleBgExpanded: () => void;
|
||||
}) {
|
||||
const live = agent.live !== undefined;
|
||||
const busy = agent.busy?.state === "busy";
|
||||
@ -360,12 +388,35 @@ function AgentLiveRow({
|
||||
|
||||
{backgroundTasks.length > 0 && (
|
||||
<div className="mt-2">
|
||||
<p className="text-[11px] font-semibold uppercase tracking-wide text-faint">Background tasks</p>
|
||||
<ul aria-label={`${agent.name} background tasks`} className="mt-1 flex flex-col gap-1">
|
||||
{backgroundTasks.map((task) => (
|
||||
<WebBackgroundTaskRow key={task.taskId} task={task} onRefresh={onRefresh} />
|
||||
))}
|
||||
</ul>
|
||||
<button
|
||||
type="button"
|
||||
aria-expanded={bgExpanded}
|
||||
aria-controls={`web-bg-tasks-${agent.agentId}`}
|
||||
aria-label={
|
||||
bgExpanded
|
||||
? `Masquer les background tasks de ${agent.name}`
|
||||
: `Afficher les background tasks de ${agent.name}`
|
||||
}
|
||||
onClick={onToggleBgExpanded}
|
||||
className="flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-faint hover:text-muted"
|
||||
>
|
||||
<span aria-hidden="true">{bgExpanded ? "▾" : "▸"}</span>
|
||||
Background tasks
|
||||
<span className="rounded-full bg-raised px-1.5 py-0.5 font-medium normal-case tracking-normal text-muted">
|
||||
{backgroundTasks.length}
|
||||
</span>
|
||||
</button>
|
||||
{bgExpanded && (
|
||||
<ul
|
||||
id={`web-bg-tasks-${agent.agentId}`}
|
||||
aria-label={`${agent.name} background tasks`}
|
||||
className="mt-1 flex flex-col gap-1"
|
||||
>
|
||||
{backgroundTasks.map((task) => (
|
||||
<WebBackgroundTaskRow key={task.taskId} task={task} onRefresh={onRefresh} />
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
|
||||
Reference in New Issue
Block a user