feat(desktop): add drag-and-drop reordering for projects in sidebar#744
feat(desktop): add drag-and-drop reordering for projects in sidebar#744
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughIntroduces project reordering functionality via a new React Query mutation hook that wraps a TRPC endpoint. The hook invalidates related workspace and project queries on success. Implements drag-and-drop reordering in ProjectSection using react-dnd, adding index prop propagation through the component hierarchy. Changes
Sequence DiagramsequenceDiagram
participant User
participant ProjectSection as ProjectSection<br/>(Component)
participant useDnD as react-dnd<br/>(useDrag/useDrop)
participant Hook as useReorderProjects<br/>(Hook)
participant TRPC as TRPC Mutation<br/>(trpc.projects.reorder)
participant QueryCache as Query Cache<br/>(React Query)
User->>ProjectSection: Drag project item
ProjectSection->>useDnD: onDrop event triggered
useDnD->>Hook: Call mutate() with new order
Hook->>TRPC: Execute projects.reorder mutation
TRPC-->>Hook: Success response
Hook->>QueryCache: Invalidate getAllGrouped
Hook->>QueryCache: Invalidate getRecents
QueryCache-->>ProjectSection: Refetch & update UI
ProjectSection->>User: Display reordered projects
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~23 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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
🤖 Fix all issues with AI agents
In
@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx:
- Around line 74-85: The hover handler inside the useDrop callback is calling
reorderProjects.mutate on every hover, causing excessive requests and races;
change this by moving the server mutation to a drop handler (add a drop: (item)
=> { ... } in the useDrop config) so you only call reorderProjects.mutate once
when the drag ends, and instead maintain local drag state for immediate UI
feedback (e.g., track a temporary index map or use local state in the component
to update item.index/index visually during hover without calling mutate). Ensure
you still update item.index locally in hover for UI ordering but remove the
mutate call from hover and invoke reorderProjects.mutate with fromIndex/toIndex
inside the new drop handler.
- Line 54: The call to the reorder mutation created via useReorderProjects in
ProjectSection currently swallows errors; wrap the mutation invocation
(reorderProjects) with proper error handling (either an async try/catch or an
onError handler on the mutation) so failures are not silent: log the error with
context (e.g., "reorderProjects failed in ProjectSection") and surface user
feedback via the app's notification/toast system (or at minimum console.error)
and ensure any optimistic UI change is rolled back or reconciled on error.
🧹 Nitpick comments (1)
apps/desktop/src/renderer/react-query/projects/useReorderProjects.ts (1)
14-18: Consider parallelizing query invalidations.The two invalidations are independent and can run concurrently using
Promise.allinstead of sequential awaits. This minor optimization reduces the delay before calling the user'sonSuccess.♻️ Suggested improvement
onSuccess: async (...args) => { - await utils.workspaces.getAllGrouped.invalidate(); - await utils.projects.getRecents.invalidate(); + await Promise.all([ + utils.workspaces.getAllGrouped.invalidate(), + utils.projects.getRecents.invalidate(), + ]); await options?.onSuccess?.(...args); },
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/desktop/src/renderer/react-query/projects/index.tsapps/desktop/src/renderer/react-query/projects/useReorderProjects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined insrc/lib/trpc
Use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from@trpc/server/observableinstead of async generators, as the library explicitly checksisObservable(result)and throws an error otherwise
Files:
apps/desktop/src/renderer/react-query/projects/index.tsapps/desktop/src/renderer/react-query/projects/useReorderProjects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use object parameters for functions with 2+ parameters instead of positional arguments
Functions with 2+ parameters should accept a single params object with named properties for self-documentation and extensibility
Use prefixed console logging with context pattern: [domain/operation] message
Extract magic numbers and hardcoded values to named constants at module top
Use lookup objects/maps instead of repeated if (type === ...) conditionals
Avoid usinganytype - maintain type safety in TypeScript code
Never swallow errors silently - at minimum log them with context
Import from concrete files directly when possible - avoid barrel file abuse that creates circular dependencies
Avoid deep nesting (4+ levels) - use early returns, extract functions, and invert conditions
Use named properties in options objects instead of boolean parameters to avoid boolean blindness
Files:
apps/desktop/src/renderer/react-query/projects/index.tsapps/desktop/src/renderer/react-query/projects/useReorderProjects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules (fs, path, os, net) in renderer process or shared code - they are externalized for browser compatibility
Files:
apps/desktop/src/renderer/react-query/projects/index.tsapps/desktop/src/renderer/react-query/projects/useReorderProjects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
apps/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Drizzle ORM for all database operations - never use raw SQL
Files:
apps/desktop/src/renderer/react-query/projects/index.tsapps/desktop/src/renderer/react-query/projects/useReorderProjects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Biome for formatting and linting - run at root level with
bun run lint:fixorbiome check --write
Files:
apps/desktop/src/renderer/react-query/projects/index.tsapps/desktop/src/renderer/react-query/projects/useReorderProjects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
One component per file - do not create multi-component files
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
🧠 Learnings (1)
📚 Learning: 2026-01-02T06:50:28.671Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-02T06:50:28.671Z
Learning: Applies to apps/*/src/components/{ui,ai-elements,react-flow}/*.tsx : Use kebab-case single files for shadcn/ui components (e.g., button.tsx, base-node.tsx) in src/components/ui/, src/components/ai-elements, and src/components/react-flow/
Applied to files:
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
🧬 Code graph analysis (2)
apps/desktop/src/renderer/react-query/projects/useReorderProjects.ts (1)
apps/desktop/src/renderer/react-query/projects/index.ts (1)
useReorderProjects(2-2)
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx (3)
apps/desktop/src/renderer/stores/new-workspace-modal.ts (1)
useOpenNewWorkspaceModal(32-33)apps/desktop/src/renderer/react-query/projects/useReorderProjects.ts (1)
useReorderProjects(7-20)packages/ui/src/lib/utils.ts (1)
cn(4-6)
⏰ 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). (1)
- GitHub Check: Build
🔇 Additional comments (3)
apps/desktop/src/renderer/react-query/projects/index.ts (1)
2-2: LGTM!Clean re-export following the existing pattern.
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx (1)
90-98: Good drag-and-drop visual feedback implementation.The ref composition pattern
drag(drop(node))is correct for combining drag source and drop target. The visual feedback with opacity reduction and cursor change provides clear indication of drag state.Also applies to: 147-156
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsx (1)
46-46: LGTM!Correctly passes the array index to enable drag-and-drop reordering in
ProjectSection.
Allow users to reorder projects in the sidebar using drag-and-drop, similar to how workspaces can already be reordered within projects. Server mutation is called only on drop (not during hover) to avoid excessive requests and race conditions.
c4eeedf to
208ec2f
Compare
Use React Query cache manipulation during hover to provide immediate visual feedback while still only calling the server mutation on drop.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
Summary
projects.reorderbackend mutationTest plan
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.