4.5 KiB
Custom Task Type Delete Fix
Problem
When attempting to delete a custom task type (asset or shot) from the frontend, a "Method Not Allowed" (405) error was returned.
Root Cause
The issue had three parts:
-
Missing Query Parameter Declaration (Backend): The
categoryparameter in the delete endpoint wasn't explicitly declared as a query parameter using FastAPI'sQuery()annotation. -
Incorrect Response Format (Backend): All three custom task type endpoints (add, update, delete) were returning simple dictionaries instead of the
AllTaskTypesResponseformat that the frontend expected. -
Dialog Event Handler Bug (Frontend): The
@update:open="closeDeleteDialog"handler was clearingtaskTypeToDeletewhen the dialog state changed for ANY reason, including when clicking the Delete button. This meant the task type value was cleared BEFORE the delete API call could use it, resulting in an empty URL path.
Solution
Backend Changes (backend/routers/projects.py)
-
Added Query import:
from fastapi import APIRouter, Depends, HTTPException, status, Query -
Created helper function to build consistent responses:
def _build_all_task_types_response(db_project: Project): """Helper function to build AllTaskTypesResponse""" from schemas.custom_task_type import AllTaskTypesResponse custom_asset_types = db_project.custom_asset_task_types or [] custom_shot_types = db_project.custom_shot_task_types or [] all_asset_types = STANDARD_ASSET_TASK_TYPES + custom_asset_types all_shot_types = STANDARD_SHOT_TASK_TYPES + custom_shot_types return AllTaskTypesResponse( asset_task_types=all_asset_types, shot_task_types=all_shot_types, standard_asset_types=STANDARD_ASSET_TASK_TYPES, standard_shot_types=STANDARD_SHOT_TASK_TYPES, custom_asset_types=custom_asset_types, custom_shot_types=custom_shot_types ) -
Updated delete endpoint signature:
@router.delete("/{project_id}/custom-task-types/{task_type}") async def delete_custom_task_type( project_id: int, task_type: str, category: str = Query(..., description="Category: 'asset' or 'shot'"), # ← Explicit query param db: Session = Depends(get_db), current_user: User = Depends(require_coordinator_or_admin) ): -
Updated all three endpoints to return
AllTaskTypesResponse:add_custom_task_type()- now returns_build_all_task_types_response(db_project)update_custom_task_type()- now returns_build_all_task_types_response(db_project)delete_custom_task_type()- now returns_build_all_task_types_response(db_project)
Frontend (No Changes Required)
The frontend service (frontend/src/services/customTaskType.ts) was already correctly sending the category as a query parameter:
async deleteCustomTaskType(projectId: number, taskType: string, category: 'asset' | 'shot'): Promise<AllTaskTypesResponse> {
const encodedTaskType = encodeURIComponent(taskType)
const response = await apiClient.delete(`/projects/${projectId}/custom-task-types/${encodedTaskType}`, {
params: { category } // ← Correctly sends as query param
})
return response.data
}
Testing
Restart Backend Server
IMPORTANT: The backend server must be restarted for changes to take effect:
cd backend
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Test Methods
-
Via Frontend UI:
- Navigate to Project Settings → Custom Task Types
- Add a custom task type
- Click the delete button
- Should now work without "Method Not Allowed" error
-
Via Test HTML Page:
- Open
frontend/test-delete-custom-task.htmlin browser - Follow the 4-step test process
- Verify delete works correctly
- Open
-
Via Python Test Script:
cd backend python test_delete_fix.py
Expected Behavior
After the fix:
- ✅ Delete button works for custom task types
- ✅ Returns updated list of all task types
- ✅ Frontend automatically refreshes the UI with updated list
- ✅ Consistent response format across all custom task type operations
Files Modified
backend/routers/projects.py- Fixed delete endpoint and response formatsbackend/test_delete_fix.py- Created test scriptfrontend/test-delete-custom-task.html- Created browser test pagefrontend/docs/custom-task-delete-fix.md- This documentation