Init Repo
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# Context Menu Selection Preservation Fix
|
||||
|
||||
## Issue
|
||||
When right-clicking on an unselected task, all previously selected tasks were being deselected, leaving only the right-clicked task selected.
|
||||
|
||||
## Expected Behavior
|
||||
According to Requirement 3.2: "WHEN a user right-clicks on an unselected task row THEN the system SHALL select that task and display the context menu"
|
||||
|
||||
The requirement means:
|
||||
- If the right-clicked task is already selected → keep all selections, show menu
|
||||
- If the right-clicked task is NOT selected → ADD it to existing selections, show menu
|
||||
|
||||
## Root Cause
|
||||
The implementation was replacing the entire selection object instead of adding to it:
|
||||
|
||||
```typescript
|
||||
// WRONG - Replaces all selections
|
||||
if (!rowSelection.value[rowIndex]) {
|
||||
rowSelection.value = { [rowIndex]: true }
|
||||
}
|
||||
```
|
||||
|
||||
This cleared all existing selections and only selected the right-clicked row.
|
||||
|
||||
## Solution
|
||||
Use the spread operator to preserve existing selections while adding the new row:
|
||||
|
||||
```typescript
|
||||
// CORRECT - Preserves existing selections
|
||||
if (!rowSelection.value[rowIndex]) {
|
||||
rowSelection.value = { ...rowSelection.value, [rowIndex]: true }
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### Before
|
||||
```typescript
|
||||
const handleContextMenu = (event: MouseEvent, rowIndex: number) => {
|
||||
event.preventDefault()
|
||||
|
||||
if (filteredTasks.value.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// This replaces all selections!
|
||||
if (!rowSelection.value[rowIndex]) {
|
||||
rowSelection.value = { [rowIndex]: true }
|
||||
}
|
||||
|
||||
contextMenuPosition.value = { x: event.clientX, y: event.clientY }
|
||||
showContextMenu.value = true
|
||||
}
|
||||
```
|
||||
|
||||
### After
|
||||
```typescript
|
||||
const handleContextMenu = (event: MouseEvent, rowIndex: number) => {
|
||||
event.preventDefault()
|
||||
|
||||
if (filteredTasks.value.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// Preserve existing selections and add the right-clicked row
|
||||
if (!rowSelection.value[rowIndex]) {
|
||||
rowSelection.value = { ...rowSelection.value, [rowIndex]: true }
|
||||
}
|
||||
|
||||
contextMenuPosition.value = { x: event.clientX, y: event.clientY }
|
||||
showContextMenu.value = true
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Scenario 1: Right-click on unselected task with existing selections
|
||||
1. Select tasks 1, 2, and 3 using checkboxes
|
||||
2. Right-click on task 4 (unselected)
|
||||
3. **Expected:** Tasks 1, 2, 3, and 4 are all selected
|
||||
4. **Result:** ✅ All 4 tasks remain selected
|
||||
|
||||
### Test Scenario 2: Right-click on already selected task
|
||||
1. Select tasks 1, 2, and 3 using checkboxes
|
||||
2. Right-click on task 2 (already selected)
|
||||
3. **Expected:** Tasks 1, 2, and 3 remain selected
|
||||
4. **Result:** ✅ All 3 tasks remain selected
|
||||
|
||||
### Test Scenario 3: Right-click with no prior selections
|
||||
1. No tasks selected
|
||||
2. Right-click on task 1
|
||||
3. **Expected:** Task 1 becomes selected
|
||||
4. **Result:** ✅ Task 1 is selected
|
||||
|
||||
## Files Modified
|
||||
- `frontend/src/components/task/TaskBrowser.vue` - Fixed handleContextMenu to preserve selections
|
||||
|
||||
## Related Requirements
|
||||
- **Requirement 3.2:** Right-click on unselected task should select it before showing menu
|
||||
- **Requirement 1.2:** User can toggle selection state for specific tasks
|
||||
- **Requirement 1.3:** Header checkbox toggles selection for all visible tasks
|
||||
|
||||
## Benefits
|
||||
- ✅ Preserves user's existing selections
|
||||
- ✅ Allows building up selections via right-click
|
||||
- ✅ Matches expected UX behavior
|
||||
- ✅ Complies with Requirement 3.2
|
||||
Reference in New Issue
Block a user