refactor: migrate vendor APIs to token-based context and consolidate architecture

## Vendor-in-Token Architecture (Complete Migration)
- Migrate all vendor API endpoints from require_vendor_context() to token_vendor_id
- Update permission dependencies to extract vendor from JWT token
- Add vendor exceptions: VendorAccessDeniedException, VendorOwnerOnlyException,
  InsufficientVendorPermissionsException
- Shop endpoints retain require_vendor_context() for URL-based detection
- Add AUTH-004 architecture rule enforcing vendor context patterns
- Fix marketplace router missing /marketplace prefix

## Exception Pattern Fixes (API-003/API-004)
- Services raise domain exceptions, endpoints let them bubble up
- Add code_quality and content_page exception modules
- Move business logic from endpoints to services (admin, auth, content_page)
- Fix exception handling in admin, shop, and vendor endpoints

## Tailwind CSS Consolidation
- Consolidate CSS to per-area files (admin, vendor, shop, platform)
- Remove shared/cdn-fallback.html and shared/css/tailwind.min.css
- Update all templates to use area-specific Tailwind output files
- Remove Node.js config (package.json, postcss.config.js, tailwind.config.js)

## Documentation & Cleanup
- Update vendor-in-token-architecture.md with completed migration status
- Update architecture-rules.md with new rules
- Move migration docs to docs/development/migration/
- Remove duplicate/obsolete documentation files
- Merge pytest.ini settings into pyproject.toml

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-04 22:24:45 +01:00
parent 76f8a59954
commit 8a367077e1
85 changed files with 21787 additions and 134978 deletions

View File

