diff --git a/web/src/app/home/components/workspace-settings/WorkspaceSettingsPanel.tsx b/web/src/app/home/components/workspace-settings/WorkspaceSettingsPanel.tsx index e8df0ced8..be98d906c 100644 --- a/web/src/app/home/components/workspace-settings/WorkspaceSettingsPanel.tsx +++ b/web/src/app/home/components/workspace-settings/WorkspaceSettingsPanel.tsx @@ -90,6 +90,9 @@ export default function WorkspaceSettingsPanel({ const cloudMembersURL = workspaceInfo ? `${systemInfo.cloud_service_url.replace(/\/$/, '')}/cloud?workspace=${encodeURIComponent(workspaceInfo.workspace.uuid)}#workspace-members` : ''; + const cloudPortalURL = workspaceInfo + ? `${systemInfo.cloud_service_url.replace(/\/$/, '')}/cloud?workspace=${encodeURIComponent(workspaceInfo.workspace.uuid)}&step=plan` + : ''; const loadWorkspace = useCallback(async () => { setLoading(true); @@ -221,6 +224,14 @@ export default function WorkspaceSettingsPanel({ {t(`workspace.roles.${workspaceInfo.membership.role}`)} )} + {isCloudProjection && workspaceInfo && ( + + )} {canManageCloudMembers && ( - - {t('workspace.switchWorkspace')} + + + {t('workspace.switchWorkspace')} + {workspaces.map((entry) => { const selected = entry.workspace.uuid === currentWorkspace.workspace.uuid; return ( { if (!selected) void switchWorkspaceAndReload(entry.workspace.uuid); }} > - - + + {entry.workspace.name} + {entry.workspace.source === 'cloud_projection' && ( + + {entry.plan_name || t('workspace.planUnavailable')} + + )} {t(`workspace.roles.${entry.membership.role}`)} {selected && } + {selected && ( + + )} ); })} - - {isCloud && ( - <> - - - {t('workspace.currentPlan')} - - - {currentWorkspace.plan_name || t('workspace.planUnavailable')} - - - - - - {t('workspace.upgradePlan')} - - - - - )} - - - {t('workspace.settings')} - ); diff --git a/web/tests/unit/workspace-switcher-layout.test.mjs b/web/tests/unit/workspace-switcher-layout.test.mjs index af88f6a9a..dabd4bc13 100644 --- a/web/tests/unit/workspace-switcher-layout.test.mjs +++ b/web/tests/unit/workspace-switcher-layout.test.mjs @@ -67,3 +67,22 @@ test('links Cloud workspace managers to the Space member invitation surface', () assert.match(workspaceSettingsPanelSource, /#workspace-members/); assert.match(workspaceSettingsPanelSource, /workspace\.inviteMember/); }); + +test('keeps workspace plan and settings controls on the workspace row', () => { + assert.match(workspaceSwitcherSource, /entry\.plan_name/); + assert.match(workspaceSwitcherSource, /aria-label=\{t\('workspace\.settings'\)\}/); + assert.match(workspaceSwitcherSource, /className="size-8"/); + assert.doesNotMatch(workspaceSwitcherSource, /workspace\.currentPlan/); + assert.doesNotMatch(workspaceSwitcherSource, /workspace\.upgradePlan/); +}); + +test('moves Cloud plan upgrades into Workspace Settings', () => { + assert.match(workspaceSettingsPanelSource, /workspace\.upgradePlan/); + assert.match(workspaceSettingsPanelSource, /cloudPortalURL/); + assert.match(workspaceSettingsPanelSource, /step=plan/); +}); + +test('uses a larger workspace trigger and menu surface', () => { + assert.match(workspaceSwitcherSource, /h-11/); + assert.match(workspaceSwitcherSource, /min-w-80/); +});