Skip to content

add: manage workspace#6424

Merged
bijin-bruno merged 5 commits intousebruno:mainfrom
naman-bruno:add/manage-workspace
Dec 17, 2025
Merged

add: manage workspace#6424
bijin-bruno merged 5 commits intousebruno:mainfrom
naman-bruno:add/manage-workspace

Conversation

@naman-bruno
Copy link
Collaborator

@naman-bruno naman-bruno commented Dec 16, 2025

Description

Contribution Checklist:

  • I've used AI significantly to create this pull request
  • The pull request only addresses one issue or adds one feature.
  • The pull request does not introduce any breaking changes
  • I have added screenshots or gifs to help explain the change if applicable.
  • I have read the contribution guidelines.
  • Create an issue and link to the pull request.

Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests.

Publishing to New Package Managers

Please see here for more information.

Summary by CodeRabbit

  • New Features

    • Added "Manage workspaces" menu item and a dedicated workspace management page.
    • Manage page supports creating, renaming, deleting, opening, and revealing workspace locations with modals, confirmations, and toasts.
    • Added focused, validated rename and delete dialogs with guarded async actions and UI feedback.
    • Introduced styled wrapper for the Manage Workspace UI.
  • Bug Fixes

    • Fixed form label associations in environment create/rename dialogs for correct input targeting.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

Walkthrough

Adds a Manage Workspaces feature: new ManageWorkspace page and UI components (rename/delete modals, styles), a title-bar menu item to open it, Redux show/hide actions/state, page wiring, and minor label fixes in environment forms.

Changes

Cohort / File(s) Summary
Menu Integration
packages/bruno-app/src/components/AppTitleBar/index.js
Import IconSettings and showManageWorkspacePage; add "Manage workspaces" menu item that dispatches showManageWorkspacePage.
ManageWorkspace feature
packages/bruno-app/src/components/ManageWorkspace/index.js, packages/bruno-app/src/components/ManageWorkspace/DeleteWorkspace/index.js, packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js, packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js
New ManageWorkspace page plus DeleteWorkspace (confirmation modal with async delete), RenameWorkspace (Formik + Yup with uniqueness check), and StyledWrapper (styles for workspace list UI).
Page wiring
packages/bruno-app/src/pages/Bruno/index.js
Import and conditionally render <ManageWorkspace /> when state.app.showManageWorkspacePage is true, before existing Home/API panels.
Redux slice
packages/bruno-app/src/providers/ReduxStore/slices/app.js
Add showManageWorkspacePage flag to initial state; add showManageWorkspacePage and hideManageWorkspacePage reducers/actions; reset flag when showing Home.
Small UI fixes
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/CreateEnvironment/index.js, packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/RenameEnvironment/index.js
Corrected label htmlFor to match input id environment-name.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AppTitleBar
    participant ReduxStore
    participant BrunoPage
    participant ManageWorkspace
    participant ModalParts

    User->>AppTitleBar: Click "Manage workspaces"
    AppTitleBar->>ReduxStore: dispatch(showManageWorkspacePage())
    ReduxStore-->>BrunoPage: state updates (showManageWorkspacePage = true)
    BrunoPage->>ManageWorkspace: render ManageWorkspace
    User->>ManageWorkspace: Click "Open"/"Rename"/"Remove"
    ManageWorkspace->>ModalParts: open modal (rename/delete)
    ModalParts->>ReduxStore: dispatch(renameWorkspace / closeWorkspace / switchWorkspace)
    ReduxStore-->>ManageWorkspace: confirm action / update workspace list
    ManageWorkspace->>User: close modal / show toast / refresh list
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to:
    • packages/bruno-app/src/components/ManageWorkspace/index.js — modal state management, dropdown refs, and action handlers.
    • packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js — Formik/Yup validation and uniqueness check against existing workspaces.
    • packages/bruno-app/src/providers/ReduxStore/slices/app.js — visibility flag lifecycle and interactions with existing showHome/showApiSpec flags.
    • Ensure IPC/filesystem error handling (showInFolder) and async deletion flows properly surface errors and reset UI state.

Possibly related PRs

Suggested reviewers

  • helloanoop
  • lohit-bruno
  • bijin-bruno