@@ -1,131 +1,158 @@
# Complete Implementation Guide - Testing Hub, Components & Icons
# Admin Sidebar Navigation
## 🎉 What's Been Created
## Overview
### ✅ All Files Follow Your Alpine.js Architecture Perfectly!
The admin sidebar provides navigation across all admin pages. It features collapsible sections with state persistence, active page indicators, and responsive mobile support.
1. **Testing Hub** - Manual QA tools
2. **Components Library** - UI component reference with navigation
3. **Icons Browser** - Searchable icon library with copy-to-clipboard
4. **Sidebar Fix** - Active menu indicator for all pages
**File Location:** `app/templates/admin/partials/sidebar.html`
---
## 📦 Files Created
## Sidebar Structure
### JavaScript Files (Alpine.js Components)
1. **[testing-hub.js](computer:///mnt/user-data/outputs/testing-hub.js)** - Testing hub component
2. **[components.js](computer:///mnt/user-data/outputs/components.js)** - Components library component
3. **[icons-page.js](computer:///mnt/user-data/outputs/icons-page.js)** - Icons browser component
The sidebar is organized into the following sections:
### HTML Templates
1. **[testing-hub.html](computer:///mnt/user-data/outputs/testing-hub.html)** - Testing hub page
2. **[components.html](computer:///mnt/user-data/outputs/components.html)** - Components library page
3. **[icons.html](computer:///mnt/user-data/outputs/icons.html)** - Icons browser page
### Sidebar Update
1. **[sidebar-fixed.html](computer:///mnt/user-data/outputs/sidebar-fixed.html)** - Fixed sidebar with active indicators
### Documentation
1. **[ARCHITECTURE_CONFIRMATION.md](computer:///mnt/user-data/outputs/ARCHITECTURE_CONFIRMATION.md)** - Architecture confirmation
| Section | Collapsible | Pages |
|---------|-------------|-------|
| Dashboard | No | Dashboard |
| Platform Administration | Yes | Companies, Vendors, Users, Customers, Marketplace |
| Content Management | Yes | Platform Homepage, Content Pages, Vendor Themes |
| Developer Tools | Yes | Components, Icons, Testing Hub, Code Quality |
| Platform Monitoring | Yes | Import Jobs, Application Logs |
| Settings | No | Settings |
---
## 🔧 Installation Steps
## Collapsible Sections
### Step 1: Install JavaScript Files
### How It Works
```bash
# Copy to your static directory
cp outputs/testing-hub.js static/admin/js/testing-hub.js
cp outputs/components.js static/admin/js/components.js
cp outputs/icons-page.js static/admin/js/icons-page.js
Sections can be expanded/collapsed by clicking the section header. The state is persisted to `localStorage` so sections remain open/closed across page navigation and browser sessions.
### State Management
**File:** `static/admin/js/init-alpine.js`
```javascript
// Default state: Platform Administration open, others closed
const defaultSections = {
platformAdmin: true,
contentMgmt: false,
devTools: false,
monitoring: false
};
// State stored in localStorage under this key
const SIDEBAR_STORAGE_KEY = 'admin_sidebar_sections';
```
### Step 2: Install HTML Templates
### Available Methods
```bash
# Copy to your templates directory
cp outputs/testing-hub.html app/templates/admin/testing-hub.html
cp outputs/components.html app/templates/admin/components.html
cp outputs/icons.html app/templates/admin/icons.html
```
| Method | Description |
|--------|-------------|
| `toggleSection(section)` | Toggle a section open/closed |
| `expandSectionForCurrentPage()` | Auto-expand section containing current page |
| `openSections.platformAdmin` | Check if Platform Administration is open |
| `openSections.contentMgmt` | Check if Content Management is open |
| `openSections.devTools` | Check if Developer Tools is open |
| `openSections.monitoring` | Check if Platform Monitoring is open |
### Step 3: Fix Sidebar (IMPORTANT!)
### CSS Transitions
```bash
# Replace your current sidebar
cp outputs/sidebar-fixed.html app/templates/partials/sidebar.html
```
### Step 4: Add Icons Route
Update `app/api/v1/admin/pages.py` - add this route:
```python
@router.get("/icons", response_class=HTMLResponse, include_in_schema=False)
async def admin_icons_page(
request: Request,
current_user: User = Depends(get_current_admin_from_cookie_or_header),
db: Session = Depends(get_db)
):
"""
Render icons browser page.
Browse and search all available icons.
"""
return templates.TemplateResponse(
"admin/icons.html",
{
"request": request,
"user": current_user,
}
)
```
### Step 5: Verify Icons Are Updated
Make sure you're using the updated `icons-updated.js` from earlier:
```bash
cp outputs/icons-updated.js static/shared/js/icons.js
```
### Step 6: Restart Server
```bash
# Stop current server (Ctrl+C)
# Start again
uvicorn app.main:app --reload
```
---
## 🐛 Sidebar Active Indicator Fix
### The Problem
You noticed that only the Dashboard menu item showed the vertical purple bar on the left when active. Other menu items didn't show this indicator.
### The Root Cause
Each page's JavaScript component needs to set `currentPage` correctly, and the sidebar HTML needs to check for that value.
**Before (Only Dashboard worked):**
```html
<!-- Only dashboard had the x-show condition -->
<span x-show="currentPage === 'dashboard'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg"></span>
```
### The Fix
**1. Sidebar HTML** - Add the indicator `<span>` to EVERY menu item:
Sections animate smoothly using CSS transitions (no plugins required):
```html
<ul
x-show="openSections.platformAdmin"
x-transition:enter="transition-all duration-200 ease-out"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition-all duration-150 ease-in"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 -translate-y-2"
class="mt-1 overflow-hidden"
>
```
### Chevron Icon Rotation
The chevron icon rotates 180 degrees when a section is expanded:
```html
<span
x-html="$icon('chevron-down', 'w-4 h-4 transition-transform duration-200')"
:class="{ 'rotate-180': openSections.platformAdmin }"
></span>
```
---
## Page-to-Section Mapping
Pages are mapped to their parent sections for auto-expansion:
```javascript
const pageSectionMap = {
// Platform Administration
companies: 'platformAdmin',
vendors: 'platformAdmin',
users: 'platformAdmin',
customers: 'platformAdmin',
marketplace: 'platformAdmin',
// Content Management
'platform-homepage': 'contentMgmt',
'content-pages': 'contentMgmt',
'vendor-theme': 'contentMgmt',
// Developer Tools
components: 'devTools',
icons: 'devTools',
testing: 'devTools',
'code-quality': 'devTools',
// Platform Monitoring
imports: 'monitoring',
logs: 'monitoring'
};
```
---
## Complete Page Mapping
| Page | `currentPage` Value | Section | URL |
|------|---------------------|---------|-----|
| Dashboard | `'dashboard'` | (always visible) | `/admin/dashboard` |
| Companies | `'companies'` | Platform Administration | `/admin/companies` |
| Vendors | `'vendors'` | Platform Administration | `/admin/vendors` |
| Users | `'users'` | Platform Administration | `/admin/users` |
| Customers | `'customers'` | Platform Administration | `/admin/customers` |
| Marketplace | `'marketplace'` | Platform Administration | `/admin/marketplace` |
| Platform Homepage | `'platform-homepage'` | Content Management | `/admin/platform-homepage` |
| Content Pages | `'content-pages'` | Content Management | `/admin/content-pages` |
| Vendor Themes | `'vendor-theme'` | Content Management | `/admin/vendor-themes` |
| Components | `'components'` | Developer Tools | `/admin/components` |
| Icons | `'icons'` | Developer Tools | `/admin/icons` |
| Testing Hub | `'testing'` | Developer Tools | `/admin/testing` |
| Code Quality | `'code-quality'` | Developer Tools | `/admin/code-quality` |
| Import Jobs | `'imports'` | Platform Monitoring | `/admin/imports` |
| Application Logs | `'logs'` | Platform Monitoring | `/admin/logs` |
| Settings | `'settings'` | (always visible) | `/admin/settings` |
---
## Active Page Indicator
Each menu item shows a purple vertical bar when active:
```html
<!-- Vendors -->
<li class="relative px-6 py-3">
<!-- ✅ Add this span for the purple bar -->
<span x-show="currentPage === 'vendors'" class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg"></span>
<a :class="currentPage === 'vendors' ? 'text-gray-800 dark:text-gray-100' : ''"
<!-- Purple bar indicator (shows when page is active) -->
<span x-show="currentPage === 'vendors'"
class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg"
aria-hidden="true"></span>
<!-- Link with active text styling -->
<a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
:class="currentPage === 'vendors' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/vendors">
<span x-html="$icon('shopping-bag')"></span>
<span class="ml-4">Vendors</span>
@@ -133,329 +160,179 @@ Each page's JavaScript component needs to set `currentPage` correctly, and the s
</li>
```
**2. JavaScript Files** - Each component must set `currentPage`:
### Setting currentPage in Components
Each page component must set `currentPage` to match the sidebar:
```javascript
// vendors.js
function adminVendors() {
return {
...data(),
currentPage: 'vendors', // Must match sidebar check
// ... rest of component
};
}
// users.js
function adminUsers() {
return {
...data(),
currentPage: 'users', // ✅ Must match sidebar check
...data(), // Inherit base (includes openSections)
currentPage: 'vendors', // Must match sidebar check
// ... rest of component
};
}
```
### Complete Page Mapping
| Page | JavaScript `currentPage` | Sidebar Check | URL |
|------|--------------------------|---------------|-----|
| Dashboard | `'dashboard'` | `x-show="currentPage === 'dashboard'"` | `/admin/dashboard` |
| Companies | `'companies'` | `x-show="currentPage === 'companies'"` | `/admin/companies` |
| Vendors | `'vendors'` | `x-show="currentPage === 'vendors'"` | `/admin/vendors` |
| Users | `'users'` | `x-show="currentPage === 'users'"` | `/admin/users` |
| Customers | `'customers'` | `x-show="currentPage === 'customers'"` | `/admin/customers` |
| Marketplace | `'marketplace'` | `x-show="currentPage === 'marketplace'"` | `/admin/marketplace` |
| Imports | `'imports'` | `x-show="currentPage === 'imports'"` | `/admin/imports` |
| Components | `'components'` | `x-show="currentPage === 'components'"` | `/admin/components` |
| Icons | `'icons'` | `x-show="currentPage === 'icons'"` | `/admin/icons` |
| Testing | `'testing'` | `x-show="currentPage === 'testing'"` | `/admin/testing` |
| Settings | `'settings'` | `x-show="currentPage === 'settings'"` | `/admin/settings` |
### Updated Sidebar Structure
The sidebar is organized into the following sections:
**Dashboard:**
- Dashboard
**Platform Administration:**
- Companies
- Vendors
- Users
- Customers
- Marketplace
**Content Management:**
- Platform Homepage
- Content Pages
- Vendor Themes
**Developer Tools:**
- Components
- Icons
- Testing Hub
- Code Quality
**Platform Monitoring:**
- Import Jobs
- Application Logs
**Settings:**
- Settings
Each section is properly separated with dividers and all menu items have active indicators.
---
## ✨ New Features
## Jinja2 Macros
### Testing Hub
- **2 Test Suites**: Auth Flow and Data Migration
- **Stats Cards**: Quick metrics overview
- **Interactive Cards**: Click to run tests
- **Best Practices**: Testing guidelines
- **Resource Links**: To Components and Icons pages
The sidebar uses Jinja2 macros for DRY code:
### Components Library
- **Sticky Section Navigation**: Jump to Forms, Buttons, Cards, etc.
- **Hash-based URLs**: Bookmarkable sections (#forms, #buttons)
- **Copy to Clipboard**: Click to copy component code
- **Live Examples**: All components with real Alpine.js
- **Dark Mode**: All examples support dark mode
### section_header
### Icons Browser
- **Search Functionality**: Filter icons by name
- **Category Navigation**: Browse by category
- **Live Preview**: See icons in multiple sizes
- **Copy Icon Name**: Quick copy to clipboard
- **Copy Usage Code**: Copy Alpine.js usage code
- **Selected Icon Details**: Full preview and size examples
- **Auto-categorization**: Icons organized automatically
Creates a collapsible section header with chevron:
---
## 🎯 How Each Feature Works
### Components Library Navigation
1. **Click a section** in the left sidebar
2. **Page scrolls** to that section smoothly
3. **URL updates** with hash (#forms)
4. **Active section** is highlighted in purple
5. **Bookmarkable**: Share URL with #section
```javascript
// How it works
goToSection(sectionId) {
this.activeSection = sectionId;
window.location.hash = sectionId;
// Smooth scroll
document.getElementById(sectionId).scrollIntoView({ behavior: 'smooth' });
}
```jinja2
{% macro section_header(title, section_key) %}
<button
@click="toggleSection('{{ section_key }}')"
class="flex items-center justify-between w-full px-6 py-2 ..."
>
<span>{{ title }}</span>
<span x-html="$icon('chevron-down', '...')"
:class="{ 'rotate-180': openSections.{{ section_key }} }"></span>
</button>
{% endmacro %}
```
### Icons Browser Search
### section_content
1. **Type in search box** - filters as you type
2. **Click category pill** - filters by category
3. **Click any icon** - shows details panel
4. **Hover icon** - shows copy buttons
5. **Click copy** - copies to clipboard
Wraps section items with collapse animation:
```javascript
// How it works
filterIcons() {
let icons = this.allIcons;
// Filter by category
if (this.activeCategory !== 'all') {
icons = icons.filter(icon => icon.category === this.activeCategory);
}
// Filter by search
if (this.searchQuery.trim()) {
const query = this.searchQuery.toLowerCase();
icons = icons.filter(icon => icon.name.toLowerCase().includes(query));
}
this.filteredIcons = icons;
}
```jinja2
{% macro section_content(section_key) %}
<ul x-show="openSections.{{ section_key }}" x-transition:...>
{{ caller() }}
</ul>
{% endmacro %}
```
### Testing Hub Navigation
### menu_item
1. **View stats** at the top
2. **Read test suite cards** with features
3. **Click "Run Tests"** to go to test page
4. **Read best practices** before testing
Creates a menu item with active indicator:
---
## 🧪 Testing Checklist
After installation, verify:
### General
- [ ] Server starts without errors
- [ ] All routes load successfully
- [ ] Icons display correctly everywhere
- [ ] Dark mode works on all pages
### Sidebar
- [ ] Dashboard shows purple bar when active
- [ ] Vendors shows purple bar when active
- [ ] Users shows purple bar when active
- [ ] Components shows purple bar when active
- [ ] Icons shows purple bar when active
- [ ] Testing shows purple bar when active
- [ ] Text is bold/highlighted on active page
### Testing Hub
- [ ] Page loads at `/admin/testing`
- [ ] Stats cards display correctly
- [ ] Test suite cards are clickable
- [ ] Icons render properly
- [ ] Links to other pages work
### Components Library
- [ ] Page loads at `/admin/components`
- [ ] Section navigation works
- [ ] Clicking section scrolls to it
- [ ] URL hash updates (#forms, etc.)
- [ ] Copy buttons work
- [ ] All form examples render
- [ ] Toast examples work
### Icons Browser
- [ ] Page loads at `/admin/icons`
- [ ] Shows correct icon count
- [ ] Search filters icons
- [ ] Category pills filter icons
- [ ] Clicking icon shows details
- [ ] Copy name button works
- [ ] Copy usage button works
- [ ] Preview shows multiple sizes
---
## 🎨 Customization
### Adding More Test Suites
Edit `testing-hub.js`:
```javascript
testSuites: [
// ... existing suites
{
id: 'new-suite',
name: 'New Test Suite',
description: 'Description here',
url: '/admin/test/new-suite',
icon: 'icon-name',
color: 'blue', // blue, orange, green, purple
testCount: 5,
features: [
'Feature 1',
'Feature 2'
]
}
]
```
### Adding More Component Sections
Edit `components.js`:
```javascript
sections: [
// ... existing sections
{ id: 'new-section', name: 'New Section', icon: 'icon-name' }
]
```
Then add the section HTML in `components.html`:
```html
<section id="new-section">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h2>New Section</h2>
<!-- Your components here -->
</div>
</section>
```
### Adding More Icon Categories
Edit `icons-page.js`:
```javascript
categories: [
// ... existing categories
{ id: 'new-category', name: 'New Category', icon: 'icon-name' }
]
```
And update the `categorizeIcon()` function:
```javascript
categoryMap: {
// ... existing mappings
'new-category': ['keyword1', 'keyword2']
}
```
---
## 📚 Quick Reference
### Alpine.js Component Pattern
```javascript
function yourPageComponent() {
return {
...data(), // ✅ Inherit base
currentPage: 'name', // ✅ Set page ID
async init() {
if (window._yourPageInitialized) return;
window._yourPageInitialized = true;
// Your init code
}
};
}
```
### Sidebar Menu Item Pattern
```html
```jinja2
{% macro menu_item(page_id, url, icon, label) %}
<li class="relative px-6 py-3">
<!-- Active indicator -->
<span x-show="currentPage === 'page-name'"
class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg">
</span>
<!-- Link -->
<a :class="currentPage === 'page-name' ? 'text-gray-800 dark:text-gray-100' : ''"
href="/admin/page-name">
<span x-html="$icon('icon-name')"></span>
<span class="ml-4">Page Name</span>
<span x-show="currentPage === '{{ page_id }}'" class="..."></span>
<a href="{{ url }}">
<span x-html="$icon('{{ icon }}')"></span>
<span class="ml-4">{{ label }}</span>
</a>
</li>
{% endmacro %}
```
### Usage Example
```jinja2
{{ section_header('Platform Administration', 'platformAdmin') }}
{% call section_content('platformAdmin') %}
{{ menu_item('companies', '/admin/companies', 'office-building', 'Companies') }}
{{ menu_item('vendors', '/admin/vendors', 'shopping-bag', 'Vendors') }}
{% endcall %}
```
---
## 🎯 Summary
## Adding a New Page
**Architecture:** ✅ All files follow your Alpine.js patterns perfectly
**Sidebar:** ✅ Fixed - all menu items now show active indicator
**Testing Hub:** ✅ Complete with test suites and navigation
**Components:** ✅ Complete with section navigation and copy feature
**Icons:** ✅ Complete with search, categories, and copy features
### Step 1: Add Route
**Total Files:** 7 (3 JS + 3 HTML + 1 Sidebar)
**Lines of Code:** ~2000+
**Features Added:** 20+
Add the route in `app/routes/admin_pages.py`:
Everything is ready to install! 🚀
```python
@router.get("/new-page", response_class=HTMLResponse, include_in_schema=False)
async def admin_new_page(
request: Request,
current_user: User = Depends(get_current_admin_from_cookie_or_header),
):
return templates.TemplateResponse(
"admin/new-page.html",
{"request": request, "user": current_user},
)
```
### Step 2: Create Template
Create `app/templates/admin/new-page.html`:
```jinja2
{% extends "admin/base.html" %}
{% block title %}New Page{% endblock %}
{% block alpine_data %}adminNewPage(){% endblock %}
{% block content %}
<!-- Your content -->
{% endblock %}
```
### Step 3: Create JavaScript Component
Create `static/admin/js/new-page.js`:
```javascript
function adminNewPage() {
return {
...data(),
currentPage: 'new-page', // Must match sidebar
// ...
};
}
```
### Step 4: Add to Sidebar
Edit `app/templates/admin/partials/sidebar.html`:
```jinja2
{# Add to appropriate section #}
{{ menu_item('new-page', '/admin/new-page', 'icon-name', 'New Page') }}
```
### Step 5: Update Page-Section Map (if in collapsible section)
Edit `static/admin/js/init-alpine.js`:
```javascript
const pageSectionMap = {
// ... existing mappings
'new-page': 'platformAdmin', // Add mapping
};
```
---
## Mobile Sidebar
The sidebar has a mobile version that slides in from the left:
- **Toggle:** Click hamburger menu in header
- **Close:** Click outside, press Escape, or navigate
- **State:** Controlled by `isSideMenuOpen`
```javascript
// In base data()
isSideMenuOpen: false,
toggleSideMenu() {
this.isSideMenuOpen = !this.isSideMenuOpen
},
closeSideMenu() {
this.isSideMenuOpen = false
}
```
---
## Testing Checklist
- [ ] Sections expand/collapse on header click
- [ ] Chevron rotates when section opens/closes
- [ ] Section state persists after page reload
- [ ] Section state persists across different pages
- [ ] Active page shows purple bar indicator
- [ ] Active page text is highlighted
- [ ] Mobile sidebar opens/closes correctly
- [ ] Collapsible sections work on mobile
- [ ] All navigation links work correctly