Files
orion/app/modules/cms/docs/media-library.md
Samir Boulahtit f141cc4e6a docs: migrate module documentation to single source of truth
Move 39 documentation files from top-level docs/ into each module's
docs/ folder, accessible via symlinks from docs/modules/. Create
data-model.md files for 10 modules with full schema documentation.
Replace originals with redirect stubs. Remove empty guide stubs.

Modules migrated: tenancy, billing, loyalty, marketplace, orders,
messaging, cms, catalog, inventory, hosting, prospecting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 23:38:37 +01:00

5.2 KiB

Media Library

The media library provides centralized management of uploaded files (images, documents) for stores. Each store has their own isolated media storage.

Overview

  • Storage Location: uploads/stores/{store_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 store:

GET    /api/v1/admin/media/stores/{store_id}           # List store's media
POST   /api/v1/admin/media/stores/{store_id}/upload    # Upload file
GET    /api/v1/admin/media/stores/{store_id}/{id}      # Get media details
DELETE /api/v1/admin/media/stores/{store_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

{
  "success": true,
  "message": "File uploaded successfully",
  "media": {
    "id": 1,
    "filename": "product-image.jpg",
    "file_url": "/uploads/stores/1/products/abc123.jpg",
    "url": "/uploads/stores/1/products/abc123.jpg",
    "thumbnail_url": "/uploads/stores/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

{% from 'shared/macros/modals.html' import media_picker_modal %}

{# Single image selection #}
{{ media_picker_modal(
    id='media-picker-main',
    show_var='showMediaPicker',
    store_id_var='storeId',
    title='Select Image'
) }}

{# Multiple image selection #}
{{ media_picker_modal(
    id='media-picker-additional',
    show_var='showMediaPickerAdditional',
    store_id_var='storeId',
    multi_select=true,
    title='Select Additional Images'
) }}

JavaScript Integration

Include the media picker mixin in your Alpine.js component:

function myComponent() {
    return {
        ...data(),

        // Include media picker functionality
        ...mediaPickerMixin(() => this.storeId, false),

        storeId: 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/
└── stores/
    └── {store_id}/
        ├── products/         # Product images
        ├── general/          # General uploads
        └── thumbnails/       # Auto-generated thumbnails

URL Paths

Files are served from /uploads/ path:

  • Full image: /uploads/stores/1/products/image.jpg
  • Thumbnail: /uploads/stores/1/thumbnails/thumb_image.jpg

Database Model

class MediaFile(Base):
    id: int
    store_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:

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 store's media library
  • Uploading new images directly
  • Entering external URLs manually