Poem

✨ Click the gear, the list appears,
modals whisper names and fears,
rename, remove, a tidy view,
Redux flips and brings it through,
workspaces hum — small joy, renewed. 🪄

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add: manage workspace' accurately summarizes the main change: introducing a workspace management feature with UI components and Redux state management.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c33f08e and 8fd8ade.

📒 Files selected for processing (2)
  • packages/bruno-app/src/components/AppTitleBar/index.js (3 hunks)
  • packages/bruno-app/src/components/ManageWorkspace/index.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/bruno-app/src/components/ManageWorkspace/index.js
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CODING_STANDARDS.md)

**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions. () => {} is good
No space between function name and parentheses. func() not func ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly

Files:

  • packages/bruno-app/src/components/AppTitleBar/index.js
🧬 Code graph analysis (1)
packages/bruno-app/src/components/AppTitleBar/index.js (1)
packages/bruno-app/src/pages/Bruno/index.js (1)
  • showManageWorkspacePage (62-62)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: CLI Tests
  • GitHub Check: Unit Tests
  • GitHub Check: Playwright E2E Tests
  • GitHub Check: SSL Tests - macOS
  • GitHub Check: SSL Tests - Windows
  • GitHub Check: SSL Tests - Linux
🔇 Additional comments (4)
packages/bruno-app/src/components/AppTitleBar/index.js (4)

2-2: LGTM!

Icon import follows the existing pattern and is used appropriately in the menu item.


7-7: LGTM!

Redux action import is clean and follows the same pattern as showHomePage.


93-95: LGTM!

Handler implementation is clean and consistent with other navigation handlers in the component.


173-179: LGTM!

Menu item structure is consistent with existing workspace actions and correctly placed as the last item. The integration follows established patterns perfectly.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js (1)

54-56: Consider removing wrapper function.

The onSubmit wrapper can be eliminated by passing formik.handleSubmit directly to handleConfirm on line 64.

Apply this diff:

