PluginProbe
WebberZone Top 10 — Popular Posts / 4.5.1
WebberZone Top 10 — Popular Posts v4.5.1
4.5.1 4.5.0 4.4.3 4.4.2 4.4.1 4.4.0 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 trunk 1.0 1.0.1 1.1 1.2 1.3 1.4 1.4.1 1.5 1.5.1 1.5.2 1.5.3 1.6 1.6.1 All 117 releases
top-10 / includes / admin / js / wpp-importer.js

wpp-importer.js in WebberZone Top 10 — Popular Posts 4.5.1, at includes/admin/js/wpp-importer.js

433 lines 18.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Top 10 - WordPress Popular Posts Importer
3 *
4 * JavaScript for handling the WordPress Popular Posts import process.
5 *
6 * @package Top_Ten
7 * @subpackage Admin/JS
8 */
9
10 /* global topTenWPPImporter */
11 jQuery(document).ready(function ($) {
12 'use strict';
13
14 // Track if the import has been cancelled
15 var importCancelled = false;
16
17 /**
18 * Escape HTML to prevent XSS attacks
19 *
20 * @param {string} unsafeText The unsafe text
21 * @return {string} Escaped text
22 */
23 function escapeHTML(unsafeText) {
24 return $('<div>').text(unsafeText).html();
25 }
26
27 // Handle form submission.
28 $('#top-ten-wpp-import-form').on('submit', function (e) {
29 e.preventDefault();
30
31 // Confirm before proceeding.
32 if (!confirm(topTenWPPImporter.strings.confirm)) {
33 return;
34 }
35
36 var $form = $(this);
37 var $submit = $('#top-ten-wpp-import-submit');
38 var $progress = $('#top-ten-wpp-import-progress');
39 var $results = $('#top-ten-wpp-import-results');
40
41 // Create cancel button if it doesn't exist
42 var $cancelBtn = $('#top-ten-wpp-import-cancel');
43 if ($cancelBtn.length === 0) {
44 $cancelBtn = $('<button>', {
45 id: 'top-ten-wpp-import-cancel',
46 class: 'button',
47 text: topTenWPPImporter.strings.cancel_button,
48 css: { 'margin-left': '10px' }
49 }).insertAfter($submit);
50
51 // Add click handler to cancel button
52 $cancelBtn.on('click', function () {
53 if (confirm(topTenWPPImporter.strings.cancel_confirm)) {
54 importCancelled = true;
55 $progress
56 .removeClass('notice-info notice-success')
57 .addClass('notice-error')
58 .html('<strong>' + topTenWPPImporter.strings.import_cancelled + '</strong>');
59 $submit.prop('disabled', false);
60 $(this).hide();
61 }
62 return false;
63 });
64 }
65
66 // Reset cancelled flag
67 importCancelled = false;
68
69 // Disable submit button and show cancel button
70 $submit.prop('disabled', true);
71 $cancelBtn.show();
72
73 // Show progress
74 $progress
75 .removeClass('hidden notice-error notice-success')
76 .addClass('notice-info')
77 .html(topTenWPPImporter.strings.importing +
78 ' <span class="import-status">' + topTenWPPImporter.strings.starting + '</span><br>' +
79 '<div class="import-progress-bar" style="background-color: #f5f5f5; border: 1px solid #ddd; height: 20px; margin: 10px 0;">' +
80 '<div style="width: 0%; height: 100%; background-color: #0073aa;"></div></div>' +
81 '<span class="import-percentage">0%</span>');
82
83 $results.addClass('hidden');
84
85 // Get selected sites for multisite.
86 var selectedSites = [];
87 var isNetworkAdmin = $('input[name="sites[]"]').length > 0;
88
89 // Only collect checked sites if we're in network admin
90 if (isNetworkAdmin) {
91 $('input[name="sites[]"]:checked').each(function () {
92 selectedSites.push($(this).val());
93 });
94
95 // Validate that at least one site is selected in network admin
96 if (selectedSites.length === 0) {
97 $progress
98 .removeClass('hidden notice-info notice-success')
99 .addClass('notice-error')
100 .html('<strong>' + topTenWPPImporter.strings.error + '</strong> ' + topTenWPPImporter.strings.no_sites_selected);
101 $submit.prop('disabled', false);
102 return false;
103 }
104 }
105
106 // Validate minimum views input
107 var minViews = $('input[name="min_views"]').val();
108 if (minViews !== '' && (!$.isNumeric(minViews) || parseInt(minViews) < 0)) {
109 $progress
110 .removeClass('hidden notice-info notice-success')
111 .addClass('notice-error')
112 .html('<strong>' + topTenWPPImporter.strings.error + '</strong> ' + topTenWPPImporter.strings.invalid_min_views);
113 $submit.prop('disabled', false);
114 return false;
115 }
116
117 // Store the form parameters for batch processing
118 var importParams = {
119 action: 'top_ten_import_wpp',
120 nonce: topTenWPPImporter.nonce,
121 import_mode: $('input[name="import_mode"]:checked').val(),
122 import_data: $('input[name="import_data"]:checked').val(),
123 min_views: $('input[name="min_views"]').val(),
124 dry_run: $('input[name="dry_run"]').is(':checked') ? 1 : 0,
125 is_network_admin: isNetworkAdmin ? 1 : 0,
126 batch: true,
127 sites: selectedSites,
128 currentSiteIndex: 0,
129 batch_number: 1,
130 total_batches: 0,
131 results: {}
132 };
133
134 // Start the batch process
135 processBatch(importParams, $progress, $results, $submit);
136 });
137
138 /**
139 * Update the progress bar with current percentage
140 *
141 * @param {jQuery} $progress The progress element
142 * @param {number} current Current step or batch
143 * @param {number} total Total steps or batches
144 */
145 function updateProgressBar($progress, current, total) {
146 // Calculate percentage, with a minimum of 5% to show activity
147 var percentage = total > 0 ? Math.min(Math.round((current / total) * 100), 100) : 5;
148
149 // Update the progress bar
150 $progress.find('.import-progress-bar div').css('width', percentage + '%');
151 $progress.find('.import-percentage').text(percentage + '%');
152 }
153
154 /**
155 * Process a single batch of the import
156 *
157 * @param {Object} params The import parameters
158 * @param {jQuery} $progress The progress element
159 * @param {jQuery} $results The results element
160 * @param {jQuery} $submit The submit button
161 */
162 function processBatch(params, $progress, $results, $submit) {
163 // Check if import has been cancelled
164 if (importCancelled) {
165 $('#top-ten-wpp-import-cancel').hide();
166 $submit.prop('disabled', false);
167 return;
168 }
169
170 // If we've processed all sites, we're done
171 if (params.currentSiteIndex >= params.sites.length && params.sites.length > 0) {
172 // Show final results
173 showFinalResults(params, $progress, $results, $submit);
174 return;
175 }
176
177 // Current site being processed
178 var currentSite = params.sites.length ? params.sites[params.currentSiteIndex] : 0;
179
180 // Update the progress indicator
181 $progress.find('.import-status').html(
182 (params.sites.length > 1 ? topTenWPPImporter.strings.processing_site + ' ' + currentSite + ' - ' : '') +
183 topTenWPPImporter.strings.batch + ' ' + params.batch_number +
184 (params.total_batches > 0 ? ' ' + topTenWPPImporter.strings.of + ' ' + params.total_batches : '')
185 );
186
187 // Calculate overall progress based on sites and batches
188 var currentSiteIndex = params.currentSiteIndex;
189 var totalSites = params.sites.length;
190 var currentBatch = params.batch_number;
191 var totalBatches = params.total_batches;
192
193 // If we know the total batches, use more precise calculation
194 if (totalBatches > 0) {
195 var overallProgress = ((currentSiteIndex * totalBatches) + currentBatch) / (totalSites * totalBatches);
196 updateProgressBar($progress, overallProgress * 100, 100);
197 } else {
198 // Simple calculation based on sites processed
199 updateProgressBar($progress, currentSiteIndex + 1, totalSites);
200 }
201
202 // Debug info to help diagnose multisite issues
203 /* console.log('Processing batch with params:', {
204 currentSite: currentSite,
205 isNetworkAdmin: params.is_network_admin,
206 selectedSites: params.sites,
207 batchNumber: params.batch_number
208 }); */
209
210 // Send AJAX request for this batch
211 $.ajax({
212 url: topTenWPPImporter.ajaxurl,
213 type: 'POST',
214 timeout: 60000, // 60 seconds timeout
215 data: {
216 action: 'top_ten_import_wpp',
217 nonce: topTenWPPImporter.nonce,
218 import_mode: params.import_mode,
219 import_data: params.import_data,
220 min_views: params.min_views,
221 dry_run: params.dry_run,
222 batch: true,
223 blog_id: currentSite,
224 batch_number: params.batch_number,
225 is_network_admin: params.is_network_admin,
226 sites: params.sites // Add sites array to fix multisite selection
227 },
228 success: function (response) {
229 if (response.success) {
230 // Handle batch response
231 if (response.data.batch_status) {
232 // Store batch results for the current site
233 if (!params.results[currentSite]) {
234 params.results[currentSite] = {
235 posts_processed: 0,
236 total_counts: 0,
237 total_views_imported: 0,
238 daily_counts: 0,
239 daily_views_imported: 0,
240 errors: []
241 };
242 }
243
244 // Update the batch status
245 params.total_batches = response.data.total_batches || params.total_batches;
246
247 // Update the progress percentage
248 var currentSiteIndex = params.currentSiteIndex;
249 var totalSites = params.sites.length;
250 var currentBatch = params.batch_number;
251 var totalBatches = params.total_batches;
252
253 if (totalBatches > 0) {
254 var overallProgress = ((currentSiteIndex * totalBatches) + currentBatch) / (totalSites * totalBatches);
255 updateProgressBar($progress, overallProgress * 100, 100);
256 }
257
258 // Increment stats from this batch
259 if (response.data.batch_results) {
260 var batchResults = response.data.batch_results;
261 params.results[currentSite].posts_processed += parseInt(batchResults.posts_processed || 0);
262 params.results[currentSite].total_counts += parseInt(batchResults.total_counts || 0);
263 params.results[currentSite].total_views_imported += parseInt(batchResults.total_views_imported || 0);
264 params.results[currentSite].daily_counts += parseInt(batchResults.daily_counts || 0);
265 params.results[currentSite].daily_views_imported += parseInt(batchResults.daily_views_imported || 0);
266
267 // Add any errors
268 if (batchResults.errors && batchResults.errors.length) {
269 params.results[currentSite].errors =
270 params.results[currentSite].errors.concat(batchResults.errors);
271 }
272 }
273
274 // If we have more batches for this site
275 if (response.data.has_more_batches) {
276 params.batch_number++;
277 // Process the next batch for this site
278 processBatch(params, $progress, $results, $submit);
279 return;
280 } else {
281 // Move to the next site
282 params.currentSiteIndex++;
283 params.batch_number = 1;
284 // Process the first batch of the next site
285 processBatch(params, $progress, $results, $submit);
286 return;
287 }
288 } else {
289 // This is the final success response - for compatibility with non-batch responses
290 // Process the response.data.results if available
291 if (response.data.results) {
292 var results = response.data.results;
293
294 // Add these results to our params.results
295 $.each(results, function (blogId, result) {
296 params.results[blogId] = result;
297 });
298 }
299
300 // Show final results
301 showFinalResults(params, $progress, $results, $submit);
302 }
303 } else {
304 // Properly handle server-side errors
305 var errorMessage = response.data && response.data.message
306 ? response.data.message
307 : topTenWPPImporter.strings.unknown_error;
308 handleError(errorMessage);
309 }
310 },
311 error: function (xhr, status, error) {
312 if (status === 'timeout') {
313 handleError(topTenWPPImporter.strings.timeout_error);
314 } else {
315 var errorMessage = topTenWPPImporter.strings.server_error + ' ' + (xhr.responseJSON && xhr.responseJSON.message
316 ? xhr.responseJSON.message
317 : error);
318 handleError(errorMessage);
319 }
320 }
321 });
322 }
323
324 /**
325 * Handle error display.
326 *
327 * @param {string} error Error message to display.
328 */
329 function handleError(error) {
330 var $progress = $('#top-ten-wpp-import-progress');
331 var $results = $('#top-ten-wpp-import-results');
332 var $submit = $('#top-ten-wpp-import-submit');
333 var $cancelBtn = $('#top-ten-wpp-import-cancel');
334
335 $progress
336 .removeClass('hidden notice-info notice-success')
337 .addClass('notice-error')
338 .html('<strong>' + topTenWPPImporter.strings.import_error + '</strong>');
339
340 $results
341 .removeClass('hidden notice-success')
342 .addClass('notice-error')
343 .html(topTenWPPImporter.strings.import_error + '<br><br>' + escapeHTML(error));
344
345 // Re-enable the submit button and hide cancel button
346 $submit.prop('disabled', false);
347 $cancelBtn.hide();
348 }
349
350 /**
351 * Display the final results after all batches are complete
352 *
353 * @param {Object} params The import parameters
354 * @param {jQuery} $progress The progress element
355 * @param {jQuery} $results The results element
356 * @param {jQuery} $submit The submit button
357 */
358 function showFinalResults(params, $progress, $results, $submit) {
359 // Enable the submit button and hide cancel button
360 $submit.prop('disabled', false);
361 $('#top-ten-wpp-import-cancel').hide();
362
363 // Update progress status
364 $progress
365 .removeClass('notice-info')
366 .addClass('notice-success')
367 .removeClass('hidden')
368 .html('<strong>' + topTenWPPImporter.strings.import_complete + '</strong>');
369
370 // Prepare to show results
371 $results
372 .removeClass('hidden notice-error')
373 .addClass('notice-success');
374
375 var message = '<br />';
376 var isDryRun = params.dry_run ? true : false;
377 var runType = isDryRun ? topTenWPPImporter.strings.dry_run + ' ' : '';
378 // Calculate the number of sites processed - use the number of keys in the results object
379 var sitesProcessed = Object.keys(params.results).length;
380
381 // If we have a multisite setup with multiple sites
382 if (Object.keys(params.results).length > 1) {
383 // Multi-site results
384 message += '<strong>' + runType + topTenWPPImporter.strings.sites_processed + ' ' + sitesProcessed + '</strong><br><br>';
385
386 $.each(params.results, function (blogId, result) {
387 message += '<strong>' + topTenWPPImporter.strings.blog_id + ' ' + blogId + ':</strong><br>';
388 message += topTenWPPImporter.strings.posts_processed + ' ' + (result.posts_processed || 0) + '<br>';
389 message += topTenWPPImporter.strings.total_records + ' ' + (result.total_counts || 0) + '<br>';
390 message += topTenWPPImporter.strings.total_views_found + ' ' + (result.total_views_imported || 0) + '<br>';
391 message += topTenWPPImporter.strings.daily_records + ' ' + (result.daily_counts || 0) + '<br>';
392 message += topTenWPPImporter.strings.daily_views_found + ' ' + (result.daily_views_imported || 0) + '<br>';
393
394 if (result.errors && result.errors.length) {
395 message += '<strong>' + topTenWPPImporter.strings.errors + '</strong><br>';
396 $.each(result.errors, function (i, error) {
397 message += '- ' + escapeHTML(error) + '<br>';
398 });
399 }
400 message += '<br>';
401 });
402 } else {
403 // Single site result
404 var siteId = Object.keys(params.results)[0] || 0;
405 var results = params.results[siteId] || {
406 posts_processed: 0,
407 total_counts: 0,
408 total_views_imported: 0,
409 daily_counts: 0,
410 daily_views_imported: 0,
411 errors: []
412 };
413
414 message += '<strong>' + runType + topTenWPPImporter.strings.results + '</strong><br>';
415 message += topTenWPPImporter.strings.posts_processed + ' ' + (results.posts_processed || 0) + '<br>';
416 message += topTenWPPImporter.strings.total_records + ' ' + (results.total_counts || 0) + '<br>';
417 message += topTenWPPImporter.strings.total_views_found + ' ' + (results.total_views_imported || 0) + '<br>';
418 message += topTenWPPImporter.strings.daily_records + ' ' + (results.daily_counts || 0) + '<br>';
419 message += topTenWPPImporter.strings.daily_views_found + ' ' + (results.daily_views_imported || 0) + '<br>';
420
421 if (results.errors && results.errors.length) {
422 message += '<strong>' + topTenWPPImporter.strings.errors + '</strong><br>';
423 $.each(results.errors, function (i, error) {
424 message += '- ' + escapeHTML(error) + '<br>';
425 });
426 }
427 }
428
429 // Display the results
430 $results.html(message);
431 }
432 });
433