Init Repo
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user