Skip to content

Reinstate the ability to duplicate a workspace#18307

Open
ConorWebb96 wants to merge 18 commits intomasterfrom
17335-reinstate-the-ability-to-duplicate-a-workspace
Open

Reinstate the ability to duplicate a workspace#18307
ConorWebb96 wants to merge 18 commits intomasterfrom
17335-reinstate-the-ability-to-duplicate-a-workspace

Conversation

@ConorWebb96
Copy link
Collaborator

Description

This PR re-adds the workspace context-menu actions in the WorkspaceSelect dropdown (allows users to more easily duplicate, export dev/prod, and delete workspaces).

  • Added right-click workspace context menu support in the workspace selector, reusing existing duplicate/export/delete action wiring.
  • Updated duplicate modal user-facing copy from “App” to “Workspace”.
  • Fixed stale UI after delete by refreshing workspace list in context-menu delete success path.
  • Fixed cross-workspace delete conflict by preventing conflicting APP_ID header attachment on DELETE /api/applications/app_dev_*.
  • Improved delete UX:
    • only reset the app store when deleting the active workspace
    • if active workspace is deleted, reload workspaces and redirect to another editable workspace (fallback /).
  • Added server route regression coverage in workspace.spec.ts for mismatched APP_ID header vs path appId (403 App id conflict) to lock in the invariant.

Addresses

Launchcontrol

Brings back the ability to duplicate workspaces and adds a context menu whenever a workspace is right-clicked.

@ConorWebb96 ConorWebb96 requested a review from a team as a code owner March 16, 2026 10:55
@ConorWebb96 ConorWebb96 requested review from adrinr and removed request for a team March 16, 2026 10:55
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 9 files

Confidence score: 3/5

  • There is some real regression risk here: packages/builder/src/components/deploy/DeleteModal.svelte can report a delete failure even after a successful delete if the post-delete refresh fails, which is user-facing and confusing.
  • packages/builder/src/components/common/WorkspaceSelect.svelte currently suppresses right-click behavior on non-editable workspaces, leaving users with neither the custom context menu nor the native browser menu.
  • packages/builder/src/components/start/AppContextMenuModals.svelte introduces a redundant workspace-list reload on active-workspace delete; if that extra refresh fails, it can surface a false error and potentially interfere with redirect flow.
  • Pay close attention to packages/builder/src/components/deploy/DeleteModal.svelte, packages/builder/src/components/common/WorkspaceSelect.svelte, packages/builder/src/components/start/AppContextMenuModals.svelte - delete/error-path handling and context-menu behavior need validation.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/builder/src/components/deploy/DeleteModal.svelte">

<violation number="1" location="packages/builder/src/components/deploy/DeleteModal.svelte:61">
P2: Handle post-delete refresh errors separately so a successful delete does not fall into the delete failure path.</violation>
</file>

<file name="packages/builder/src/components/start/AppContextMenuModals.svelte">

<violation number="1" location="packages/builder/src/components/start/AppContextMenuModals.svelte:41">
P2: This adds a second workspace-list reload on the active-workspace delete path, which can surface a false delete error and block the redirect if the redundant refresh fails.</violation>
</file>

<file name="packages/builder/src/components/common/WorkspaceSelect.svelte">

<violation number="1" location="packages/builder/src/components/common/WorkspaceSelect.svelte:124">
P2: Don't swallow right-clicks on non-editable workspaces. These rows return early from `openWorkspaceContextMenu`, so the new handler leaves users with no custom menu and no native browser menu.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@ConorWebb96
Copy link
Collaborator Author

@cubic-dev-ai can you give this another review?

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Mar 16, 2026

@cubic-dev-ai can you give this another review?

@ConorWebb96 I have started the AI code review. It will take a few minutes to complete.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 8 files

Confidence score: 3/5

  • There is some merge risk because packages/builder/src/components/deploy/DeleteModal.svelte has concrete user-facing failure paths around delete success handling (one issue at 6/10 severity with high confidence).
  • Most severe: if appsStore.load() blocks redirect and refresh fails, deleting the active workspace can strand users on a removed-workspace route after a successful delete.
  • The optional onDeleteSuccess callback should not block the required workspace refresh; if that callback throws, users may still see a workspace that was already deleted in the selector.
  • Pay close attention to packages/builder/src/components/deploy/DeleteModal.svelte - decouple redirect/refresh/callback flow so delete success remains consistent even when follow-up async steps fail.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/builder/src/components/deploy/DeleteModal.svelte">

<violation number="1" location="packages/builder/src/components/deploy/DeleteModal.svelte:62">
P2: Run the optional `onDeleteSuccess` callback without blocking the required workspace-list refresh. A callback failure here can leave a successfully deleted workspace visible in the selector.</violation>

<violation number="2" location="packages/builder/src/components/deploy/DeleteModal.svelte:63">
P2: Don’t let `appsStore.load()` block the redirect after a successful delete. If the refresh request fails, active-workspace deletes leave the user stranded on the removed workspace route.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@ConorWebb96
Copy link
Collaborator Author

@cubic-dev-ai can you do one more review?

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Mar 16, 2026

@cubic-dev-ai can you do one more review?

@ConorWebb96 I have started the AI code review. It will take a few minutes to complete.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 8 files

Confidence score: 3/5

  • There is a concrete user-facing behavior risk: in packages/bbui/src/Menu/Item.svelte, newly forwarded contextmenu and keydown events are not gated by disabled, so disabled menu items may still trigger parent actions.
  • Given the issue’s moderate severity (5/10) and fairly high confidence (8/10), this is more than a cosmetic concern and could cause regression in expected disabled-state behavior.
  • Pay close attention to packages/bbui/src/Menu/Item.svelte - ensure contextmenu/keydown forwarding is blocked when disabled is true.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/bbui/src/Menu/Item.svelte">

<violation number="1" location="packages/bbui/src/Menu/Item.svelte:44">
P2: Guard the new `contextmenu`/`keydown` forwarding behind `disabled` as well; disabled menu items can still trigger parent actions through these events.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

<li
on:click={disabled ? null : onClick}
on:auxclick
on:contextmenu
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Guard the new contextmenu/keydown forwarding behind disabled as well; disabled menu items can still trigger parent actions through these events.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/bbui/src/Menu/Item.svelte, line 44:

<comment>Guard the new `contextmenu`/`keydown` forwarding behind `disabled` as well; disabled menu items can still trigger parent actions through these events.</comment>

<file context>
@@ -41,6 +41,8 @@
 <li
   on:click={disabled ? null : onClick}
   on:auxclick
+  on:contextmenu
+  on:keydown
   class="spectrum-Menu-item"
</file context>
Fix with Cubic

@deanhannigan
Copy link
Contributor

@ConorWebb96 had a run through this today and it's working really well. One minor thing I noticed is that when switching workspace, if the new context menu is visible, the menu will get stuck open during the swap.

Other than that, this is looking great 🚀

Copy link
Member

@adrinr adrinr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the use case of this? We will have some issues with the agents we should sort

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants