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>
14 KiB
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 |
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
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:
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
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
# 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:
# In module definition
billing_module = ModuleDefinition(
code="billing",
menu_items={
FrontendType.ADMIN: ["subscription-tiers", "subscriptions", "billing-history"],
FrontendType.VENDOR: ["billing", "invoices"],
},
)
Menu Filtering Logic
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:
- Registry: All possible menu items
- Module Enablement: Items from disabled modules are hidden
- 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
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
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
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:
- Module enablement
- Visibility configuration
- User role (super admin check)
{% 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_accessdependency to protect routes
Don't
- Hardcode menu item IDs as strings (use enums)
- Store
is_visible=Truein 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 architecture and menu item mapping
- Multi-Tenant System - Platform isolation
- Feature Gating - Tier-based access