feat(bulk): add bulk random assign functionality#13
Conversation
Add the ability to randomly assign multiple project items to team members in a single bulk operation. This feature includes: - Random distribution algorithm for balanced assignment - Visual distribution preview before applying changes - Modal UI for assignee selection and strategy configuration - Background queue processing with rate limiting - GraphQL mutations for clearing and reassigning issue assignees Files changed: - bulk-actions-bar.tsx: Add handleConfirmRandomAssign and wire up modal - bulk-random-assign-modal.tsx: Implement distribution preview and confirmation - background/index.ts: Add bulkRandomAssign message handler - graphql/mutations.ts: Add REMOVE_ASSIGNEES mutation - graphql/queries.ts: Add GET_ISSUE_ASSIGNEES query
There was a problem hiding this comment.
Cursor auto review
Found 1 actionable issue(s) on changed lines.
Adds bulk random assign (modal, distribution helpers, background queue, and GraphQL for clearing assignees). Bug: In the assignee list, the row uses onClick to toggle selection while each Checkbox also toggles on onChange, so a direct checkbox click fires both handlers and the selection does not change. No other high-confidence correctness or security issues stood out in the diff.
Generated automatically when this PR was submitted using Cursor CLI with --model auto.
| }} | ||
| onClick={() => toggleAssignee(assignee.id)} | ||
| > | ||
| <Checkbox |
There was a problem hiding this comment.
Clicks on the checkbox bubble to the row onClick, so toggleAssignee runs twice (checkbox onChange + row click) and the checked state snaps back. Call stopPropagation on the checkbox click (or drop the duplicate handler / use label+htmlFor only).
There was a problem hiding this comment.
4 issues found across 7 files
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="src/components/bulk/bulk-random-assign-modal.tsx">
<violation number="1" location="src/components/bulk/bulk-random-assign-modal.tsx:41">
P2: Async assignee search responses are not guarded against out-of-order completion, so stale results can replace newer query results.</violation>
<violation number="2" location="src/components/bulk/bulk-random-assign-modal.tsx:139">
P1: Clicking the checkbox triggers both its `onChange` and the parent row's `onClick`, so `toggleAssignee` runs twice and the checked state snaps back to its original value. Add `onClick={(e) => e.stopPropagation()}` on the `Checkbox` to prevent the click from bubbling to the row handler.</violation>
</file>
<file name="src/entries/background/index.ts">
<violation number="1" location="src/entries/background/index.ts:1145">
P2: When no items resolve, this returns without sending a final queue update, so the UI can stay stuck in the “Resolving items…” state. Broadcast a terminal queue state before returning.</violation>
</file>
<file name="src/components/bulk/bulk-random-assign-utils.ts">
<violation number="1" location="src/components/bulk/bulk-random-assign-utils.ts:27">
P2: Balanced distribution has deterministic tie-breaking, so extra items always favor earlier assignees instead of being randomly spread.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Fixes identified by cubic-dev-ai code review: 1. Checkbox click handler conflict (P1) - Add onClick stopPropagation to prevent double toggle - Resolves: bulk-random-assign-modal.tsx:139 2. Async assignee search race condition (P2) - Add requestId tracking to ignore stale responses - Resolves: bulk-random-assign-modal.tsx:41 3. Missing terminal queue state (P2) - Broadcast final state when no items resolve - Decrement activeBulkCount before early return - Resolves: background/index.ts:1145 4. Deterministic tie-breaking in balanced distribution (P2) - Randomly select among candidates with equal minimum counts - Prevents extra items from always favoring earlier assignees - Resolves: bulk-random-assign-utils.ts:27
✅ All Review Issues ResolvedThanks to @github-actions and @cubic-dev-ai for the thorough review. All 4 identified issues have been fixed: Issue 1: Checkbox click handler conflict (P1) — RESOLVEDFile: Issue 2: Async assignee search race condition (P2) — RESOLVEDFile: Issue 3: Missing terminal queue state (P2) — RESOLVEDFile: Issue 4: Deterministic tie-breaking in balanced distribution (P2) — RESOLVEDFile: All changes committed and pushed. Ready for re-review! 🚀 |
There was a problem hiding this comment.
2 issues found across 3 files (changes from recent commits).
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="src/components/bulk/bulk-random-assign-modal.tsx">
<violation number="1" location="src/components/bulk/bulk-random-assign-modal.tsx:45">
P2: The request freshness check is ineffective (`currentRequestId === requestId` is always true), so stale async responses can still update assignees/loading state out of order.</violation>
</file>
<file name="src/entries/background/index.ts">
<violation number="1" location="src/entries/background/index.ts:1147">
P1: `activeBulkCount` is decremented twice on the no-items early return path, which can corrupt bulk concurrency tracking.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Fix 2 issues identified in re-review: 1. Race condition guard ineffective (P2) - bulk-random-assign-modal.tsx:45 - Problem: currentRequestId === requestId was always true (same closure) - Fix: Use useRef to track latestRequestIdRef.current across renders - Now properly ignores stale async responses 2. Double decrement of activeBulkCount (P1) - background/index.ts:1147 - Problem: activeBulkCount-- was called before return AND in finally block - Fix: Remove the early decrement; let finally block handle it consistently - Prevents corruption of bulk concurrency tracking
✅ Re-Review Issues FixedThanks @cubic-dev-ai for the re-review. Both new issues have been addressed: Issue 1: Race condition guard ineffective (P2) — FIXEDFile: Issue 2: Double decrement of activeBulkCount (P1) — FIXEDFile: Changes committed and pushed. Ready for another pass! 🚀 |
@fathiraz I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
1 issue found across 7 files
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="src/components/bulk/bulk-actions-bar.tsx">
<violation number="1" location="src/components/bulk/bulk-actions-bar.tsx:402">
P2: The selected random-assign strategy is ignored and the message always sends `balanced`.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
…essage Fixes issue identified by cubic-dev-ai: - The selected random-assign strategy was being ignored - Message always sent hardcoded 'balanced' strategy Changes: - Update onConfirm callback signature to include strategy parameter - Pass strategy from modal state when calling onConfirm - Update handleConfirmRandomAssign to receive and use strategy - Remove hardcoded 'balanced' value File: bulk-actions-bar.tsx:402
✅ Issue Fixed: Strategy Now Properly PassedThanks @cubic-dev-ai for catching this! Issue: Selected random-assign strategy was ignored, always sent 'balanced' Fix:
The selected strategy (balanced/random/round-robin) is now correctly sent to the background worker. Changes committed and pushed! 🚀 |
* main: feat(bulk): add bulk random assign functionality (#13)
Summary
Add the ability to randomly assign multiple project items to team members in a single bulk operation.
Features
Technical Changes
Components
bulk-actions-bar.tsx: Added "Random Assign" menu item and confirmation handlerbulk-random-assign-modal.tsx: Complete modal with distribution preview stepBackground Service Worker
bulkRandomAssignmessage handler inbackground/index.tsGraphQL
REMOVE_ASSIGNEESmutation for clearing existing assigneesGET_ISSUE_ASSIGNEESquery to fetch current assignees before reassignmentTesting
Related Commits
This PR includes the cumulative work from:
Summary by cubic
Adds bulk “Random Assign” to distribute selected project items across chosen assignees using balanced, random, or round‑robin strategies. Includes a preview and runs in a safe, rate‑limited background job.
New Features
GET_ISSUE_ASSIGNEESandREMOVE_ASSIGNEESGraphQL ops and abulkRandomAssignbackground handler.Bug Fixes
Written for commit 1e9e81a. Summary will update on new commits.