PluginProbe
wpForo Forum / 3.2.1
wpForo Forum v3.2.1
3.2.1 3.2.0 3.1.7 3.1.6 3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 All 141 releases
wpforo / admin / assets / js / ai-features-wp-indexing.js

ai-features-wp-indexing.js in wpForo Forum 3.2.1, at admin/assets/js/ai-features-wp-indexing.js

747 lines 22.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * wpForo AI Features - WordPress Content Indexing
3 *
4 * Isolated JavaScript for WordPress content indexing tab.
5 * Completely independent from forum indexing handlers.
6 *
7 * @package wpForo
8 * @subpackage Admin
9 * @since 3.0.0
10 */
11
12 (function($) {
13 'use strict';
14
15 const WpForoWPIndexing = {
16 initialized: false,
17 wpIndexingPollInterval: null,
18 _wpAutoRefreshTimeout: null,
19
20 /**
21 * Initialize WordPress content indexing features
22 */
23 init: function() {
24 if (this.initialized) return;
25
26 // Only init if on WordPress Indexing tab
27 if (!$('.wpforo-ai-wp-indexing-tab').length) return;
28
29 this.initialized = true;
30 this.bindEvents();
31 this.loadWPIndexingStatus();
32 this.checkWPIndexingAutoRefresh();
33 },
34
35 /**
36 * Bind all event handlers
37 */
38 bindEvents: function() {
39 const self = this;
40
41 // Refresh status button
42 $(document).on('click', '.wpforo-ai-wp-refresh-status', this.handleRefreshWPStatus.bind(this));
43
44 // Taxonomy dropdown change
45 $(document).on('change', '#wp-taxonomy-select', this.handleTaxonomyChange.bind(this));
46
47 // Form submissions
48 $(document).on('submit', '.wpforo-ai-wp-taxonomy-form', this.handleWPTaxonomyIndex.bind(this));
49 $(document).on('submit', '.wpforo-ai-wp-custom-form', this.handleWPCustomIndex.bind(this));
50 $(document).on('submit', '.wpforo-ai-wp-ids-form', this.handleWPIndexByIds.bind(this));
51
52 // Clear index button
53 $(document).on('click', '.wpforo-ai-wp-clear-index', this.handleWPClearIndex.bind(this));
54
55 // Cleanup session button (WordPress-specific)
56 $(document).on('click', '.wpforo-ai-wp-cleanup-session', this.handleCleanupSession.bind(this));
57
58 // Toggle switches
59 $(document).on('change', '#wpforo-ai-wp-auto-indexing', this.handleWPAutoIndexingToggle.bind(this));
60 $(document).on('change', '#wpforo-ai-wp-image-indexing', this.handleWPImageIndexingToggle.bind(this));
61
62 // Select All / Deselect All for terms
63 $(document).on('click', '.wpforo-ai-wp-select-all-terms', function() {
64 $('#wp-terms-container input[type="checkbox"]').prop('checked', true);
65 self.updateTermIndexButton();
66 });
67 $(document).on('click', '.wpforo-ai-wp-deselect-all-terms', function() {
68 $('#wp-terms-container input[type="checkbox"]').prop('checked', false);
69 self.updateTermIndexButton();
70 });
71 },
72
73 /**
74 * Refresh WordPress indexing status
75 */
76 handleRefreshWPStatus: function(e) {
77 e.preventDefault();
78 const self = this;
79 const $button = $(e.currentTarget);
80 const $icon = $button.find('.dashicons-update');
81
82 $icon.addClass('wpforo-spin');
83 $button.prop('disabled', true);
84
85 this.loadWPIndexingStatus(function() {
86 $icon.removeClass('wpforo-spin');
87 $button.prop('disabled', false);
88 });
89 },
90
91 /**
92 * Load WordPress indexing status from API
93 */
94 loadWPIndexingStatus: function(callback) {
95 const self = this;
96
97 $.ajax({
98 url: wpforoAIAdmin.ajaxUrl,
99 type: 'POST',
100 data: {
101 action: 'wpforo_ai_wp_get_indexing_status',
102 security: wpforoAIAdmin.adminNonce
103 },
104 success: function(response) {
105 if (response.success && response.data) {
106 self.updateWPIndexingDisplay(response.data);
107
108 // Start polling if indexing is in progress
109 if (response.data.queue && response.data.queue.status === 'processing') {
110 self.startWPIndexingPolling();
111 } else {
112 self.stopWPIndexingPolling();
113 }
114 }
115 },
116 error: function(xhr, status, error) {
117 console.error('Failed to load WordPress indexing status:', error);
118 },
119 complete: function() {
120 if (typeof callback === 'function') {
121 callback();
122 }
123 }
124 });
125 },
126
127 /**
128 * Start polling for WordPress indexing status
129 */
130 startWPIndexingPolling: function() {
131 const self = this;
132
133 // Don't start if already polling
134 if (this.wpIndexingPollInterval) {
135 return;
136 }
137
138 // Poll every 5 seconds
139 this.wpIndexingPollInterval = setInterval(function() {
140 self.loadWPIndexingStatus();
141 }, 5000);
142 },
143
144 /**
145 * Stop polling for WordPress indexing status
146 */
147 stopWPIndexingPolling: function() {
148 if (this.wpIndexingPollInterval) {
149 clearInterval(this.wpIndexingPollInterval);
150 this.wpIndexingPollInterval = null;
151 }
152 },
153
154 /**
155 * Start auto page refresh for WordPress content indexing.
156 */
157 startWPIndexingAutoRefresh: function() {
158 // Store flag to indicate we're in auto-refresh mode
159 try {
160 localStorage.setItem('wpforo_wp_indexing_auto_refresh', '1');
161 } catch (e) { /* localStorage may be blocked */ }
162
163 console.log('WP content indexing: reloading page to trigger cron nudge...');
164 window.location.hash = 'wp-indexing-status-box'; window.location.reload();
165 },
166
167 /**
168 * Check on page load if auto-refresh should continue.
169 */
170 checkWPIndexingAutoRefresh: function() {
171 const self = this;
172
173 // Check if we're in auto-refresh mode
174 let inAutoRefresh = false;
175 try {
176 inAutoRefresh = localStorage.getItem('wpforo_wp_indexing_auto_refresh') === '1';
177 } catch (e) { /* localStorage may be blocked */ }
178
179 if (!inAutoRefresh) {
180 return;
181 }
182
183 // Check current indexing status
184 $.ajax({
185 url: wpforoAIAdmin.ajaxUrl,
186 type: 'POST',
187 data: {
188 action: 'wpforo_ai_wp_get_indexing_status',
189 security: wpforoAIAdmin.adminNonce
190 },
191 success: function(response) {
192 if (response.success && response.data) {
193 // Check if still processing
194 if (response.data.queue && response.data.queue.status === 'processing') {
195 console.log('WP indexing in progress, will refresh in 20 seconds...');
196 // Schedule next refresh in 20 seconds
197 self._wpAutoRefreshTimeout = setTimeout(function() {
198 window.location.hash = 'wp-indexing-status-box'; window.location.reload();
199 }, 20000);
200 } else {
201 // Done - clear auto-refresh flag and do final reload
202 // to ensure server-rendered HTML shows correct state
203 console.log('WP content indexing complete, final reload');
204 self.stopWPIndexingAutoRefresh();
205 window.location.hash = 'wp-indexing-status-box'; window.location.reload();
206 }
207 }
208 },
209 error: function() {
210 // On error, stop auto-refresh to avoid infinite reload loop
211 self.stopWPIndexingAutoRefresh();
212 }
213 });
214 },
215
216 /**
217 * Stop auto page refresh and clear the flag.
218 */
219 stopWPIndexingAutoRefresh: function() {
220 try {
221 localStorage.removeItem('wpforo_wp_indexing_auto_refresh');
222 } catch (e) { /* localStorage may be blocked */ }
223
224 if (this._wpAutoRefreshTimeout) {
225 clearTimeout(this._wpAutoRefreshTimeout);
226 this._wpAutoRefreshTimeout = null;
227 }
228 },
229
230 /**
231 * Update WordPress indexing display with status data
232 */
233 updateWPIndexingDisplay: function(data) {
234 // Update total indexed
235 if (data.total_indexed !== undefined) {
236 $('#wp-total-indexed').text(data.total_indexed.toLocaleString());
237
238 // Update coverage percentage
239 const totalContent = parseInt($('#wp-total-content').text().replace(/,/g, ''), 10) || 0;
240 if (totalContent > 0) {
241 const percentage = Math.round((data.total_indexed / totalContent) * 100 * 10) / 10;
242 $('#wp-indexed-percentage').text(percentage + '%');
243 }
244 }
245
246 // Update by_type counts
247 if (data.by_type) {
248 for (const [type, info] of Object.entries(data.by_type)) {
249 const postType = type.replace('wp_', '');
250 const $indexed = $('#wp-indexed-' + postType + ' .indexed-count');
251 if ($indexed.length) {
252 $indexed.text(info.indexed || 0);
253 }
254 }
255 }
256
257 // Update last activity
258 if (data.last_indexed_at_formatted) {
259 $('#wp-last-activity').text(data.last_indexed_at_formatted);
260 } else if (!data.last_indexed_at) {
261 $('#wp-last-activity').text(wpforoAIAdmin.strings?.noActivity || 'No activity yet');
262 }
263
264 // Get status elements
265 const $statusElement = $('#wp-indexing-status');
266
267 // Update status with spinner animation
268 if (data.queue && data.queue.status === 'processing') {
269 $statusElement.html(
270 '<span class="dashicons dashicons-update-alt wpforo-wp-indexing-spin"></span> ' +
271 (wpforoAIAdmin.strings?.indexing || 'Indexing...')
272 ).removeClass('status-idle').addClass('status-active');
273 } else {
274 $statusElement.html(
275 '<span class="dashicons dashicons-yes-alt"></span> ' +
276 (wpforoAIAdmin.strings?.idle || 'Idle')
277 ).removeClass('status-active').addClass('status-idle');
278 }
279 },
280
281 /**
282 * Handle taxonomy dropdown change - load terms as checkboxes
283 */
284 handleTaxonomyChange: function(e) {
285 const self = this;
286 const taxonomy = $(e.currentTarget).val();
287 const $termsContainer = $('#wp-terms-container');
288 const $termsActions = $('#wp-terms-actions');
289 const $indexBtn = $('.wpforo-ai-wp-index-taxonomy');
290
291 if (!taxonomy) {
292 $termsContainer.html('<div class="wpforo-ai-terms-placeholder">Select a taxonomy first to load terms...</div>');
293 $termsActions.hide();
294 $indexBtn.prop('disabled', true);
295 return;
296 }
297
298 $termsContainer.html('<div class="wpforo-ai-terms-loading"><span class="spinner is-active"></span> Loading terms...</div>');
299 $termsActions.hide();
300
301 $.ajax({
302 url: wpforoAIAdmin.ajaxUrl,
303 type: 'POST',
304 data: {
305 action: 'wpforo_ai_wp_get_taxonomy_terms',
306 security: wpforoAIAdmin.adminNonce,
307 taxonomy: taxonomy
308 },
309 success: function(response) {
310 if (response.success && response.data && response.data.terms) {
311 const terms = response.data.terms;
312 if (terms.length === 0) {
313 $termsContainer.html('<div class="wpforo-ai-terms-placeholder">No terms found in this taxonomy.</div>');
314 $termsActions.hide();
315 $indexBtn.prop('disabled', true);
316 return;
317 }
318
319 let html = '<div class="wpforo-ai-terms-checklist">';
320 terms.forEach(function(term) {
321 const indexed = term.indexed || 0;
322 const total = term.count || 0;
323 html += self.renderTermCheckbox(term, indexed, total, false);
324
325 // Add children if any
326 if (term.children && term.children.length) {
327 term.children.forEach(function(child) {
328 const childIndexed = child.indexed || 0;
329 const childTotal = child.count || 0;
330 html += self.renderTermCheckbox(child, childIndexed, childTotal, true);
331 });
332 }
333 });
334 html += '</div>';
335
336 $termsContainer.html(html);
337 $termsActions.show();
338
339 // Bind checkbox change events
340 $termsContainer.find('input[type="checkbox"]').on('change', function() {
341 self.updateTermIndexButton();
342 });
343
344 self.updateTermIndexButton();
345 } else {
346 $termsContainer.html('<div class="wpforo-ai-terms-placeholder">Error loading terms.</div>');
347 $termsActions.hide();
348 }
349 },
350 error: function() {
351 $termsContainer.html('<div class="wpforo-ai-terms-placeholder">Error loading terms.</div>');
352 $termsActions.hide();
353 }
354 });
355 },
356
357 /**
358 * Render a single term checkbox item
359 */
360 renderTermCheckbox: function(term, indexed, total, isChild) {
361 const itemClass = isChild ? 'wpforo-ai-term-checkbox-item wpforo-ai-term-child' : 'wpforo-ai-term-checkbox-item';
362 return '<label class="' + itemClass + '">' +
363 '<input type="checkbox" name="term_ids[]" value="' + term.term_id + '" data-count="' + total + '">' +
364 '<span class="term-name">' + this.escapeHtml(term.name) + '</span>' +
365 '<span class="wpforo-ai-term-info">(' + indexed + '/' + total + ')</span>' +
366 '</label>';
367 },
368
369 /**
370 * Update the index button state based on selected terms
371 */
372 updateTermIndexButton: function() {
373 const $indexBtn = $('.wpforo-ai-wp-index-taxonomy');
374 const checkedCount = $('#wp-terms-container input[type="checkbox"]:checked').length;
375 $indexBtn.prop('disabled', checkedCount === 0);
376 },
377
378 /**
379 * Escape HTML special characters
380 */
381 escapeHtml: function(text) {
382 const div = document.createElement('div');
383 div.appendChild(document.createTextNode(text));
384 return div.innerHTML;
385 },
386
387 /**
388 * Handle taxonomy-based indexing form submission
389 */
390 handleWPTaxonomyIndex: function(e) {
391 e.preventDefault();
392 const self = this;
393 const $form = $(e.currentTarget);
394 const $button = $form.find('.wpforo-ai-wp-index-taxonomy');
395 const taxonomy = $form.find('#wp-taxonomy-select').val();
396
397 // Collect all selected term IDs from checkboxes
398 const termIds = [];
399 $('#wp-terms-container input[type="checkbox"]:checked').each(function() {
400 termIds.push($(this).val());
401 });
402
403 if (!taxonomy || termIds.length === 0) {
404 alert('Please select a taxonomy and at least one term.');
405 return;
406 }
407
408 // Get selected post types
409 const postTypes = [];
410 $('.wpforo-ai-wp-type-checkbox:checked').each(function() {
411 postTypes.push($(this).val());
412 });
413
414 if (postTypes.length === 0) {
415 alert('Please select at least one content type.');
416 return;
417 }
418
419 $button.prop('disabled', true).text('Indexing...');
420
421 // Build request data including optional date range
422 const requestData = {
423 action: 'wpforo_ai_wp_index_by_taxonomy',
424 security: wpforoAIAdmin.adminNonce,
425 taxonomy: taxonomy,
426 term_ids: termIds,
427 post_types: postTypes
428 };
429
430 // Add date range if specified
431 const dateFrom = $form.find('#wp-tax-date-from').val();
432 const dateTo = $form.find('#wp-tax-date-to').val();
433 if (dateFrom) requestData.date_from = dateFrom;
434 if (dateTo) requestData.date_to = dateTo;
435
436 $.ajax({
437 url: wpforoAIAdmin.ajaxUrl,
438 type: 'POST',
439 data: requestData,
440 success: function(response) {
441 if (response.success) {
442 // Start auto page refresh - each refresh triggers inline cron nudge
443 self.startWPIndexingAutoRefresh();
444 } else {
445 alert('Error: ' + (response.data?.message || 'Unknown error'));
446 $button.prop('disabled', false).html('<span class="dashicons dashicons-upload"></span> Index Selected Terms');
447 }
448 },
449 error: function() {
450 alert('Error starting indexing. Please try again.');
451 $button.prop('disabled', false).html('<span class="dashicons dashicons-upload"></span> Index Selected Terms');
452 }
453 });
454 },
455
456 /**
457 * Handle custom indexing form submission
458 */
459 handleWPCustomIndex: function(e) {
460 e.preventDefault();
461 const self = this;
462 const $form = $(e.currentTarget);
463 const $button = $form.find('.wpforo-ai-wp-index-custom');
464
465 // Get selected post types from within this form
466 const postTypes = [];
467 $form.find('.wpforo-ai-wp-type-checkbox:checked').each(function() {
468 postTypes.push($(this).val());
469 });
470
471 if (postTypes.length === 0) {
472 alert('Please select at least one content type.');
473 return;
474 }
475
476 const data = {
477 action: 'wpforo_ai_wp_index_custom',
478 security: wpforoAIAdmin.adminNonce,
479 post_types: postTypes,
480 date_from: $form.find('#wp-date-from').val(),
481 date_to: $form.find('#wp-date-to').val()
482 };
483
484 $button.prop('disabled', true).text('Indexing...');
485
486 $.ajax({
487 url: wpforoAIAdmin.ajaxUrl,
488 type: 'POST',
489 data: data,
490 success: function(response) {
491 if (response.success) {
492 // Start auto page refresh - each refresh triggers inline cron nudge
493 self.startWPIndexingAutoRefresh();
494 } else {
495 alert('Error: ' + (response.data?.message || 'Unknown error'));
496 $button.prop('disabled', false).html('<span class="dashicons dashicons-upload"></span> Index Selected Content');
497 }
498 },
499 error: function() {
500 alert('Error starting indexing. Please try again.');
501 $button.prop('disabled', false).html('<span class="dashicons dashicons-upload"></span> Index Selected Content');
502 }
503 });
504 },
505
506 /**
507 * Handle index by specific IDs form submission
508 */
509 handleWPIndexByIds: function(e) {
510 e.preventDefault();
511 const self = this;
512 const $form = $(e.currentTarget);
513 const $button = $form.find('.wpforo-ai-wp-index-ids');
514 const postIds = $form.find('#wp-post-ids').val().trim();
515
516 if (!postIds) {
517 alert('Please enter at least one post ID.');
518 return;
519 }
520
521 const data = {
522 action: 'wpforo_ai_wp_index_custom',
523 security: wpforoAIAdmin.adminNonce,
524 post_ids: postIds
525 };
526
527 $button.prop('disabled', true).text('Indexing...');
528
529 $.ajax({
530 url: wpforoAIAdmin.ajaxUrl,
531 type: 'POST',
532 data: data,
533 success: function(response) {
534 if (response.success) {
535 $form.find('#wp-post-ids').val(''); // Clear the field
536 // Start auto page refresh - each refresh triggers inline cron nudge
537 self.startWPIndexingAutoRefresh();
538 } else {
539 alert('Error: ' + (response.data?.message || 'Unknown error'));
540 $button.prop('disabled', false).html('<span class="dashicons dashicons-upload"></span> Index by IDs');
541 }
542 },
543 error: function() {
544 alert('Error starting indexing. Please try again.');
545 $button.prop('disabled', false).html('<span class="dashicons dashicons-upload"></span> Index by IDs');
546 }
547 });
548 },
549
550 /**
551 * Handle Clear WordPress index button
552 */
553 handleWPClearIndex: function(e) {
554 e.preventDefault();
555 const self = this;
556 const $button = $(e.currentTarget);
557 const confirmMessage = $button.data('confirm');
558
559 if (!confirm(confirmMessage)) {
560 return;
561 }
562
563 $button.prop('disabled', true).text('Clearing...');
564
565 $.ajax({
566 url: wpforoAIAdmin.ajaxUrl,
567 type: 'POST',
568 data: {
569 action: 'wpforo_ai_wp_delete_content',
570 security: wpforoAIAdmin.adminNonce,
571 delete_all: 'true'
572 },
573 success: function(response) {
574 if (response.success) {
575 // Stop any auto-refresh cycle
576 self.stopWPIndexingAutoRefresh();
577 // Reload page to show updated stats
578 window.location.hash = 'wp-indexing-status-box'; window.location.reload();
579 } else {
580 alert('Error: ' + (response.data?.message || 'Unknown error'));
581 $button.prop('disabled', false).html('<span class="dashicons dashicons-trash"></span> Clear WordPress Index');
582 }
583 },
584 error: function() {
585 alert('Error clearing index. Please try again.');
586 $button.prop('disabled', false).html('<span class="dashicons dashicons-trash"></span> Clear WordPress Index');
587 }
588 });
589 },
590
591 /**
592 * Handle WordPress auto-indexing toggle change
593 */
594 handleWPAutoIndexingToggle: function(e) {
595 const $input = $(e.currentTarget);
596 const isEnabled = $input.is(':checked') ? 1 : 0;
597 const optionName = $input.data('option-name') || 'ai_wp_auto_indexing_enabled';
598 const $toggle = $input.closest('.wpforo-ai-auto-index-toggle');
599
600 // Disable the toggle during AJAX request
601 $input.prop('disabled', true);
602 $toggle.css('opacity', '0.6');
603
604 // Save via AJAX
605 $.ajax({
606 url: wpforoAIAdmin.ajaxUrl,
607 type: 'POST',
608 data: {
609 action: 'wpforo_ai_save_wp_indexing_option',
610 nonce: wpforoAIAdmin.nonce,
611 option_name: optionName,
612 enabled: isEnabled
613 },
614 success: function(response) {
615 $input.prop('disabled', false);
616 $toggle.css('opacity', '1');
617 if (!response.success) {
618 // Revert the change on failure
619 $input.prop('checked', !isEnabled);
620 alert('Error: ' + (response.data?.message || 'Failed to save setting'));
621 }
622 },
623 error: function() {
624 $input.prop('disabled', false);
625 $toggle.css('opacity', '1');
626 $input.prop('checked', !isEnabled);
627 alert('Error saving setting. Please try again.');
628 }
629 });
630 },
631
632 /**
633 * Handle WordPress image indexing toggle change
634 */
635 handleWPImageIndexingToggle: function(e) {
636 const $input = $(e.currentTarget);
637 const isEnabled = $input.is(':checked') ? 1 : 0;
638 const optionName = $input.data('option-name') || 'ai_wp_image_indexing_enabled';
639 const $toggle = $input.closest('.wpforo-ai-auto-index-toggle');
640
641 // Show confirmation when enabling (due to credit impact)
642 if (isEnabled) {
643 const confirmed = confirm(
644 'Enable Image Indexing for WordPress Content?\n\n' +
645 'When enabled, posts with images will consume +1 additional credit during indexing.\n\n' +
646 '• Maximum 10 images per post are processed\n' +
647 '• Images are converted to text descriptions for search\n' +
648 '• Small images (< 50x50px) like smileys are skipped\n\n' +
649 'Continue?'
650 );
651 if (!confirmed) {
652 $input.prop('checked', false);
653 return;
654 }
655 }
656
657 // Disable the toggle during AJAX request
658 $input.prop('disabled', true);
659 $toggle.css('opacity', '0.6');
660
661 // Save via AJAX
662 $.ajax({
663 url: wpforoAIAdmin.ajaxUrl,
664 type: 'POST',
665 data: {
666 action: 'wpforo_ai_save_wp_indexing_option',
667 nonce: wpforoAIAdmin.nonce,
668 option_name: optionName,
669 enabled: isEnabled
670 },
671 success: function(response) {
672 $input.prop('disabled', false);
673 $toggle.css('opacity', '1');
674 if (!response.success) {
675 // Revert the change on failure
676 $input.prop('checked', !isEnabled);
677 alert('Error: ' + (response.data?.message || 'Failed to save setting'));
678 }
679 },
680 error: function() {
681 $input.prop('disabled', false);
682 $toggle.css('opacity', '1');
683 $input.prop('checked', !isEnabled);
684 alert('Error saving setting. Please try again.');
685 }
686 });
687 },
688
689 /**
690 * Handle WordPress-specific cleanup session
691 */
692 handleCleanupSession: function(e) {
693 e.preventDefault();
694 const self = this;
695 const $button = $(e.currentTarget);
696 const confirmMsg = $button.data('confirm') || 'Reset stuck WordPress indexing session?';
697
698 if (!window.confirm(confirmMsg)) {
699 return;
700 }
701
702 const originalHtml = $button.html();
703 $button.prop('disabled', true).html('<span class="dashicons dashicons-update wpforo-spin"></span> Cleaning up...');
704
705 // Clear browser-side state
706 try {
707 localStorage.removeItem('wpforo_wp_indexing_auto_refresh');
708 } catch (err) { /* localStorage may be blocked */ }
709 this.stopWPIndexingAutoRefresh();
710
711 $.ajax({
712 url: wpforoAIAdmin.ajaxUrl,
713 type: 'POST',
714 data: {
715 action: 'wpforo_ai_cleanup_indexing_session',
716 scope: 'wp',
717 _wpnonce: wpforoAIAdmin.nonce
718 },
719 success: function(response) {
720 $button.prop('disabled', false).html(originalHtml);
721 if (response && response.success) {
722 // Reload to refresh all server-rendered counts
723 window.location.hash = 'wp-indexing-status-box'; window.location.reload();
724 } else {
725 const msg = (response && response.data && response.data.message) || 'Cleanup failed.';
726 window.alert(msg);
727 }
728 },
729 error: function(xhr, status, error) {
730 $button.prop('disabled', false).html(originalHtml);
731 console.error('Cleanup indexing session failed:', error);
732 window.alert('Cleanup failed. Check the browser console for details.');
733 }
734 });
735 }
736 };
737
738 // Initialize when DOM ready
739 $(document).ready(function() {
740 WpForoWPIndexing.init();
741 });
742
743 // Expose globally for debugging
744 window.WpForoWPIndexing = WpForoWPIndexing;
745
746 })(jQuery);
747