docs: add Media Manager V2 architecture and mockup
This commit is contained in:
111
docs/MEDIA_MANAGER_DESIGN.md
Normal file
111
docs/MEDIA_MANAGER_DESIGN.md
Normal file
@ -0,0 +1,111 @@
|
||||
# Media Manager V2 Design & Architecture
|
||||
|
||||
## Overview
|
||||
The **Media Manager V2** transforms the product image management experience from a simple upload utility to a full-featured "WYSIWYG" editor. It introduces a persistent "Draft" state, drag-and-drop reordering, and a robust generic synchronization engine that reconciles state between Google Drive (Source of Truth) and Shopify.
|
||||
|
||||
## UI UX Design
|
||||
|
||||
### Launch Logic
|
||||
To work around Google Apps Script limitations (triggers cannot open modals):
|
||||
1. **Watcher Sidebar**: A lightweight sidebar remains open, polling for selection changes.
|
||||
2. **Context Action**: When a user selects a cell in **Column A** (Product Image), the sidebar presents a large **"Edit Media"** button.
|
||||
3. **Modal**: Clicking the button launches the full Media Manager Modal.
|
||||
|
||||
### Interface Features
|
||||
- **Grid Layout**: Drag-and-drop sortable grid.
|
||||
- **Badges**:
|
||||
- ☁️ **Drive Only**: New uploads or files not yet synced.
|
||||
- 🛍️ **Shopify Only**: Media found on Shopify but missing from Drive (will be backfilled).
|
||||
- ✅ **Synced**: Verifiable link between Drive and Shopify.
|
||||
- **Video Support**:
|
||||
- Grid: Videos play silently loop (`muted autoplay`).
|
||||
- Preview: Full modal with controls.
|
||||
- **Details Mode**: A togglable text view listing pending operations (e.g., "Deleting 2 files, Reordering 3...").
|
||||
|
||||

|
||||
|
||||
## Data Architecture
|
||||
|
||||
### 1. Naming Convention
|
||||
Files in Drive function as the source of truth for order.
|
||||
- **Pattern**: `[SKU]_[Index].[Extension]`
|
||||
- **Example**: `TSHIRT-001_0001.jpg`, `TSHIRT-001_0002.mp4`
|
||||
- **Padding**: 4 digits to support >10 items cleanly.
|
||||
|
||||
### 2. Session Recovery (Draft State)
|
||||
To prevent data loss during browser refreshes or crashes, the edit state is persisted immediately to `UserProperties`.
|
||||
|
||||
- **Storage**: `PropertiesService.getUserProperties()`
|
||||
- **Key**: `MEDIA_SESSION_[SKU]`
|
||||
- **Schema**:
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"timestamp": 1234567890,
|
||||
"sku": "SKU-123",
|
||||
"items": [
|
||||
{
|
||||
"id": "drive_file_id_or_shopify_id",
|
||||
"source": "drive|shopify|new",
|
||||
"filename": "original_name.jpg",
|
||||
"status": "active|deleted|staged",
|
||||
"thumbnail": "data:image..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Synchronization Logic (Two-Way Reconcile)
|
||||
|
||||
#### Phase A: Load & Match (Read-Only)
|
||||
Executed when opening the manager.
|
||||
1. **Fetch**: Get all Drive Files in SKU folder and all Shopify Media via GraphQL.
|
||||
2. **Match**:
|
||||
- **Strong Verification**: `Drive.appProperties.shopify_media_id === Shopify.media.id`
|
||||
- **Legacy Fallback**: `Drive.name === Shopify.filename` (Only if no ID match)
|
||||
3. **Conflict Resolution**: If duplicates found, prefer high-res/latest.
|
||||
|
||||
#### Phase B: Save (Transactional)
|
||||
Executed when user clicks "Save".
|
||||
1. **Delete**: Process items marked `deleted` (Remove from Shopify & Trash in Drive).
|
||||
2. **Backfill**: Download "Shopify Only" items to Drive -> Set `appProperties`.
|
||||
3. **Upload**: Upload "Drive Only" items -> Create Media -> Set `appProperties`.
|
||||
4. **Reorder**: Execute `productReorderMedia` GraphQL mutation with final ID list.
|
||||
5. **Finalize**:
|
||||
- Rename all Drive files to `SKU_{index}` sequence.
|
||||
- Clear `MEDIA_SESSION_[SKU]` property.
|
||||
|
||||
## Technical Components
|
||||
|
||||
### Frontend
|
||||
- **HTML/CSS**: Glassmorphism aesthetic (Inter font, backdrop-filter).
|
||||
- **JS**: Vanilla JS with HTML5 Drag & Drop API.
|
||||
|
||||
### Backend Services
|
||||
- **`MediaService`**: Orchestrates the Phase A/B logic.
|
||||
- **`ShopifyMediaService`**: Handles GraphQL mutations (`productCreateMedia`, `productReorderMedia`).
|
||||
- **`GASDriveService`**: Manages File renaming and `appProperties` metadata.
|
||||
|
||||
## Future Proofing
|
||||
- **Metadata**: We avoid relying on file hashes/sizes due to Shopify's aggressive image compression. We rely strictly on stored IDs (`appProperties`) where possible.
|
||||
- **Scale**: Pagination may be needed if SKUs usually exceed 50 images (current limit 250 in GraphQL).
|
||||
|
||||
## Development Roadmap
|
||||
- [ ] **Backend Implementation**
|
||||
- [ ] Update `getMediaForSku` to return combined state (Drive + Shopify + Session)
|
||||
- [ ] Implement `saveMediaChanges(sku, changes)` transaction logic
|
||||
- [ ] Renaming files (`SKU_####.ext`)
|
||||
- [ ] Deleting/Trashing files
|
||||
- [ ] Uploading/Backfilling
|
||||
- [ ] Implement Session Recovery (Read/Write `UserProperties`)
|
||||
- [ ] **Frontend Implementation**
|
||||
- [ ] **Watcher Sidebar**: Create `MediaSidebar.html` to poll for selection.
|
||||
- [ ] **Manager Modal**: Refactor `MediaManager.html`.
|
||||
- [ ] State Management (Staging)
|
||||
- [ ] Drag-and-Drop Grid
|
||||
- [ ] Preview Modal (Image + Video)
|
||||
- [ ] "Details..." View
|
||||
- [ ] **Verification**
|
||||
- [ ] Manual Test: Drag & Drop ordering
|
||||
- [ ] Manual Test: Save & Sync
|
||||
- [ ] Manual Test: Session Recovery (Reload browser mid-edit)
|
||||
BIN
docs/images/media_manager_mockup.png
Normal file
BIN
docs/images/media_manager_mockup.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 536 KiB |
Reference in New Issue
Block a user