6.0 KiB
Project Thumbnail Implementation
Overview
This document describes the implementation of project thumbnail upload functionality for the VFX Project Management System.
Requirements
Based on Requirement 2.1, the system allows coordinators and administrators to:
- Upload thumbnail images for projects
- Replace existing thumbnails
- Delete thumbnails
- View thumbnails on project cards
Implementation Details
1. Database Changes
Migration Script: backend/migrate_project_thumbnail.py
Added thumbnail_path column to the projects table:
ALTER TABLE projects ADD COLUMN thumbnail_path VARCHAR
Model Update: backend/models/project.py
thumbnail_path = Column(String, nullable=True) # Path to project thumbnail image
2. API Endpoints
Upload Thumbnail
Endpoint: POST /api/projects/{project_id}/thumbnail
Access: Coordinators and Admins only
Request: Multipart form data with image file
Response:
{
"message": "Thumbnail uploaded successfully",
"thumbnail_url": "/api/files/projects/{project_id}/thumbnail"
}
Features:
- Validates file format (jpg, jpeg, png, gif, webp)
- Validates file size (max 10MB)
- Processes and resizes images to max 800x600 while maintaining aspect ratio
- Converts images with transparency to RGB with white background
- Generates unique filenames with timestamp and hash
- Automatically deletes old thumbnail when uploading new one
- Stores processed images in
uploads/project_thumbnails/
Delete Thumbnail
Endpoint: DELETE /api/projects/{project_id}/thumbnail
Access: Coordinators and Admins only
Response: 204 No Content
Features:
- Removes thumbnail file from filesystem
- Clears
thumbnail_pathin database - Returns 404 if project has no thumbnail
Serve Thumbnail
Endpoint: GET /api/files/projects/{project_id}/thumbnail
Access: All authenticated users (with project access)
Response: Image file with appropriate content-type
Features:
- Checks user has access to the project
- Artists can only access thumbnails for projects they're members of
- Returns 404 if thumbnail doesn't exist
- Serves image with proper MIME type
3. Schema Updates
File: backend/schemas/project.py
Added thumbnail_url field to response schemas:
class ProjectResponse(ProjectBase):
# ... existing fields ...
thumbnail_url: Optional[str] = None
class ProjectListResponse(BaseModel):
# ... existing fields ...
thumbnail_url: Optional[str] = None
4. Router Updates
File: backend/routers/projects.py
Updated project endpoints to include thumbnail URL:
# In list_projects
if project.thumbnail_path:
project_data.thumbnail_url = f"/api/files/projects/{project.id}/thumbnail"
# In get_project
if project.thumbnail_path:
project_data.thumbnail_url = f"/api/files/projects/{project.id}/thumbnail"
# In update_project
'thumbnail_url': f"/api/files/projects/{db_project.id}/thumbnail" if db_project.thumbnail_path else None
File Storage Structure
backend/
└── uploads/
└── project_thumbnails/
├── project_1_20241119_123456_a1b2c3d4.jpg
├── project_2_20241119_123457_e5f6g7h8.jpg
└── ...
Image Processing
The system processes uploaded thumbnails as follows:
- Format Validation: Only accepts jpg, jpeg, png, gif, webp
- Size Validation: Maximum 10MB file size
- Color Conversion: Converts RGBA/LA/P modes to RGB with white background
- Resizing: Maintains aspect ratio while fitting within 800x600 pixels
- Optimization: Saves as JPEG with 90% quality and optimization enabled
Access Control
| Role | Upload | Delete | View |
|---|---|---|---|
| Admin | ✓ | ✓ | ✓ |
| Coordinator | ✓ | ✓ | ✓ |
| Director | ✗ | ✗ | ✓ |
| Artist | ✗ | ✗ | ✓ (own projects only) |
| Developer | ✗ | ✗ | ✓ |
Testing
A test script is provided at backend/test_project_thumbnail.py that verifies:
- Thumbnail upload
- Thumbnail URL in project responses
- Thumbnail download
- Thumbnail deletion
- Thumbnail removal verification
To run the test:
cd backend
python test_project_thumbnail.py
Note: The backend server must be running on http://localhost:8000
Error Handling
| Error | Status Code | Description |
|---|---|---|
| Invalid file format | 400 | File extension not in allowed list |
| File too large | 413 | File exceeds 10MB limit |
| Image processing failed | 400 | PIL failed to process image |
| Project not found | 404 | Invalid project_id |
| No thumbnail | 404 | Project has no thumbnail |
| Access denied | 403 | User lacks permission |
Frontend Integration
The frontend can now:
- Display thumbnails on project cards using
project.thumbnail_url - Upload thumbnails in project settings
- Replace existing thumbnails
- Remove thumbnails
- Show placeholder when no thumbnail exists
Example usage:
// Display thumbnail
<img :src="project.thumbnail_url || '/default-project-thumbnail.png'" />
// Upload thumbnail
const formData = new FormData()
formData.append('file', file)
await apiClient.post(`/projects/${projectId}/thumbnail`, formData)
// Delete thumbnail
await apiClient.delete(`/projects/${projectId}/thumbnail`)
Next Steps
The following frontend tasks remain to be implemented:
- Task 22: Implement frontend project thumbnail upload component
- Task 22.1: Add thumbnail preview and management
- Task 22.2: Integrate thumbnail upload in project settings
- Task 22.3: Update project card to display thumbnails
- Task 22.4: Update project type definitions
Related Files
backend/models/project.py- Project model with thumbnail_pathbackend/routers/projects.py- Thumbnail upload/delete endpointsbackend/routers/files.py- Thumbnail serving endpointbackend/schemas/project.py- Response schemas with thumbnail_urlbackend/migrate_project_thumbnail.py- Database migration scriptbackend/test_project_thumbnail.py- Test script