Group and clear workspace status in the sidebar (#1317)

* Add status grouping to the workspace sidebar

* Mark workspaces as read from the sidebar

* Clean package builds before release checks

* Fix sidebar status follow-up checks
This commit is contained in:
Mohamed Boudra
2026-06-04 01:20:20 +08:00
committed by GitHub
parent 71ce96b913
commit 31ae545289
65 changed files with 3758 additions and 290 deletions
@@ -10,6 +10,7 @@ import { useKeyboardShortcutsStore } from "@/stores/keyboard-shortcuts-store";
import { useSessionStore, type WorkspaceDescriptor } from "@/stores/session-store";
import { useSidebarCollapsedSectionsStore } from "@/stores/sidebar-collapsed-sections-store";
import { useSidebarOrderStore } from "@/stores/sidebar-order-store";
import { useSidebarViewStore } from "@/stores/sidebar-view-store";
import { WorkspaceShortcutTargetsSubscriber } from "./workspace-shortcut-targets-subscriber";
vi.hoisted(() => {
@@ -20,18 +21,22 @@ function workspaceDescriptor(input: {
id: string;
name?: string;
projectId?: string;
projectDisplayName?: string;
status?: WorkspaceDescriptor["status"];
statusEnteredAt?: Date | null;
}): WorkspaceDescriptor {
return {
id: input.id,
projectId: input.projectId ?? "project-1",
projectDisplayName: "Project 1",
projectDisplayName: input.projectDisplayName ?? "Project 1",
projectRootPath: "/repo/main",
workspaceDirectory: `/repo/main/${input.id}`,
projectKind: "git",
workspaceKind: "worktree",
name: input.name ?? input.id,
status: "done",
status: input.status ?? "done",
archivingAt: null,
statusEnteredAt: input.statusEnteredAt ?? null,
diffStat: null,
scripts: [],
};
@@ -56,6 +61,9 @@ describe("WorkspaceShortcutTargetsSubscriber", () => {
projectOrderByServerId: {},
workspaceOrderByServerAndProject: {},
});
useSidebarViewStore.setState({
groupModeByServerId: {},
});
act(() => {
useSessionStore.getState().initializeSession("srv", null as unknown as DaemonClient);
@@ -95,6 +103,72 @@ describe("WorkspaceShortcutTargetsSubscriber", () => {
]);
});
it("publishes status-mode shortcut targets in visual status order", async () => {
act(() => {
useSidebarViewStore.getState().setGroupMode("srv", "status");
useSessionStore.getState().setWorkspaces(
"srv",
new Map([
[
"ws-done",
workspaceDescriptor({
id: "ws-done",
name: "Done",
projectId: "project-1",
projectDisplayName: "Project 1",
status: "done",
statusEnteredAt: new Date("2026-01-01T00:00:00.000Z"),
}),
],
[
"ws-running-old",
workspaceDescriptor({
id: "ws-running-old",
name: "Running old",
projectId: "project-2",
projectDisplayName: "Project 2",
status: "running",
statusEnteredAt: new Date("2026-02-01T00:00:00.000Z"),
}),
],
[
"ws-needs-input",
workspaceDescriptor({
id: "ws-needs-input",
name: "Needs input",
projectId: "project-1",
projectDisplayName: "Project 1",
status: "needs_input",
statusEnteredAt: new Date("2026-01-15T00:00:00.000Z"),
}),
],
[
"ws-running-new",
workspaceDescriptor({
id: "ws-running-new",
name: "Running new",
projectId: "project-2",
projectDisplayName: "Project 2",
status: "running",
statusEnteredAt: new Date("2026-03-01T00:00:00.000Z"),
}),
],
]),
);
});
await act(async () => {
root?.render(<WorkspaceShortcutTargetsSubscriber enabled={true} serverId="srv" />);
});
expect(useKeyboardShortcutsStore.getState().sidebarShortcutWorkspaceTargets).toEqual([
{ serverId: "srv", workspaceId: "ws-needs-input" },
{ serverId: "srv", workspaceId: "ws-running-new" },
{ serverId: "srv", workspaceId: "ws-running-old" },
{ serverId: "srv", workspaceId: "ws-done" },
]);
});
it("clears targets when disabled", async () => {
await act(async () => {
root?.render(<WorkspaceShortcutTargetsSubscriber enabled={true} serverId="srv" />);