revamping frontend logging system and reorganising documentation
This commit is contained in:
562
docs/__REVAMPING/FRONTEND/FRONTEND_ALPINE_PAGE_TEMPLATE.md
Normal file
562
docs/__REVAMPING/FRONTEND/FRONTEND_ALPINE_PAGE_TEMPLATE.md
Normal file
@@ -0,0 +1,562 @@
|
||||
# Alpine.js Page Template - Quick Reference (WITH CENTRALIZED LOGGING)
|
||||
|
||||
## ✅ Correct Page Structure
|
||||
|
||||
```javascript
|
||||
// static/admin/js/your-page.js (or vendor/shop)
|
||||
|
||||
// 1. ✅ Use centralized logger (ONE LINE!)
|
||||
const yourPageLog = window.LogConfig.loggers.yourPage;
|
||||
// OR create custom if not pre-configured
|
||||
// const yourPageLog = window.LogConfig.createLogger('YOUR-PAGE', window.LogConfig.logLevel);
|
||||
|
||||
// 2. Create your Alpine.js component
|
||||
function yourPageComponent() {
|
||||
return {
|
||||
// ✅ CRITICAL: Inherit base layout functionality
|
||||
...data(),
|
||||
|
||||
// ✅ CRITICAL: Set page identifier
|
||||
currentPage: 'your-page',
|
||||
|
||||
// Your page-specific state
|
||||
items: [],
|
||||
loading: false,
|
||||
error: null,
|
||||
|
||||
// ✅ CRITICAL: Proper initialization with guard
|
||||
async init() {
|
||||
yourPageLog.info('=== YOUR PAGE INITIALIZING ===');
|
||||
|
||||
// Prevent multiple initializations
|
||||
if (window._yourPageInitialized) {
|
||||
yourPageLog.warn('Page already initialized, skipping...');
|
||||
return;
|
||||
}
|
||||
window._yourPageInitialized = true;
|
||||
|
||||
// Load your data
|
||||
await this.loadData();
|
||||
|
||||
yourPageLog.info('=== YOUR PAGE INITIALIZATION COMPLETE ===');
|
||||
},
|
||||
|
||||
// Your methods
|
||||
async loadData() {
|
||||
yourPageLog.info('Loading data...');
|
||||
this.loading = true;
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
const startTime = performance.now();
|
||||
|
||||
// Log API request
|
||||
const url = '/your/endpoint';
|
||||
window.LogConfig.logApiCall('GET', url, null, 'request');
|
||||
|
||||
// ✅ CRITICAL: Use lowercase apiClient
|
||||
const response = await apiClient.get(url);
|
||||
|
||||
// Log API response
|
||||
window.LogConfig.logApiCall('GET', url, response, 'response');
|
||||
|
||||
this.items = response.items || [];
|
||||
|
||||
// Log performance
|
||||
const duration = performance.now() - startTime;
|
||||
window.LogConfig.logPerformance('Load Data', duration);
|
||||
|
||||
yourPageLog.info(`Data loaded successfully`, {
|
||||
count: this.items.length,
|
||||
duration: `${duration}ms`
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
// Use centralized error logging
|
||||
window.LogConfig.logError(error, 'Load Data');
|
||||
this.error = error.message;
|
||||
Utils.showToast('Failed to load data', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
// Format date helper (if needed)
|
||||
formatDate(dateString) {
|
||||
if (!dateString) return '-';
|
||||
return Utils.formatDate(dateString);
|
||||
},
|
||||
|
||||
// Your other methods...
|
||||
};
|
||||
}
|
||||
|
||||
yourPageLog.info('Your page module loaded');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Checklist for New Pages
|
||||
|
||||
### HTML Template
|
||||
```jinja2
|
||||
{# app/templates/admin/your-page.html #}
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block title %}Your Page{% endblock %}
|
||||
|
||||
{# ✅ CRITICAL: Link to your Alpine.js component #}
|
||||
{% block alpine_data %}yourPageComponent(){% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
{# ✅ CRITICAL: Load your JavaScript file #}
|
||||
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
### JavaScript File Checklist
|
||||
|
||||
- [ ] ✅ Use centralized logger (ONE line instead of 15!)
|
||||
- [ ] ✅ Function name matches `alpine_data` in template
|
||||
- [ ] ✅ `...data(),` at start of return object
|
||||
- [ ] ✅ `currentPage: 'your-page'` set
|
||||
- [ ] ✅ Initialization guard in `init()`
|
||||
- [ ] ✅ Use lowercase `apiClient` for API calls
|
||||
- [ ] ✅ Use `window.LogConfig.logApiCall()` for API logging
|
||||
- [ ] ✅ Use `window.LogConfig.logPerformance()` for performance
|
||||
- [ ] ✅ Use `window.LogConfig.logError()` for errors
|
||||
- [ ] ✅ Module loaded log at end
|
||||
|
||||
---
|
||||
|
||||
## 📦 Pre-configured Loggers by Frontend
|
||||
|
||||
### Admin Frontend
|
||||
```javascript
|
||||
window.LogConfig.loggers.vendors // Vendor management
|
||||
window.LogConfig.loggers.vendorTheme // Theme customization
|
||||
window.LogConfig.loggers.vendorUsers // Vendor users
|
||||
window.LogConfig.loggers.products // Product management
|
||||
window.LogConfig.loggers.inventory // Inventory
|
||||
window.LogConfig.loggers.orders // Order management
|
||||
window.LogConfig.loggers.users // User management
|
||||
window.LogConfig.loggers.audit // Audit logs
|
||||
window.LogConfig.loggers.dashboard // Dashboard
|
||||
window.LogConfig.loggers.imports // Import operations
|
||||
```
|
||||
|
||||
### Vendor Frontend
|
||||
```javascript
|
||||
window.LogConfig.loggers.dashboard // Vendor dashboard
|
||||
window.LogConfig.loggers.products // Product management
|
||||
window.LogConfig.loggers.inventory // Inventory
|
||||
window.LogConfig.loggers.orders // Order management
|
||||
window.LogConfig.loggers.theme // Theme customization
|
||||
window.LogConfig.loggers.settings // Settings
|
||||
window.LogConfig.loggers.analytics // Analytics
|
||||
```
|
||||
|
||||
### Shop Frontend
|
||||
```javascript
|
||||
window.LogConfig.loggers.catalog // Product browsing
|
||||
window.LogConfig.loggers.product // Product details
|
||||
window.LogConfig.loggers.search // Search
|
||||
window.LogConfig.loggers.cart // Shopping cart
|
||||
window.LogConfig.loggers.checkout // Checkout
|
||||
window.LogConfig.loggers.account // User account
|
||||
window.LogConfig.loggers.orders // Order history
|
||||
window.LogConfig.loggers.wishlist // Wishlist
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ❌ Common Mistakes to Avoid
|
||||
|
||||
### 1. Old Way vs New Way
|
||||
```javascript
|
||||
// ❌ OLD WAY - 15 lines of duplicate code
|
||||
const YOUR_PAGE_LOG_LEVEL = 3;
|
||||
const yourPageLog = {
|
||||
error: (...args) => YOUR_PAGE_LOG_LEVEL >= 1 && console.error('❌ [YOUR_PAGE ERROR]', ...args),
|
||||
warn: (...args) => YOUR_PAGE_LOG_LEVEL >= 2 && console.warn('⚠️ [YOUR_PAGE WARN]', ...args),
|
||||
info: (...args) => YOUR_PAGE_LOG_LEVEL >= 3 && console.info('ℹ️ [YOUR_PAGE INFO]', ...args),
|
||||
debug: (...args) => YOUR_PAGE_LOG_LEVEL >= 4 && console.log('🔍 [YOUR_PAGE DEBUG]', ...args)
|
||||
};
|
||||
|
||||
// ✅ NEW WAY - 1 line!
|
||||
const yourPageLog = window.LogConfig.loggers.yourPage;
|
||||
```
|
||||
|
||||
### 2. Missing Base Inheritance
|
||||
```javascript
|
||||
// ❌ WRONG
|
||||
function myPage() {
|
||||
return {
|
||||
items: [],
|
||||
// Missing ...data()
|
||||
};
|
||||
}
|
||||
|
||||
// ✅ CORRECT
|
||||
function myPage() {
|
||||
return {
|
||||
...data(), // Must be first!
|
||||
items: [],
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Wrong API Client Name
|
||||
```javascript
|
||||
// ❌ WRONG - Capital letters
|
||||
await ApiClient.get('/endpoint');
|
||||
await API_CLIENT.get('/endpoint');
|
||||
|
||||
// ✅ CORRECT - lowercase
|
||||
await apiClient.get('/endpoint');
|
||||
```
|
||||
|
||||
### 4. Missing Init Guard
|
||||
```javascript
|
||||
// ❌ WRONG
|
||||
async init() {
|
||||
await this.loadData();
|
||||
}
|
||||
|
||||
// ✅ CORRECT
|
||||
async init() {
|
||||
if (window._myPageInitialized) return;
|
||||
window._myPageInitialized = true;
|
||||
await this.loadData();
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Missing currentPage
|
||||
```javascript
|
||||
// ❌ WRONG
|
||||
return {
|
||||
...data(),
|
||||
items: [],
|
||||
// Missing currentPage
|
||||
};
|
||||
|
||||
// ✅ CORRECT
|
||||
return {
|
||||
...data(),
|
||||
currentPage: 'my-page', // Must set this!
|
||||
items: [],
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 API Client Pattern
|
||||
|
||||
### GET Request
|
||||
```javascript
|
||||
try {
|
||||
const response = await apiClient.get('/endpoint');
|
||||
this.data = response;
|
||||
} catch (error) {
|
||||
console.error('Failed:', error);
|
||||
Utils.showToast('Failed to load', 'error');
|
||||
}
|
||||
```
|
||||
|
||||
### POST Request
|
||||
```javascript
|
||||
try {
|
||||
const response = await apiClient.post('/endpoint', {
|
||||
name: 'value',
|
||||
// ... data
|
||||
});
|
||||
Utils.showToast('Created successfully', 'success');
|
||||
} catch (error) {
|
||||
console.error('Failed:', error);
|
||||
Utils.showToast('Failed to create', 'error');
|
||||
}
|
||||
```
|
||||
|
||||
### PUT Request
|
||||
```javascript
|
||||
try {
|
||||
const response = await apiClient.put('/endpoint/123', {
|
||||
name: 'updated value'
|
||||
});
|
||||
Utils.showToast('Updated successfully', 'success');
|
||||
} catch (error) {
|
||||
console.error('Failed:', error);
|
||||
Utils.showToast('Failed to update', 'error');
|
||||
}
|
||||
```
|
||||
|
||||
### DELETE Request
|
||||
```javascript
|
||||
try {
|
||||
await apiClient.delete('/endpoint/123');
|
||||
Utils.showToast('Deleted successfully', 'success');
|
||||
await this.reloadData();
|
||||
} catch (error) {
|
||||
console.error('Failed:', error);
|
||||
Utils.showToast('Failed to delete', 'error');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Centralized Logging Patterns
|
||||
|
||||
### Basic Logging
|
||||
```javascript
|
||||
const log = window.LogConfig.loggers.yourPage;
|
||||
|
||||
log.info('Page loaded');
|
||||
log.warn('Connection slow');
|
||||
log.error('Failed to load data', error);
|
||||
log.debug('User data:', userData);
|
||||
```
|
||||
|
||||
### Grouped Logging
|
||||
```javascript
|
||||
log.group('Loading Theme Data');
|
||||
log.info('Fetching vendor...');
|
||||
log.info('Fetching theme...');
|
||||
log.info('Fetching presets...');
|
||||
log.groupEnd();
|
||||
```
|
||||
|
||||
### API Call Logging
|
||||
```javascript
|
||||
const url = '/api/vendors';
|
||||
|
||||
// Before request
|
||||
window.LogConfig.logApiCall('GET', url, null, 'request');
|
||||
|
||||
// Make request
|
||||
const data = await apiClient.get(url);
|
||||
|
||||
// After response
|
||||
window.LogConfig.logApiCall('GET', url, data, 'response');
|
||||
```
|
||||
|
||||
### Error Logging
|
||||
```javascript
|
||||
try {
|
||||
await saveTheme();
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Save Theme');
|
||||
}
|
||||
```
|
||||
|
||||
### Performance Logging
|
||||
```javascript
|
||||
const start = performance.now();
|
||||
await loadThemeData();
|
||||
const duration = performance.now() - start;
|
||||
window.LogConfig.logPerformance('Load Theme Data', duration);
|
||||
```
|
||||
|
||||
### Table Logging
|
||||
```javascript
|
||||
log.table([
|
||||
{ id: 1, name: 'Vendor A', status: 'active' },
|
||||
{ id: 2, name: 'Vendor B', status: 'inactive' }
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Benefits of Centralized Logging
|
||||
|
||||
| Aspect | Old Way | New Way |
|
||||
|--------|---------|---------|
|
||||
| **Lines of code** | ~15 per file | 1 line per file |
|
||||
| **Consistency** | Varies by file | Unified across all frontends |
|
||||
| **Maintenance** | Update each file | Update one shared file |
|
||||
| **Features** | Basic logging | Advanced (groups, perf, API) |
|
||||
| **Environment** | Manual config | Auto-detected |
|
||||
| **Frontend aware** | No | Yes (admin/vendor/shop) |
|
||||
| **Log levels** | Per file | Per frontend + environment |
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Common UI Patterns
|
||||
|
||||
### Loading State
|
||||
```javascript
|
||||
async loadData() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const data = await apiClient.get('/endpoint');
|
||||
this.items = data;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Refresh/Reload
|
||||
```javascript
|
||||
async refresh() {
|
||||
console.info('Refreshing...');
|
||||
await this.loadData();
|
||||
Utils.showToast('Refreshed successfully', 'success');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Available Utilities
|
||||
|
||||
### From `init-alpine.js` (via `...data()`)
|
||||
- `this.dark` - Dark mode state
|
||||
- `this.toggleTheme()` - Toggle theme
|
||||
- `this.isSideMenuOpen` - Side menu state
|
||||
- `this.toggleSideMenu()` - Toggle side menu
|
||||
- `this.closeSideMenu()` - Close side menu
|
||||
- `this.isNotificationsMenuOpen` - Notifications menu state
|
||||
- `this.toggleNotificationsMenu()` - Toggle notifications
|
||||
- `this.closeNotificationsMenu()` - Close notifications
|
||||
- `this.isProfileMenuOpen` - Profile menu state
|
||||
- `this.toggleProfileMenu()` - Toggle profile menu
|
||||
- `this.closeProfileMenu()` - Close profile menu
|
||||
- `this.isPagesMenuOpen` - Pages menu state
|
||||
- `this.togglePagesMenu()` - Toggle pages menu
|
||||
|
||||
### From `Utils` (global)
|
||||
- `Utils.showToast(message, type, duration)` - Show toast notification
|
||||
- `Utils.formatDate(dateString)` - Format date for display
|
||||
- `Utils.confirm(message, title)` - Show confirmation dialog (if available)
|
||||
|
||||
### From `apiClient` (global)
|
||||
- `apiClient.get(url)` - GET request
|
||||
- `apiClient.post(url, data)` - POST request
|
||||
- `apiClient.put(url, data)` - PUT request
|
||||
- `apiClient.delete(url)` - DELETE request
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Complete Example
|
||||
|
||||
```javascript
|
||||
// static/admin/js/vendor-theme.js
|
||||
|
||||
// 1. Use centralized logger
|
||||
const themeLog = window.LogConfig.loggers.vendorTheme;
|
||||
|
||||
// 2. Create component
|
||||
function adminVendorTheme() {
|
||||
return {
|
||||
...data(),
|
||||
currentPage: 'vendor-theme',
|
||||
|
||||
vendor: null,
|
||||
themeData: {},
|
||||
loading: true,
|
||||
|
||||
async init() {
|
||||
themeLog.info('Initializing vendor theme editor');
|
||||
|
||||
if (window._vendorThemeInitialized) {
|
||||
themeLog.warn('Already initialized, skipping...');
|
||||
return;
|
||||
}
|
||||
window._vendorThemeInitialized = true;
|
||||
|
||||
const startTime = performance.now();
|
||||
|
||||
try {
|
||||
themeLog.group('Loading theme data');
|
||||
|
||||
await Promise.all([
|
||||
this.loadVendor(),
|
||||
this.loadTheme()
|
||||
]);
|
||||
|
||||
themeLog.groupEnd();
|
||||
|
||||
const duration = performance.now() - startTime;
|
||||
window.LogConfig.logPerformance('Theme Editor Init', duration);
|
||||
|
||||
themeLog.info('Theme editor initialized successfully');
|
||||
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Theme Editor Init');
|
||||
Utils.showToast('Failed to initialize', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async loadVendor() {
|
||||
const url = `/admin/vendors/${this.vendorCode}`;
|
||||
window.LogConfig.logApiCall('GET', url, null, 'request');
|
||||
|
||||
const response = await apiClient.get(url);
|
||||
this.vendor = response;
|
||||
|
||||
window.LogConfig.logApiCall('GET', url, response, 'response');
|
||||
themeLog.debug('Vendor loaded:', this.vendor);
|
||||
},
|
||||
|
||||
async saveTheme() {
|
||||
themeLog.info('Saving theme changes');
|
||||
|
||||
try {
|
||||
const url = `/admin/vendor-themes/${this.vendorCode}`;
|
||||
window.LogConfig.logApiCall('PUT', url, this.themeData, 'request');
|
||||
|
||||
const response = await apiClient.put(url, this.themeData);
|
||||
|
||||
window.LogConfig.logApiCall('PUT', url, response, 'response');
|
||||
|
||||
themeLog.info('Theme saved successfully');
|
||||
Utils.showToast('Theme saved', 'success');
|
||||
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Save Theme');
|
||||
Utils.showToast('Failed to save theme', 'error');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
themeLog.info('Vendor theme editor module loaded');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start Template Files
|
||||
|
||||
Copy these to create a new page:
|
||||
|
||||
1. **Copy base file:** `dashboard.js` → rename to `your-page.js`
|
||||
2. **Update logger:**
|
||||
```javascript
|
||||
// Change from:
|
||||
const dashLog = window.LogConfig.loggers.dashboard;
|
||||
// To:
|
||||
const yourPageLog = window.LogConfig.loggers.yourPage;
|
||||
// Or create custom:
|
||||
const yourPageLog = window.LogConfig.createLogger('YOUR-PAGE');
|
||||
```
|
||||
3. **Replace function name:** `adminDashboard()` → `yourPageComponent()`
|
||||
4. **Update init flag:** `_dashboardInitialized` → `_yourPageInitialized`
|
||||
5. **Update page identifier:** `currentPage: 'dashboard'` → `currentPage: 'your-page'`
|
||||
6. **Replace data loading logic** with your API endpoints
|
||||
7. **Update HTML template** to use your function name:
|
||||
```jinja2
|
||||
{% block alpine_data %}yourPageComponent(){% endblock %}
|
||||
```
|
||||
8. **Load your script** in the template:
|
||||
```jinja2
|
||||
{% block extra_scripts %}
|
||||
<script src="{{ url_for('static', path='admin/js/your-page.js') }}"></script>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
Done! ✅
|
||||
Reference in New Issue
Block a user