PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.10
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.10
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 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / admin / js / metasync-execution-settings.js

metasync-execution-settings.js in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.10, at admin/js/metasync-execution-settings.js

269 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global metasyncExecSettingsData, jQuery, ajaxurl */
2 /**
3 * MetaSync Execution Settings
4 *
5 * Extracted for Phase 5, #887.
6 * Real-time validation and AJAX save for execution / performance settings.
7 *
8 * Localized object: metasyncExecSettingsData
9 * - serverMaxExecTime (int|string 'Infinity')
10 * - serverMaxMemory (int|string 'Infinity')
11 * - canChangeMemory (bool)
12 *
13 * @since Phase 5
14 */
15 jQuery(document).ready(function ($) {
16 var $form = $('#metasync-execution-settings-form');
17 var $saveBtn = $('#metasync-execution-settings-save-btn');
18 var $message = $('#metasync-execution-settings-message');
19
20 // Server limit values from localized data
21 var serverMaxExecTime = metasyncExecSettingsData.serverMaxExecTime;
22 var serverMaxMemory = metasyncExecSettingsData.serverMaxMemory;
23 var canChangeMemory = metasyncExecSettingsData.canChangeMemory;
24
25 // Normalize string 'Infinity' to JS Infinity
26 if (serverMaxExecTime === 'Infinity') {
27 serverMaxExecTime = Infinity;
28 }
29 if (serverMaxMemory === 'Infinity') {
30 serverMaxMemory = Infinity;
31 }
32
33 // Real-time validation for server limits
34 function checkServerLimits() {
35 var maxExecTime = parseInt($('#max_execution_time').val()) || 0;
36 var maxMemory = parseInt($('#max_memory_limit').val()) || 0;
37
38 // Check execution time limit
39 if (serverMaxExecTime !== Infinity && maxExecTime > serverMaxExecTime) {
40 $('#max_execution_time_warning').show();
41 } else {
42 $('#max_execution_time_warning').hide();
43 }
44
45 // Check memory limit (only if server allows changing it)
46 if (canChangeMemory && serverMaxMemory !== Infinity && maxMemory > serverMaxMemory) {
47 $('#max_memory_limit_warning').show();
48 } else {
49 $('#max_memory_limit_warning').hide();
50 }
51 }
52
53 // Real-time validation on input change
54 $('#max_execution_time, #max_memory_limit').on('input change', function () {
55 checkServerLimits();
56 // Remove error styling when user starts typing
57 $(this).css('border-color', 'var(--dashboard-border)');
58 });
59
60 // Add visual feedback for invalid inputs
61 function highlightInvalidField($field, isValid) {
62 if (isValid) {
63 $field.css({
64 'border-color': 'var(--dashboard-border)',
65 'box-shadow': 'none'
66 });
67 } else {
68 $field.css({
69 'border-color': '#ef4444',
70 'box-shadow': '0 0 0 3px rgba(239, 68, 68, 0.1)'
71 });
72 }
73 }
74
75 // Validate individual fields on blur
76 $('#max_execution_time').on('blur', function () {
77 var value = parseInt($(this).val()) || 0;
78 var isValid = value >= 1 && value <= 300 && (serverMaxExecTime === Infinity || value <= serverMaxExecTime);
79 highlightInvalidField($(this), isValid);
80 });
81
82 $('#max_memory_limit').on('blur', function () {
83 if (!canChangeMemory) {
84 return;
85 }
86 var value = parseInt($(this).val()) || 0;
87 var isValid = value >= 64 && value <= 512 && (serverMaxMemory === Infinity || value <= serverMaxMemory);
88 highlightInvalidField($(this), isValid);
89 });
90
91 // Initial check on page load
92 checkServerLimits();
93
94 // Save button click (not form submit — form is nested inside #metaSyncGeneralSetting which would double-fire)
95 $saveBtn.on('click', function (e) {
96 e.preventDefault();
97
98 var formData = {
99 action: 'metasync_save_execution_settings',
100 execution_settings_nonce: $('#execution_settings_nonce').val(),
101 max_execution_time: $('#max_execution_time').val(),
102 max_memory_limit: $('#max_memory_limit').val(),
103 log_batch_size: $('#log_batch_size').val(),
104 action_scheduler_batches: $('#action_scheduler_batches').val(),
105 otto_rate_limit: $('#otto_rate_limit').val(),
106 queue_cleanup_days: $('#queue_cleanup_days').val()
107 };
108
109 // Clear previous error highlights
110 $('input[type="number"]').css({
111 'border-color': 'var(--dashboard-border)',
112 'box-shadow': 'none'
113 });
114
115 // Validate ranges
116 var hasError = false;
117 var errorField = null;
118
119 if (formData.max_execution_time < 1 || formData.max_execution_time > 300) {
120 showMessage('Max Execution Time must be between 1 and 300 seconds.', 'error');
121 highlightInvalidField($('#max_execution_time'), false);
122 errorField = $('#max_execution_time');
123 hasError = true;
124 } else if (serverMaxExecTime !== Infinity && formData.max_execution_time > serverMaxExecTime) {
125 showMessage('Max Execution Time exceeds server limit of ' + serverMaxExecTime + ' seconds. Please reduce the value.', 'error');
126 highlightInvalidField($('#max_execution_time'), false);
127 errorField = $('#max_execution_time');
128 hasError = true;
129 }
130
131 // Only validate memory limit if server allows changing it
132 if (canChangeMemory) {
133 if (formData.max_memory_limit < 64 || formData.max_memory_limit > 512) {
134 showMessage('Max Memory Limit must be between 64 and 512 MB.', 'error');
135 highlightInvalidField($('#max_memory_limit'), false);
136 if (!hasError) {
137 errorField = $('#max_memory_limit');
138 hasError = true;
139 }
140 } else if (serverMaxMemory !== Infinity && formData.max_memory_limit > serverMaxMemory) {
141 showMessage('Max Memory Limit exceeds server limit of ' + serverMaxMemory + ' MB. Please reduce the value.', 'error');
142 highlightInvalidField($('#max_memory_limit'), false);
143 if (!hasError) {
144 errorField = $('#max_memory_limit');
145 hasError = true;
146 }
147 }
148 }
149
150 if (formData.log_batch_size < 100 || formData.log_batch_size > 5000) {
151 showMessage('Log Batch Size must be between 100 and 5000 lines.', 'error');
152 highlightInvalidField($('#log_batch_size'), false);
153 if (!hasError) {
154 errorField = $('#log_batch_size');
155 hasError = true;
156 }
157 }
158 if (formData.action_scheduler_batches < 1 || formData.action_scheduler_batches > 10) {
159 showMessage('Action Scheduler Batches must be between 1 and 10.', 'error');
160 highlightInvalidField($('#action_scheduler_batches'), false);
161 if (!hasError) {
162 errorField = $('#action_scheduler_batches');
163 hasError = true;
164 }
165 }
166 if (formData.otto_rate_limit < 1 || formData.otto_rate_limit > 60) {
167 showMessage('OTTO Rate Limit must be between 1 and 60 calls per minute.', 'error');
168 highlightInvalidField($('#otto_rate_limit'), false);
169 if (!hasError) {
170 errorField = $('#otto_rate_limit');
171 hasError = true;
172 }
173 }
174 if (formData.queue_cleanup_days < 7 || formData.queue_cleanup_days > 90) {
175 showMessage('Queue Cleanup Days must be between 7 and 90 days.', 'error');
176 highlightInvalidField($('#queue_cleanup_days'), false);
177 if (!hasError) {
178 errorField = $('#queue_cleanup_days');
179 hasError = true;
180 }
181 }
182
183 if (hasError) {
184 if (errorField) {
185 errorField.focus();
186 // Scroll to error field
187 $('html, body').animate({
188 scrollTop: errorField.offset().top - 100
189 }, 300);
190 }
191 return;
192 }
193
194 // Show loading state
195 $saveBtn.prop('disabled', true);
196 $saveBtn.find('.save-text').text('Saving...');
197 $saveBtn.find('.save-spinner').show();
198 $message.hide();
199
200 $.ajax({
201 url: ajaxurl,
202 type: 'POST',
203 data: formData,
204 success: function (response) {
205 if (response.success) {
206 showMessage(response.data.message || 'Settings saved successfully!', 'success');
207 // Re-enable button
208 $saveBtn.prop('disabled', false);
209 $saveBtn.find('.save-text').text('Save Settings');
210 $saveBtn.find('.save-spinner').hide();
211 // Re-check server limits after save
212 setTimeout(function () {
213 checkServerLimits();
214 }, 100);
215 // Scroll to top to show success message
216 $('html, body').animate({
217 scrollTop: $form.offset().top - 100
218 }, 300);
219 } else {
220 showMessage(response.data.message || 'Error saving settings.', 'error');
221 $saveBtn.prop('disabled', false);
222 $saveBtn.find('.save-text').text('Save Settings');
223 $saveBtn.find('.save-spinner').hide();
224 // Scroll to show error message
225 $('html, body').animate({
226 scrollTop: $message.offset().top - 100
227 }, 300);
228 }
229 },
230 error: function () {
231 showMessage('An error occurred while saving settings. Please try again.', 'error');
232 $saveBtn.prop('disabled', false);
233 $saveBtn.find('.save-text').text('Save Settings');
234 $saveBtn.find('.save-spinner').hide();
235 // Scroll to show error message
236 $('html, body').animate({
237 scrollTop: $message.offset().top - 100
238 }, 300);
239 }
240 });
241 });
242
243 function showMessage(text, type) {
244 $message.removeClass('notice-success notice-error')
245 .addClass('notice-' + type)
246 .css({
247 'background': type === 'success' ? 'rgba(34, 197, 94, 0.1)' : 'rgba(239, 68, 68, 0.1)',
248 'border': '1px solid ' + (type === 'success' ? 'rgba(34, 197, 94, 0.3)' : 'rgba(239, 68, 68, 0.3)'),
249 'color': type === 'success' ? '#22c55e' : '#ef4444',
250 'padding': '12px 16px',
251 'border-radius': '6px',
252 'font-size': '14px',
253 'line-height': '1.5',
254 'display': 'block'
255 })
256 .empty()
257 .append($('<strong>').css('margin-right', '8px').text(type === 'success' ? '\u2713' : '\u2717'))
258 .show();
259 $message[0].appendChild(document.createTextNode(text));
260
261 // Auto-hide success messages after 5 seconds
262 if (type === 'success') {
263 setTimeout(function () {
264 $message.fadeOut(300);
265 }, 5000);
266 }
267 }
268 });
269