6.0 KiB
Shot Task Creation Endpoint
Overview
Added a new backend endpoint to create tasks for shots, enabling AJAX-based task status editing in the frontend shot table.
Endpoint Details
POST /shots/{shot_id}/tasks
Purpose: Create a new task for a specific shot
Location: backend/routers/shots.py (after get_shot endpoint)
Authentication: Requires coordinator or admin role
Parameters:
shot_id(path): The ID of the shottask_type(query): The type of task to create (e.g., "layout", "animation")
Request Example:
POST /shots/1/tasks?task_type=layout
Authorization: Bearer {token}
Response (201 Created):
{
"task_type": "layout",
"status": "not_started",
"task_id": 123,
"assigned_user_id": null
}
Response (200 OK - if task already exists):
{
"task_type": "layout",
"status": "in_progress",
"task_id": 123,
"assigned_user_id": 5
}
Implementation
@router.post("/{shot_id}/tasks", response_model=TaskStatusInfo, status_code=status.HTTP_201_CREATED)
async def create_shot_task(
shot_id: int,
task_type: str,
db: Session = Depends(get_db),
current_user: User = Depends(require_coordinator_or_admin)
):
"""Create a new task for a shot"""
shot = db.query(Shot).filter(Shot.id == shot_id).first()
if not shot:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Shot not found"
)
# Check episode access
episode = check_episode_access(shot.episode_id, current_user, db)
# Check if task already exists
existing_task = db.query(Task).filter(
Task.shot_id == shot_id,
Task.task_type == task_type
).first()
if existing_task:
# Return existing task info instead of error (idempotent)
return TaskStatusInfo(
task_type=existing_task.task_type,
status=existing_task.status,
task_id=existing_task.id,
assigned_user_id=existing_task.assigned_user_id
)
# Create the task
task_name = f"{shot.name} - {task_type.title()}"
db_task = Task(
project_id=episode.project_id,
shot_id=shot.id,
task_type=task_type,
name=task_name,
description=f"{task_type.title()} task for {shot.name}",
status=TaskStatus.NOT_STARTED
)
db.add(db_task)
db.commit()
db.refresh(db_task)
return TaskStatusInfo(
task_type=db_task.task_type,
status=db_task.status,
task_id=db_task.id,
assigned_user_id=db_task.assigned_user_id
)
Key Features
1. Idempotent Operation
- If task already exists, returns existing task info
- No error thrown for duplicate creation attempts
- Simplifies frontend logic (no need to check existence first)
2. Permission Validation
- Requires coordinator or admin role
- Uses
require_coordinator_or_admindependency - Artists cannot create tasks directly
3. Access Control
- Validates shot exists
- Checks episode access via
check_episode_access - Ensures user has permission to access the project
4. Automatic Task Naming
- Format:
{shot_name} - {task_type} - Example: "SH010 - Layout"
- Consistent with asset task naming
5. Default Values
- Status:
NOT_STARTED - Description: Auto-generated
- Project ID: Inherited from episode
- No assignee initially
Error Responses
404 Not Found
{
"detail": "Shot not found"
}
403 Forbidden
{
"detail": "Insufficient permissions"
}
Or:
{
"detail": "Access denied to this project"
}
Comparison with Asset Endpoint
The shot task creation endpoint mirrors the asset version:
| Feature | Asset Endpoint | Shot Endpoint |
|---|---|---|
| Path | /assets/{asset_id}/tasks |
/shots/{shot_id}/tasks |
| Permission | Coordinator/Admin | Coordinator/Admin |
| Idempotent | ✅ Yes | ✅ Yes |
| Access Check | check_project_access |
check_episode_access |
| Task Naming | {asset.name} - {type} |
{shot.name} - {type} |
| Project ID | From asset | From episode |
Frontend Integration
This endpoint is called by:
frontend/src/services/task.ts-createShotTask()methodfrontend/src/components/shot/EditableTaskStatus.vue- When changing status for non-existent task
Usage Flow:
- User changes task status in shot table
- Frontend checks if task exists (via
taskIdprop) - If no task exists, calls
createShotTask(shotId, taskType) - Backend creates task and returns task ID
- Frontend then calls
updateTaskStatus(taskId, newStatus) - Status is updated and table refreshes
Testing
Test file created: backend/test_shot_task_creation.py
Manual Testing:
- Navigate to project shots tab
- Switch to table view
- Click on a task status cell for a shot without that task
- Select a status
- Verify:
- Task is created
- Status is set
- No errors in console
- Table updates correctly
Related Files
backend/routers/shots.py- Endpoint implementationbackend/routers/assets.py- Reference implementation for assetsbackend/schemas/shot.py- TaskStatusInfo schemabackend/models/task.py- Task modelfrontend/src/services/task.ts- Frontend service calling this endpointfrontend/src/components/shot/EditableTaskStatus.vue- Component using this endpoint
Future Enhancements
Potential improvements:
- Bulk Task Creation: Create multiple tasks at once
- Custom Defaults: Allow project-specific default task settings
- Template Support: Use task templates for consistent setup
- Validation: Validate task_type against allowed types
- Webhooks: Trigger notifications when tasks are created
- Audit Log: Track who created which tasks and when
Conclusion
The shot task creation endpoint successfully enables AJAX-based task status editing in the shot table, providing a seamless user experience without page refreshes. The implementation follows the same pattern as the asset endpoint, ensuring consistency across the application.