jQuery(document).ready(function($) { // Current page state let currentPage = 1; const perPage = 50; // Display 50 sessions per page let totalPages = 1; // Track selected sessions for bulk delete let selectedSessions = new Set(); // Select/Deselect All functionality const selectButton = $('#mxchat-select-all-transcripts'); let isSelected = false; selectButton.click(function() { isSelected = !isSelected; $(this).toggleClass('selected'); // Update button text const buttonText = $(this).find('.button-text'); buttonText.text(isSelected ? 'Deselect All' : 'Select All'); // Update session selection (for current page) $('.mxchat-session-header').each(function() { const sessionId = $(this).data('session-id'); const sessionContainer = $(this).closest('.mxchat-session'); if (isSelected) { selectedSessions.add(sessionId); sessionContainer.addClass('selected'); } else { selectedSessions.delete(sessionId); sessionContainer.removeClass('selected'); } }); updateDeleteButtonState(); }); // Search functionality $('#mxchat-search-transcripts').on('input', function() { var searchTerm = $(this).val().toLowerCase(); if (searchTerm.length > 0) { // Reset to first page when searching currentPage = 1; // Load with search filter loadTranscripts(currentPage, searchTerm); } else { // Reset to first page with no search term currentPage = 1; loadTranscripts(currentPage, ''); } }); // Initial load of transcripts loadTranscripts(currentPage, ''); // Function to load transcripts with pagination function loadTranscripts(page, searchTerm = '') { $('#mxchat-transcripts').html('
Loading transcripts...
'); $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'mxchat_fetch_chat_history', page: page, per_page: perPage, search: searchTerm }, success: function(response) { $('#mxchat-transcripts').html(response.html); currentPage = response.page; totalPages = response.total_pages; // Reset selection state when page changes (but keep selectedSessions for bulk operations) isSelected = false; selectButton.removeClass('selected'); selectButton.find('.button-text').text('Select All'); // Restore selection state for sessions on this page $('.mxchat-session-header').each(function() { const sessionId = $(this).data('session-id'); const sessionContainer = $(this).closest('.mxchat-session'); if (selectedSessions.has(sessionId)) { sessionContainer.addClass('selected'); } }); updateDeleteButtonState(); // Add click handlers to pagination buttons $('.mxchat-pagination-button').on('click', function() { var pageNum = $(this).data('page'); loadTranscripts(pageNum, searchTerm); // Scroll to top of transcripts $('html, body').animate({ scrollTop: $('#mxchat-transcripts').offset().top - 50 }, 300); }); // Re-attach event handlers for newly loaded content attachDynamicEventHandlers(); }, error: function(xhr, status, error) { $('#mxchat-transcripts').html('
Error loading chat transcripts. Please try again.
'); console.error("AJAX Error: " + status + " - " + error); } }); } // Attach event handlers to dynamically loaded content function attachDynamicEventHandlers() { // Handle individual delete button clicks $('.mxchat-delete-btn').off('click').on('click', function(e) { e.preventDefault(); e.stopPropagation(); const sessionId = $(this).data('session-id'); if (!confirm("Are you sure you want to delete this chat session? This action cannot be undone.")) { return; } // Delete single session deleteSessions([sessionId]); }); // Handle session header clicks for selection (bulk delete) $('.mxchat-session-header').off('click').on('click', function(e) { // Don't trigger if clicking the delete button if ($(e.target).hasClass('mxchat-delete-btn') || $(e.target).closest('.mxchat-delete-btn').length) { return; } const sessionId = $(this).data('session-id'); const sessionContainer = $(this).closest('.mxchat-session'); if (selectedSessions.has(sessionId)) { selectedSessions.delete(sessionId); sessionContainer.removeClass('selected'); } else { selectedSessions.add(sessionId); sessionContainer.addClass('selected'); } updateDeleteButtonState(); }); // Handle clicks on Sources link for RAG context $('.mxchat-rag-link').off('click').on('click', function(e) { e.preventDefault(); e.stopPropagation(); const messageId = $(this).closest('.mxchat-message').data('message-id'); if (messageId) { openRagContextModal(messageId); } }); } // Update delete button state based on selections function updateDeleteButtonState() { const deleteButton = $('.delete-chats-button'); if (selectedSessions.size > 0) { deleteButton.prop('disabled', false); } else { deleteButton.prop('disabled', true); } } // Function to delete sessions function deleteSessions(sessionIds) { $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'mxchat_delete_chat_history', delete_session_ids: sessionIds, security: $('#mxchat_delete_chat_nonce').val() }, success: function(response) { var jsonResponse = JSON.parse(response); if (jsonResponse.success) { alert("Success: " + jsonResponse.success); // Remove deleted sessions from selectedSessions sessionIds.forEach(id => selectedSessions.delete(id)); } else if (jsonResponse.error) { alert("Error: " + jsonResponse.error); } else { //console.log("Unexpected response format."); } // Reload the current page of transcripts loadTranscripts(currentPage); }, error: function(xhr, status, error) { //console.error("AJAX Error: " + status + " - " + error); //console.log(xhr.responseText); alert("An error occurred while deleting chat sessions. Please try again."); } }); } // Delete form submission (bulk delete) $('#mxchat-delete-form').submit(function(e) { e.preventDefault(); if (selectedSessions.size === 0) { alert("Please select at least one chat session to delete."); return; } // Confirm deletion if (!confirm(`Are you sure you want to delete the selected ${selectedSessions.size} chat session(s)? This action cannot be undone.`)) { return; } // Convert Set to Array and delete deleteSessions(Array.from(selectedSessions)); }); // Export functionality - this remains unchanged as it should export all transcripts $('#mxchat-export-transcripts').on('click', function() { var $button = $(this); $button.prop('disabled', true).addClass('loading'); // Create a form and submit it var $form = $('
', { 'method': 'post', 'action': ajaxurl }); $form.append($('', { 'type': 'hidden', 'name': 'action', 'value': 'mxchat_export_transcripts' })); $form.append($('', { 'type': 'hidden', 'name': 'security', 'value': mxchatAdmin.export_nonce })); $form.appendTo('body').submit(); // Re-enable the button after a short delay setTimeout(function() { $button.prop('disabled', false).removeClass('loading'); }, 2000); }); // Chat Email Notification Modal functionality // Open modal $('#mxchat-chat-email-notification-btn').on('click', function(e) { e.preventDefault(); $('#mxchat-chat-email-notification-modal').fadeIn(300); }); // Close modal $('.mxchat-chat-notification-modal-close, .mxchat-chat-notification-modal-cancel').on('click', function() { $('#mxchat-chat-email-notification-modal').fadeOut(300); }); // Close modal on outside click $('#mxchat-chat-email-notification-modal').on('click', function(e) { if ($(e.target).is('#mxchat-chat-email-notification-modal')) { $(this).fadeOut(300); } }); // Handle form submission - Let WordPress handle it normally for settings $('#mxchat-chat-email-notification-form').on('submit', function(e) { // Don't prevent default - let the form submit normally to WordPress options.php var $submitButton = $(this).find('button[type="submit"]'); var originalText = $submitButton.text(); // Just show a loading state $submitButton.text('Saving...').prop('disabled', true); // The form will submit normally and reload the page }); // ========== RAG Context Modal Functions ========== // Open RAG context modal and fetch data function openRagContextModal(messageId) { const $modal = $('#mxchat-rag-context-modal'); const $loading = $modal.find('.mxchat-rag-loading'); const $content = $modal.find('.mxchat-rag-content'); // Show modal with loading state $modal.fadeIn(300); $loading.show(); $content.html(''); // Fetch RAG context via AJAX $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'mxchat_get_rag_context', message_id: messageId }, success: function(response) { $loading.hide(); if (response.success && response.data) { renderRagContext(response.data, $content); } else { $content.html('
Unable to load document context.
'); } }, error: function() { $loading.hide(); $content.html('
Error loading document context. Please try again.
'); } }); } // Render RAG context data in the modal function renderRagContext(data, $container) { let html = ''; // Summary section html += '
'; html += '
'; html += 'Knowledge Base: '; html += '' + escapeHtml(data.knowledge_base_type || 'WordPress Database') + ''; html += '
'; html += '
'; html += 'Similarity Threshold: '; html += '' + Math.round((data.similarity_threshold || 0.35) * 100) + '%'; html += '
'; html += '
'; html += 'Documents Checked: '; html += '' + (data.total_documents_checked || 0) + ''; html += '
'; html += '
'; // Top matches section if (data.top_matches && data.top_matches.length > 0) { html += '
'; html += '

