Repository navigation
Rank saved research areas with a drag-and-drop editor (research-area phase D) - #194
Conversation
Research-area phase D: the settings "Issues you care about" section becomes a ranked editor instead of flat toggles, so the seven saved areas finally carry the rank the scoring formula weights. - Selected areas render as a numbered sortable list (dnd-kit: pointer drag with a 4px activation distance so row buttons stay clickable, keyboard sorting for accessibility) with up/down arrow buttons as the no-drag fallback and a remove control per row. - List position is the rank: every add, remove, or reorder PUTs the full list with rank = index + 1 (the API already validated ranks; the UI just never sent them). - The unselected catalog renders below as add buttons, disabled at the 7-area cap with a visible counter, replacing the previous uncapped toggles that let an 8th selection 400. - Same write-safety pattern as the other full-replace preference sections: optimistic pending overlay for quick consecutive edits and a cross-mount useIsMutating guard keyed on ["put-research-area-preferences"]. New dependencies: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 41 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds ChangesResearch Areas Drag-and-Drop Reordering
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant SortableAreaRow
participant ResearchAreasSection
participant API
User->>SortableAreaRow: drag row to new position
SortableAreaRow->>ResearchAreasSection: onDragEnd(DragEndEvent)
ResearchAreasSection->>ResearchAreasSection: arrayMove(orderedIds)
ResearchAreasSection->>ResearchAreasSection: set pending overlay
ResearchAreasSection->>API: PUT ranked {research_area_id, rank}
API-->>ResearchAreasSection: updated preferences
ResearchAreasSection->>ResearchAreasSection: clear pending, saving=false
ResearchAreasSection->>User: render updated ordered list
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Greptile SummaryThis PR turns the research-area settings list into a ranked editor. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (4): Last reviewed commit: "Check the mutation cache in save(); inva..." | Re-trigger Greptile |
Feedback on the rank editor: drag is the one reordering gesture, and the per-row up/down arrows read as a competing second mechanism. Rows now drag from anywhere (not just the handle glyph, which stays as a visual hint), the arrows are gone, and rows keep only the rank badge, the name, and remove. Touch gets its own sensor: press-and-hold (200ms, 5px tolerance) starts a drag so finger-dragging works on mobile without hijacking page scrolling. Mouse drags still need 4px of movement, so the remove button stays an ordinary click. Keyboard sorting remains for accessibility. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
frontend/src/pages/SettingsPage.tsx (1)
477-501: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winMove the drag listeners to the grip. Spreading
attributes/listenersonto the<li>makes the whole row the drag activator, so the remove button sits inside the drag target. Attach them to the⠿handle instead and keep the row itself as a plain container.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/pages/SettingsPage.tsx` around lines 477 - 501, The drag-and-drop row in the reorder item is using the entire <li> as the activator because attributes/listeners are spread on the container, which makes the remove button part of the drag target. Update the reorder item component in SettingsPage so the drag props from useSortable are attached to the ⠿ grip element instead of the <li>, while keeping the <li> as a plain layout container; preserve the existing aria-labels, transform/transition styling, and onClick remove behavior on the button.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/pages/SettingsPage.tsx`:
- Around line 356-360: The sensor setup in SettingsPage.tsx is pairing
PointerSensor with TouchSensor, but PointerSensor already covers touch and
blocks the intended press-and-hold behavior. Update the sensors used in the
useSensors call to avoid this overlap by switching the mouse path to
MouseSensor, or by using a single PointerSensor with pointer-type-specific
constraints, while keeping KeyboardSensor and sortableKeyboardCoordinates
intact.
---
Nitpick comments:
In `@frontend/src/pages/SettingsPage.tsx`:
- Around line 477-501: The drag-and-drop row in the reorder item is using the
entire <li> as the activator because attributes/listeners are spread on the
container, which makes the remove button part of the drag target. Update the
reorder item component in SettingsPage so the drag props from useSortable are
attached to the ⠿ grip element instead of the <li>, while keeping the <li> as a
plain layout container; preserve the existing aria-labels, transform/transition
styling, and onClick remove behavior on the button.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 49f3a8e4-f615-4e15-b96b-f3925bff5a11
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (2)
frontend/package.jsonfrontend/src/pages/SettingsPage.tsx
…PUTs Review follow-ups on the rank editor: - PointerSensor also claims touch input, so pairing it with TouchSensor meant the 4px pointer path won on touch devices and the press-and-hold delay never engaged — a finger drag started on 4px of movement and fought page scrolling. MouseSensor + TouchSensor split the inputs the way the dnd-kit docs prescribe, and rows switch touch-none → touch-manipulation since the TouchSensor prevents scrolling itself once its delay activates, leaving plain touches free to scroll. - save() now no-ops while a PUT is in flight: controls disable during a save, but a drag already in progress when the save started can still drop, and committing that drop would race the full-list replace. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two more review follow-ups on the rank editor: - The save guard read the rendered `saving` value, which only updates after React re-renders: a handler created before that re-render could pass the guard in the same tick as another edit's mutate() and send a second full-list PUT from an older snapshot. save() now asks the mutation cache imperatively (queryClient.isMutating), which reflects an in-flight mutation synchronously, closing the pre-render window. - Saving areas now invalidates ["me", "ballot"] and ["me", "ballot-preferences"]: the saved ballot is server-sorted by these preferences under my_areas, and the ballot-preferences default flips from vote_power to my_areas when the first area is saved — without invalidation the saved ballot page kept its stale order and subtitle until staleTime expired or a reload. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What
Research-area phase D: the settings "Issues you care about" section becomes a ranked editor. Until now the UI saved areas without ranks, so the
my_areasweighting (rank 1 → weight 7 … rank 7 → weight 1) treated everything as weight-1. Now the list order is the rank.#nrank badge per row.rank = index + 1— the API validated ranks since migration 125; the UI just never sent them.n/7counter, disabled at the cap (previously an 8th toggle just 400'd).useIsMutatingguard on["put-research-area-preferences"].New dependencies:
@dnd-kit/core,@dnd-kit/sortable,@dnd-kit/utilities(keyboard-accessible sortable, the one dependency the plan budgeted for phase D).Testing
GET /api/me/research-area-preferencesreturnedimmigration:1, housing_affordability:2, data_privacy:3;🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes