calliope-media-import-export
Last commit date
assets
8 months ago
languages
8 months ago
export-import-media.php
8 months ago
importer.js
8 months ago
readme.txt
8 months ago
style.css
8 months ago
importer.js
170 lines
| 1 | jQuery(document).ready(function($) { |
| 2 | const importForm = $('#eim-import-form'); |
| 3 | const startButton = $('#eim-start-button'); |
| 4 | const continueButton = $('#eim-continue-button'); |
| 5 | const stopButton = $('#eim-stop-button'); |
| 6 | const progressBar = $('#eimp-progress-bar'); |
| 7 | const progressContainer = $('#eimp-progress-container'); |
| 8 | const logContainer = $('#eimp-log'); |
| 9 | |
| 10 | let totalRows = 0; |
| 11 | let isImportStopped = false; |
| 12 | let currentFile = ''; |
| 13 | let currentRow = 0; |
| 14 | |
| 15 | const i18n = eim_ajax.i18n; |
| 16 | |
| 17 | importForm.on('submit', function(e) { e.preventDefault(); startNewImport(); }); |
| 18 | continueButton.on('click', function() { if (currentFile) { $(this).hide(); startButton.hide(); stopButton.show(); processBatch(); } }); |
| 19 | stopButton.on('click', function() { isImportStopped = true; logMessage(i18n.stopping_process, 'INFO'); $(this).prop('disabled', true); }); |
| 20 | |
| 21 | function startNewImport() { |
| 22 | const fileInput = $('#eim_csv')[0]; |
| 23 | if (fileInput.files.length === 0) { alert(i18n.select_csv); return; } |
| 24 | |
| 25 | isImportStopped = false; totalRows = 0; currentRow = 0; |
| 26 | progressContainer.show(); logContainer.html(''); updateProgress(0); |
| 27 | logMessage(i18n.uploading_preparing, 'INFO'); |
| 28 | |
| 29 | startButton.prop('disabled', true); continueButton.hide(); stopButton.hide(); |
| 30 | progressBar.css('background-color', '#0073aa'); |
| 31 | |
| 32 | const formData = new FormData(importForm[0]); |
| 33 | formData.append('action', 'eim_prepare_import'); |
| 34 | formData.append('nonce', eim_ajax.nonce); |
| 35 | |
| 36 | $.ajax({ |
| 37 | url: eim_ajax.ajax_url, type: 'POST', data: formData, |
| 38 | processData: false, contentType: false, dataType: 'json', |
| 39 | success: function(response) { |
| 40 | if (response.success) { |
| 41 | totalRows = response.data.total_rows; currentFile = response.data.file; |
| 42 | if (totalRows > 0) { |
| 43 | logMessage(`${i18n.file_ready} ${totalRows}`, 'INFO'); |
| 44 | startButton.hide(); stopButton.show().prop('disabled', false); |
| 45 | processBatch(); |
| 46 | } else { |
| 47 | logMessage(i18n.empty_csv, 'ERROR'); |
| 48 | finishImport(true); |
| 49 | } |
| 50 | } else { |
| 51 | logMessage(`${i18n.error_prefix} ${response.data.message}`, 'ERROR'); |
| 52 | finishImport(true); |
| 53 | } |
| 54 | }, |
| 55 | error: function() { logMessage(i18n.server_error, 'ERROR'); finishImport(true); } |
| 56 | }); |
| 57 | } |
| 58 | |
| 59 | function processBatch() { |
| 60 | if (isImportStopped || currentRow >= totalRows) { |
| 61 | finishImport(false); |
| 62 | return; |
| 63 | } |
| 64 | |
| 65 | const batchSize = parseInt($('#batch_size').val(), 10); |
| 66 | logMessage(`${i18n.processing_batch} (${currentRow} - ${Math.min(currentRow + batchSize, totalRows)})`, 'INFO'); |
| 67 | |
| 68 | $.ajax({ |
| 69 | url: eim_ajax.ajax_url, |
| 70 | type: 'POST', |
| 71 | data: { |
| 72 | action: 'eim_process_batch', |
| 73 | nonce: eim_ajax.nonce, |
| 74 | file: currentFile, |
| 75 | start_row: currentRow, |
| 76 | batch_size: batchSize |
| 77 | }, |
| 78 | dataType: 'json', |
| 79 | success: function(response) { |
| 80 | if (response.success && response.data.results) { |
| 81 | // ¡NUEVA LÓGICA! Procesar resultados secuencialmente |
| 82 | processResultsSequentially(response.data.results); |
| 83 | } else { |
| 84 | logMessage(i18n.invalid_response, 'ERROR', response.data ? JSON.stringify(response.data) : 'No data'); |
| 85 | finishImport(true); |
| 86 | } |
| 87 | }, |
| 88 | error: function(error) { |
| 89 | logMessage(i18n.request_failed, 'ERROR', JSON.stringify(error)); |
| 90 | finishImport(true); |
| 91 | } |
| 92 | }); |
| 93 | } |
| 94 | |
| 95 | // -- ¡NUEVA FUNCIÓN! -- |
| 96 | // Muestra los resultados uno por uno para simular el tiempo real |
| 97 | function processResultsSequentially(results) { |
| 98 | let index = 0; |
| 99 | |
| 100 | function next() { |
| 101 | // Si ya mostramos todos los resultados del lote |
| 102 | if (index >= results.length) { |
| 103 | if (currentRow >= totalRows) { |
| 104 | logMessage(i18n.process_complete, 'FIN'); |
| 105 | finishImport(false); |
| 106 | } else if (isImportStopped) { |
| 107 | logMessage(i18n.process_stopped, 'FIN'); |
| 108 | finishImport(false); |
| 109 | } else { |
| 110 | // ¡AVISO DE LOTE TERMINADO RESTAURADO! |
| 111 | logMessage(i18n.batch_complete, 'INFO', i18n.click_continue); |
| 112 | stopButton.hide(); |
| 113 | continueButton.show(); |
| 114 | } |
| 115 | return; |
| 116 | } |
| 117 | |
| 118 | const result = results[index]; |
| 119 | index++; |
| 120 | |
| 121 | // Si el servidor nos dice que ya no hay más filas, marcamos como terminado |
| 122 | if (result.status === 'FINISHED') { |
| 123 | currentRow = totalRows; |
| 124 | setTimeout(next, 50); // Llama a la siguiente para activar la lógica final |
| 125 | return; |
| 126 | } |
| 127 | |
| 128 | // Muestra el log y actualiza el progreso |
| 129 | logMessage(result.file, result.status, result.message); |
| 130 | currentRow++; |
| 131 | updateProgress((currentRow / totalRows) * 100); |
| 132 | |
| 133 | // Espera 50ms y procesa la siguiente línea del log |
| 134 | setTimeout(next, 50); |
| 135 | } |
| 136 | |
| 137 | // Inicia el proceso |
| 138 | next(); |
| 139 | } |
| 140 | |
| 141 | |
| 142 | function finishImport(isError) { |
| 143 | startButton.show().prop('disabled', false); |
| 144 | continueButton.hide(); stopButton.hide(); |
| 145 | if (isError) { |
| 146 | progressBar.css('background-color', '#c0392b'); |
| 147 | } else if (!isImportStopped) { |
| 148 | updateProgress(100); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | function updateProgress(percent) { |
| 153 | percent = Math.min(100, Math.max(0, percent)); |
| 154 | progressBar.css('width', percent + '%').text(Math.round(percent) + '%'); |
| 155 | } |
| 156 | |
| 157 | function logMessage(message, status, details = '') { |
| 158 | let statusColor = '#333'; |
| 159 | switch (status) { |
| 160 | case 'SKIPPED': statusColor = '#e67e22'; break; |
| 161 | case 'IMPORTED': statusColor = '#27ae60'; break; |
| 162 | case 'ERROR': statusColor = '#c0392b'; break; |
| 163 | case 'INFO': statusColor = '#2980b9'; break; |
| 164 | case 'FIN': statusColor = '#0073aa'; break; |
| 165 | } |
| 166 | const detailsText = details ? ` <small><i>(${details})</i></small>` : ''; |
| 167 | logContainer.append(`<div><strong style="color: ${statusColor};">${status}:</strong> ${message}${detailsText}</div>`); |
| 168 | logContainer.scrollTop(logContainer[0].scrollHeight); |
| 169 | } |
| 170 | }); |