Conversation
WalkthroughAdds 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
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used📓 Path-based instructions (1)**/*.{js,jsx,ts,tsx}📄 CodeRabbit inference engine (CODING_STANDARDS.md)
Files:
🧬 Code graph analysis (1)packages/bruno-app/src/components/AppTitleBar/index.js (1)
⏰ 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)
🔇 Additional comments (4)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js (1)
54-56: Consider removing wrapper function.The
onSubmitwrapper can be eliminated by passingformik.handleSubmitdirectly tohandleConfirmon 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.
IconCopyis 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
📒 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()notfunc ()
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.jspackages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.jspackages/bruno-app/src/providers/ReduxStore/slices/app.jspackages/bruno-app/src/pages/Bruno/index.jspackages/bruno-app/src/components/ManageWorkspace/index.jspackages/bruno-app/src/components/ManageWorkspace/DeleteWorkspace/index.jspackages/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.
packages/bruno-app/src/components/ManageWorkspace/RenameWorkspace/index.js
Outdated
Show resolved
Hide resolved
| </button> | ||
| )} | ||
| {!isDefault && ( | ||
| <Dropdown |
There was a problem hiding this comment.
Please use the new MenuDropdown component
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/bruno-app/src/components/ManageWorkspace/index.js (1)
138-138: UseisDefaultfor consistency.The condition checks
workspace.type !== 'default', butisDefaultis 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
📒 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()notfunc ()
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 —showInFolderreturns a promise via Redux Thunk.The
showInFolderaction is a thunk that returns a Promise, making the.catch()chaining valid. Redux Thunk middleware returns the thunk's return value from dispatch, sodispatch(showInFolder(workspace.pathname)).catch(...)properly handles async errors. No changes needed.
| 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; | ||
| }; |
There was a problem hiding this comment.
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.
Description
Contribution Checklist:
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
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.