Files
orion/static/admin/js/settings.js
Samir Boulahtit 6f8434f200 feat: add PlatformSettings for pagination and vendor filter improvements
Platform Settings:
- Add PlatformSettings utility in init-alpine.js with 5-min cache
- Add Display tab in /admin/settings for rows_per_page config
- Integrate PlatformSettings.getRowsPerPage() in all paginated pages
- Standardize default per_page to 20 across all admin pages
- Add documentation at docs/frontend/shared/platform-settings.md

Architecture Rules:
- Add JS-010: enforce PlatformSettings usage for pagination
- Add JS-011: enforce standard pagination structure
- Add JS-012: detect double /api/v1 prefix in apiClient calls
- Implement all rules in validate_architecture.py

Vendor Filter (Tom Select):
- Add vendor filter to marketplace-products, vendor-products,
  customers, inventory, and vendor-themes pages
- Add selectedVendor display panel with clear button
- Add localStorage persistence for vendor selection
- Fix double /api/v1 prefix in vendor-selector.js

Bug Fixes:
- Remove duplicate PlatformSettings from utils.js
- Fix customers.js pagination structure (page_size → per_page)
- Fix code-quality-violations.js pagination structure

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 22:39:34 +01:00

270 lines
10 KiB
JavaScript

// static/admin/js/settings.js
// noqa: JS-003 - Uses ...baseData which is data() with safety check
const settingsLog = window.LogConfig?.loggers?.settings || console;
function adminSettings() {
// Get base data with safety check for standalone usage
const baseData = typeof data === 'function' ? data() : {};
return {
// Inherit base layout functionality from init-alpine.js
...baseData,
// Settings-specific state
currentPage: 'settings',
loading: true,
saving: false,
error: null,
successMessage: null,
activeTab: 'display',
displaySettings: {
rows_per_page: 20
},
logSettings: {
log_level: 'INFO',
log_file_max_size_mb: 10,
log_file_backup_count: 5,
db_log_retention_days: 30,
file_logging_enabled: true,
db_logging_enabled: true
},
notificationSettings: {
email_enabled: true,
in_app_enabled: true,
critical_only: false
},
shippingSettings: {
carrier_greco_label_url: 'https://dispatchweb.fr/Tracky/Home/',
carrier_colissimo_label_url: '',
carrier_xpresslogistics_label_url: ''
},
async init() {
try {
settingsLog.info('=== SETTINGS PAGE INITIALIZING ===');
await Promise.all([
this.loadDisplaySettings(),
this.loadLogSettings(),
this.loadShippingSettings()
]);
} catch (error) {
settingsLog.error('Init failed:', error);
this.error = 'Failed to initialize settings page';
}
},
async refresh() {
this.error = null;
this.successMessage = null;
await Promise.all([
this.loadDisplaySettings(),
this.loadLogSettings(),
this.loadShippingSettings()
]);
},
async loadDisplaySettings() {
try {
const data = await apiClient.get('/admin/settings/display/rows-per-page');
this.displaySettings.rows_per_page = data.rows_per_page || 20;
settingsLog.info('Display settings loaded:', this.displaySettings);
} catch (error) {
settingsLog.error('Failed to load display settings:', error);
// Use default value on error
this.displaySettings.rows_per_page = 20;
}
},
async saveDisplaySettings() {
this.saving = true;
this.error = null;
this.successMessage = null;
try {
const data = await apiClient.put(`/admin/settings/display/rows-per-page?rows=${this.displaySettings.rows_per_page}`);
this.successMessage = data.message || 'Display settings saved successfully';
// Clear the cached platform settings so pages pick up the new value
if (window.PlatformSettings) {
window.PlatformSettings.clearCache();
}
// Auto-hide success message after 5 seconds
setTimeout(() => {
this.successMessage = null;
}, 5000);
settingsLog.info('Display settings saved successfully');
} catch (error) {
settingsLog.error('Failed to save display settings:', error);
this.error = error.response?.data?.detail || 'Failed to save display settings';
} finally {
this.saving = false;
}
},
async loadLogSettings() {
this.loading = true;
this.error = null;
try {
const data = await apiClient.get('/admin/logs/settings');
this.logSettings = data;
settingsLog.info('Log settings loaded:', this.logSettings);
} catch (error) {
settingsLog.error('Failed to load log settings:', error);
this.error = error.response?.data?.detail || 'Failed to load log settings';
} finally {
this.loading = false;
}
},
async saveLogSettings() {
this.saving = true;
this.error = null;
this.successMessage = null;
try {
const data = await apiClient.put('/admin/logs/settings', this.logSettings);
this.successMessage = data.message || 'Log settings saved successfully';
// Auto-hide success message after 5 seconds
setTimeout(() => {
this.successMessage = null;
}, 5000);
settingsLog.info('Log settings saved successfully');
} catch (error) {
settingsLog.error('Failed to save log settings:', error);
this.error = error.response?.data?.detail || 'Failed to save log settings';
} finally {
this.saving = false;
}
},
async cleanupOldLogs() {
if (!confirm(`This will delete all logs older than ${this.logSettings.db_log_retention_days} days. Continue?`)) {
return;
}
this.error = null;
this.successMessage = null;
try {
const data = await apiClient.delete(
`/admin/logs/database/cleanup?retention_days=${this.logSettings.db_log_retention_days}&confirm=true`
);
this.successMessage = data.message || 'Old logs cleaned up successfully';
// Auto-hide success message after 5 seconds
setTimeout(() => {
this.successMessage = null;
}, 5000);
settingsLog.info('Old logs cleaned up successfully');
} catch (error) {
settingsLog.error('Failed to cleanup logs:', error);
this.error = error.response?.data?.detail || 'Failed to cleanup old logs';
}
},
async saveNotificationSettings() {
this.saving = true;
this.error = null;
this.successMessage = null;
try {
// TODO: Implement API endpoint for notification settings
// const data = await apiClient.put('/admin/notifications/settings', this.notificationSettings);
// For now, just show success (settings are client-side only)
this.successMessage = 'Notification settings saved successfully';
// Auto-hide success message after 5 seconds
setTimeout(() => {
this.successMessage = null;
}, 5000);
settingsLog.info('Notification settings saved:', this.notificationSettings);
} catch (error) {
settingsLog.error('Failed to save notification settings:', error);
this.error = error.response?.data?.detail || 'Failed to save notification settings';
} finally {
this.saving = false;
}
},
async loadShippingSettings() {
try {
// Load each carrier setting
const carriers = ['greco', 'colissimo', 'xpresslogistics'];
for (const carrier of carriers) {
try {
const key = `carrier_${carrier}_label_url`;
const data = await apiClient.get(`/admin/settings/${key}`);
if (data && data.value) {
this.shippingSettings[key] = data.value;
}
} catch (error) {
// Setting doesn't exist yet, use default
settingsLog.debug(`Setting carrier_${carrier}_label_url not found, using default`);
}
}
settingsLog.info('Shipping settings loaded:', this.shippingSettings);
} catch (error) {
settingsLog.error('Failed to load shipping settings:', error);
// Don't show error for missing settings, just use defaults
}
},
async saveShippingSettings() {
this.saving = true;
this.error = null;
this.successMessage = null;
try {
// Save each carrier setting using upsert
const carriers = [
{ key: 'carrier_greco_label_url', name: 'Greco' },
{ key: 'carrier_colissimo_label_url', name: 'Colissimo' },
{ key: 'carrier_xpresslogistics_label_url', name: 'XpressLogistics' }
];
for (const carrier of carriers) {
await apiClient.post('/admin/settings/upsert', {
key: carrier.key,
value: this.shippingSettings[carrier.key] || '',
category: 'shipping',
value_type: 'string',
description: `Label URL prefix for ${carrier.name} carrier`
});
}
this.successMessage = 'Shipping settings saved successfully';
// Auto-hide success message after 5 seconds
setTimeout(() => {
this.successMessage = null;
}, 5000);
settingsLog.info('Shipping settings saved:', this.shippingSettings);
} catch (error) {
settingsLog.error('Failed to save shipping settings:', error);
this.error = error.response?.data?.detail || 'Failed to save shipping settings';
} finally {
this.saving = false;
}
},
getShippingLabelUrl(carrier, shipmentNumber) {
// Helper to generate full label URL
const prefix = this.shippingSettings[`carrier_${carrier}_label_url`] || '';
if (!prefix || !shipmentNumber) return null;
return prefix + shipmentNumber;
}
};
}
settingsLog.info('Settings module loaded');