PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.15
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.15
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
metasync / views / js / metasync-import-external-data.js

metasync-import-external-data.js in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.15, at views/js/metasync-import-external-data.js

270 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global metasyncImportData, jQuery, ajaxurl */
2 /**
3 * MetaSync Import External Data
4 *
5 * Extracted for Phase 5, #887.
6 * Handles importing external plugin data (redirections, SEO metadata)
7 * with batch progress tracking for SEO metadata imports.
8 *
9 * Localized object: metasyncImportData
10 * - importNonce (string) Nonce for metasync_import_external_data
11 * - seoImportNonce (string) Nonce for metasync_import_seo_metadata
12 *
13 * @since Phase 5
14 */
15 jQuery(document).ready(function ($) {
16 var importNonce = metasyncImportData.importNonce;
17 var seoImportNonce = metasyncImportData.seoImportNonce;
18 var currentImportData = null;
19
20 // Handle import button clicks
21 $('.metasync-import-btn').on('click', function () {
22 var btn = $(this);
23 var type = btn.data('type');
24 var plugin = btn.data('plugin');
25 var card = btn.closest('.metasync-plugin-card');
26
27 // Special handling for SEO metadata - show options modal
28 if (type === 'seo_metadata') {
29 currentImportData = {
30 btn: btn,
31 type: type,
32 plugin: plugin,
33 card: card
34 };
35 $('#metasync-seo-options-modal').addClass('active');
36 return;
37 }
38
39 // Indexation imports are batched to avoid PHP memory exhaustion on large sites
40 if (type === 'indexation') {
41 performIndexationImport(btn, type, plugin, card);
42 return;
43 }
44
45 // For other import types, proceed directly
46 performImport(btn, type, plugin, card);
47 });
48
49 // Modal close handlers
50 $('.metasync-modal-close, #modal-cancel').on('click', function () {
51 $('#metasync-seo-options-modal').removeClass('active');
52 $('.metasync-progress-container').removeClass('active');
53 $('.metasync-progress-fill').css('width', '0%');
54 $('.metasync-progress-text').text('0%');
55 $('.metasync-progress-status').text('');
56 currentImportData = null;
57 });
58
59 // Click outside modal to close
60 $('.metasync-modal-overlay').on('click', function (e) {
61 if (e.target === this) {
62 $(this).find('.metasync-modal-close').click();
63 }
64 });
65
66 // Start Import button in modal
67 $('#modal-start-import').on('click', function () {
68 if (!currentImportData) {
69 return;
70 }
71
72 var options = {
73 import_titles: $('#import-titles').is(':checked'),
74 import_descriptions: $('#import-descriptions').is(':checked'),
75 import_social_text: $('#import-social-text').is(':checked'),
76 import_social_images: $('#import-social-images').is(':checked'),
77 overwrite_existing: $('#overwrite-existing').is(':checked')
78 };
79
80 // Disable form elements
81 $('#modal-start-import, #modal-cancel, #import-titles, #import-descriptions, #import-social-text, #import-social-images, #overwrite-existing')
82 .prop('disabled', true);
83
84 // Show progress
85 $('.metasync-progress-container').addClass('active');
86
87 // Start batch import
88 performBatchImport(currentImportData, options);
89 });
90
91 // Perform direct import (for non-SEO metadata types)
92 function performImport(btn, type, plugin, card) {
93 var resultDiv = card.find('.metasync-import-result');
94
95 btn.prop('disabled', true).text('Importing...');
96 resultDiv.removeClass('success error').hide();
97
98 $.ajax({
99 url: ajaxurl,
100 type: 'POST',
101 data: {
102 action: 'metasync_import_external_data',
103 nonce: importNonce,
104 type: type,
105 plugin: plugin
106 },
107 success: function (response) {
108 if (response.success) {
109 btn.addClass('success').text('\u2713 Imported');
110 resultDiv.addClass('success').text(response.data.message).slideDown();
111 } else {
112 btn.prop('disabled', false).text('Import ' + type.charAt(0).toUpperCase() + type.slice(1));
113 resultDiv.addClass('error').text(response.data.message || 'Import failed.').slideDown();
114 }
115 },
116 error: function () {
117 btn.prop('disabled', false).text('Retry Import');
118 resultDiv.addClass('error').text('Network error. Please try again.').slideDown();
119 }
120 });
121 }
122
123 // Perform batched indexation import with progress tracking
124 function performIndexationImport(btn, type, plugin, card) {
125 var resultDiv = card.find('.metasync-import-result');
126 var progressContainer = card.find('.metasync-progress-container');
127 var progressFill = card.find('.metasync-progress-fill');
128 var progressText = card.find('.metasync-progress-text');
129 var offset = 0;
130 var totalImported = 0;
131 var totalSkipped = 0;
132
133 btn.prop('disabled', true).text('Importing...');
134 resultDiv.removeClass('success error').hide();
135 progressFill.css('width', '0%');
136 progressText.text('0%');
137 progressContainer.addClass('active');
138
139 function processBatch() {
140 $.ajax({
141 url: ajaxurl,
142 type: 'POST',
143 data: {
144 action: 'metasync_import_external_data',
145 nonce: importNonce,
146 type: type,
147 plugin: plugin,
148 offset: offset
149 },
150 success: function (response) {
151 if (response.success && response.data) {
152 var data = response.data;
153 totalImported += data.imported || 0;
154 totalSkipped += data.skipped || 0;
155
156 var percent = data.progress_percent || 0;
157 progressFill.css('width', percent + '%');
158 progressText.text(percent + '%');
159
160 resultDiv.removeClass('error').addClass('success')
161 .text('Processing... ' + (data.processed || 0).toLocaleString() + ' of ' + (data.total || 0).toLocaleString() + ' posts')
162 .show();
163
164 if (data.is_complete) {
165 progressFill.css('width', '100%');
166 progressText.text('100%');
167 btn.addClass('success').text('✓ Imported');
168 resultDiv.text('✓ Import Complete! Imported: ' + totalImported.toLocaleString() + ' | Skipped: ' + totalSkipped.toLocaleString());
169 } else {
170 offset = data.processed || 0;
171 processBatch();
172 }
173 } else {
174 btn.prop('disabled', false).text('Retry Import');
175 progressContainer.removeClass('active');
176 var errMsg = (response.data && response.data.message) ? response.data.message : 'Import failed.';
177 resultDiv.removeClass('success').addClass('error').text(errMsg).show();
178 }
179 },
180 error: function () {
181 btn.prop('disabled', false).text('Retry Import');
182 progressContainer.removeClass('active');
183 resultDiv.removeClass('success').addClass('error').text('Network error. Please try again.').show();
184 }
185 });
186 }
187
188 processBatch();
189 }
190
191 // Perform batch import with progress tracking (for SEO metadata)
192 function performBatchImport(importData, options) {
193 var offset = 0;
194 var totalImported = 0;
195 var totalSkipped = 0;
196
197 function processBatch() {
198 $.ajax({
199 url: ajaxurl,
200 type: 'POST',
201 data: {
202 action: 'metasync_import_seo_metadata',
203 nonce: seoImportNonce,
204 plugin: importData.plugin,
205 import_titles: options.import_titles ? 1 : 0,
206 import_descriptions: options.import_descriptions ? 1 : 0,
207 import_social_text: options.import_social_text ? 1 : 0,
208 import_social_images: options.import_social_images ? 1 : 0,
209 overwrite_existing: options.overwrite_existing ? 1 : 0,
210 offset: offset
211 },
212 success: function (response) {
213 if (response.success && response.data) {
214 var data = response.data;
215 totalImported += data.imported || 0;
216 totalSkipped += data.skipped || 0;
217
218 // Update progress bar
219 var percent = data.progress_percent || 0;
220 $('.metasync-progress-fill').css('width', percent + '%');
221 $('.metasync-progress-text').text(percent + '%');
222 $('.metasync-progress-status').text(
223 'Processing... ' + (data.processed || 0) + ' of ' + (data.total || 0) + ' posts'
224 );
225
226 if (data.is_complete) {
227 // Import complete
228 $('.metasync-progress-status').empty()
229 .append($('<strong>').css('color', 'var(--dashboard-success)').text('\u2713 Import Complete!'))
230 .append(document.createTextNode(' Imported: ' + totalImported + ' posts | Skipped: ' + totalSkipped + ' posts'));
231
232 importData.btn.addClass('success').text('\u2713 Imported');
233
234 // Close modal after 2 seconds
235 setTimeout(function () {
236 $('#metasync-seo-options-modal .metasync-modal-close').click();
237 // Re-enable button for future imports
238 $('#modal-start-import, #modal-cancel, #import-titles, #import-descriptions, #import-social-text, #import-social-images, #overwrite-existing')
239 .prop('disabled', false);
240 }, 2000);
241 } else {
242 // Continue with next batch
243 offset = data.processed || 0;
244 processBatch();
245 }
246 } else {
247 // Error occurred
248 var importErrMsg = (response.data && response.data.message ? response.data.message : 'Unknown error occurred');
249 var $importStatus = $('.metasync-progress-status').empty();
250 $importStatus.append($('<strong>').css('color', 'var(--dashboard-error)').text('\u2717 Import Failed'));
251 $importStatus[0].appendChild(document.createTextNode(' ' + importErrMsg));
252 $('#modal-start-import, #modal-cancel, #import-titles, #import-descriptions, #import-social-text, #import-social-images, #overwrite-existing')
253 .prop('disabled', false);
254 }
255 },
256 error: function () {
257 $('.metasync-progress-status').empty()
258 .append($('<strong>').css('color', 'var(--dashboard-error)').text('\u2717 Network Error'))
259 .append(document.createTextNode(' Please try again'));
260 $('#modal-start-import, #modal-cancel, #import-titles, #import-descriptions, #import-social-text, #import-social-images, #overwrite-existing')
261 .prop('disabled', false);
262 }
263 });
264 }
265
266 // Start first batch
267 processBatch();
268 }
269 });
270