# Bulk Status Update with Custom Status Support
## Overview
This document describes the implementation of custom task status support in the bulk status update feature. The TaskBulkActionsMenu component has been enhanced to fetch and display both system and custom statuses, with proper validation to ensure all selected tasks belong to the same project.
## Requirements
- **10.1**: Modify `TaskBulkActionsMenu.vue` component
- **10.2**: Fetch custom statuses for current project
- **10.3**: Include custom statuses in bulk update dropdown
- **10.4**: Validate all selected tasks are from same project
- **10.5**: Show color indicators in dropdown
## Implementation Details
### 1. Component Props Enhancement
**File**: `frontend/src/components/task/TaskBulkActionsMenu.vue`
Added `selectedTasks` prop to receive task data for validation:
```typescript
interface Props {
open: boolean
position: { x: number; y: number }
selectedCount: number
selectedTasks: Task[] // NEW: For project validation
projectMembers: ProjectMember[]
isProcessing?: boolean
}
```
### 2. Custom Status Fetching
Implemented status fetching logic that:
- Fetches both system and custom statuses from the API
- Triggers when the menu opens
- Refetches when the project changes
- Handles loading and error states
```typescript
const fetchStatuses = async () => {
if (!currentProjectId.value || hasMultipleProjects.value) {
systemStatuses.value = []
customStatuses.value = []
return
}
try {
isLoadingStatuses.value = true
const response = await customTaskStatusService.getAllStatuses(currentProjectId.value)
systemStatuses.value = response.system_statuses
customStatuses.value = response.statuses
} catch (error) {
console.error('Failed to fetch task statuses:', error)
systemStatuses.value = []
customStatuses.value = []
} finally {
isLoadingStatuses.value = false
}
}
```
### 3. Multi-Project Validation
Implemented validation to ensure all selected tasks belong to the same project:
```typescript
const hasMultipleProjects = computed(() => {
if (props.selectedTasks.length === 0) return false
const projectIds = new Set(props.selectedTasks.map(task => task.project_id))
return projectIds.size > 1
})
const currentProjectId = computed(() => {
if (props.selectedTasks.length === 0) return null
return props.selectedTasks[0].project_id
})
```
When multiple projects are detected:
- A warning message is displayed: "Selected tasks are from different projects"
- The "Set Status" button is disabled
- The "Assign To" buttons are disabled
### 4. Status Display with Color Indicators
The dropdown now displays statuses with:
- Section labels ("System Statuses" and "Custom Statuses")
- Color indicator dots for each status
- Proper separation between system and custom statuses
```vue
System Statuses
{{ status.name }}
Custom Statuses
{{ status.name }}
```
### 5. Service Layer Updates
**File**: `frontend/src/services/task.ts`
Updated the bulk status update service to accept string status IDs instead of enum values:
```typescript
// Before
async bulkUpdateStatus(taskIds: number[], status: TaskStatus): Promise
// After
async bulkUpdateStatus(taskIds: number[], status: string): Promise
```
This change allows the service to handle both system status IDs (e.g., "not_started") and custom status IDs (e.g., "custom_status_123").
### 6. Parent Component Integration
**File**: `frontend/src/components/task/TaskBrowser.vue`
Updated to pass the `selectedTasks` prop:
```vue
:project-members="projectMembers"
@status-selected="handleBulkStatusUpdate"
@assignee-selected="handleBulkAssignment"
/>
```
Updated the status update handler to accept string:
```typescript
const handleBulkStatusUpdate = async (status: string) => {
// ... implementation
}
```
## User Experience
### Normal Flow (Single Project)
1. User selects multiple tasks from the same project
2. User right-clicks to open context menu
3. User clicks "Set Status" to open submenu
4. Statuses load (brief loading indicator)
5. System statuses appear first with label
6. Custom statuses appear below with label
7. Each status shows a colored dot indicator
8. User clicks a status
9. All selected tasks are updated
10. Success toast shows count of updated tasks
### Multi-Project Detection
1. User selects tasks from different projects
2. User right-clicks to open context menu
3. Warning message appears: "Selected tasks are from different projects"
4. "Set Status" button is disabled
5. "Assign To" buttons are disabled
6. User must adjust selection to single project
## Testing
### Manual Testing Steps
1. **Setup**:
- Create a project with custom task statuses
- Create multiple tasks in the project
- Navigate to the Tasks view
2. **Test Single Project Selection**:
- Select multiple tasks from the same project
- Right-click to open context menu
- Click "Set Status" submenu
- Verify system statuses appear with label
- Verify custom statuses appear with label
- Verify color indicators are displayed
- Click a custom status
- Verify tasks are updated successfully
3. **Test Multi-Project Validation**:
- Select tasks from different projects
- Right-click to open context menu
- Verify warning message appears
- Verify "Set Status" is disabled
- Verify "Assign To" is disabled
4. **Test Status Loading**:
- Select tasks and open context menu
- Verify loading indicator appears briefly
- Verify statuses load correctly
5. **Test Color Indicators**:
- Verify each status has a colored dot
- Verify colors match configured status colors
## Files Modified
1. `frontend/src/components/task/TaskBulkActionsMenu.vue`
- Added selectedTasks prop
- Implemented status fetching logic
- Added multi-project validation
- Updated UI to show color indicators
- Added loading and error states
2. `frontend/src/components/task/TaskBrowser.vue`
- Pass selectedTasks to TaskBulkActionsMenu
- Updated handleBulkStatusUpdate to accept string
3. `frontend/src/services/task.ts`
- Updated bulkUpdateStatus signature to accept string
- Updated BulkStatusUpdateRequest interface
## API Integration
The component uses the `customTaskStatusService.getAllStatuses()` method which returns:
```typescript
interface AllTaskStatusesResponse {
statuses: CustomTaskStatus[] // Custom statuses
system_statuses: SystemTaskStatus[] // System statuses
default_status_id: string
}
interface CustomTaskStatus {
id: string
name: string
color: string
order: number
is_default: boolean
}
interface SystemTaskStatus {
id: string
name: string
color: string
is_system: boolean
}
```
## Benefits
1. **Flexibility**: Users can now use custom statuses in bulk operations
2. **Consistency**: Same status options available in bulk and individual updates
3. **Safety**: Multi-project validation prevents accidental cross-project updates
4. **Usability**: Color indicators help users quickly identify statuses
5. **Organization**: Clear separation between system and custom statuses
## Future Enhancements
Potential improvements for future iterations:
1. Add status search/filter for projects with many custom statuses
2. Show status usage count in dropdown
3. Add keyboard shortcuts for common status changes
4. Support status presets for common bulk operations
5. Add undo functionality for bulk status changes
## Related Documentation
- [Custom Task Status Manager Implementation](./custom-task-status-manager-implementation.md)
- [Custom Task Status Service Implementation](./custom-task-status-service-implementation.md)
- [Bulk Actions Implementation](../../backend/docs/bulk-actions-implementation.md)