PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 2.4.6
MxChat – AI Chatbot & Content Generation for WordPress v2.4.6
3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 2.0.3 2.0.4 2.0.5 2.0.6 All 152 releases
mxchat-basic / js / content-selector.js

content-selector.js in MxChat – AI Chatbot & Content Generation for WordPress 2.4.6, at js/content-selector.js

771 lines 30.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(document).ready(function($) {
2 // Modal elements
3 const $modal = $('#mxchat-kb-content-selector-modal');
4 const $openButton = $('#mxchat-open-content-selector');
5 const $closeButtons = $('.mxchat-kb-modal-close');
6 const $contentList = $('.mxchat-kb-content-list');
7 const $loading = $('.mxchat-kb-loading');
8 const $pagination = $('.mxchat-kb-pagination');
9 const $processButton = $('#mxchat-kb-process-selected');
10 const $selectAll = $('#mxchat-kb-select-all');
11 const $selectionCount = $('.mxchat-kb-selection-count');
12
13 // Filter elements
14 const $searchInput = $('#mxchat-kb-content-search');1
15 const $typeFilter = $('#mxchat-kb-content-type-filter');
16 const $statusFilter = $('#mxchat-kb-content-status-filter');
17 const $processedFilter = $('#mxchat-kb-processed-filter');
18
19 // Current state - using let for variables that change
20 let currentPage = 1;
21 let totalPages = 1;
22 let selectedItems = new Set();
23 let allItems = [];
24
25 // Open modal when WordPress import button is clicked
26 $openButton.on('click', function() {
27 $modal.show();
28 // Reset to first page when opening the modal
29 currentPage = 1;
30 loadContent();
31 });
32
33 // Close modal
34 $closeButtons.on('click', function() {
35 $modal.hide();
36 });
37 // Handle import option box clicks (for non-WordPress options)
38 $('.mxchat-import-box').on('click', function() {
39 const $box = $(this);
40 const option = $box.data('option');
41
42 // Skip if this is the WordPress option (it has its own handler)
43 if (option === 'wordpress') {
44 return;
45 }
46
47 // Update active state
48 $('.mxchat-import-box').removeClass('active');
49 $box.addClass('active');
50
51 // Hide all input areas
52 $('#mxchat-url-input-area, #mxchat-content-input-area').hide();
53
54 // Handle different import options
55 switch (option) {
56 case 'pdf':
57 case 'sitemap':
58 case 'url':
59 // Show URL input area with appropriate placeholder
60 $('#mxchat-url-input-area').show();
61 $('#sitemap_url').attr('placeholder', $box.data('placeholder'));
62 $('#import_type').val(option);
63
64 // UPDATED: Add or update bot_id hidden field for URL forms
65 updateBotIdInForm('#mxchat-url-form');
66
67 // Update the description text based on the import type
68 let descriptionText = '';
69 if (option === 'pdf') {
70 descriptionText = 'Import a PDF document by entering its URL above. PDFs are processed via cron job. If processing does not start, you can manually process batch 5 pages at a time.';
71 } else if (option === 'sitemap') {
72 descriptionText = 'Enter a content-specific sub-sitemap URL, not the sitemap index. Sitemaps are processed via cron job. If processing does not start, you can manually process batch 5 pages at a time.';
73 } else if (option === 'url') {
74 descriptionText = 'Import content from any webpage by entering its URL.';
75 }
76 $('#url-description-text').text(descriptionText);
77 break;
78
79 case 'content':
80 // Show content input area
81 $('#mxchat-content-input-area').show();
82
83 // UPDATED: Add or update bot_id hidden field for content forms
84 updateBotIdInForm('#mxchat-content-form');
85 break;
86 }
87 });
88
89 // Helper function to add/update bot_id hidden field in forms
90 function updateBotIdInForm(formSelector) {
91 const $form = $(formSelector);
92 if ($form.length === 0) return;
93
94 // Get current bot_id from the bot selector dropdown
95 const currentBotId = $('#mxchat-bot-selector').val();
96
97 // Only add bot_id field if multi-bot is active and bot is not 'default'
98 if (currentBotId && currentBotId !== 'default') {
99 // Remove existing bot_id field if it exists
100 $form.find('input[name="bot_id"]').remove();
101
102 // Add new bot_id field
103 $form.append('<input type="hidden" name="bot_id" value="' + currentBotId + '">');
104
105 console.log('Updated bot_id in form ' + formSelector + ' to: ' + currentBotId);
106 } else {
107 // Remove bot_id field if bot is default
108 $form.find('input[name="bot_id"]').remove();
109 }
110 }
111
112 // Load content via AJAX
113 function loadContent() {
114 $loading.show();
115 $contentList.find('.mxchat-kb-content-item').remove();
116
117 const data = {
118 action: 'mxchat_get_content_list',
119 nonce: mxchatSelector.nonce,
120 page: currentPage,
121 per_page: 50,
122 search: $searchInput.val(),
123 post_type: $typeFilter.val(),
124 post_status: $statusFilter.val(),
125 processed_filter: $processedFilter.val()
126 };
127
128 //console.log('Loading content for page', currentPage, 'with filters:', data);
129
130 $.ajax({
131 url: mxchatSelector.ajaxurl,
132 data: data,
133 method: 'GET',
134 dataType: 'json',
135 success: function(response) {
136 $loading.hide();
137
138 if (response.success && response.data.items && response.data.items.length > 0) {
139 // Store the items directly
140 let items = response.data.items;
141
142 if (items.length > 0) {
143 renderContentItems(items);
144 renderPagination(parseInt(response.data.current_page), parseInt(response.data.total_pages));
145
146 // Update state
147 allItems = items;
148 totalPages = parseInt(response.data.total_pages);
149 currentPage = parseInt(response.data.current_page);
150
151 // Update select all checkbox based on current selection
152 updateSelectAllState();
153 } else {
154 displayNoResults($processedFilter.val());
155 }
156 } else {
157 displayNoResults($processedFilter.val());
158 }
159 },
160 error: function(xhr, status, error) {
161 $loading.hide();
162 console.error('AJAX Error:', status, error);
163 $contentList.html('<div class="mxchat-kb-error">Error loading content. Please try again.</div>');
164 // Clear pagination on error
165 $pagination.empty();
166 }
167 });
168 }
169
170 // Helper function to display appropriate "no results" message
171 function displayNoResults(processedStatus) {
172 let message = 'No content found matching your criteria.';
173
174 if (processedStatus === 'processed') {
175 message = 'No content found in knowledge base.';
176 } else if (processedStatus === 'unprocessed') {
177 message = 'All content is already in knowledge base.';
178 }
179
180 $contentList.html('<div class="mxchat-kb-no-results">' + message + '</div>');
181 // Clear pagination when no results
182 $pagination.empty();
183 }
184
185 // Render content items
186 function renderContentItems(items) {
187 let html = '';
188
189 items.forEach(function(item) {
190 const isSelected = selectedItems.has(item.id);
191 const isProcessed = item.already_processed;
192
193 // Updated badge text
194 const badgeText = isProcessed ? 'In Knowledge Base' : 'Not In Knowledge Base';
195 const badgeClass = isProcessed ? 'mxchat-kb-processed-badge' : 'mxchat-kb-unprocessed-badge';
196
197
198 html += `
199 <div class="mxchat-kb-content-item ${isProcessed ? 'processed' : ''}" data-id="${item.id}">
200 <div class="mxchat-kb-content-checkbox">
201 <input type="checkbox" id="content-${item.id}" ${isSelected ? 'checked' : ''}>
202 </div>
203 <div class="mxchat-kb-content-details">
204 <div class="mxchat-kb-content-title">
205 <a href="${item.permalink}" target="_blank">${item.title}</a>
206 <span class="${badgeClass}">${badgeText}</span>
207 ${isProcessed ? '<span class="mxchat-kb-last-updated">Last updated: ' + item.processed_date + '</span>' : ''}
208 </div>
209 <div class="mxchat-kb-content-meta">
210 <span class="mxchat-kb-content-type">${item.type}</span>
211 <span class="mxchat-kb-content-date">${item.date}</span>
212 <span class="mxchat-kb-content-words">${item.word_count} words</span>
213 </div>
214 <div class="mxchat-kb-content-excerpt">${item.excerpt}</div>
215 </div>
216 </div>
217 `;
218 });
219
220 $contentList.html(html);
221
222 // Add event listeners for checkboxes using delegation for better performance
223 $contentList.off('change', 'input[type="checkbox"]').on('change', 'input[type="checkbox"]', function() {
224 const $checkbox = $(this);
225 const itemId = parseInt($checkbox.closest('.mxchat-kb-content-item').data('id'));
226
227 if ($checkbox.is(':checked')) {
228 selectedItems.add(itemId);
229 } else {
230 selectedItems.delete(itemId);
231 }
232
233 updateSelection();
234 });
235 }
236
237 // Render pagination - FIXED VERSION
238 function renderPagination(currentPage, totalPages) {
239 // Clear existing pagination first
240 $pagination.empty();
241
242 // Don't render pagination if only one page
243 if (totalPages <= 1) {
244 return;
245 }
246
247 let html = '<div class="mxchat-kb-pagination-links">';
248
249 // Previous button
250 if (currentPage > 1) {
251 html += '<a href="#" class="mxchat-kb-page-link prev" data-page="' + (currentPage - 1) + '">&laquo; Previous</a>';
252 }
253
254 // Page numbers
255 const startPage = Math.max(1, currentPage - 2);
256 const endPage = Math.min(totalPages, startPage + 4);
257
258 for (let i = startPage; i <= endPage; i++) {
259 if (i === currentPage) {
260 html += '<span class="mxchat-kb-page-current">' + i + '</span>';
261 } else {
262 html += '<a href="#" class="mxchat-kb-page-link" data-page="' + i + '">' + i + '</a>';
263 }
264 }
265
266 // Next button
267 if (currentPage < totalPages) {
268 html += '<a href="#" class="mxchat-kb-page-link next" data-page="' + (currentPage + 1) + '">Next &raquo;</a>';
269 }
270
271 html += '</div>';
272
273 $pagination.html(html);
274 }
275
276 // Handle pagination clicks directly on the document
277 $(document).on('click', '.mxchat-kb-page-link', function(e) {
278 e.preventDefault();
279 const newPage = parseInt($(this).data('page'));
280 //console.log('Pagination clicked: changing from page', currentPage, 'to', newPage);
281
282 // Only reload if the page actually changed
283 if (currentPage !== newPage) {
284 currentPage = newPage;
285 loadContent();
286 }
287 });
288
289 // Update selection counts and button state
290 function updateSelection() {
291 const selectedCount = selectedItems.size;
292 $selectionCount.text(selectedCount + ' ' + (selectedCount === 1 ? 'selected' : 'selected'));
293 $('.mxchat-kb-selected-count').text('(' + selectedCount + ')');
294
295 // Determine if any selected items are already processed
296 const hasProcessedItems = Array.from(selectedItems).some(id => {
297 const item = allItems.find(item => item.id === id);
298 return item && item.already_processed;
299 });
300
301 if (selectedCount > 0) {
302 $processButton.prop('disabled', false);
303
304 // Update button text based on selection
305 if (hasProcessedItems && selectedCount === 1) {
306 $processButton.text('Update Selected Content (1)').addClass('update-mode');
307 } else if (hasProcessedItems && selectedCount > 1) {
308 $processButton.text('Process/Update Selected (' + selectedCount + ')').addClass('mixed-mode');
309 } else {
310 $processButton.text('Process Selected Content (' + selectedCount + ')').removeClass('update-mode mixed-mode');
311 }
312 } else {
313 $processButton.prop('disabled', true);
314 $processButton.text('Process Selected Content').removeClass('update-mode mixed-mode');
315 $('.mxchat-kb-selected-count').text('(0)');
316 }
317
318 updateSelectAllState();
319 }
320
321 // Update "Select All" checkbox state
322 function updateSelectAllState() {
323 const availableItems = allItems.length;
324 const selectedAvailableItems = allItems.filter(item => selectedItems.has(item.id)).length;
325
326 if (availableItems === 0) {
327 $selectAll.prop('checked', false);
328 $selectAll.prop('disabled', true);
329 } else if (selectedAvailableItems === availableItems) {
330 $selectAll.prop('checked', true);
331 } else {
332 $selectAll.prop('checked', false);
333 }
334 }
335
336 // Handle Select All checkbox
337 $selectAll.on('change', function() {
338 const isChecked = $(this).is(':checked');
339
340 $contentList.find('.mxchat-kb-content-item input[type="checkbox"]').each(function() {
341 const $checkbox = $(this);
342 const $item = $checkbox.closest('.mxchat-kb-content-item');
343 const itemId = parseInt($item.data('id'));
344
345 $checkbox.prop('checked', isChecked);
346
347 if (isChecked) {
348 selectedItems.add(itemId);
349 } else {
350 selectedItems.delete(itemId);
351 }
352 });
353
354 updateSelection();
355 });
356
357 // Handle search input
358 let searchTimer;
359 $searchInput.on('keyup', function() {
360 clearTimeout(searchTimer);
361 searchTimer = setTimeout(function() {
362 currentPage = 1; // Reset to first page on new search
363 loadContent();
364 }, 500);
365 });
366
367 // Handle filter changes
368 $typeFilter.add($statusFilter).add($processedFilter).on('change', function() {
369 currentPage = 1; // Reset to first page on filter change
370 selectedItems.clear(); // Clear selection when filter changes
371 loadContent();
372 });
373
374 // Process selected content
375 $processButton.on('click', function() {
376 if (selectedItems.size === 0) {
377 return;
378 }
379
380 const $button = $(this);
381 $button.prop('disabled', true);
382
383 // Update button text based on mode
384 if ($button.hasClass('update-mode')) {
385 $button.text('Updating...');
386 } else if ($button.hasClass('mixed-mode')) {
387 $button.text('Processing/Updating...');
388 } else {
389 $button.text('Processing...');
390 }
391
392 // Convert selected items to array
393 const selectedPostIds = Array.from(selectedItems);
394 const totalToProcess = selectedPostIds.length;
395 let processed = 0;
396 let updated = 0;
397 let failed = 0;
398 const results = {
399 success: [],
400 updated: [],
401 failed: []
402 };
403
404 // UPDATED: Get current bot_id for WordPress content processing
405 const currentBotId = $('#mxchat-bot-selector').val();
406
407 // Create a modal to show progress
408 const $progressModal = $('<div class="mxchat-kb-processing-overlay">' +
409 '<div class="mxchat-kb-processing-content">' +
410 '<h3>Processing Content</h3>' +
411 '<p class="mxchat-kb-processing-status">Processing 1 of ' + totalToProcess + '...</p>' +
412 '<div class="mxchat-kb-progress-bar"><div class="mxchat-kb-progress-fill" style="width: 0%"></div></div>' +
413 '<p class="mxchat-kb-current-item"></p>' +
414 '</div>' +
415 '</div>');
416
417 $('body').append($progressModal);
418
419 // Process posts one by one
420 function processNext(index) {
421 if (index >= selectedPostIds.length) {
422 // All done
423 finishProcessing();
424 return;
425 }
426
427 const postId = selectedPostIds[index];
428 const percent = Math.round((index / totalToProcess) * 100);
429 const item = allItems.find(item => item.id === postId);
430 const isUpdate = item && item.already_processed;
431
432 // Update progress UI
433 $progressModal.find('.mxchat-kb-processing-status')
434 .text((isUpdate ? 'Updating' : 'Processing') + ' ' + (index + 1) + ' of ' + totalToProcess + '...');
435 $progressModal.find('.mxchat-kb-progress-fill').css('width', percent + '%');
436
437 // UPDATED: Prepare AJAX data with bot_id
438 const ajaxData = {
439 action: 'mxchat_process_selected_content',
440 nonce: mxchatSelector.nonce,
441 post_ids: [postId],
442 is_update: isUpdate
443 };
444
445 // Add bot_id if multi-bot is active and not default
446 if (currentBotId && currentBotId !== 'default') {
447 ajaxData.bot_id = currentBotId;
448 }
449
450 // Make AJAX request for this post
451 $.ajax({
452 url: mxchatSelector.ajaxurl,
453 method: 'POST',
454 data: ajaxData,
455 dataType: 'json',
456 success: function(response) {
457 if (response.success) {
458 if (isUpdate) {
459 updated++;
460 results.updated.push({
461 id: postId,
462 title: response.data.title || ('ID: ' + postId)
463 });
464 } else {
465 processed++;
466 results.success.push({
467 id: postId,
468 title: response.data.title || ('ID: ' + postId)
469 });
470 }
471
472 $progressModal.find('.mxchat-kb-current-item')
473 .text('Successfully ' + (isUpdate ? 'updated' : 'processed') + ': ' + response.data.title);
474 } else {
475 failed++;
476 results.failed.push({
477 id: postId,
478 error: response.data || 'Unknown error'
479 });
480
481 $progressModal.find('.mxchat-kb-current-item')
482 .text('Failed to ' + (isUpdate ? 'update' : 'process') + ' ID: ' + postId);
483 }
484
485 // Process next post
486 setTimeout(function() {
487 processNext(index + 1);
488 }, 500); // Small delay between requests
489 },
490 error: function(xhr, status, error) {
491 failed++;
492 results.failed.push({
493 id: postId,
494 error: error || 'Server error'
495 });
496
497 $progressModal.find('.mxchat-kb-current-item')
498 .text('Error ' + (isUpdate ? 'updating' : 'processing') + ' ID: ' + postId);
499
500 // Process next post
501 setTimeout(function() {
502 processNext(index + 1);
503 }, 500);
504 }
505 });
506 }
507
508 // Function to finish processing and show results
509 function finishProcessing() {
510 // Remove progress modal
511 $progressModal.remove();
512
513 // Determine notification type based on results
514 let notificationClass = 'success';
515 if (failed > 0) {
516 notificationClass = processed > 0 || updated > 0 ? 'warning' : 'error';
517 }
518
519 // Create summary message
520 let resultHTML = '<div class="mxchat-kb-notification ' + notificationClass + '">' +
521 '<h4>';
522
523 if (processed > 0 && updated > 0) {
524 resultHTML += 'Processed ' + processed + ' new items and updated ' + updated + ' existing items';
525 } else if (processed > 0) {
526 resultHTML += 'Processed ' + processed + ' items successfully';
527 } else if (updated > 0) {
528 resultHTML += 'Updated ' + updated + ' items successfully';
529 } else {
530 resultHTML += 'No items were processed successfully';
531 }
532
533 if (failed > 0) {
534 resultHTML += ' with ' + failed + ' failures';
535 }
536
537 resultHTML += '</h4>';
538
539 // Add details if there were failures
540 if (failed > 0) {
541 resultHTML += '<div class="mxchat-kb-results-details">';
542 resultHTML += '<h5>Failed Items:</h5><ul>';
543
544 results.failed.forEach(function(item) {
545 resultHTML += '<li><strong>ID: ' + item.id + '</strong>: ' + item.error + '</li>';
546 });
547
548 resultHTML += '</ul></div>';
549 }
550
551 resultHTML += '</div>';
552
553 // Show results in modal
554 $modal.find('.mxchat-kb-modal-content').prepend($(resultHTML));
555
556 // Clear selection
557 selectedItems.clear();
558 updateSelection();
559
560 // Enable button
561 $button.prop('disabled', false)
562 .text('Process Selected Content')
563 .removeClass('update-mode mixed-mode');
564 $('.mxchat-kb-selected-count').text('(0)');
565
566 // Only reload if there were successful operations
567 if (processed > 0 || updated > 0) {
568 // Reload after delay
569 setTimeout(function() {
570 // Reload the knowledge base table - if this function exists
571 if (typeof reloadKnowledgeBaseTable === 'function') {
572 reloadKnowledgeBaseTable();
573 } else {
574 // Fallback: reload content list instead of full page reload
575 loadContent();
576 }
577 }, 3000);
578 }
579 }
580
581 // Start processing the first post
582 processNext(0);
583 });
584
585 // Initialize - Set WordPress as the active option by default
586 $('.mxchat-import-box[data-option="wordpress"]').addClass('active');
587 });
588
589 // Tab switching functionality - Keep this separate
590 jQuery(document).ready(function($) {
591
592 // Tab switching functionality
593 // Modified tab switching to check for Pinecone changes
594 $('.mxchat-kb-tab-button').on('click', function() {
595 var tabId = $(this).data('tab');
596 var $button = $(this);
597
598 // Switch tabs immediately for all tabs
599 $('.mxchat-kb-tab-button').removeClass('active');
600 $('.mxchat-kb-tab-content').removeClass('active');
601 $button.addClass('active');
602 $('#mxchat-kb-tab-' + tabId).addClass('active');
603
604 // Check if Pinecone was changed and we're going to import tab
605 if (tabId === 'import' && sessionStorage.getItem('mxchat_pinecone_changed') === 'true') {
606 sessionStorage.removeItem('mxchat_pinecone_changed');
607
608 // Show refresh notice
609 var $knowledgeCard = $('#mxchat-kb-tab-import .mxchat-card').eq(1);
610 if ($knowledgeCard.length > 0 && $knowledgeCard.find('.notice-warning').length === 0) {
611 var refreshNotice = $('<div class="notice notice-warning" style="margin: 15px 0; padding: 10px 15px;">' +
612 '<p style="margin: 0;">' +
613 '<span class="dashicons dashicons-info" style="color: #f0ad4e; margin-right: 5px;"></span>' +
614 'Database settings have changed. ' +
615 '<a href="#" onclick="location.reload(); return false;" style="font-weight: bold;">Click here to refresh</a> to see the updated knowledge base.' +
616 '</p></div>');
617
618 $knowledgeCard.prepend(refreshNotice);
619 }
620 }
621
622 // Initialize Pinecone functionality when Pinecone tab is activated
623 if (tabId === 'pinecone') {
624 setTimeout(function() {
625 initPineconeFeatures();
626 }, 100);
627 }
628 });
629
630
631 // Pinecone functionality
632 function initPineconeFeatures() {
633 //console.log('Initializing Pinecone features...');
634
635 if ($('#mxchat-kb-tab-pinecone').length === 0) {
636 return;
637 }
638
639 initPineconeToggle();
640 initPineconeConnectionTest();
641 checkPineconeCompatibility();
642 }
643
644 function initPineconeToggle() {
645 // Remove any existing handlers to prevent duplicates
646 $('input[name="mxchat_pinecone_addon_options[mxchat_use_pinecone]"]').off('change.pineconeToggle');
647
648 // Add the toggle handler for UI only (auto-save will handle the actual saving)
649 $('input[name="mxchat_pinecone_addon_options[mxchat_use_pinecone]"]').on('change.pineconeToggle', function() {
650 var $checkbox = $(this);
651 var isChecked = $checkbox.is(':checked');
652 var settingsDiv = $('.mxchat-pinecone-settings');
653
654 //console.log('Pinecone toggle changed to:', isChecked);
655
656 // Update the UI immediately
657 if (isChecked) {
658 settingsDiv.slideDown(300);
659 } else {
660 settingsDiv.slideUp(300);
661 }
662 });
663
664 // Set initial state based on current checkbox value
665 var currentToggle = $('input[name="mxchat_pinecone_addon_options[mxchat_use_pinecone]"]');
666 if (currentToggle.length > 0) {
667 var settingsDiv = $('.mxchat-pinecone-settings');
668 if (currentToggle.is(':checked')) {
669 settingsDiv.show();
670 } else {
671 settingsDiv.hide();
672 }
673 }
674 }
675
676 function initPineconeConnectionTest() {
677 $('#test-pinecone-connection').off('click.pinecone');
678
679 $('#test-pinecone-connection').on('click.pinecone', function() {
680 var button = $(this);
681 var resultDiv = $('#connection-test-result');
682
683 var apiKey = $('#mxchat_pinecone_api_key').val();
684 var host = $('#mxchat_pinecone_host').val();
685 var index = $('#mxchat_pinecone_index').val();
686
687 if (!apiKey || !host || !index) {
688 resultDiv.html('<div class="notice notice-error"><p>Please fill in all required fields first.</p></div>').show();
689 return;
690 }
691
692 button.prop('disabled', true).text('Testing...');
693 resultDiv.hide();
694
695 var ajaxUrl = (typeof mxchatPromptsAdmin !== 'undefined') ? mxchatPromptsAdmin.ajax_url : ajaxurl;
696 var nonce = (typeof mxchatPromptsAdmin !== 'undefined') ? mxchatPromptsAdmin.prompts_setting_nonce :
697 (typeof mxchatAdmin !== 'undefined') ? mxchatAdmin.setting_nonce : '';
698
699 $.ajax({
700 url: ajaxUrl,
701 type: 'POST',
702 data: {
703 action: 'mxchat_test_pinecone_connection',
704 _ajax_nonce: nonce,
705 api_key: apiKey,
706 host: host,
707 index_name: index
708 },
709 success: function(response) {
710 if (response.success) {
711 resultDiv.html('<div class="notice notice-success"><p><span class="dashicons dashicons-yes-alt"></span> ' + response.data.message + '</p></div>');
712 } else {
713 resultDiv.html('<div class="notice notice-error"><p><span class="dashicons dashicons-warning"></span> ' + response.data.message + '</p></div>');
714 }
715 resultDiv.show();
716 },
717 error: function() {
718 resultDiv.html('<div class="notice notice-error"><p>Connection test failed. Please check your settings.</p></div>').show();
719 },
720 complete: function() {
721 button.prop('disabled', false).text('Test Connection');
722 }
723 });
724 });
725 }
726
727 function checkPineconeCompatibility() {
728 if ($('.mxchat-pinecone-compatibility-notice').length > 0) {
729 return;
730 }
731
732 var hasOldAddon = $('body').hasClass('mxchat-pinecone-addon-active') ||
733 $('.pcm-card').length > 0;
734
735 if (hasOldAddon) {
736 var compatibilityNotice = $(`
737 <div class="notice notice-info mxchat-pinecone-compatibility-notice">
738 <p><strong>Pinecone Integration Notice:</strong> We've detected you have the Pinecone add-on installed.
739 Pinecone functionality is now built into the core plugin. You can safely deactivate the separate
740 Pinecone add-on after confirming your settings are migrated below.</p>
741 </div>
742 `);
743
744 $('#mxchat-kb-tab-pinecone .mxchat-card').prepend(compatibilityNotice);
745
746 migratePineconeSettings();
747 }
748 }
749
750 function migratePineconeSettings() {
751 if (typeof ajaxurl !== 'undefined') {
752 $.ajax({
753 url: ajaxurl,
754 type: 'POST',
755 data: {
756 action: 'mxchat_migrate_pinecone_settings',
757 _ajax_nonce: (typeof mxchatAdmin !== 'undefined') ? mxchatAdmin.setting_nonce : ''
758 },
759 success: function(response) {
760 if (response.success && response.data.migrated) {
761 location.reload();
762 }
763 },
764 error: function() {
765 //console.log('Pinecone settings migration not available');
766 }
767 });
768 }
769 }
770
771 });