LinkDesk/backend/docs/project-thumbnail-implement...

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_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:

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:

  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:

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:

// 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
  • 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