// static/admin/js/imports.js /** * Admin platform monitoring - all import jobs */ // ✅ Use centralized logger const adminImportsLog = window.LogConfig.loggers.imports; adminImportsLog.info('Loading...'); function adminImports() { adminImportsLog.debug('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 || []; adminImportsLog.debug('Loaded vendors:', this.vendors.length); } catch (error) { adminImportsLog.error('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 }; adminImportsLog.debug('Loaded stats:', this.stats); } catch (error) { adminImportsLog.error('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; adminImportsLog.debug('Loaded all jobs:', this.jobs.length); } catch (error) { adminImportsLog.error('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; } adminImportsLog.debug('Refreshed job:', jobId); } catch (error) { adminImportsLog.error('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; adminImportsLog.debug('Viewing job details:', jobId); } catch (error) { adminImportsLog.error('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) { adminImportsLog.debug('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(); } });