171 lines
5.4 KiB
Markdown
171 lines
5.4 KiB
Markdown
# Bulk Assignment Implementation
|
|
|
|
## Overview
|
|
Implemented bulk assignment functionality for the TaskBrowser component, allowing users to assign multiple selected tasks to a user through the context menu.
|
|
|
|
## Implementation Details
|
|
|
|
### Frontend Changes
|
|
|
|
#### TaskBrowser.vue
|
|
Added `handleBulkAssignment` method that:
|
|
1. Extracts selected task IDs from the selection state
|
|
2. Calls `taskService.bulkAssignTasks` with task IDs and user ID
|
|
3. Shows loading state during the operation
|
|
4. Displays success toast with count of assigned tasks
|
|
5. Handles errors and displays error toast
|
|
6. Refreshes task list after successful update
|
|
7. Closes context menu and clears selection after completion
|
|
|
|
```typescript
|
|
const handleBulkAssignment = async (userId: number) => {
|
|
try {
|
|
const taskIds = selectedTasks.value.map(task => task.id)
|
|
|
|
if (taskIds.length === 0) {
|
|
return
|
|
}
|
|
|
|
isLoading.value = true
|
|
const result = await taskService.bulkAssignTasks(taskIds, userId)
|
|
|
|
toast({
|
|
title: 'Success',
|
|
description: `${result.success_count} ${result.success_count === 1 ? 'task' : 'tasks'} assigned`,
|
|
})
|
|
|
|
await fetchTasks()
|
|
closeContextMenu()
|
|
rowSelection.value = {}
|
|
} catch (error) {
|
|
console.error('Failed to assign tasks:', error)
|
|
toast({
|
|
title: 'Error',
|
|
description: 'Failed to assign tasks. Please try again.',
|
|
variant: 'destructive',
|
|
})
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
```
|
|
|
|
Connected the method to the TaskBulkActionsMenu component:
|
|
```vue
|
|
<TaskBulkActionsMenu
|
|
v-model:open="showContextMenu"
|
|
:position="contextMenuPosition"
|
|
:selected-count="selectedCount"
|
|
:project-members="projectMembers"
|
|
@status-selected="handleBulkStatusUpdate"
|
|
@assignee-selected="handleBulkAssignment"
|
|
/>
|
|
```
|
|
|
|
### Backend
|
|
The backend endpoint was already implemented in task 1:
|
|
- Endpoint: `PUT /tasks/bulk/assign`
|
|
- Handles atomic assignment (all or nothing)
|
|
- Validates user exists and is a project member
|
|
- Returns success/failure counts
|
|
|
|
### Service Layer
|
|
The `bulkAssignTasks` method was already implemented in `frontend/src/services/task.ts`:
|
|
```typescript
|
|
async bulkAssignTasks(taskIds: number[], assignedUserId: number): Promise<BulkActionResult> {
|
|
const response = await apiClient.put('/tasks/bulk/assign', {
|
|
task_ids: taskIds,
|
|
assigned_user_id: assignedUserId
|
|
})
|
|
return response.data
|
|
}
|
|
```
|
|
|
|
## Requirements Validated
|
|
|
|
### Requirement 5.3
|
|
✅ When a user selects an assignee from the submenu, the system updates all selected tasks to be assigned to that user
|
|
|
|
### Requirement 5.4
|
|
✅ When the bulk assignment completes successfully, the system displays a success notification indicating the number of tasks assigned
|
|
|
|
### Requirement 5.5
|
|
✅ When the bulk assignment fails, the system displays an error notification and maintains the original assignments (backend handles atomicity)
|
|
|
|
### Requirement 5.6
|
|
✅ When the assignment update completes, the system refreshes the task list to reflect the changes
|
|
|
|
### Requirement 6.1
|
|
✅ When a user completes a bulk action from the context menu, the system closes the context menu automatically
|
|
|
|
### Requirement 6.3
|
|
✅ When a bulk action completes, the system clears the task selections
|
|
|
|
## User Flow
|
|
|
|
1. User selects multiple tasks using checkboxes
|
|
2. User right-clicks on a selected task
|
|
3. Context menu appears with "Assign To" option
|
|
4. User hovers over "Assign To" to see submenu with project members
|
|
5. User clicks on a project member
|
|
6. System shows loading state
|
|
7. System calls backend API to assign all selected tasks
|
|
8. On success:
|
|
- Success toast appears showing count of assigned tasks
|
|
- Task list refreshes to show updated assignments
|
|
- Context menu closes
|
|
- Selection is cleared
|
|
9. On error:
|
|
- Error toast appears with user-friendly message
|
|
- Original assignments are maintained (backend atomicity)
|
|
- Context menu remains open for retry
|
|
|
|
## Error Handling
|
|
|
|
The implementation includes comprehensive error handling:
|
|
- Try-catch block wraps the entire operation
|
|
- Loading state is properly managed in finally block
|
|
- Error toast displays user-friendly message
|
|
- Console logs detailed error for debugging
|
|
- Backend ensures atomicity (all tasks assigned or none)
|
|
- Backend validates user exists and is a project member
|
|
|
|
## Testing
|
|
|
|
Manual testing steps:
|
|
1. Open TaskBrowser in the application
|
|
2. Select multiple tasks using checkboxes
|
|
3. Right-click on a selected task
|
|
4. Click "Assign To" in the context menu
|
|
5. Select a user from the submenu
|
|
6. Verify success toast appears
|
|
7. Verify task list refreshes
|
|
8. Verify context menu closes
|
|
9. Verify selection is cleared
|
|
10. Verify tasks show the assigned user
|
|
|
|
See `frontend/test-bulk-assignment.html` for detailed test documentation.
|
|
|
|
## Files Modified
|
|
|
|
- `frontend/src/components/task/TaskBrowser.vue` - Added handleBulkAssignment method and connected to context menu
|
|
|
|
## Files Created
|
|
|
|
- `frontend/test-bulk-assignment.html` - Test documentation
|
|
- `frontend/docs/bulk-assignment-implementation.md` - This file
|
|
|
|
## Related Tasks
|
|
|
|
- Task 1: Set up backend bulk action endpoints (completed)
|
|
- Task 2: Update task service with bulk action methods (completed)
|
|
- Task 7: Create TaskBulkActionsMenu component (completed)
|
|
- Task 8: Implement context menu trigger in TaskBrowser (completed)
|
|
- Task 9: Implement bulk status update action (completed)
|
|
- Task 10: Implement bulk assignment action (completed) ✅
|
|
|
|
## Next Steps
|
|
|
|
The next task in the implementation plan is:
|
|
- Task 11: Implement keyboard shortcuts for selection operations
|