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