Add comprehensive documentation for: - Module system architecture (three-tier classification, registry, events, migrations) - Menu management system (registry, visibility config, module integration) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
404 lines
14 KiB
Markdown
404 lines
14 KiB
Markdown
# Menu Management Architecture
|
|
|
|
The Wizamart platform provides a flexible menu system that supports per-platform and per-user customization. This document explains the menu architecture, configuration options, and how menus integrate with the module system.
|
|
|
|
## Overview
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│ MENU REGISTRY (Source of Truth) │
|
|
│ app/config/menu_registry.py │
|
|
│ │
|
|
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
|
|
│ │ ADMIN_MENU_REGISTRY │ │ VENDOR_MENU_REGISTRY │ │
|
|
│ │ (Admin panel menus) │ │ (Vendor dashboard menus) │ │
|
|
│ └─────────────────────────────┘ └─────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│ VISIBILITY CONFIGURATION │
|
|
│ models/database/admin_menu_config.py │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
|
│ │ AdminMenuConfig Table │ │
|
|
│ │ Stores visibility overrides (hidden items only) │ │
|
|
│ │ - Platform scope: applies to platform admins/vendors │ │
|
|
│ │ - User scope: applies to specific super admin │ │
|
|
│ └─────────────────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│ FILTERED MENU OUTPUT │
|
|
│ │
|
|
│ Registry - Hidden Items - Disabled Modules = Visible Menu Items │
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Frontend Types
|
|
|
|
The system supports two distinct frontend types:
|
|
|
|
| Frontend | Description | Users |
|
|
|----------|-------------|-------|
|
|
| `ADMIN` | Admin panel | Super admins, platform admins |
|
|
| `VENDOR` | Vendor dashboard | Vendors on a platform |
|
|
|
|
```python
|
|
from models.database.admin_menu_config import FrontendType
|
|
|
|
# Use in code
|
|
FrontendType.ADMIN # "admin"
|
|
FrontendType.VENDOR # "vendor"
|
|
```
|
|
|
|
## Menu Registry
|
|
|
|
The menu registry (`app/config/menu_registry.py`) is the **single source of truth** for menu structure. The database only stores visibility overrides.
|
|
|
|
### Admin Menu Structure
|
|
|
|
```python
|
|
ADMIN_MENU_REGISTRY = {
|
|
"frontend_type": FrontendType.ADMIN,
|
|
"sections": [
|
|
{
|
|
"id": "main",
|
|
"label": None, # No header
|
|
"items": [
|
|
{"id": "dashboard", "label": "Dashboard", "icon": "home", "url": "/admin/dashboard"},
|
|
],
|
|
},
|
|
{
|
|
"id": "superAdmin",
|
|
"label": "Super Admin",
|
|
"super_admin_only": True, # Only visible to super admins
|
|
"items": [
|
|
{"id": "admin-users", "label": "Admin Users", "icon": "shield", "url": "/admin/admin-users"},
|
|
],
|
|
},
|
|
# ... more sections
|
|
],
|
|
}
|
|
```
|
|
|
|
### Admin Menu Sections
|
|
|
|
| Section ID | Label | Description |
|
|
|------------|-------|-------------|
|
|
| `main` | (none) | Dashboard - always at top |
|
|
| `superAdmin` | Super Admin | Super admin only tools |
|
|
| `platformAdmin` | Platform Administration | Companies, vendors, messages |
|
|
| `vendorOps` | Vendor Operations | Products, customers, inventory, orders |
|
|
| `marketplace` | Marketplace | Letzshop integration |
|
|
| `billing` | Billing & Subscriptions | Tiers, subscriptions, billing history |
|
|
| `contentMgmt` | Content Management | Platforms, content pages, themes |
|
|
| `devTools` | Developer Tools | Components, icons |
|
|
| `platformHealth` | Platform Health | Capacity, testing, code quality |
|
|
| `monitoring` | Platform Monitoring | Imports, tasks, logs, notifications |
|
|
| `settingsSection` | Platform Settings | General settings, email templates, my menu |
|
|
|
|
### Vendor Menu Sections
|
|
|
|
| Section ID | Label | Description |
|
|
|------------|-------|-------------|
|
|
| `main` | (none) | Dashboard, analytics |
|
|
| `products` | Products & Inventory | Products, inventory, marketplace import |
|
|
| `sales` | Sales & Orders | Orders, Letzshop orders, invoices |
|
|
| `customers` | Customers | Customers, messages, notifications |
|
|
| `shop` | Shop & Content | Content pages, media library |
|
|
| `account` | Account & Settings | Team, profile, billing, settings |
|
|
|
|
### Menu Item Properties
|
|
|
|
Each menu item has these properties:
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `id` | string | Unique identifier (used for config and access control) |
|
|
| `label` | string | Display text |
|
|
| `icon` | string | Heroicons icon name |
|
|
| `url` | string | Route URL |
|
|
| `super_admin_only` | boolean | (Optional) Only visible to super admins |
|
|
|
|
## Visibility Configuration
|
|
|
|
### Opt-Out Model
|
|
|
|
The system uses an **opt-out model**:
|
|
- All menu items are **visible by default**
|
|
- Only **hidden** items are stored in the database
|
|
- This keeps the database small and makes the default state explicit
|
|
|
|
### Mandatory Items
|
|
|
|
Certain menu items cannot be hidden:
|
|
|
|
```python
|
|
MANDATORY_MENU_ITEMS = {
|
|
FrontendType.ADMIN: frozenset({
|
|
"dashboard", # Landing page
|
|
"companies", # Platform admin core
|
|
"vendors", # Platform admin core
|
|
"admin-users", # Super admin core
|
|
"settings", # Configuration access
|
|
"my-menu", # Must be able to undo changes
|
|
}),
|
|
FrontendType.VENDOR: frozenset({
|
|
"dashboard", # Landing page
|
|
"settings", # Configuration access
|
|
}),
|
|
}
|
|
```
|
|
|
|
### Scope Types
|
|
|
|
Menu configuration supports two scopes:
|
|
|
|
| Scope | Field | Description | Use Case |
|
|
|-------|-------|-------------|----------|
|
|
| Platform | `platform_id` | Applies to all users on platform | Hide features not used by platform |
|
|
| User | `user_id` | Applies to specific super admin | Personal preference customization |
|
|
|
|
**Important Rules:**
|
|
- Exactly one scope must be set (platform XOR user)
|
|
- User scope is only allowed for admin frontend (super admins only)
|
|
- Vendor frontend only supports platform scope
|
|
|
|
### Resolution Order
|
|
|
|
**Admin Frontend:**
|
|
```
|
|
Platform admin → Check platform config → Fall back to default (all visible)
|
|
Super admin → Check user config → Fall back to default (all visible)
|
|
```
|
|
|
|
**Vendor Frontend:**
|
|
```
|
|
Vendor → Check platform config → Fall back to default (all visible)
|
|
```
|
|
|
|
## Database Model
|
|
|
|
### AdminMenuConfig Table
|
|
|
|
```sql
|
|
CREATE TABLE admin_menu_configs (
|
|
id SERIAL PRIMARY KEY,
|
|
frontend_type VARCHAR(10) NOT NULL, -- 'admin' or 'vendor'
|
|
platform_id INTEGER REFERENCES platforms(id),
|
|
user_id INTEGER REFERENCES users(id),
|
|
menu_item_id VARCHAR(50) NOT NULL,
|
|
is_visible BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMP,
|
|
updated_at TIMESTAMP,
|
|
|
|
-- Constraints
|
|
CONSTRAINT uq_frontend_platform_menu_config
|
|
UNIQUE (frontend_type, platform_id, menu_item_id),
|
|
CONSTRAINT uq_frontend_user_menu_config
|
|
UNIQUE (frontend_type, user_id, menu_item_id),
|
|
CONSTRAINT ck_admin_menu_config_scope
|
|
CHECK ((platform_id IS NOT NULL AND user_id IS NULL) OR
|
|
(platform_id IS NULL AND user_id IS NOT NULL)),
|
|
CONSTRAINT ck_user_scope_admin_only
|
|
CHECK ((user_id IS NULL) OR (frontend_type = 'admin'))
|
|
);
|
|
```
|
|
|
|
### Examples
|
|
|
|
```python
|
|
# Platform "OMS" hides inventory from admin panel
|
|
AdminMenuConfig(
|
|
frontend_type=FrontendType.ADMIN,
|
|
platform_id=1,
|
|
menu_item_id="inventory",
|
|
is_visible=False
|
|
)
|
|
|
|
# Platform "OMS" hides letzshop from vendor dashboard
|
|
AdminMenuConfig(
|
|
frontend_type=FrontendType.VENDOR,
|
|
platform_id=1,
|
|
menu_item_id="letzshop",
|
|
is_visible=False
|
|
)
|
|
|
|
# Super admin "john" hides code-quality from their admin panel
|
|
AdminMenuConfig(
|
|
frontend_type=FrontendType.ADMIN,
|
|
user_id=5,
|
|
menu_item_id="code-quality",
|
|
is_visible=False
|
|
)
|
|
```
|
|
|
|
## Module Integration
|
|
|
|
Menu items are associated with modules. When a module is disabled for a platform, its menu items are automatically hidden.
|
|
|
|
### Module to Menu Item Mapping
|
|
|
|
Each module defines its menu items per frontend:
|
|
|
|
```python
|
|
# In module definition
|
|
billing_module = ModuleDefinition(
|
|
code="billing",
|
|
menu_items={
|
|
FrontendType.ADMIN: ["subscription-tiers", "subscriptions", "billing-history"],
|
|
FrontendType.VENDOR: ["billing", "invoices"],
|
|
},
|
|
)
|
|
```
|
|
|
|
### Menu Filtering Logic
|
|
|
|
```python
|
|
from app.modules.service import module_service
|
|
|
|
# Get available menu items (module-aware)
|
|
available_items = module_service.get_module_menu_items(
|
|
db, platform_id, FrontendType.ADMIN
|
|
)
|
|
|
|
# Check if specific menu item's module is enabled
|
|
is_available = module_service.is_menu_item_module_enabled(
|
|
db, platform_id, "subscription-tiers", FrontendType.ADMIN
|
|
)
|
|
```
|
|
|
|
### Three-Layer Filtering
|
|
|
|
The final visible menu is computed by three layers:
|
|
|
|
1. **Registry**: All possible menu items
|
|
2. **Module Enablement**: Items from disabled modules are hidden
|
|
3. **Visibility Config**: Explicitly hidden items are removed
|
|
|
|
```
|
|
Final Menu = Registry Items
|
|
- Items from Disabled Modules
|
|
- Items with is_visible=False in config
|
|
- Items not matching user role (super_admin_only)
|
|
```
|
|
|
|
## Helper Functions
|
|
|
|
### Getting Menu Items
|
|
|
|
```python
|
|
from app.config.menu_registry import (
|
|
get_all_menu_item_ids,
|
|
get_menu_item,
|
|
is_super_admin_only_item,
|
|
ADMIN_MENU_REGISTRY,
|
|
VENDOR_MENU_REGISTRY,
|
|
)
|
|
|
|
# Get all item IDs for a frontend
|
|
admin_items = get_all_menu_item_ids(FrontendType.ADMIN)
|
|
# Returns: {'dashboard', 'admin-users', 'companies', ...}
|
|
|
|
# Get specific item details
|
|
item = get_menu_item(FrontendType.ADMIN, "subscription-tiers")
|
|
# Returns: {
|
|
# 'id': 'subscription-tiers',
|
|
# 'label': 'Subscription Tiers',
|
|
# 'icon': 'tag',
|
|
# 'url': '/admin/subscription-tiers',
|
|
# 'section_id': 'billing',
|
|
# 'section_label': 'Billing & Subscriptions'
|
|
# }
|
|
|
|
# Check if item requires super admin
|
|
is_restricted = is_super_admin_only_item("admin-users") # True
|
|
```
|
|
|
|
### Menu Enums
|
|
|
|
```python
|
|
from app.config.menu_registry import AdminMenuItem, VendorMenuItem
|
|
|
|
# Use enums for type safety
|
|
AdminMenuItem.DASHBOARD.value # "dashboard"
|
|
AdminMenuItem.INVENTORY.value # "inventory"
|
|
|
|
VendorMenuItem.PRODUCTS.value # "products"
|
|
VendorMenuItem.ANALYTICS.value # "analytics"
|
|
```
|
|
|
|
## Access Control
|
|
|
|
### Route Protection
|
|
|
|
```python
|
|
from app.api.deps import require_menu_access
|
|
|
|
@router.get("/admin/inventory")
|
|
async def inventory_page(
|
|
_access: bool = Depends(require_menu_access("inventory", FrontendType.ADMIN))
|
|
):
|
|
# Only accessible if menu item is visible for user's context
|
|
pass
|
|
```
|
|
|
|
### Sidebar Rendering
|
|
|
|
The sidebar template filters items based on:
|
|
1. Module enablement
|
|
2. Visibility configuration
|
|
3. User role (super admin check)
|
|
|
|
```jinja2
|
|
{% for section in menu_sections %}
|
|
{% if not section.super_admin_only or current_user.is_super_admin %}
|
|
{% for item in section.items %}
|
|
{% if item.id in visible_menu_items %}
|
|
<a href="{{ item.url }}">{{ item.label }}</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
```
|
|
|
|
## UI for Menu Configuration
|
|
|
|
### Platform Admin Menu Config
|
|
|
|
Located at `/admin/platform-menu-config` (accessible by super admins):
|
|
- Configure which menu items are visible for platform admins
|
|
- Configure which menu items are visible for vendors on this platform
|
|
- Mandatory items cannot be unchecked
|
|
|
|
### Personal Menu Config (Super Admins)
|
|
|
|
Located at `/admin/my-menu`:
|
|
- Super admins can customize their own admin panel menu
|
|
- Personal preferences that don't affect other users
|
|
- Useful for hiding rarely-used features
|
|
|
|
## Best Practices
|
|
|
|
### Do
|
|
|
|
- Use menu item enums (`AdminMenuItem`, `VendorMenuItem`) for type safety
|
|
- Check module enablement before showing module-specific menu items
|
|
- Respect mandatory items - don't try to hide them
|
|
- Use `require_menu_access` dependency to protect routes
|
|
|
|
### Don't
|
|
|
|
- Hardcode menu item IDs as strings (use enums)
|
|
- Store `is_visible=True` in database (default state, wastes space)
|
|
- Allow hiding mandatory items via API
|
|
- Create menu items without registering them in the registry
|
|
|
|
## Related Documentation
|
|
|
|
- [Module System](module-system.md) - Module architecture and menu item mapping
|
|
- [Multi-Tenant System](multi-tenant.md) - Platform isolation
|
|
- [Feature Gating](../implementation/feature-gating-system.md) - Tier-based access
|