Files
orion/static/admin/js/imports.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

346 lines
10 KiB
JavaScript

// static/admin/js/imports.js
/**
* Admin platform monitoring - all import jobs
*/
// ✅ Use centralized logger
const adminImportsLog = window.LogConfig.loggers.imports;
console.log('[ADMIN IMPORTS] Loading...');
function adminImports() {
console.log('[ADMIN IMPORTS] adminImports() called');
return {
// ✅ Inherit base layout state
...data(),
// ✅ Set page identifier
currentPage: 'imports',
// Loading states
loading: false,
error: '',
// Vendors list
vendors: [],
// Stats
stats: {
total: 0,
active: 0,
completed: 0,
failed: 0
},
// Filters
filters: {
vendor_id: '',
status: '',
marketplace: '',
created_by: '' // 'me' or empty
},
// Import jobs
jobs: [],
totalJobs: 0,
page: 1,
limit: 20,
// Modal state
showJobModal: false,
selectedJob: null,
// Auto-refresh for active jobs
autoRefreshInterval: null,
async init() {
// Guard against multiple initialization
if (window._adminImportsInitialized) {
return;
}
window._adminImportsInitialized = true;
// IMPORTANT: Call parent init first
const parentInit = data().init;
if (parentInit) {
await parentInit.call(this);
}
await this.loadVendors();
await this.loadJobs();
await this.loadStats();
// Auto-refresh active jobs every 15 seconds
this.startAutoRefresh();
},
/**
* Load all vendors for filtering
*/
async loadVendors() {
try {
const response = await apiClient.get('/admin/vendors?limit=1000');
this.vendors = response.vendors || [];
console.log('[ADMIN IMPORTS] Loaded vendors:', this.vendors.length);
} catch (error) {
console.error('[ADMIN IMPORTS] Failed to load vendors:', error);
}
},
/**
* Load statistics
*/
async loadStats() {
try {
const response = await apiClient.get('/admin/marketplace-import-jobs/stats');
this.stats = {
total: response.total || 0,
active: (response.pending || 0) + (response.processing || 0),
completed: response.completed || 0,
failed: response.failed || 0
};
console.log('[ADMIN IMPORTS] Loaded stats:', this.stats);
} catch (error) {
console.error('[ADMIN IMPORTS] Failed to load stats:', error);
// Non-critical, don't show error
}
},
/**
* Load ALL import jobs (with filters)
*/
async loadJobs() {
this.loading = true;
this.error = '';
try {
// Build query params
const params = new URLSearchParams({
page: this.page,
limit: this.limit
});
// Add filters
if (this.filters.vendor_id) {
params.append('vendor_id', this.filters.vendor_id);
}
if (this.filters.status) {
params.append('status', this.filters.status);
}
if (this.filters.marketplace) {
params.append('marketplace', this.filters.marketplace);
}
if (this.filters.created_by === 'me') {
params.append('created_by_me', 'true');
}
const response = await apiClient.get(
`/admin/marketplace-import-jobs?${params.toString()}`
);
this.jobs = response.items || [];
this.totalJobs = response.total || 0;
console.log('[ADMIN IMPORTS] Loaded all jobs:', this.jobs.length);
} catch (error) {
console.error('[ADMIN IMPORTS] Failed to load jobs:', error);
this.error = error.message || 'Failed to load import jobs';
} finally {
this.loading = false;
}
},
/**
* Apply filters and reload
*/
async applyFilters() {
this.page = 1; // Reset to first page when filtering
await this.loadJobs();
await this.loadStats(); // Update stats based on filters
},
/**
* Clear all filters and reload
*/
async clearFilters() {
this.filters.vendor_id = '';
this.filters.status = '';
this.filters.marketplace = '';
this.filters.created_by = '';
this.page = 1;
await this.loadJobs();
await this.loadStats();
},
/**
* Refresh jobs list
*/
async refreshJobs() {
await this.loadJobs();
await this.loadStats();
},
/**
* Refresh single job status
*/
async refreshJobStatus(jobId) {
try {
const response = await apiClient.get(`/admin/marketplace-import-jobs/${jobId}`);
// Update job in list
const index = this.jobs.findIndex(j => j.id === jobId);
if (index !== -1) {
this.jobs[index] = response;
}
// Update selected job if modal is open
if (this.selectedJob && this.selectedJob.id === jobId) {
this.selectedJob = response;
}
console.log('[ADMIN IMPORTS] Refreshed job:', jobId);
} catch (error) {
console.error('[ADMIN IMPORTS] Failed to refresh job:', error);
}
},
/**
* View job details in modal
*/
async viewJobDetails(jobId) {
try {
const response = await apiClient.get(`/admin/marketplace-import-jobs/${jobId}`);
this.selectedJob = response;
this.showJobModal = true;
console.log('[ADMIN IMPORTS] Viewing job details:', jobId);
} catch (error) {
console.error('[ADMIN IMPORTS] Failed to load job details:', error);
this.error = error.message || 'Failed to load job details';
}
},
/**
* Close job details modal
*/
closeJobModal() {
this.showJobModal = false;
this.selectedJob = null;
},
/**
* Get vendor name by ID
*/
getVendorName(vendorId) {
const vendor = this.vendors.find(v => v.id === vendorId);
return vendor ? `${vendor.name} (${vendor.vendor_code})` : `Vendor #${vendorId}`;
},
/**
* Pagination: Previous page
*/
async previousPage() {
if (this.page > 1) {
this.page--;
await this.loadJobs();
}
},
/**
* Pagination: Next page
*/
async nextPage() {
if (this.page * this.limit < this.totalJobs) {
this.page++;
await this.loadJobs();
}
},
/**
* Format date for display
*/
formatDate(dateString) {
if (!dateString) return 'N/A';
try {
const date = new Date(dateString);
return date.toLocaleString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
} catch (error) {
return dateString;
}
},
/**
* Calculate duration between start and end
*/
calculateDuration(job) {
if (!job.started_at) {
return 'Not started';
}
const start = new Date(job.started_at);
const end = job.completed_at ? new Date(job.completed_at) : new Date();
const durationMs = end - start;
// Convert to human-readable format
const seconds = Math.floor(durationMs / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
if (hours > 0) {
return `${hours}h ${minutes % 60}m`;
} else if (minutes > 0) {
return `${minutes}m ${seconds % 60}s`;
} else {
return `${seconds}s`;
}
},
/**
* Start auto-refresh for active jobs
*/
startAutoRefresh() {
// Clear any existing interval
if (this.autoRefreshInterval) {
clearInterval(this.autoRefreshInterval);
}
// Refresh every 15 seconds if there are active jobs
this.autoRefreshInterval = setInterval(async () => {
const hasActiveJobs = this.jobs.some(job =>
job.status === 'pending' || job.status === 'processing'
);
if (hasActiveJobs) {
console.log('[ADMIN IMPORTS] Auto-refreshing active jobs...');
await this.loadJobs();
await this.loadStats();
}
}, 15000); // 15 seconds
},
/**
* Stop auto-refresh (cleanup)
*/
stopAutoRefresh() {
if (this.autoRefreshInterval) {
clearInterval(this.autoRefreshInterval);
this.autoRefreshInterval = null;
}
}
};
}
// Cleanup on page unload
window.addEventListener('beforeunload', () => {
if (window._adminImportsInstance && window._adminImportsInstance.stopAutoRefresh) {
window._adminImportsInstance.stopAutoRefresh();
}
});