-  const onSubmit = () => {
-    formik.handleSubmit();
-  };
-
   return (
     <Portal>
       <Modal
         size="sm"
         title="Rename Workspace"
         confirmText="Rename"
-        handleConfirm={onSubmit}
+        handleConfirm={formik.handleSubmit}
         handleCancel={onClose}
       >
packages/bruno-app/src/components/ManageWorkspace/index.js (1)

3-3: Remove unused import.

IconCopy is imported but never used in the component.

Apply this diff:

-import { IconArrowLeft, IconPlus, IconFolder, IconLock, IconDots, IconEdit, IconCopy, IconX, IconCategory, IconTrash, IconLogin } from '@tabler/icons';
+import { IconArrowLeft, IconPlus, IconFolder, IconLock, IconDots, IconEdit, IconX, IconCategory, IconTrash, IconLogin } from '@tabler/icons';
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30d2a6d and 2d852fc.

📒 Files selected for processing (7)
  • packages/bruno-app/src/components/AppTitleBar/index.js (3 hunks)
  • packages/bruno-app/src/components/ManageWorkspace/DeleteWorkspace/index.js (1 hunks)
  • packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js (1 hunks)
  • packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js (1 hunks)
  • packages/bruno-app/src/components/ManageWorkspace/index.js (1 hunks)
  • packages/bruno-app/src/pages/Bruno/index.js (3 hunks)
  • packages/bruno-app/src/providers/ReduxStore/slices/app.js (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CODING_STANDARDS.md)

**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions. () => {} is good
No space between function name and parentheses. func() not func ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly

Files:

  • packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js
  • packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js
  • packages/bruno-app/src/providers/ReduxStore/slices/app.js
  • packages/bruno-app/src/pages/Bruno/index.js
  • packages/bruno-app/src/components/ManageWorkspace/index.js
  • packages/bruno-app/src/components/ManageWorkspace/DeleteWorkspace/index.js
  • packages/bruno-app/src/components/AppTitleBar/index.js
🧠 Learnings (3)
📚 Learning: 2025-12-05T20:31:33.005Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:33.005Z
Learning: Applies to **/*.{jsx,tsx} : Styled Components are used as wrappers to define both self and children components style; Tailwind classes are used specifically for layout based styles

Applied to files:

  • packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js
📚 Learning: 2025-12-05T20:31:33.005Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:33.005Z
Learning: Applies to **/*.{jsx,tsx} : Styled Component CSS might also change layout but Tailwind classes shouldn't define colors

Applied to files:

  • packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js
📚 Learning: 2025-12-05T20:31:33.005Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:33.005Z
Learning: Applies to **/*.{jsx,tsx} : Use styled component's theme prop to manage CSS colors and not CSS variables when in the context of a styled component or any React component using the styled component

Applied to files:

  • packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js
🧬 Code graph analysis (3)
packages/bruno-app/src/pages/Bruno/index.js (1)
packages/bruno-app/src/components/ManageWorkspace/index.js (2)
  • useSelector (19-19)
  • ManageWorkspace (17-190)
packages/bruno-app/src/components/ManageWorkspace/index.js (5)
packages/bruno-app/src/components/ManageWorkspace/DeleteWorkspace/index.js (2)
  • dispatch (10-10)
  • DeleteWorkspace (9-53)
packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js (3)
  • dispatch (11-11)
  • useSelector (12-12)
  • RenameWorkspace (10-93)
packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js (1)
  • StyledWrapper (3-173)
packages/bruno-app/src/components/WorkspaceSidebar/CreateWorkspace/index.js (1)
  • CreateWorkspace (13-147)
packages/bruno-app/src/components/Dropdown/index.js (1)
  • Dropdown (5-25)
packages/bruno-app/src/components/AppTitleBar/index.js (1)
packages/bruno-app/src/pages/Bruno/index.js (1)
  • showManageWorkspacePage (62-62)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Unit Tests
  • GitHub Check: CLI Tests
  • GitHub Check: SSL Tests - Windows
  • GitHub Check: SSL Tests - Linux
  • GitHub Check: SSL Tests - macOS
  • GitHub Check: Playwright E2E Tests
🔇 Additional comments (6)
packages/bruno-app/src/components/ManageWorkspace/DeleteWorkspace/index.js (1)

9-53: LGTM!

The deletion flow is well-implemented with proper guard against duplicate submissions, clear user messaging, and appropriate error handling.

packages/bruno-app/src/providers/ReduxStore/slices/app.js (1)

14-14: LGTM!

The Redux state management for the new ManageWorkspace page follows existing patterns and correctly maintains mutual exclusivity between different page views.

Also applies to: 78-78, 83-90, 145-146

packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js (1)

1-173: LGTM!

The styled component correctly uses theme tokens for all colors and styling properties, adhering to the project's styling guidelines. Layout is well-structured with appropriate responsive behavior.

Based on learnings, the use of styled components with theme props for color management is correct.

packages/bruno-app/src/pages/Bruno/index.js (1)

4-4: LGTM!

The ManageWorkspace integration follows existing patterns for page routing. The conditional rendering logic correctly prioritizes the new manage workspace page.

Also applies to: 62-62, 124-126

packages/bruno-app/src/components/AppTitleBar/index.js (1)

2-2: LGTM!

The Manage Workspaces menu integration is clean and follows existing patterns. The IconSettings choice appropriately conveys workspace management functionality.

Also applies to: 7-7, 91-93, 162-167

packages/bruno-app/src/components/ManageWorkspace/index.js (1)

17-74: Well-structured handlers.

The component's event handlers are well-organized with appropriate error handling, guard clauses for the default workspace, and proper state management.

</button>
)}
{!isDefault && (
<Dropdown
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use the new MenuDropdown component

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/bruno-app/src/components/ManageWorkspace/index.js (1)

138-138: Use isDefault for consistency.

The condition checks workspace.type !== 'default', but isDefault is already calculated on line 108. Using the existing variable improves consistency and readability.

-                  {workspace.pathname && workspace.type !== 'default' && (
+                  {workspace.pathname && !isDefault && (
                    <button
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb11451 and c33f08e.

📒 Files selected for processing (1)
  • packages/bruno-app/src/components/ManageWorkspace/index.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CODING_STANDARDS.md)

**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions. () => {} is good
No space between function name and parentheses. func() not func ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly

Files:

  • packages/bruno-app/src/components/ManageWorkspace/index.js
🧬 Code graph analysis (1)
packages/bruno-app/src/components/ManageWorkspace/index.js (8)
packages/bruno-app/src/components/AppTitleBar/index.js (2)
  • dispatch (25-25)
  • useSelector (48-48)
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/CreateEnvironment/index.js (1)
  • dispatch (19-19)
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/RenameEnvironment/index.js (1)
  • dispatch (13-13)
packages/bruno-app/src/components/ManageWorkspace/DeleteWorkspace/index.js (2)
  • dispatch (10-10)
  • DeleteWorkspace (9-53)
packages/bruno-app/src/pages/Bruno/index.js (1)
  • showHomePage (60-60)
packages/bruno-app/src/components/ManageWorkspace/StyledWrapper.js (1)
  • StyledWrapper (3-173)
packages/bruno-app/src/components/WorkspaceSidebar/CreateWorkspace/index.js (1)
  • CreateWorkspace (13-147)
packages/bruno-app/src/ui/MenuDropdown/index.js (1)
  • MenuDropdown (53-467)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: SSL Tests - macOS
  • GitHub Check: SSL Tests - Windows
  • GitHub Check: SSL Tests - Linux
  • GitHub Check: CLI Tests
  • GitHub Check: Unit Tests
  • GitHub Check: Playwright E2E Tests
🔇 Additional comments (4)
packages/bruno-app/src/components/ManageWorkspace/index.js (4)

1-15: LGTM: Clean imports and addresses past feedback.

The MenuDropdown component is now imported and used, addressing bijin-bruno's previous comment. All imports are relevant and properly structured.


17-30: LGTM: Well-structured component setup.

Redux hooks, local state, and memoization are all properly implemented. The useMemo dependency array correctly includes both workspaces and preferences.


68-167: LGTM: Clean JSX structure with proper conditionals.

The rendering logic is well-organized with clear separation between modals, header, and workspace list. The empty state handling and conditional rendering of workspace actions are properly implemented.


42-48: Code pattern is correct — showInFolder returns a promise via Redux Thunk.

The showInFolder action is a thunk that returns a Promise, making the .catch() chaining valid. Redux Thunk middleware returns the thunk's return value from dispatch, so dispatch(showInFolder(workspace.pathname)).catch(...) properly handles async errors. No changes needed.

Comment on lines +50 to +66
const handleRenameClick = (workspace) => {
dropdownRefs.current[workspace.uid]?.hide();
setRenameWorkspaceModal({ open: true, workspace });
};

const handleCloseClick = (workspace) => {
dropdownRefs.current[workspace.uid]?.hide();
if (workspace.type === 'default') {
toast.error('Cannot remove the default workspace');
return;
}
setDeleteWorkspaceModal({ open: true, workspace });
};

const onDropdownCreate = (workspaceUid) => (ref) => {
dropdownRefs.current[workspaceUid] = ref;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Dropdown refs are never assigned.

The onDropdownCreate callback is defined but never used. Lines 51 and 56 call dropdownRefs.current[workspace.uid]?.hide(), but the MenuDropdown component on line 148 doesn't receive a ref prop. This means the dropdown close operations won't work.

Add a ref prop to the MenuDropdown on line 148:

                  {!isDefault && (
                    <MenuDropdown
+                     ref={onDropdownCreate(workspace.uid)}
                      placement="bottom-end"
                      items={[
                        { id: 'rename', label: 'Rename', onClick: () => handleRenameClick(workspace) },
                        { id: 'remove', label: 'Remove', onClick: () => handleCloseClick(workspace) }
                      ]}
                    >

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
packages/bruno-app/src/components/ManageWorkspace/index.js lines ~50-66: the
onDropdownCreate callback is defined but never passed to the MenuDropdown, so
dropdownRefs.current[...] is never populated and .hide() calls are no-ops; fix
by passing the callback as the ref prop on the MenuDropdown at line ~148 (e.g.
ref={onDropdownCreate(workspace.uid)}), and if MenuDropdown does not accept
forwarded refs update MenuDropdown to forward its ref (or accept an innerRef
prop and pass that through) so dropdownRefs.current[workspaceUid] receives the
dropdown instance and hide() will work.

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.

2 participants