209 lines
6.0 KiB
Markdown
209 lines
6.0 KiB
Markdown
# 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:
|
|
```sql
|
|
ALTER TABLE projects ADD COLUMN thumbnail_path VARCHAR
|
|
```
|
|
|
|
**Model Update**: `backend/models/project.py`
|
|
```python
|
|
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**:
|
|
```json
|
|
{
|
|
"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_path` in 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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
# 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:
|
|
|
|
1. **Format Validation**: Only accepts jpg, jpeg, png, gif, webp
|
|
2. **Size Validation**: Maximum 10MB file size
|
|
3. **Color Conversion**: Converts RGBA/LA/P modes to RGB with white background
|
|
4. **Resizing**: Maintains aspect ratio while fitting within 800x600 pixels
|
|
5. **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:
|
|
1. Thumbnail upload
|
|
2. Thumbnail URL in project responses
|
|
3. Thumbnail download
|
|
4. Thumbnail deletion
|
|
5. Thumbnail removal verification
|
|
|
|
To run the test:
|
|
```bash
|
|
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:
|
|
1. Display thumbnails on project cards using `project.thumbnail_url`
|
|
2. Upload thumbnails in project settings
|
|
3. Replace existing thumbnails
|
|
4. Remove thumbnails
|
|
5. Show placeholder when no thumbnail exists
|
|
|
|
Example usage:
|
|
```typescript
|
|
// 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_path
|
|
- `backend/routers/projects.py` - Thumbnail upload/delete endpoints
|
|
- `backend/routers/files.py` - Thumbnail serving endpoint
|
|
- `backend/schemas/project.py` - Response schemas with thumbnail_url
|
|
- `backend/migrate_project_thumbnail.py` - Database migration script
|
|
- `backend/test_project_thumbnail.py` - Test script
|