Files
orion/static/admin/js/logs.js
Samir Boulahtit cc74970223 feat: add logging, marketplace, and admin enhancements
Database & Migrations:
- Add application_logs table migration for hybrid cloud logging
- Add companies table migration and restructure vendor relationships

Logging System:
- Implement hybrid logging system (database + file)
- Add log_service for centralized log management
- Create admin logs page with filtering and viewing capabilities
- Add init_log_settings.py script for log configuration
- Enhance core logging with database integration

Marketplace Integration:
- Add marketplace admin page with product management
- Create marketplace vendor page with product listings
- Implement marketplace.js for both admin and vendor interfaces
- Add marketplace integration documentation

Admin Enhancements:
- Add imports management page and functionality
- Create settings page for admin configuration
- Add vendor themes management page
- Enhance vendor detail and edit pages
- Improve code quality dashboard and violation details
- Add logs viewing and management
- Update icons guide and shared icon system

Architecture & Documentation:
- Document frontend structure and component architecture
- Document models structure and relationships
- Add vendor-in-token architecture documentation
- Add vendor RBAC (role-based access control) documentation
- Document marketplace integration patterns
- Update architecture patterns documentation

Infrastructure:
- Add platform static files structure (css, img, js)
- Move architecture_scan.py to proper models location
- Update model imports and registrations
- Enhance exception handling
- Update dependency injection patterns

UI/UX:
- Improve vendor edit interface
- Update admin user interface
- Enhance page templates documentation
- Add vendor marketplace interface
2025-12-01 21:51:07 +01:00

174 lines
5.4 KiB
JavaScript

// static/admin/js/logs.js
const logsLog = window.LogConfig?.loggers?.logs || console;
function adminLogs() {
// Get base data
const baseData = typeof data === 'function' ? data() : {};
return {
// Inherit base layout functionality from init-alpine.js
...baseData,
// Logs-specific state
currentPage: 'logs',
loading: true,
error: null,
successMessage: null,
logSource: 'database',
logs: [],
totalLogs: 0,
stats: {
total_count: 0,
warning_count: 0,
error_count: 0,
critical_count: 0
},
selectedLog: null,
filters: {
level: '',
module: '',
search: '',
skip: 0,
limit: 50
},
logFiles: [],
selectedFile: '',
fileContent: null,
async init() {
logsLog.info('=== LOGS PAGE INITIALIZING ===');
await this.loadStats();
await this.loadLogs();
},
async refresh() {
this.error = null;
this.successMessage = null;
await this.loadStats();
if (this.logSource === 'database') {
await this.loadLogs();
} else {
await this.loadFileLogs();
}
},
async loadStats() {
try {
const data = await apiClient.get('/admin/logs/statistics?days=7');
this.stats = data;
logsLog.info('Log statistics loaded:', this.stats);
} catch (error) {
logsLog.error('Failed to load log statistics:', error);
}
},
async loadLogs() {
this.loading = true;
this.error = null;
try {
const params = new URLSearchParams();
if (this.filters.level) params.append('level', this.filters.level);
if (this.filters.module) params.append('module', this.filters.module);
if (this.filters.search) params.append('search', this.filters.search);
params.append('skip', this.filters.skip);
params.append('limit', this.filters.limit);
const data = await apiClient.get(`/admin/logs/database?${params}`);
this.logs = data.logs;
this.totalLogs = data.total;
logsLog.info(`Loaded ${this.logs.length} logs (total: ${this.totalLogs})`);
} catch (error) {
logsLog.error('Failed to load logs:', error);
this.error = error.response?.data?.detail || 'Failed to load logs';
} finally {
this.loading = false;
}
},
async loadFileLogs() {
this.loading = true;
this.error = null;
try {
const data = await apiClient.get('/admin/logs/files');
this.logFiles = data.files;
if (this.logFiles.length > 0 && !this.selectedFile) {
this.selectedFile = this.logFiles[0].filename;
await this.loadFileContent();
}
logsLog.info(`Loaded ${this.logFiles.length} log files`);
} catch (error) {
logsLog.error('Failed to load log files:', error);
this.error = error.response?.data?.detail || 'Failed to load log files';
} finally {
this.loading = false;
}
},
async loadFileContent() {
if (!this.selectedFile) return;
this.loading = true;
this.error = null;
try {
const data = await apiClient.get(`/admin/logs/files/${this.selectedFile}?lines=500`);
this.fileContent = data;
logsLog.info(`Loaded file content for ${this.selectedFile}`);
} catch (error) {
logsLog.error('Failed to load file content:', error);
this.error = error.response?.data?.detail || 'Failed to load file content';
} finally {
this.loading = false;
}
},
async downloadLogFile() {
if (!this.selectedFile) return;
try {
const token = localStorage.getItem('admin_token');
// Note: window.open bypasses apiClient, so we need the full path
window.open(`/api/v1/admin/logs/files/${this.selectedFile}/download?token=${token}`, '_blank');
} catch (error) {
logsLog.error('Failed to download log file:', error);
this.error = 'Failed to download log file';
}
},
resetFilters() {
this.filters = {
level: '',
module: '',
search: '',
skip: 0,
limit: 50
};
this.loadLogs();
},
nextPage() {
this.filters.skip += this.filters.limit;
this.loadLogs();
},
previousPage() {
this.filters.skip = Math.max(0, this.filters.skip - this.filters.limit);
this.loadLogs();
},
showLogDetail(log) {
this.selectedLog = log;
},
formatTimestamp(timestamp) {
return new Date(timestamp).toLocaleString();
}
};
}
logsLog.info('Logs module loaded');