| @@ -1,0 +1,365 @@ | ||
| 1 | +/** | |
| 2 | + * Admin status auto-update functionality | |
| 3 | + */ | |
| 4 | +(function($) { | |
| 5 | + 'use strict'; | |
| 6 | + | |
| 7 | + // Status update interval ID | |
| 8 | + let statusInterval = null; | |
| 9 | + const refreshInterval = 3000; // 3 seconds | |
| 10 | + | |
| 11 | + // Flag to track if we've seen an error | |
| 12 | + let errorDetected = false; | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * Updates the status cards with fresh data | |
| 16 | + */ | |
| 17 | + function updateStatus() { | |
| 18 | + $.ajax({ | |
| 19 | + url: mxchat_status_data.ajax_url, | |
| 20 | + type: 'POST', | |
| 21 | + data: { | |
| 22 | + action: 'mxchat_get_status_updates', | |
| 23 | + nonce: mxchat_status_data.nonce | |
| 24 | + }, | |
| 25 | + success: function(response) { | |
| 26 | + // Check for error states in sitemap or PDF | |
| 27 | + const hasSitemapError = response.sitemap_status && response.sitemap_status.status === 'error'; | |
| 28 | + const hasPdfError = response.pdf_status && response.pdf_status.status === 'error'; | |
| 29 | + | |
| 30 | + // If any error is detected | |
| 31 | + if (hasSitemapError || hasPdfError) { | |
| 32 | + //console.log('Error detected in processing, stopping auto-refresh'); | |
| 33 | + | |
| 34 | + // Update PDF status UI if it has an error | |
| 35 | + if (hasPdfError) { | |
| 36 | + updatePdfErrorStatus(response.pdf_status); | |
| 37 | + } | |
| 38 | + | |
| 39 | + // If this is the first time we're seeing an error | |
| 40 | + if (!errorDetected) { | |
| 41 | + errorDetected = true; | |
| 42 | + | |
| 43 | + // Stop the interval immediately | |
| 44 | + if (statusInterval) { | |
| 45 | + clearInterval(statusInterval); | |
| 46 | + statusInterval = null; | |
| 47 | + } | |
| 48 | + | |
| 49 | + // Show single URL status if available | |
| 50 | + if (response.single_url_status) { | |
| 51 | + $('#mxchat-single-url-status-container').show(); | |
| 52 | + updateSingleUrlStatus(response.single_url_status); | |
| 53 | + } | |
| 54 | + } | |
| 55 | + | |
| 56 | + // Return early to prevent any page reloads | |
| 57 | + return; | |
| 58 | + } | |
| 59 | + | |
| 60 | + // Check if sitemap or PDF is in active processing | |
| 61 | + const isActiveProcessing = | |
| 62 | + (response.sitemap_status && response.sitemap_status.status === 'processing') || | |
| 63 | + (response.pdf_status && response.pdf_status.status === 'processing'); | |
| 64 | + | |
| 65 | + // Handle single URL status | |
| 66 | + if (response.single_url_status && !isActiveProcessing) { | |
| 67 | + $('#mxchat-single-url-status-container').show(); | |
| 68 | + updateSingleUrlStatus(response.single_url_status); | |
| 69 | + } else if (isActiveProcessing) { | |
| 70 | + $('#mxchat-single-url-status-container').hide(); | |
| 71 | + } | |
| 72 | + | |
| 73 | + // Update sitemap status if it exists and is not in error state | |
| 74 | + if (response.sitemap_status && response.sitemap_status.status !== 'error') { | |
| 75 | + // Update progress bar | |
| 76 | + $('.mxchat-status-card:contains("Sitemap Processing") .mxchat-progress-fill') | |
| 77 | + .css('width', response.sitemap_status.percentage + '%'); | |
| 78 | + | |
| 79 | + // Update status text | |
| 80 | + $('.mxchat-status-card:contains("Sitemap Processing") .mxchat-status-details p:first') | |
| 81 | + .text('Progress: ' + response.sitemap_status.processed_urls + ' of ' + | |
| 82 | + response.sitemap_status.total_urls + ' URLs (' + | |
| 83 | + response.sitemap_status.percentage + '%)'); | |
| 84 | + | |
| 85 | + // If complete, reload once | |
| 86 | + if (response.sitemap_status.status === 'complete') { | |
| 87 | + //console.log('Sitemap processing complete, reloading page'); | |
| 88 | + if (statusInterval) { | |
| 89 | + clearInterval(statusInterval); | |
| 90 | + statusInterval = null; | |
| 91 | + } | |
| 92 | + location.reload(); | |
| 93 | + return; | |
| 94 | + } | |
| 95 | + } else if (!response.sitemap_status) { | |
| 96 | + // If no sitemap status, remove the card with animation | |
| 97 | + $('.mxchat-status-card:contains("Sitemap Processing")').fadeOut(300); | |
| 98 | + } | |
| 99 | + | |
| 100 | + // Update PDF status if it exists and is not in error state | |
| 101 | + if (response.pdf_status && response.pdf_status.status !== 'error') { | |
| 102 | + updatePdfStatus(response.pdf_status); | |
| 103 | + | |
| 104 | + // If complete, reload once | |
| 105 | + if (response.pdf_status.status === 'complete') { | |
| 106 | + //console.log('PDF processing complete, reloading page'); | |
| 107 | + if (statusInterval) { | |
| 108 | + clearInterval(statusInterval); | |
| 109 | + statusInterval = null; | |
| 110 | + } | |
| 111 | + location.reload(); | |
| 112 | + return; | |
| 113 | + } | |
| 114 | + } else if (!response.pdf_status) { | |
| 115 | + // If no PDF status, remove the card with animation | |
| 116 | + $('.mxchat-status-card:contains("PDF Processing")').fadeOut(300); | |
| 117 | + } | |
| 118 | + | |
| 119 | + // If nothing is processing anymore and no errors detected, stop checking | |
| 120 | + if (!isActiveProcessing && !errorDetected) { | |
| 121 | + //console.log('No active processing, stopping auto-refresh'); | |
| 122 | + if (statusInterval) { | |
| 123 | + clearInterval(statusInterval); | |
| 124 | + statusInterval = null; | |
| 125 | + } | |
| 126 | + | |
| 127 | + // Show single URL status if it exists | |
| 128 | + if (response.single_url_status) { | |
| 129 | + $('#mxchat-single-url-status-container').show(); | |
| 130 | + updateSingleUrlStatus(response.single_url_status); | |
| 131 | + } else { | |
| 132 | + // Only reload if we have no single URL status | |
| 133 | + location.reload(); | |
| 134 | + } | |
| 135 | + } | |
| 136 | + }, | |
| 137 | + error: function(xhr, status, error) { | |
| 138 | + //console.error('AJAX error:', error); | |
| 139 | + // If AJAX fails, stop the interval | |
| 140 | + if (statusInterval) { | |
| 141 | + clearInterval(statusInterval); | |
| 142 | + statusInterval = null; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + }); | |
| 146 | + } | |
| 147 | + | |
| 148 | + /** | |
| 149 | + * Updates the PDF status card with normal processing info | |
| 150 | + */ | |
| 151 | + function updatePdfStatus(status) { | |
| 152 | + // Update progress bar | |
| 153 | + $('.mxchat-status-card:contains("PDF Processing") .mxchat-progress-fill') | |
| 154 | + .css('width', status.percentage + '%'); | |
| 155 | + | |
| 156 | + // Update status text | |
| 157 | + $('.mxchat-status-card:contains("PDF Processing") .mxchat-status-details p:first') | |
| 158 | + .text('Progress: ' + status.processed_pages + ' of ' + | |
| 159 | + status.total_pages + ' pages (' + | |
| 160 | + status.percentage + '%)'); | |
| 161 | + | |
| 162 | + // Update status and last update | |
| 163 | + let statusText = $('.mxchat-status-card:contains("PDF Processing") .mxchat-status-details p:nth-child(2)'); | |
| 164 | + if (statusText.length) { | |
| 165 | + statusText.text('Status: ' + (status.status.charAt(0).toUpperCase() + status.status.slice(1))); | |
| 166 | + } | |
| 167 | + | |
| 168 | + let lastUpdateText = $('.mxchat-status-card:contains("PDF Processing") .mxchat-status-details p:nth-child(3)'); | |
| 169 | + if (lastUpdateText.length) { | |
| 170 | + lastUpdateText.text('Last update: ' + status.last_update); | |
| 171 | + } | |
| 172 | + } | |
| 173 | + | |
| 174 | + /** | |
| 175 | + * Updates the PDF status card with error information | |
| 176 | + */ | |
| 177 | + function updatePdfErrorStatus(status) { | |
| 178 | + // Find the PDF status card | |
| 179 | + let pdfCard = $('.mxchat-status-card:contains("PDF Processing")'); | |
| 180 | + | |
| 181 | + if (pdfCard.length === 0) { | |
| 182 | + // If card doesn't exist for some reason, we'll create it | |
| 183 | + pdfCard = $('<div class="mxchat-status-card"></div>'); | |
| 184 | + $('.mxchat-import-form').after(pdfCard); | |
| 185 | + | |
| 186 | + // Create header | |
| 187 | + let header = $('<div class="mxchat-status-header"></div>'); | |
| 188 | + header.append('<h4>PDF Processing Status</h4>'); | |
| 189 | + header.append('<span class="mxchat-status-badge mxchat-status-failed">Error</span>'); | |
| 190 | + pdfCard.append(header); | |
| 191 | + | |
| 192 | + // Create progress bar | |
| 193 | + let progressBar = $('<div class="mxchat-progress-bar"></div>'); | |
| 194 | + progressBar.append('<div class="mxchat-progress-fill" style="width: ' + status.percentage + '%"></div>'); | |
| 195 | + pdfCard.append(progressBar); | |
| 196 | + | |
| 197 | + // Create details section | |
| 198 | + let details = $('<div class="mxchat-status-details"></div>'); | |
| 199 | + pdfCard.append(details); | |
| 200 | + | |
| 201 | + // Add progress info | |
| 202 | + details.append('<p>Progress: ' + status.processed_pages + ' of ' + | |
| 203 | + status.total_pages + ' pages (' + status.percentage + '%)</p>'); | |
| 204 | + | |
| 205 | + // Add status info | |
| 206 | + details.append('<p>Status: Error</p>'); | |
| 207 | + | |
| 208 | + // Add last update info | |
| 209 | + details.append('<p>Last update: ' + status.last_update + '</p>'); | |
| 210 | + | |
| 211 | + // Add error message | |
| 212 | + if (status.error) { | |
| 213 | + let errorNotice = $('<div class="mxchat-error-notice"></div>'); | |
| 214 | + errorNotice.append('<p class="error">' + status.error + '</p>'); | |
| 215 | + details.append(errorNotice); | |
| 216 | + } | |
| 217 | + } else { | |
| 218 | + // Update existing card | |
| 219 | + | |
| 220 | + // Make sure we have the error badge | |
| 221 | + if (pdfCard.find('.mxchat-status-badge.mxchat-status-failed').length === 0) { | |
| 222 | + pdfCard.find('.mxchat-status-header').append('<span class="mxchat-status-badge mxchat-status-failed">Error</span>'); | |
| 223 | + } | |
| 224 | + | |
| 225 | + // Update progress bar | |
| 226 | + pdfCard.find('.mxchat-progress-fill').css('width', status.percentage + '%'); | |
| 227 | + | |
| 228 | + // Update status text | |
| 229 | + pdfCard.find('.mxchat-status-details p:first') | |
| 230 | + .text('Progress: ' + status.processed_pages + ' of ' + | |
| 231 | + status.total_pages + ' pages (' + | |
| 232 | + status.percentage + '%)'); | |
| 233 | + | |
| 234 | + // Update status and last update | |
| 235 | + let statusText = pdfCard.find('.mxchat-status-details p:nth-child(2)'); | |
| 236 | + if (statusText.length) { | |
| 237 | + statusText.text('Status: Error'); | |
| 238 | + } else { | |
| 239 | + pdfCard.find('.mxchat-status-details').append('<p>Status: Error</p>'); | |
| 240 | + } | |
| 241 | + | |
| 242 | + let lastUpdateText = pdfCard.find('.mxchat-status-details p:nth-child(3)'); | |
| 243 | + if (lastUpdateText.length) { | |
| 244 | + lastUpdateText.text('Last update: ' + status.last_update); | |
| 245 | + } else { | |
| 246 | + pdfCard.find('.mxchat-status-details').append('<p>Last update: ' + status.last_update + '</p>'); | |
| 247 | + } | |
| 248 | + | |
| 249 | + // Add or update error message | |
| 250 | + if (status.error) { | |
| 251 | + let errorNotice = pdfCard.find('.mxchat-error-notice'); | |
| 252 | + if (errorNotice.length) { | |
| 253 | + errorNotice.find('p.error').text(status.error); | |
| 254 | + } else { | |
| 255 | + errorNotice = $('<div class="mxchat-error-notice"></div>'); | |
| 256 | + errorNotice.append('<p class="error">' + status.error + '</p>'); | |
| 257 | + pdfCard.find('.mxchat-status-details').append(errorNotice); | |
| 258 | + } | |
| 259 | + } | |
| 260 | + } | |
| 261 | + } | |
| 262 | + | |
| 263 | + /** | |
| 264 | + * Updates the single URL status card | |
| 265 | + */ | |
| 266 | + function updateSingleUrlStatus(status) { | |
| 267 | + // Check if the status container exists | |
| 268 | + let container = $('#mxchat-single-url-status-container'); | |
| 269 | + | |
| 270 | + if (container.length === 0) { | |
| 271 | + // Create container if it doesn't exist | |
| 272 | + container = $('<div id="mxchat-single-url-status-container"></div>'); | |
| 273 | + $('.mxchat-import-form').after(container); | |
| 274 | + } | |
| 275 | + | |
| 276 | + // Generate the HTML for the status card | |
| 277 | + const html = generateSingleUrlStatusHtml(status); | |
| 278 | + | |
| 279 | + // Update the container - replace entire content | |
| 280 | + container.html(html); | |
| 281 | + } | |
| 282 | + | |
| 283 | + /** | |
| 284 | + * Generates HTML for the single URL status card | |
| 285 | + */ | |
| 286 | + function generateSingleUrlStatusHtml(status) { | |
| 287 | + let html = '<div class="mxchat-status-card">'; | |
| 288 | + html += '<div class="mxchat-status-header">'; | |
| 289 | + html += '<h4>Last URL Submission</h4>'; | |
| 290 | + | |
| 291 | + if (status.status === 'failed') { | |
| 292 | + html += '<span class="mxchat-status-badge mxchat-status-failed">Failed</span>'; | |
| 293 | + } else { | |
| 294 | + html += '<span class="mxchat-status-badge mxchat-status-success">Success</span>'; | |
| 295 | + } | |
| 296 | + | |
| 297 | + html += '</div>'; // End header | |
| 298 | + | |
| 299 | + html += '<div class="mxchat-status-details">'; | |
| 300 | + html += '<p><strong>URL:</strong> '; | |
| 301 | + html += '<a href="' + status.url + '" target="_blank">'; | |
| 302 | + | |
| 303 | + // Truncate URL if needed | |
| 304 | + const displayUrl = status.url.length > 60 ? status.url.substring(0, 57) + '...' : status.url; | |
| 305 | + html += displayUrl; | |
| 306 | + | |
| 307 | + html += '</a></p>'; | |
| 308 | + html += '<p><strong>Submitted:</strong> ' + status.human_time + '</p>'; | |
| 309 | + | |
| 310 | + if (status.status === 'failed' && status.error) { | |
| 311 | + html += '<div class="mxchat-error-notice">'; | |
| 312 | + html += '<p class="error">' + status.error + '</p>'; | |
| 313 | + html += '</div>'; | |
| 314 | + } | |
| 315 | + | |
| 316 | + if (status.status === 'complete') { | |
| 317 | + html += '<p><strong>Content Length:</strong> ' + status.content_length + ' characters</p>'; | |
| 318 | + html += '<p><strong>Embedding Dimensions:</strong> ' + status.embedding_dimensions + '</p>'; | |
| 319 | + } | |
| 320 | + | |
| 321 | + html += '</div>'; // End details | |
| 322 | + html += '</div>'; // End card | |
| 323 | + | |
| 324 | + return html; | |
| 325 | + } | |
| 326 | + | |
| 327 | + // Initialize when the document is ready | |
| 328 | + $(document).ready(function() { | |
| 329 | + // Reset error detection flag | |
| 330 | + errorDetected = false; | |
| 331 | + | |
| 332 | + // Change the text in the status headers | |
| 333 | + $('.mxchat-status-header h4:contains("Refresh for update")').each(function() { | |
| 334 | + $(this).text($(this).text().replace('(Refresh for update)', '(Auto-updating)')); | |
| 335 | + }); | |
| 336 | + | |
| 337 | + // Check if we already have error messages displayed | |
| 338 | + if ($('.mxchat-error-notice').length > 0) { | |
| 339 | + //console.log('Error notices already present, not starting auto-refresh'); | |
| 340 | + errorDetected = true; | |
| 341 | + return; // Don't start auto-refresh if errors are already shown | |
| 342 | + } | |
| 343 | + | |
| 344 | + // Start auto-updating if we have status cards and no errors | |
| 345 | + if ($('.mxchat-status-card').length > 0 && !errorDetected) { | |
| 346 | + //console.log('Starting auto-refresh for status updates'); | |
| 347 | + updateStatus(); // Run once immediately | |
| 348 | + statusInterval = setInterval(updateStatus, refreshInterval); | |
| 349 | + } | |
| 350 | + | |
| 351 | + // Monitor for form submissions to start the updates | |
| 352 | + $('#mxchat-sitemap-form').on('submit', function() { | |
| 353 | + //console.log('Form submitted, resetting error detection'); | |
| 354 | + // Reset error detection on new submission | |
| 355 | + errorDetected = false; | |
| 356 | + | |
| 357 | + // Start updating after submission if not already running | |
| 358 | + if (statusInterval === null) { | |
| 359 | + //console.log('Starting auto-refresh after form submission'); | |
| 360 | + statusInterval = setInterval(updateStatus, refreshInterval); | |
| 361 | + } | |
| 362 | + }); | |
| 363 | + }); | |
| 364 | + | |
| 365 | +})(jQuery); | |