feat: complete multi-platform CMS phases 2-5

Phase 2 - OMS Migration & Integration:
- Fix platform_pages.py to use get_platform_page for marketing pages
- Fix shop_pages.py to pass platform_id to content page service calls

Phase 3 - Admin Interface:
- Add platform management API (app/api/v1/admin/platforms.py)
- Add platforms admin page with stats cards
- Add Platforms menu item to admin sidebar
- Update content pages admin with platform filter and four-tab tier system

Phase 4 - Documentation:
- Add comprehensive architecture docs (docs/architecture/multi-platform-cms.md)
- Update implementation plan with completion status

Phase 5 - Vendor Dashboard:
- Add CMS usage API endpoint with tier limits
- Add usage progress bar to vendor content pages
- Add platform-default/{slug} API for preview
- Add View Default button and modal in page editor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-19 16:30:31 +01:00
parent fe49008fef
commit 968002630e
19 changed files with 1424 additions and 99 deletions

View File

@@ -35,6 +35,11 @@ function vendorContentPageEditor(pageId) {
error: null,
successMessage: null,
// Default preview modal state
showingDefaultPreview: false,
loadingDefault: false,
defaultContent: null,
// Initialize
async init() {
// Prevent multiple initializations
@@ -179,6 +184,31 @@ function vendorContentPageEditor(pageId) {
}
},
// Show default content preview
async showDefaultPreview() {
this.showingDefaultPreview = true;
this.loadingDefault = true;
this.defaultContent = null;
try {
contentPageEditLog.info('Loading platform default for slug:', this.form.slug);
const response = await apiClient.get(`/vendor/content-pages/platform-default/${this.form.slug}`);
this.defaultContent = response.data || response;
contentPageEditLog.info('Default content loaded');
} catch (err) {
contentPageEditLog.error('Error loading default content:', err);
this.defaultContent = {
title: 'Error',
content: `<p class="text-red-500">Failed to load platform default: ${err.message}</p>`
};
} finally {
this.loadingDefault = false;
}
},
// Delete page (revert to default for overrides)
async deletePage() {
const message = this.isOverride

View File

@@ -24,6 +24,7 @@ function vendorContentPagesManager() {
platformPages: [], // Platform default pages
customPages: [], // Vendor's own pages (overrides + custom)
overrideMap: {}, // Map of slug -> page id for quick lookup
cmsUsage: null, // CMS usage statistics
// Initialize
async init() {
@@ -43,7 +44,10 @@ function vendorContentPagesManager() {
await parentInit.call(this);
}
await this.loadPages();
await Promise.all([
this.loadPages(),
this.loadCmsUsage()
]);
contentPagesLog.info('=== VENDOR CONTENT PAGES MANAGER INITIALIZATION COMPLETE ===');
} catch (error) {
@@ -92,6 +96,19 @@ function vendorContentPagesManager() {
}
},
// Load CMS usage statistics
async loadCmsUsage() {
try {
contentPagesLog.info('Loading CMS usage...');
const response = await apiClient.get('/vendor/content-pages/usage');
this.cmsUsage = response.data || response;
contentPagesLog.info('CMS usage loaded:', this.cmsUsage);
} catch (err) {
contentPagesLog.error('Error loading CMS usage:', err);
// Non-critical - don't set error state
}
},
// Check if vendor has overridden a platform page
hasOverride(slug) {
return slug in this.overrideMap;