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:
239
docs/architecture/multi-platform-cms.md
Normal file
239
docs/architecture/multi-platform-cms.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# Multi-Platform CMS Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
The Multi-Platform CMS enables Wizamart to serve multiple business offerings (OMS, Loyalty, Site Builder) from a single codebase, each with its own marketing site and vendor ecosystem.
|
||||
|
||||
## Three-Tier Content Hierarchy
|
||||
|
||||
Content pages follow a three-tier inheritance model:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ TIER 1: Platform Marketing │
|
||||
│ Public pages for the platform (homepage, pricing, features) │
|
||||
│ is_platform_page=TRUE, vendor_id=NULL │
|
||||
│ NOT inherited by vendors │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ TIER 2: Vendor Defaults │
|
||||
│ Default pages all vendors inherit (about, terms, privacy) │
|
||||
│ is_platform_page=FALSE, vendor_id=NULL │
|
||||
│ Inherited by ALL vendors on the platform │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ TIER 3: Vendor Overrides │
|
||||
│ Custom pages created by individual vendors │
|
||||
│ is_platform_page=FALSE, vendor_id=<vendor_id> │
|
||||
│ Overrides vendor defaults for specific vendor │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Content Resolution Flow
|
||||
|
||||
When a customer visits a vendor page (e.g., `/vendors/shopname/about`):
|
||||
|
||||
```
|
||||
Customer visits: /vendors/shopname/about
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Step 1: Check Vendor Override │
|
||||
│ SELECT * FROM content_pages │
|
||||
│ WHERE platform_id=1 AND vendor_id=123 AND slug='about' │
|
||||
│ Found? → Return vendor's custom "About" page │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│ Not found
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Step 2: Check Vendor Default │
|
||||
│ SELECT * FROM content_pages │
|
||||
│ WHERE platform_id=1 AND vendor_id IS NULL │
|
||||
│ AND is_platform_page=FALSE AND slug='about' │
|
||||
│ Found? → Return platform's default "About" template │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│ Not found
|
||||
▼
|
||||
Return 404
|
||||
```
|
||||
|
||||
## Database Schema
|
||||
|
||||
### platforms
|
||||
|
||||
```sql
|
||||
CREATE TABLE platforms (
|
||||
id SERIAL PRIMARY KEY,
|
||||
code VARCHAR(50) UNIQUE NOT NULL, -- 'oms', 'loyalty', 'sitebuilder'
|
||||
name VARCHAR(100) NOT NULL, -- 'Order Management System'
|
||||
description TEXT,
|
||||
domain VARCHAR(255), -- 'oms.wizamart.lu'
|
||||
path_prefix VARCHAR(50), -- '/oms'
|
||||
logo VARCHAR(255),
|
||||
logo_dark VARCHAR(255),
|
||||
favicon VARCHAR(255),
|
||||
theme_config JSONB DEFAULT '{}',
|
||||
default_language VARCHAR(10) DEFAULT 'fr',
|
||||
supported_languages JSONB DEFAULT '["fr", "de", "en"]',
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
is_public BOOLEAN DEFAULT TRUE,
|
||||
settings JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### vendor_platforms (Junction Table)
|
||||
|
||||
```sql
|
||||
CREATE TABLE vendor_platforms (
|
||||
vendor_id INTEGER REFERENCES vendors(id) ON DELETE CASCADE,
|
||||
platform_id INTEGER REFERENCES platforms(id) ON DELETE CASCADE,
|
||||
joined_at TIMESTAMP DEFAULT NOW(),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
settings JSONB DEFAULT '{}',
|
||||
PRIMARY KEY (vendor_id, platform_id)
|
||||
);
|
||||
```
|
||||
|
||||
### content_pages (Extended)
|
||||
|
||||
```sql
|
||||
ALTER TABLE content_pages ADD COLUMN platform_id INTEGER REFERENCES platforms(id);
|
||||
ALTER TABLE content_pages ADD COLUMN is_platform_page BOOLEAN DEFAULT FALSE;
|
||||
|
||||
-- Platform marketing pages: is_platform_page=TRUE, vendor_id=NULL
|
||||
-- Vendor defaults: is_platform_page=FALSE, vendor_id=NULL
|
||||
-- Vendor overrides: is_platform_page=FALSE, vendor_id=<id>
|
||||
```
|
||||
|
||||
## Request Flow
|
||||
|
||||
```
|
||||
Request: GET /oms/vendors/shopname/about
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ PlatformContextMiddleware │
|
||||
│ - Detects platform from path prefix (/oms) or domain │
|
||||
│ - Sets request.state.platform = Platform(code='oms') │
|
||||
│ - Sets request.state.platform_clean_path = /vendors/shopname/about │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ VendorContextMiddleware │
|
||||
│ - Uses platform_clean_path for vendor detection │
|
||||
│ - Sets request.state.vendor = Vendor(subdomain='shopname') │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Route Handler (shop_pages.py) │
|
||||
│ - Gets platform_id from request.state.platform │
|
||||
│ - Calls content_page_service.get_page_for_vendor( │
|
||||
│ platform_id=1, vendor_id=123, slug='about' │
|
||||
│ ) │
|
||||
│ - Service handles three-tier resolution │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Admin Interface
|
||||
|
||||
### Platform Management (`/admin/platforms`)
|
||||
|
||||
- Lists all platforms with statistics
|
||||
- Shows vendor count, marketing pages, vendor defaults
|
||||
- Links to platform detail and edit pages
|
||||
|
||||
### Content Pages (`/admin/content-pages`)
|
||||
|
||||
- Platform filter dropdown
|
||||
- Four-tab view:
|
||||
- **All Pages**: Complete list
|
||||
- **Platform Marketing**: Public platform pages (is_platform_page=TRUE)
|
||||
- **Vendor Defaults**: Inherited by vendors (is_platform_page=FALSE, vendor_id=NULL)
|
||||
- **Vendor Overrides**: Vendor-specific (vendor_id set)
|
||||
- Color-coded tier badges:
|
||||
- Blue: Platform Marketing
|
||||
- Teal: Vendor Default
|
||||
- Purple: Vendor Override
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Platform Management
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| GET | `/api/v1/admin/platforms` | List all platforms |
|
||||
| GET | `/api/v1/admin/platforms/{code}` | Get platform details |
|
||||
| PUT | `/api/v1/admin/platforms/{code}` | Update platform |
|
||||
| GET | `/api/v1/admin/platforms/{code}/stats` | Platform statistics |
|
||||
|
||||
### Content Pages
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| GET | `/api/v1/admin/content-pages/` | List all pages (supports `platform` filter) |
|
||||
| GET | `/api/v1/admin/content-pages/platform` | Platform default pages only |
|
||||
| POST | `/api/v1/admin/content-pages/platform` | Create platform page |
|
||||
| POST | `/api/v1/admin/content-pages/vendor` | Create vendor page |
|
||||
|
||||
## Key Files
|
||||
|
||||
### Models
|
||||
- `models/database/platform.py` - Platform model
|
||||
- `models/database/vendor_platform.py` - Junction table
|
||||
- `models/database/content_page.py` - Extended with platform_id
|
||||
|
||||
### Middleware
|
||||
- `middleware/platform_context.py` - Platform detection and context
|
||||
|
||||
### Services
|
||||
- `app/services/content_page_service.py` - Three-tier content resolution
|
||||
|
||||
### Routes
|
||||
- `app/routes/platform_pages.py` - Platform marketing pages
|
||||
- `app/routes/shop_pages.py` - Vendor shop pages with inheritance
|
||||
|
||||
### Admin
|
||||
- `app/api/v1/admin/platforms.py` - Platform management API
|
||||
- `app/templates/admin/platforms.html` - Platform admin UI
|
||||
- `static/admin/js/platforms.js` - Alpine.js component
|
||||
|
||||
## CMS Tier Limits (Subscription-Based)
|
||||
|
||||
| Tier | Total Pages | Custom Pages |
|
||||
|------|-------------|--------------|
|
||||
| Essential | 3 | 0 |
|
||||
| Professional | 10 | 5 |
|
||||
| Business | 30 | 20 |
|
||||
| Enterprise | Unlimited | Unlimited |
|
||||
|
||||
## Adding a New Platform
|
||||
|
||||
1. Insert platform record:
|
||||
```sql
|
||||
INSERT INTO platforms (code, name, description, path_prefix)
|
||||
VALUES ('loyalty', 'Loyalty Program', 'Customer loyalty and rewards', '/loyalty');
|
||||
```
|
||||
|
||||
2. Create platform-specific content pages:
|
||||
```sql
|
||||
INSERT INTO content_pages (platform_id, slug, title, content, is_platform_page)
|
||||
VALUES (2, 'home', 'Loyalty Program', '<h1>Welcome</h1>', TRUE);
|
||||
```
|
||||
|
||||
3. Configure routing (if using path prefix):
|
||||
- Platform detected by `PlatformContextMiddleware`
|
||||
- No additional route configuration needed
|
||||
|
||||
4. Assign vendors to platform:
|
||||
```sql
|
||||
INSERT INTO vendor_platforms (vendor_id, platform_id)
|
||||
VALUES (1, 2);
|
||||
```
|
||||
@@ -1,8 +1,12 @@
|
||||
# Multi-Platform CMS Architecture - Implementation Plan
|
||||
|
||||
> **Status:** Phase 1 Complete | Phases 2-6 Pending
|
||||
> **Last Updated:** 2026-01-18
|
||||
> **Commit:** `408019d` (feat: add multi-platform CMS architecture Phase 1)
|
||||
> **Status:** Phases 1-4 Complete | Phase 5 Pending
|
||||
> **Last Updated:** 2026-01-19
|
||||
> **Commits:**
|
||||
> - `408019d` (Phase 1: Database & Models)
|
||||
> - Phase 2: OMS Migration & Integration
|
||||
> - Phase 3: Admin Interface
|
||||
> - Phase 4: Vendor Dashboard
|
||||
|
||||
---
|
||||
|
||||
@@ -32,7 +36,7 @@ Transform the single-platform OMS into a multi-platform system supporting indepe
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: OMS Migration & Integration 🔄 NEXT
|
||||
## Phase 2: OMS Migration & Integration ✅ COMPLETE
|
||||
|
||||
### 2.1 Run Database Migration
|
||||
|
||||
@@ -109,42 +113,57 @@ Files to update:
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Admin Interface
|
||||
## Phase 3: Admin Interface ✅ COMPLETE
|
||||
|
||||
### 3.1 Platform Management UI
|
||||
|
||||
New routes needed:
|
||||
- [ ] `GET /admin/platforms` - List all platforms
|
||||
- [ ] `GET /admin/platforms/{code}` - Platform details
|
||||
- [ ] `GET /admin/platforms/{code}/pages` - Platform marketing pages
|
||||
- [ ] `GET /admin/platforms/{code}/defaults` - Vendor default pages
|
||||
- [ ] `POST/PUT/DELETE` endpoints for CRUD operations
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Platform list page route | `app/routes/admin_pages.py` | ✅ |
|
||||
| Platform detail/edit routes | `app/routes/admin_pages.py` | ✅ |
|
||||
| Platform API endpoints | `app/api/v1/admin/platforms.py` | ✅ |
|
||||
| Register API router | `app/api/v1/admin/__init__.py` | ✅ |
|
||||
| Platforms template | `app/templates/admin/platforms.html` | ✅ |
|
||||
| Platforms JS component | `static/admin/js/platforms.js` | ✅ |
|
||||
| Sidebar menu item | `app/templates/admin/partials/sidebar.html` | ✅ |
|
||||
|
||||
### 3.2 Update Content Pages Admin
|
||||
|
||||
Changes to existing admin:
|
||||
- [ ] Add platform dropdown filter
|
||||
- [ ] Show page tier badge (Platform / Default / Override)
|
||||
- [ ] Add `is_platform_page` toggle for platform-level pages
|
||||
- [ ] Group pages by tier in list view
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Platform dropdown filter | `app/templates/admin/content-pages.html` | ✅ |
|
||||
| Four-tab tier view | `app/templates/admin/content-pages.html` | ✅ |
|
||||
| Tier badges (Blue/Teal/Purple) | `static/admin/js/content-pages.js` | ✅ |
|
||||
| Platform filter in JS | `static/admin/js/content-pages.js` | ✅ |
|
||||
| API schema with platform fields | `app/api/v1/admin/content_pages.py` | ✅ |
|
||||
| Model to_dict with platform_name | `models/database/content_page.py` | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Vendor Dashboard
|
||||
## Phase 4: Vendor Dashboard ✅ COMPLETE
|
||||
|
||||
### 4.1 Content Pages List Updates
|
||||
|
||||
- [ ] Show source indicator: "Default" / "Override" / "Custom"
|
||||
- [ ] Add "Override Default" button for vendor default pages
|
||||
- [ ] Add "Revert to Default" button for vendor overrides
|
||||
- [ ] Show CMS usage: "3 of 10 pages used" with progress bar
|
||||
- [ ] Upgrade prompt when approaching limit
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Source indicators (Default/Override/Custom) | `app/templates/vendor/content-pages.html` | ✅ Already existed |
|
||||
| Override Default button | `app/templates/vendor/content-pages.html` | ✅ Already existed |
|
||||
| Revert to Default (delete override) | `static/vendor/js/content-pages.js` | ✅ Already existed |
|
||||
| CMS usage API endpoint | `app/api/v1/vendor/content_pages.py` | ✅ New |
|
||||
| CMS usage progress bar | `app/templates/vendor/content-pages.html` | ✅ New |
|
||||
| Upgrade prompt at 80% limit | `app/templates/vendor/content-pages.html` | ✅ New |
|
||||
| Load usage in JS | `static/vendor/js/content-pages.js` | ✅ New |
|
||||
|
||||
### 4.2 Page Editor Updates
|
||||
|
||||
- [ ] Show banner: "This page overrides the platform default"
|
||||
- [ ] "View Default" button to preview default content
|
||||
- [ ] "Revert" button inline in editor
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Override info banner | `app/templates/vendor/content-page-edit.html` | ✅ Already existed |
|
||||
| View Default button | `app/templates/vendor/content-page-edit.html` | ✅ New |
|
||||
| Default preview modal | `app/templates/vendor/content-page-edit.html` | ✅ New |
|
||||
| Platform default API | `app/api/v1/vendor/content_pages.py` | ✅ New |
|
||||
| Show default preview JS | `static/vendor/js/content-page-edit.js` | ✅ New |
|
||||
| Revert button (styled) | `app/templates/vendor/content-page-edit.html` | ✅ New |
|
||||
|
||||
---
|
||||
|
||||
@@ -202,30 +221,32 @@ VALUES ('loyalty', 'Loyalty+', 'Customer loyalty program', 'loyalty.lu', 'loyalt
|
||||
|
||||
---
|
||||
|
||||
## Documentation Requirements
|
||||
## Documentation Requirements ✅ PARTIAL
|
||||
|
||||
### Architecture Documentation
|
||||
### Architecture Documentation ✅ COMPLETE
|
||||
|
||||
Create `docs/architecture/multi-platform-cms.md`:
|
||||
- [ ] Three-tier content hierarchy explanation
|
||||
- [ ] Platform vs Vendor Default vs Vendor Override
|
||||
- [ ] Database schema diagrams
|
||||
- [ ] Request flow diagrams
|
||||
Created `docs/architecture/multi-platform-cms.md`:
|
||||
- [x] Three-tier content hierarchy explanation
|
||||
- [x] Platform vs Vendor Default vs Vendor Override
|
||||
- [x] Database schema diagrams
|
||||
- [x] Request flow diagrams
|
||||
- [x] API endpoints reference
|
||||
- [x] Key files reference
|
||||
- [x] Adding new platform guide
|
||||
|
||||
### API Documentation
|
||||
|
||||
Update OpenAPI specs:
|
||||
- [ ] Platform endpoints
|
||||
- [ ] Content page endpoints with platform_id
|
||||
- [ ] Vendor platform membership endpoints
|
||||
OpenAPI specs auto-generated from FastAPI:
|
||||
- [x] Platform endpoints (`/api/v1/admin/platforms`)
|
||||
- [x] Content page endpoints with platform fields
|
||||
- [ ] Vendor platform membership endpoints (future)
|
||||
|
||||
### Developer Guide
|
||||
|
||||
Create `docs/guides/adding-new-platform.md`:
|
||||
- [ ] Step-by-step platform creation
|
||||
- [ ] Required database records
|
||||
- [ ] Required config files
|
||||
- [ ] Required routes and templates
|
||||
Included in `docs/architecture/multi-platform-cms.md`:
|
||||
- [x] Step-by-step platform creation
|
||||
- [x] Required database records
|
||||
- [x] Key files reference
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user