docs: add media library documentation

Document the media library feature including:
- API endpoints for admin media management
- Media picker component usage in templates
- JavaScript mixin integration guide
- File storage structure and URL paths
- Product image handling (main + additional)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-08 02:50:06 +01:00
parent e0b3325e84
commit ad3306c394
2 changed files with 183 additions and 0 deletions

View File

@@ -0,0 +1,182 @@
# Media Library
The media library provides centralized management of uploaded files (images, documents) for vendors. Each vendor has their own isolated media storage.
## Overview
- **Storage Location**: `uploads/vendors/{vendor_id}/{folder}/`
- **Supported Types**: Images (JPG, PNG, GIF, WebP), Documents (PDF)
- **Max File Size**: 10MB per file
- **Automatic Thumbnails**: Generated for images (200x200px)
## API Endpoints
### Admin Media Management
Admins can manage media for any vendor:
```
GET /api/v1/admin/media/vendors/{vendor_id} # List vendor's media
POST /api/v1/admin/media/vendors/{vendor_id}/upload # Upload file
GET /api/v1/admin/media/vendors/{vendor_id}/{id} # Get media details
DELETE /api/v1/admin/media/vendors/{vendor_id}/{id} # Delete media
```
### Query Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| `skip` | int | Pagination offset (default: 0) |
| `limit` | int | Items per page (default: 100, max: 1000) |
| `media_type` | string | Filter by type: `image`, `video`, `document` |
| `folder` | string | Filter by folder: `products`, `general`, etc. |
| `search` | string | Search by filename |
### Upload Response
```json
{
"success": true,
"message": "File uploaded successfully",
"media": {
"id": 1,
"filename": "product-image.jpg",
"file_url": "/uploads/vendors/1/products/abc123.jpg",
"url": "/uploads/vendors/1/products/abc123.jpg",
"thumbnail_url": "/uploads/vendors/1/thumbnails/thumb_abc123.jpg",
"media_type": "image",
"file_size": 245760,
"width": 1200,
"height": 800
}
}
```
## Media Picker Component
A reusable Alpine.js component for selecting images from the media library.
### Usage in Templates
```jinja2
{% from 'shared/macros/modals.html' import media_picker_modal %}
{# Single image selection #}
{{ media_picker_modal(
id='media-picker-main',
show_var='showMediaPicker',
vendor_id_var='vendorId',
title='Select Image'
) }}
{# Multiple image selection #}
{{ media_picker_modal(
id='media-picker-additional',
show_var='showMediaPickerAdditional',
vendor_id_var='vendorId',
multi_select=true,
title='Select Additional Images'
) }}
```
### JavaScript Integration
Include the media picker mixin in your Alpine.js component:
```javascript
function myComponent() {
return {
...data(),
// Include media picker functionality
...mediaPickerMixin(() => this.vendorId, false),
vendorId: null,
// Override to handle selected image
setMainImage(media) {
this.form.image_url = media.url;
},
// Override for multiple images
addAdditionalImages(mediaList) {
const urls = mediaList.map(m => m.url);
this.form.additional_images.push(...urls);
}
};
}
```
### Media Picker Mixin API
| Property/Method | Description |
|-----------------|-------------|
| `showMediaPicker` | Boolean to show/hide main image picker modal |
| `showMediaPickerAdditional` | Boolean to show/hide additional images picker |
| `mediaPickerState` | Object containing loading, media array, selected items |
| `openMediaPickerMain()` | Open picker for main image |
| `openMediaPickerAdditional()` | Open picker for additional images |
| `loadMediaLibrary()` | Fetch media from API |
| `uploadMediaFile(event)` | Handle file upload |
| `toggleMediaSelection(media)` | Select/deselect a media item |
| `confirmMediaSelection()` | Confirm selection and call callbacks |
| `setMainImage(media)` | Override to handle main image selection |
| `addAdditionalImages(mediaList)` | Override to handle multiple selections |
## File Storage
### Directory Structure
```
uploads/
└── vendors/
└── {vendor_id}/
├── products/ # Product images
├── general/ # General uploads
└── thumbnails/ # Auto-generated thumbnails
```
### URL Paths
Files are served from `/uploads/` path:
- Full image: `/uploads/vendors/1/products/image.jpg`
- Thumbnail: `/uploads/vendors/1/thumbnails/thumb_image.jpg`
## Database Model
```python
class MediaFile(Base):
id: int
vendor_id: int
filename: str # Stored filename (UUID-based)
original_filename: str # Original upload name
file_path: str # Relative path from uploads/
thumbnail_path: str # Thumbnail relative path
media_type: str # image, video, document
mime_type: str # image/jpeg, etc.
file_size: int # Bytes
width: int # Image width
height: int # Image height
folder: str # products, general, etc.
```
## Product Images
Products support both a main image and additional images:
```python
class Product(Base):
primary_image_url: str # Main product image
additional_images: list[str] # Array of additional image URLs
```
### In Product Forms
The product create/edit forms include:
1. **Main Image**: Single image with preview and media picker
2. **Additional Images**: Grid of images with add/remove functionality
Both support:
- Browsing the vendor's media library
- Uploading new images directly
- Entering external URLs manually