PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.6
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.6
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 / admin / js / metasync-execution-settings.js

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

265 lines 10.7 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) return;
84 var value = parseInt($(this).val()) || 0;
85 var isValid = value >= 64 && value <= 512 && (serverMaxMemory === Infinity || value <= serverMaxMemory);
86 highlightInvalidField($(this), isValid);
87 });
88
89 // Initial check on page load
90 checkServerLimits();
91
92 // Save button click (not form submit — form is nested inside #metaSyncGeneralSetting which would double-fire)
93 $saveBtn.on('click', function (e) {
94 e.preventDefault();
95
96 var formData = {
97 action: 'metasync_save_execution_settings',
98 execution_settings_nonce: $('#execution_settings_nonce').val(),
99 max_execution_time: $('#max_execution_time').val(),
100 max_memory_limit: $('#max_memory_limit').val(),
101 log_batch_size: $('#log_batch_size').val(),
102 action_scheduler_batches: $('#action_scheduler_batches').val(),
103 otto_rate_limit: $('#otto_rate_limit').val(),
104 queue_cleanup_days: $('#queue_cleanup_days').val()
105 };
106
107 // Clear previous error highlights
108 $('input[type="number"]').css({
109 'border-color': 'var(--dashboard-border)',
110 'box-shadow': 'none'
111 });
112
113 // Validate ranges
114 var hasError = false;
115 var errorField = null;
116
117 if (formData.max_execution_time < 1 || formData.max_execution_time > 300) {
118 showMessage('Max Execution Time must be between 1 and 300 seconds.', 'error');
119 highlightInvalidField($('#max_execution_time'), false);
120 errorField = $('#max_execution_time');
121 hasError = true;
122 } else if (serverMaxExecTime !== Infinity && formData.max_execution_time > serverMaxExecTime) {
123 showMessage('Max Execution Time exceeds server limit of ' + serverMaxExecTime + ' seconds. Please reduce the value.', 'error');
124 highlightInvalidField($('#max_execution_time'), false);
125 errorField = $('#max_execution_time');
126 hasError = true;
127 }
128
129 // Only validate memory limit if server allows changing it
130 if (canChangeMemory) {
131 if (formData.max_memory_limit < 64 || formData.max_memory_limit > 512) {
132 showMessage('Max Memory Limit must be between 64 and 512 MB.', 'error');
133 highlightInvalidField($('#max_memory_limit'), false);
134 if (!hasError) {
135 errorField = $('#max_memory_limit');
136 hasError = true;
137 }
138 } else if (serverMaxMemory !== Infinity && formData.max_memory_limit > serverMaxMemory) {
139 showMessage('Max Memory Limit exceeds server limit of ' + serverMaxMemory + ' MB. Please reduce the value.', 'error');
140 highlightInvalidField($('#max_memory_limit'), false);
141 if (!hasError) {
142 errorField = $('#max_memory_limit');
143 hasError = true;
144 }
145 }
146 }
147
148 if (formData.log_batch_size < 100 || formData.log_batch_size > 5000) {
149 showMessage('Log Batch Size must be between 100 and 5000 lines.', 'error');
150 highlightInvalidField($('#log_batch_size'), false);
151 if (!hasError) {
152 errorField = $('#log_batch_size');
153 hasError = true;
154 }
155 }
156 if (formData.action_scheduler_batches < 1 || formData.action_scheduler_batches > 10) {
157 showMessage('Action Scheduler Batches must be between 1 and 10.', 'error');
158 highlightInvalidField($('#action_scheduler_batches'), false);
159 if (!hasError) {
160 errorField = $('#action_scheduler_batches');
161 hasError = true;
162 }
163 }
164 if (formData.otto_rate_limit < 1 || formData.otto_rate_limit > 60) {
165 showMessage('OTTO Rate Limit must be between 1 and 60 calls per minute.', 'error');
166 highlightInvalidField($('#otto_rate_limit'), false);
167 if (!hasError) {
168 errorField = $('#otto_rate_limit');
169 hasError = true;
170 }
171 }
172 if (formData.queue_cleanup_days < 7 || formData.queue_cleanup_days > 90) {
173 showMessage('Queue Cleanup Days must be between 7 and 90 days.', 'error');
174 highlightInvalidField($('#queue_cleanup_days'), false);
175 if (!hasError) {
176 errorField = $('#queue_cleanup_days');
177 hasError = true;
178 }
179 }
180
181 if (hasError) {
182 if (errorField) {
183 errorField.focus();
184 // Scroll to error field
185 $('html, body').animate({
186 scrollTop: errorField.offset().top - 100
187 }, 300);
188 }
189 return;
190 }
191
192 // Show loading state
193 $saveBtn.prop('disabled', true);
194 $saveBtn.find('.save-text').text('Saving...');
195 $saveBtn.find('.save-spinner').show();
196 $message.hide();
197
198 $.ajax({
199 url: ajaxurl,
200 type: 'POST',
201 data: formData,
202 success: function (response) {
203 if (response.success) {
204 showMessage(response.data.message || 'Settings saved successfully!', 'success');
205 // Re-enable button
206 $saveBtn.prop('disabled', false);
207 $saveBtn.find('.save-text').text('Save Settings');
208 $saveBtn.find('.save-spinner').hide();
209 // Re-check server limits after save
210 setTimeout(function () {
211 checkServerLimits();
212 }, 100);
213 // Scroll to top to show success message
214 $('html, body').animate({
215 scrollTop: $form.offset().top - 100
216 }, 300);
217 } else {
218 showMessage(response.data.message || 'Error saving settings.', 'error');
219 $saveBtn.prop('disabled', false);
220 $saveBtn.find('.save-text').text('Save Settings');
221 $saveBtn.find('.save-spinner').hide();
222 // Scroll to show error message
223 $('html, body').animate({
224 scrollTop: $message.offset().top - 100
225 }, 300);
226 }
227 },
228 error: function () {
229 showMessage('An error occurred while saving settings. Please try again.', 'error');
230 $saveBtn.prop('disabled', false);
231 $saveBtn.find('.save-text').text('Save Settings');
232 $saveBtn.find('.save-spinner').hide();
233 // Scroll to show error message
234 $('html, body').animate({
235 scrollTop: $message.offset().top - 100
236 }, 300);
237 }
238 });
239 });
240
241 function showMessage(text, type) {
242 $message.removeClass('notice-success notice-error')
243 .addClass('notice-' + type)
244 .css({
245 'background': type === 'success' ? 'rgba(34, 197, 94, 0.1)' : 'rgba(239, 68, 68, 0.1)',
246 'border': '1px solid ' + (type === 'success' ? 'rgba(34, 197, 94, 0.3)' : 'rgba(239, 68, 68, 0.3)'),
247 'color': type === 'success' ? '#22c55e' : '#ef4444',
248 'padding': '12px 16px',
249 'border-radius': '6px',
250 'font-size': '14px',
251 'line-height': '1.5',
252 'display': 'block'
253 })
254 .html('<strong style="margin-right: 8px;">' + (type === 'success' ? '\u2713' : '\u2717') + '</strong>' + text)
255 .show();
256
257 // Auto-hide success messages after 5 seconds
258 if (type === 'success') {
259 setTimeout(function () {
260 $message.fadeOut(300);
261 }, 5000);
262 }
263 }
264 });
265