Retrieved Documents

'; data.top_matches.forEach(function(match, index) { const isUsed = match.used_for_context; const isAboveThreshold = match.above_threshold; const cardClass = isUsed ? 'mxchat-rag-match-used' : (isAboveThreshold ? 'mxchat-rag-match-above' : 'mxchat-rag-match-below'); const statusIcon = isUsed ? '✅' : (isAboveThreshold ? '⚠️' : '❌'); const statusLabel = isUsed ? 'Used for Response' : (isAboveThreshold ? 'Above Threshold' : 'Below Threshold'); html += '
'; html += '
'; html += '#' + (index + 1) + ''; html += '' + match.similarity_percentage + '%'; html += ''; html += statusIcon + ' ' + statusLabel; html += ''; html += '
'; html += '
'; if (match.source_display && match.source_display.startsWith('http')) { html += ''; html += '🔗 ' + escapeHtml(match.source_display); html += ''; } else { html += '📄 ' + escapeHtml(match.source_display || 'Content snippet'); } html += '
'; if (match.content_preview) { html += '
'; html += escapeHtml(match.content_preview); html += '
'; } // Show role restriction if not public if (match.role_restriction && match.role_restriction !== 'public') { html += '
'; html += '🔒 ' + escapeHtml(match.role_restriction) + ''; html += '
'; } html += '
'; }); html += '
'; } else { html += '
No document matches found for this response.
'; } // Approved URLs section if (data.approved_urls && data.approved_urls.length > 0) { html += '
'; html += '

Approved URLs for Citations (' + data.approved_urls.length + ')

'; html += ''; html += '
'; } $container.html(html); } // Helper function to escape HTML function escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // Close RAG context modal $('.mxchat-rag-modal-close').on('click', function() { $('#mxchat-rag-context-modal').fadeOut(300); }); // Close modal on outside click $('#mxchat-rag-context-modal').on('click', function(e) { if ($(e.target).is('#mxchat-rag-context-modal')) { $(this).fadeOut(300); } }); // Close modal on Escape key $(document).on('keydown', function(e) { if (e.key === 'Escape') { $('#mxchat-rag-context-modal').fadeOut(300); } }); });