Keep selected projects when switching hosts (#2700)
* fix(app): preserve project selection across hosts Rendered project identity and persisted equivalence were conflated after duplicate-project handling. Keep them separate so host changes resolve selectable equivalents deterministically without resetting legacy sidebar identity. * fix(app): restore selected clone after host round trip Keep manual origin and current destination placements separately so switching back restores the chosen checkout while archive gaps preserve the active host selection. * fix(app): key status icons by project view * fix(app): preserve origin during archive gaps
This commit is contained in:
@@ -3,6 +3,7 @@ import type { DaemonClient as InternalDaemonClient } from "@getpaseo/client/inte
|
||||
import { decodeWorkspaceIdFromPathSegment } from "@/utils/host-routes";
|
||||
import { connectDaemonClient } from "./daemon-client-loader";
|
||||
import { daemonWsRoutePattern } from "./daemon-port";
|
||||
import { projectEquivalenceViewKey } from "./project-view-key";
|
||||
import { expectWorkspaceHeader } from "./workspace-ui";
|
||||
|
||||
type NewWorkspaceDaemonClient = Pick<
|
||||
@@ -167,11 +168,12 @@ export async function openNewWorkspaceComposer(
|
||||
page: Page,
|
||||
input: { projectKey: string; projectDisplayName: string },
|
||||
): Promise<void> {
|
||||
const projectRow = page.getByTestId(`sidebar-project-row-${input.projectKey}`).first();
|
||||
const projectViewKey = projectEquivalenceViewKey(input.projectKey);
|
||||
const projectRow = page.getByTestId(`sidebar-project-row-${projectViewKey}`).first();
|
||||
await expect(projectRow).toBeVisible({ timeout: 30_000 });
|
||||
await projectRow.hover();
|
||||
|
||||
const button = page.getByTestId(`sidebar-project-new-worktree-${input.projectKey}`).first();
|
||||
const button = page.getByTestId(`sidebar-project-new-worktree-${projectViewKey}`).first();
|
||||
await expect(button).toBeVisible({ timeout: 30_000 });
|
||||
await button.click();
|
||||
|
||||
@@ -216,8 +218,10 @@ export async function expectNewWorkspaceDraft(page: Page, draft: string): Promis
|
||||
}
|
||||
|
||||
export async function selectNewWorkspaceHost(page: Page, hostLabel: string): Promise<void> {
|
||||
await page.getByTestId("host-picker-trigger").click();
|
||||
await page.getByText(hostLabel, { exact: true }).click();
|
||||
const trigger = page.getByTestId("host-picker-trigger");
|
||||
await trigger.click();
|
||||
await page.getByRole("button", { name: hostLabel, exact: true }).click();
|
||||
await expect(trigger).toContainText(hostLabel);
|
||||
}
|
||||
|
||||
export async function submitNewWorkspacePrompt(
|
||||
@@ -244,13 +248,14 @@ export async function clickNewWorkspaceButton(
|
||||
|
||||
export async function selectNewWorkspaceProject(
|
||||
page: Page,
|
||||
input: { projectKey: string; projectDisplayName: string },
|
||||
input: { projectKey: string; projectDisplayName: string; projectViewKey?: string },
|
||||
): Promise<void> {
|
||||
const trigger = page.getByTestId("new-workspace-project-picker-trigger");
|
||||
await expect(trigger).toBeVisible({ timeout: 30_000 });
|
||||
await trigger.click();
|
||||
|
||||
const option = page.getByTestId(`new-workspace-project-picker-option-${input.projectKey}`);
|
||||
const projectViewKey = input.projectViewKey ?? projectEquivalenceViewKey(input.projectKey);
|
||||
const option = page.getByTestId(`new-workspace-project-picker-option-${projectViewKey}`);
|
||||
await expect(option).toBeVisible({ timeout: 30_000 });
|
||||
await option.click();
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export function projectEquivalenceViewKey(projectKey: string): string {
|
||||
return projectKey;
|
||||
}
|
||||
|
||||
export function projectPlacementViewKey(serverId: string, projectId: string): string {
|
||||
return JSON.stringify([serverId, projectId]);
|
||||
}
|
||||
Reference in New Issue
Block a user