File: /var/www/html/www.winghung.com/wp-content/plugins/upkyk-assistant-ai/admin/js/training-page.js
/**
* Upkyk AssistantAI Custom Phrases JavaScript
*/
// Diagnostic information
console.log('====== UPKYK ASSISTANT AI DIAGNOSTIC INFO ======');
console.log('WordPress AJAX URL: "' + (typeof upkyk_admin_vars !== 'undefined' ? upkyk_admin_vars.ajax_url : 'undefined') + '"');
console.log('WordPress Plugin URL: "' + (typeof upkyk_admin_vars !== 'undefined' ? upkyk_admin_vars.plugin_url : 'undefined') + '"');
console.log('Nonce: "' + (typeof upkyk_admin_vars !== 'undefined' ? upkyk_admin_vars.nonce.substring(0, 5) + '...' : 'undefined') + '" (partial for security)');
console.log('DB Table Check: "' + (typeof upkyk_admin_vars !== 'undefined' ? (upkyk_admin_vars.db_table_exists ? 'Table Exists' : 'Table Missing') : 'undefined') + '"');
// Initialize global variables including nonce
window.upkykDiagnostic = {
scriptLoaded: true, // We're in the script, so it's loaded
functionsAvailable: {
loadDocuments: typeof window.loadDocuments === 'function',
loadTrainingDocuments: typeof window.loadTrainingDocuments === 'function',
handleDocumentUpload: typeof window.handleDocumentUpload === 'function'
}
};
// After document ready, check again
jQuery(document).ready(function($) {
window.upkykDiagnostic.functionsAvailable = {
loadDocuments: typeof window.loadDocuments === 'function',
loadTrainingDocuments: typeof window.loadTrainingDocuments === 'function',
handleDocumentUpload: typeof window.handleDocumentUpload === 'function'
};
console.log('Functions available after document ready:', window.upkykDiagnostic.functionsAvailable);
});
// Define noConflict mode to avoid conflicts with other libraries
jQuery.noConflict();
// Define global functions first so they're available everywhere
function editPhrase(id) {
console.log('Global editPhrase called with id:', id);
jQuery(document).ready(function($) {
// First try to find the phrase row in the tab table
let $row = $(`#upkyk-phrases-list tr[data-id="${id}"]`);
// If not found in the tab table, try to find it in the direct database diagnosis table
if (!$row.length) {
// Look for the row with the matching ID in the first column of the direct table
$row = $(`#phrases-database-diagnosis table tr`).filter(function() {
return $(this).find('td:first-child').text().trim() === id.toString();
});
}
if (!$row.length) {
console.error('Phrase row not found:', id);
showNotification('Error', 'Phrase not found in the list', 'error');
return;
}
// Different cell structure based on which table we found the row in
let question, answer, category;
// If we found the row in the direct table (has at least 4 cells)
if ($row.find('td').length >= 4) {
question = $row.find('td:nth-child(2)').text().trim();
answer = $row.find('td:nth-child(3)').text().trim();
category = $row.find('td:nth-child(4)').text().trim();
} else {
// Default tab structure - adjust indices as needed
question = $row.find('td:nth-child(2)').text().trim();
answer = $row.find('td:nth-child(3)').text().trim();
category = $row.find('td:nth-child(4)').text().trim();
}
// Populate form fields
$('#upkyk-phrase-question').val(question);
$('#upkyk-phrase-answer').val(answer);
$('#upkyk-phrase-category').val(category);
// Change button text
$('#upkyk-add-phrase-form button[type="submit"]').text('Update Phrase');
// Store edit ID in the form
$('#upkyk-add-phrase-form').data('edit-id', id);
// Scroll to form
$('html, body').animate({
scrollTop: $('#upkyk-add-phrase-form').offset().top - 50
}, 300);
// Focus first field
$('#upkyk-phrase-question').focus();
// Show notification
showNotification('Info', 'Editing phrase. Submit the form to save changes.', 'info');
// Add cancel button if it doesn't exist
if (!$('#upkyk-cancel-phrase-edit').length) {
$('#upkyk-add-phrase-form button[type="submit"]').after(' <button type="button" id="upkyk-cancel-phrase-edit" class="button">Cancel</button>');
// Add cancel handler
$('#upkyk-cancel-phrase-edit').on('click', function() {
resetForms();
$(this).remove();
});
}
});
}
// Global deletePhrase function for direct access from HTML
function deletePhrase(id) {
console.log('deletePhrase called with ID:', id);
if (!confirm('Are you sure you want to delete this phrase?')) {
return;
}
// Disable the button to prevent multiple clicks
const $button = jQuery('.delete-phrase[data-id="' + id + '"]');
$button.prop('disabled', true).text('Deleting...');
// IMPORTANT: Use the exact same approach as the working rebuild_tables function
// Use the global ajaxurl variable that WordPress provides
if (typeof ajaxurl === 'undefined') {
console.error('WordPress ajaxurl not defined!');
showNotification('Error', 'WordPress configuration error', 'error');
$button.prop('disabled', false).text('Delete');
return;
}
// Make a direct AJAX request with minimal complexity
jQuery.ajax({
url: ajaxurl, // Use WordPress global variable
type: 'POST',
data: {
action: 'upkyk_delete_phrase',
id: id,
// Use inline nonce from the form - this is how rebuild_tables works
nonce: jQuery('#upkyk-add-phrase-form input[name="nonce"]').val()
},
success: function(response) {
console.log('Delete response:', response);
if (response.success) {
// Remove the row from the table
const $row = $button.closest('tr');
$row.fadeOut(400, function() {
$row.remove();
// Update phrase count
const $countText = jQuery('#phrases-database-diagnosis p:contains("Contains")');
if ($countText.length) {
const currentCount = parseInt($countText.text().match(/\d+/)[0]);
$countText.text('Contains ' + (currentCount - 1) + ' phrases');
// Hide delete selected button if no more phrases
if (currentCount - 1 <= 0) {
jQuery('#delete-selected-phrases').hide();
}
}
});
// Show success message
showNotification('Success', response.data && response.data.message ? response.data.message : 'Phrase deleted successfully', 'success');
} else {
// Show error message
showNotification('Error', response.data && response.data.message ? response.data.message : 'Failed to delete phrase', 'error');
// Re-enable the button
$button.prop('disabled', false).text('Delete');
}
},
error: function(xhr, status, error) {
console.error('AJAX error:', status, error);
console.log('Response text:', xhr.responseText);
showNotification('Error', 'Server error: ' + error, 'error');
// Re-enable the button
$button.prop('disabled', false).text('Delete');
}
});
}
// Global helper function for notifications
function showNotification(title, message, type) {
console.log('Showing notification:', { title, message, type });
// Use the WordPress admin notices element if it exists
const $notices = jQuery('#upkyk-admin-notices');
if (!$notices.length) {
console.warn('Admin notices container not found, falling back to default method');
// Remove any existing notifications of the same type
jQuery('.notice.' + type).remove();
const notificationClass = type === 'error' ? 'notice-error' :
type === 'success' ? 'notice-success' :
type === 'info' ? 'notice-info' : 'notice-warning';
const notification = jQuery(`
<div class="notice ${notificationClass} is-dismissible" style="margin: 5px 0 15px;">
<p><strong>${title}:</strong> ${message}</p>
<button type="button" class="notice-dismiss">
<span class="screen-reader-text">Dismiss this notice.</span>
</button>
</div>
`);
// Find the best place to show the notification
// First try to find specific containers
var $container;
if (jQuery('#phrases-tab').is(':visible')) {
$container = jQuery('#phrases-tab');
// Insert after the form container if present
const $formContainer = $container.find('.upkyk-form-container');
if ($formContainer.length) {
$formContainer.after(notification);
// Scroll to notification if not in viewport
if (!isElementInViewport(notification[0])) {
jQuery('html, body').animate({
scrollTop: notification.offset().top - 50
}, 300);
}
return;
}
}
// Otherwise, look for tab content containers
$container = jQuery('.upkyk-tab-content:visible, .upkyk-tab-pane:visible').first();
if (!$container.length) {
// Fallback to main containers
$container = jQuery('#knowledge-base').length ? jQuery('#knowledge-base') : jQuery('#training');
}
const $existingNotifications = $container.find('.notice');
if ($existingNotifications.length) {
// If there are existing notifications, add after the last one
$existingNotifications.last().after(notification);
} else {
// Otherwise, add at the top of the container
$container.prepend(notification);
}
// Add dismiss button functionality
notification.find('.notice-dismiss').on('click', function() {
jQuery(this).parent().fadeOut(100, function() {
jQuery(this).remove();
});
});
// Auto-dismiss success and info messages after 5 seconds
if (type === 'success' || type === 'info') {
setTimeout(function() {
notification.fadeOut(500, function() {
jQuery(this).remove();
});
}, 5000);
}
return;
}
// Create the notice
const noticeClass = type === 'error' ? 'notice-error' :
type === 'success' ? 'notice-success' :
type === 'warning' ? 'notice-warning' : 'notice-info';
const $notice = jQuery(`
<div class="notice ${noticeClass} is-dismissible">
<p><strong>${title}:</strong> ${message}</p>
<button type="button" class="notice-dismiss">
<span class="screen-reader-text">Dismiss this notice.</span>
</button>
</div>
`);
// Add the notice to the container
$notices.append($notice);
// Add dismiss button functionality
$notice.find('.notice-dismiss').on('click', function() {
jQuery(this).parent().fadeOut(100, function() {
jQuery(this).remove();
});
});
// Auto-dismiss success and info messages after 5 seconds
if (type === 'success' || type === 'info') {
setTimeout(function() {
$notice.fadeOut(500, function() {
jQuery(this).remove();
});
}, 5000);
}
}
// Helper function to check if an element is in viewport
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
// Global helper function to reset forms
function resetForms() {
jQuery(document).ready(function($) {
// Reset custom phrase form
$('#upkyk-add-phrase-form').removeData('edit-id');
$('#upkyk-phrase-question, #upkyk-phrase-answer, #upkyk-phrase-category').val('');
$('#upkyk-add-phrase-form button[type="submit"]').text('Add Phrase').prop('disabled', false);
});
}
// Global helper function to escape HTML
function escapeHtml(text) {
if (!text) return '';
return text
.toString()
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// Global helper function for showing PRO upgrade notifications
function showProUpgradeNotification() {
console.log('showProUpgradeNotification called');
if (typeof window.showNotification === 'function') {
window.showNotification('PRO Feature', 'This feature is available in the PRO version', 'info');
} else if (typeof showNotification === 'function') {
showNotification('PRO Feature', 'This feature is available in the PRO version', 'info');
} else {
console.log('Unable to show notification - notification function not available');
}
}
// Make global helper accessible
window.showProUpgradeNotification = showProUpgradeNotification;
// Main jQuery module
(function($) {
'use strict';
// Function declarations for all the key functions
/**
* Initialize modal functionality
*/
function initModals() {
console.log('Initializing modals');
var modal = document.getElementById('upkyk-confirmation-modal');
var closeBtn = document.getElementsByClassName('upkyk-modal-close')[0];
var cancelBtn = document.getElementById('upkyk-modal-cancel');
if (closeBtn) {
closeBtn.onclick = function() {
modal.style.display = "none";
}
}
if (cancelBtn) {
cancelBtn.onclick = function() {
modal.style.display = "none";
}
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
}
// Make initModals available globally
window.initModals = initModals;
/**
* Initialize tab navigation
*/
function initTabs() {
console.log('Initializing tabs...');
// First, remove any existing click handlers
$('.upkyk-tab-link').off('click');
// Remove initial .hide() - rely on CSS .upkyk-tab-pane { display: none; } instead
// $('.upkyk-tab-pane').hide();
// Add click handler to all tabs
$('.upkyk-tab-link').on('click', function(e) {
e.preventDefault();
var targetTab = $(this).attr('href');
console.log('Tab clicked:', targetTab);
// Update active tab link
$('.upkyk-tab-link').removeClass('active');
$(this).addClass('active');
// Remove explicit .hide() and .show() - manage visibility via CSS and the 'active' class
$('.upkyk-tab-pane').removeClass('active');
$(targetTab).addClass('active');
// Store active tab in localStorage for persistence
localStorage.setItem('upkyk_training_active_tab', targetTab);
});
// Restore previously active tab or default to first tab
var activeTab = localStorage.getItem('upkyk_training_active_tab');
var initialTabLink = null;
if (activeTab && $(activeTab).length) {
initialTabLink = $('.upkyk-tab-link[href="' + activeTab + '"]');
} else {
// Default to the first tab link
initialTabLink = $('.upkyk-tab-link').first();
}
// Activate the initial tab (link and pane) using classes, don't trigger click
if (initialTabLink && initialTabLink.length) {
var initialTargetPane = initialTabLink.attr('href');
$('.upkyk-tab-link').removeClass('active');
initialTabLink.addClass('active');
$('.upkyk-tab-pane').removeClass('active');
$(initialTargetPane).addClass('active');
console.log('Initial tab set to:', initialTargetPane);
} else {
console.error('Could not determine initial tab.');
// Fallback: Ensure at least the first pane is shown if detection fails
$('.upkyk-tab-pane').first().addClass('active');
}
console.log('Tabs initialized using class-based logic');
}
// Global function to ensure tables exist
window.ensureTablesExist = function() {
console.log('Ensuring tables exist...');
// Get AJAX URL and nonce
const ajaxUrl = typeof ajaxurl !== 'undefined' ? ajaxurl : '/wp-admin/admin-ajax.php';
const nonce = jQuery('#upkyk-add-phrase-form input[name="nonce"]').val();
console.log('Using Ajax URL for ensuring tables:', ajaxUrl);
jQuery.ajax({
url: ajaxUrl,
type: 'POST',
data: {
action: 'upkyk_ensure_tables_exist',
nonce: nonce
},
success: function(response) {
console.log('Ensure tables response:', response);
if (response.success) {
console.log('Tables exist or were created successfully');
// No longer auto-reload the page
if (typeof window.loadTrainingData === 'function') {
window.loadTrainingData();
}
} else {
window.showNotification('Error', 'Failed to create tables: ' + (response.data?.message || 'Unknown error'), 'error');
}
},
error: function(xhr, status, error) {
console.error('Tables creation error:', status, error);
window.showNotification('Error', 'Server error when creating tables: ' + error, 'error');
}
});
};
// Global function to initialize direct buttons
window.initDirectButtons = function() {
console.log('Initializing direct action buttons');
// Direct delete phrase buttons
jQuery('.delete-phrase').off('click').on('click', function(e) {
e.preventDefault();
const id = jQuery(this).data('id');
console.log('Delete phrase clicked for ID:', id);
// Call the global deletePhrase function
window.deletePhrase = deletePhrase; // Make sure it's available on window
deletePhrase(id);
});
// Checkbox select all handlers
jQuery('#select-all-phrases').on('change', function() {
const isChecked = jQuery(this).prop('checked');
jQuery('.phrase-checkbox').prop('checked', isChecked);
});
};
// Global function to load training data
window.loadTrainingData = function() {
console.log('Loading training data...');
// Get AJAX URL and nonce
const ajaxUrl = typeof ajaxurl !== 'undefined' ? ajaxurl : '/wp-admin/admin-ajax.php';
const nonce = jQuery('#upkyk-add-phrase-form input[name="nonce"]').val();
console.log('Using Ajax URL for loading data:', ajaxUrl);
jQuery.ajax({
url: ajaxUrl,
type: 'POST',
data: {
action: 'upkyk_get_training_data',
nonce: nonce
},
beforeSend: function() {
console.log('Fetching training data...');
// Show loading indicators
jQuery('#phrases-database-diagnosis').append(
'<div class="upkyk-loading">Loading...</div>'
);
},
success: function(response) {
console.log('Training data response:', response);
jQuery('.upkyk-loading').remove();
if (response.success) {
// Update phrases table
if (response.data.phrases) {
updatePhrasesTable(response.data.phrases);
}
} else {
window.showNotification('Error', 'Failed to load training data: ' + (response.data?.message || 'Unknown error'), 'error');
}
},
error: function(xhr, status, error) {
jQuery('.upkyk-loading').remove();
console.error('AJAX error:', status, error);
console.log('Response text:', xhr.responseText);
window.showNotification('Error', 'Server error: ' + error, 'error');
}
});
};
/**
* Update phrases table with new data
* @param {Array} phrases - Array of phrase objects
*/
function updatePhrasesTable(phrases) {
console.log('Updating phrases table with new data:', phrases);
// Get the table body
const $tableBody = jQuery('#phrases-database-diagnosis table tbody');
if (!$tableBody.length) {
console.error('Phrases table body not found');
return;
}
// Clear existing rows
$tableBody.empty();
// If no phrases, show empty message
if (!phrases || !phrases.length) {
$tableBody.html('<tr><td colspan="6">No phrases found in the database.</td></tr>');
// Hide the delete selected button if we have no phrases
jQuery('#delete-selected-phrases').hide();
return;
}
// Show the delete selected button since we have phrases
jQuery('#delete-selected-phrases').show();
// Add rows for each phrase
phrases.forEach(function(phrase) {
const row = `
<tr>
<td><input type="checkbox" class="phrase-checkbox" value="${phrase.id}"></td>
<td>${phrase.id}</td>
<td>${escapeHtml(phrase.question)}</td>
<td>${escapeHtml(phrase.answer)}</td>
<td>${escapeHtml(phrase.category || 'General')}</td>
<td>
<button type="button" class="button button-small delete-phrase" data-id="${phrase.id}">Delete</button>
</td>
</tr>
`;
$tableBody.append(row);
});
// Reinitialize delete buttons
jQuery('.delete-phrase').off('click').on('click', function() {
const id = jQuery(this).data('id');
deletePhrase(id);
});
// Reinitialize checkbox select all handlers
jQuery('#select-all-phrases').off('change').on('change', function() {
const isChecked = jQuery(this).prop('checked');
jQuery('.phrase-checkbox').prop('checked', isChecked);
});
}
// Initialize tabs immediately after definition within this scope
initTabs();
})(jQuery); // End of Main jQuery module
// Add a handler for PRO feature elements
jQuery(document).ready(function($) {
// Show PRO upgrade notification for any document training elements
// IMPORTANT: Exclude the test-delete-button from triggering PRO notifications
$(document).on('click', '#upkyk-document-file, .upkyk-choose-file, #upkyk-document-upload-btn, .delete-document, #upkyk-train-button, .upkyk-pro-teaser button:not(#test-delete-button), .upkyk-pro-message a', function(e) {
e.preventDefault();
showProUpgradeNotification();
});
});
/**
* Add a custom phrase to the database
*/
function addCustomPhrase() {
console.log('addCustomPhrase called');
// Get form data
var $form = jQuery('#upkyk-add-phrase-form');
var question = jQuery('#upkyk-phrase-question').val().trim();
var answer = jQuery('#upkyk-phrase-answer').val().trim();
var category = jQuery('#upkyk-phrase-category').val().trim() || 'General';
var nonce = $form.find('input[name="nonce"]').val();
// Validate required fields
if (!question) {
showNotification('Error', 'Please enter a question', 'error');
return false;
}
if (!answer) {
showNotification('Error', 'Please enter an answer', 'error');
return false;
}
// Disable the button during submission
var $button = $form.find('button[type="button"]');
$button.prop('disabled', true).html('Saving...');
// Add a loading indicator to the phrases table
var $tableContainer = jQuery('#phrases-database-diagnosis');
if ($tableContainer.length) {
$tableContainer.addClass('loading');
$tableContainer.append('<div class="upkyk-loading-overlay"><span class="spinner is-active"></span> Adding phrase...</div>');
}
// Create a timeout to reset the button if the request takes too long
var buttonResetTimeout = setTimeout(function() {
$button.prop('disabled', false).html('Add Phrase');
jQuery('.upkyk-loading-overlay').remove();
if ($tableContainer.length) {
$tableContainer.removeClass('loading');
}
showNotification('Warning', 'The request is taking longer than expected. Please check if the phrase was added.', 'warning');
}, 15000); // 15 seconds timeout
// Get proper AJAX URL
var ajaxUrl = (typeof upkykAssistantAITraining !== 'undefined' && upkykAssistantAITraining.ajax_url) ?
upkykAssistantAITraining.ajax_url :
(typeof ajaxurl !== 'undefined' ? ajaxurl : '/wp-admin/admin-ajax.php');
console.log('Using AJAX URL:', ajaxUrl);
console.log('Using nonce (first few chars):', nonce ? nonce.substring(0, 5) + '...' : 'none');
// Send AJAX request
jQuery.ajax({
url: ajaxUrl,
type: 'POST',
data: {
action: 'upkyk_add_phrase',
nonce: nonce,
question: question,
answer: answer,
category: category
},
success: function(response) {
// Clear the timeout since we got a response
clearTimeout(buttonResetTimeout);
// Re-enable the button
$button.prop('disabled', false).html('Add Phrase');
// Remove loading overlay
jQuery('.upkyk-loading-overlay').remove();
if ($tableContainer.length) {
$tableContainer.removeClass('loading');
}
if (response.success) {
showNotification('Success', 'Phrase added successfully', 'success');
// Clear the form
$form[0].reset();
// If the response includes the updated phrases list, use it directly
if (response.data && response.data.phrases) {
// Update the phrases table directly with the returned data
updatePhrasesTable(response.data.phrases);
console.log('Table updated directly from add phrase response');
} else {
// Fall back to page reload if phrases aren't in the response
console.log('Phrases not found in response, falling back to page reload');
localStorage.setItem('upkyk_reload_phrases', 'true');
setTimeout(function() {
window.location.reload();
}, 500);
}
} else {
showNotification('Error', response.data?.message || 'Failed to add phrase', 'error');
}
},
error: function(xhr, status, error) {
// Clear the timeout since we got a response
clearTimeout(buttonResetTimeout);
console.error('AJAX error:', status, error);
console.log('Response text:', xhr.responseText);
showNotification('Error', 'Server error: ' + error, 'error');
// Remove loading overlay
jQuery('.upkyk-loading-overlay').remove();
if ($tableContainer.length) {
$tableContainer.removeClass('loading');
}
// Re-enable the button
$button.prop('disabled', false).html('Add Phrase');
}
});
return false;
}
/**
* Refresh the phrases list after adding or deleting
*/
function refreshPhrasesList() {
console.log('Refreshing phrases list...');
// Show loading indicator
var $tableContainer = jQuery('#phrases-database-diagnosis');
if ($tableContainer.length) {
$tableContainer.addClass('loading');
$tableContainer.append('<div class="upkyk-loading-overlay"><span class="spinner is-active"></span> Loading phrases...</div>');
}
// Get proper AJAX URL and nonce
var ajaxUrl = (typeof upkykAssistantAITraining !== 'undefined' && upkykAssistantAITraining.ajax_url) ?
upkykAssistantAITraining.ajax_url :
(typeof ajaxurl !== 'undefined' ? ajaxurl : '/wp-admin/admin-ajax.php');
var nonce = '';
// Try multiple sources for the nonce value
if (typeof upkykAssistantAITraining !== 'undefined' && upkykAssistantAITraining.nonce) {
nonce = upkykAssistantAITraining.nonce;
} else if (typeof upkyk_admin_vars !== 'undefined' && upkyk_admin_vars.nonce) {
nonce = upkyk_admin_vars.nonce;
} else {
// Try to get nonce from the form
var formNonce = jQuery('#upkyk-add-phrase-form input[name="nonce"]').val();
if (formNonce) {
nonce = formNonce;
}
}
console.log('Using AJAX URL:', ajaxUrl);
console.log('Using nonce (first few chars):', nonce ? nonce.substring(0, 5) + '...' : 'none');
jQuery.ajax({
url: ajaxUrl,
type: 'POST',
data: {
action: 'upkyk_get_training_data',
nonce: nonce
},
success: function(response) {
// Remove loading indicator
jQuery('.upkyk-loading-overlay').remove();
if ($tableContainer.length) {
$tableContainer.removeClass('loading');
}
if (response.success && response.data && response.data.phrases) {
// Update the table with the new data
updatePhrasesTable(response.data.phrases);
showNotification('Success', 'Phrases list refreshed successfully', 'success');
} else {
console.error('Failed to refresh phrases list:', response);
showNotification('Error', 'Failed to refresh phrases list: ' + (response.data?.message || 'Unknown error'), 'error');
// Since we had an error refreshing, trigger a manual page reload after a delay
setTimeout(function() {
window.location.reload();
}, 2000);
}
},
error: function(xhr, status, error) {
// Remove loading indicator
jQuery('.upkyk-loading-overlay').remove();
if ($tableContainer.length) {
$tableContainer.removeClass('loading');
}
console.error('AJAX error while refreshing phrases:', status, error);
console.log('Response text:', xhr.responseText);
showNotification('Error', 'Error refreshing phrases: ' + error, 'error');
// Since we couldn't refresh the list via AJAX, reload the page after a short delay
setTimeout(function() {
window.location.reload();
}, 2000);
}
});
}
// Make addCustomPhrase function globally available
window.addCustomPhrase = addCustomPhrase;
// Make refreshPhrasesList function globally available
window.refreshPhrasesList = refreshPhrasesList;
// Tabs are initialized by the initTabs function below
/**
* Initialize form handlers and validation
*/
function initForms() {
console.log('Initializing forms...');
// Initialize custom phrase form
var $phraseForm = jQuery('#upkyk-add-phrase-form');
if ($phraseForm.length) {
console.log('Custom phrase form found, initializing');
// Handle form submission event (Canonical way)
$phraseForm.on('submit', function(e) {
e.preventDefault();
console.log('Form submitted');
window.addCustomPhrase();
});
} else {
console.log('Custom phrase form not found');
}
// Reset any editing state on page load
resetForms();
console.log('Forms initialized');
}
// Document ready function at the beginning to check for reload flag
jQuery(document).ready(function($) {
// Check if we should reload the phrases tab
if (localStorage.getItem('upkyk_reload_phrases') === 'true') {
// Clear the flag
localStorage.removeItem('upkyk_reload_phrases');
// Make sure we're on the phrases tab
$('.upkyk-tab-link[href="#phrases-tab"]').trigger('click');
// Show notification
if (typeof showNotification === 'function') {
setTimeout(function() {
showNotification('Success', 'Phrase list updated successfully', 'success');
}, 500);
}
}
// Initialize forms
if (typeof initForms === 'function') {
initForms();
} else {
console.error('initForms function not found in training-page.js');
}
// Initialize delete buttons
console.log('Initializing delete buttons...');
// Add click handler for individual delete buttons
$(document).on('click', '.delete-phrase', function(e) {
e.preventDefault();
const id = $(this).data('id');
console.log('Delete button clicked for ID:', id);
deletePhrase(id);
});
// Add click handler for bulk delete button
$(document).on('click', '#delete-selected-phrases', function(e) {
e.preventDefault();
const selectedIds = [];
$('.phrase-checkbox:checked').each(function() {
selectedIds.push($(this).val());
});
console.log('Selected IDs for bulk delete:', selectedIds);
if (selectedIds.length === 0) {
alert('Please select at least one phrase to delete.');
return;
}
if (!confirm('Are you sure you want to delete ' + selectedIds.length + ' selected phrases?')) {
return;
}
// Disable the button
const $button = $(this);
$button.prop('disabled', true).text('Deleting...');
// Get nonce from the form
const nonce = $('#upkyk-add-phrase-form input[name="nonce"]').val();
$.ajax({
url: ajaxurl, // Use WordPress global variable
type: 'POST',
data: {
action: 'upkyk_delete_phrases',
phrase_ids: selectedIds,
nonce: nonce
},
success: function(response) {
console.log('Bulk delete response:', response);
if (response.success) {
// Remove the selected rows
selectedIds.forEach(function(id) {
$('.phrase-checkbox[value="' + id + '"]').closest('tr').fadeOut(400, function() {
$(this).remove();
});
});
// Update phrase count
const $countText = $('p:contains("Contains")');
if ($countText.length) {
const currentCount = parseInt($countText.text().match(/\d+/)[0]);
const newCount = currentCount - selectedIds.length;
$countText.text('Contains ' + newCount + ' phrases');
// Hide delete selected button if no more phrases
if (newCount <= 0) {
$('#delete-selected-phrases').hide();
}
}
// Uncheck the "select all" checkbox
$('#select-all-phrases').prop('checked', false);
// Show success message
showNotification('Success', response.data && response.data.message ? response.data.message : 'Phrases deleted successfully', 'success');
} else {
// Show error message
showNotification('Error', response.data && response.data.message ? response.data.message : 'Failed to delete phrases', 'error');
// Re-enable the button
$button.prop('disabled', false).text('Delete Selected');
}
},
error: function(xhr, status, error) {
console.error('AJAX error:', status, error);
console.log('Response text:', xhr.responseText);
showNotification('Error', 'Server error: ' + error, 'error');
// Re-enable the button
$button.prop('disabled', false).text('Delete Selected');
}
});
});
// Handle "select all" checkbox
$(document).on('change', '#select-all-phrases', function() {
$('.phrase-checkbox').prop('checked', $(this).prop('checked'));
});
console.log('Delete buttons initialized');
});
// Test Chatbot Functionality
jQuery(document).ready(function($) {
// Function to send message directly
function sendDirectTestMessage() {
var message = $('#upkyk-test-input').val().trim();
if (!message) {
return;
}
// Add user message to chat
$('#upkyk-test-messages').append(
'<div class="upkyk-test-message user">' + message + '</div>'
);
// Clear input
$('#upkyk-test-input').val('');
// Add loading indicator
$('#upkyk-test-messages').append(
'<div class="upkyk-test-message bot loading">' +
'<div class="upkyk-typing-indicator"><span></span><span></span><span></span></div>' +
'</div>'
);
// Send AJAX request
$.ajax({
url: upkyk_admin_vars.ajax_url,
type: 'POST',
data: {
action: 'upkyk_test_assistant_ai',
message: message,
nonce: upkyk_admin_vars.nonce
},
success: function(response) {
// Remove loading indicator
$('.upkyk-test-message.loading').remove();
if (response.success) {
// Add bot response
$('#upkyk-test-messages').append(
'<div class="upkyk-test-message bot">' +
response.data.response +
'</div>'
);
// Update analysis
$('#upkyk-response-analysis').html(
'<p><strong>' + upkyk_admin_vars.test_i18n.question + '</strong> ' + message + '</p>' +
'<p><strong>' + upkyk_admin_vars.test_i18n.ai_response + '</strong> ' + upkyk_admin_vars.test_i18n.generated_success + '</p>'
);
} else {
// Add error message
$('#upkyk-test-messages').append(
'<div class="upkyk-test-message bot error">' +
upkyk_admin_vars.test_i18n.error + ' ' + (response.data ? response.data.message : upkyk_admin_vars.test_i18n.unknown_error) +
'</div>'
);
// Update analysis
$('#upkyk-response-analysis').html(
'<p><strong>' + upkyk_admin_vars.test_i18n.error + '</strong> ' +
(response.data ? response.data.message : upkyk_admin_vars.test_i18n.unknown_error) +
'</p>' +
'<p>' + upkyk_admin_vars.test_i18n.check_api + '</p>'
);
}
// Scroll to bottom
$('#upkyk-test-messages').scrollTop($('#upkyk-test-messages')[0].scrollHeight);
},
error: function(xhr, status, error) {
// Remove loading indicator
$('.upkyk-test-message.loading').remove();
// Add error message
$('#upkyk-test-messages').append(
'<div class="upkyk-test-message bot error">' +
upkyk_admin_vars.test_i18n.server_error + ' ' + error + '. ' + upkyk_admin_vars.test_i18n.try_again +
'</div>'
);
// Update analysis
$('#upkyk-response-analysis').html(
'<p><strong>' + upkyk_admin_vars.test_i18n.server_error_title + '</strong> ' + error + '</p>' +
'<p>' + upkyk_admin_vars.test_i18n.check_network + '</p>'
);
// Scroll to bottom
$('#upkyk-test-messages').scrollTop($('#upkyk-test-messages')[0].scrollHeight);
}
});
}
// Attach direct event handlers to buttons
$('#upkyk-test-send').on('click', function() {
sendDirectTestMessage();
});
// Direct input keypress listener
$('#upkyk-test-input').on('keypress', function(e) {
if (e.which === 13) {
sendDirectTestMessage();
e.preventDefault();
}
});
});
// Function to bind events to document list items
function bindDocumentEvents() {
// Use event delegation for document deletion
jQuery(document).off('click', '.delete-document').on('click', '.delete-document', function(e) {
e.preventDefault();
const documentId = jQuery(this).data('id');
if (confirm(upkyk_admin_vars.i18n.confirm_delete_document || 'Are you sure you want to delete this document? This action cannot be undone.')) {
deleteDocument(documentId);
}
});
// Document search functionality
jQuery('#upkyk-document-search').off('keyup').on('keyup', function() {
const searchTerm = jQuery(this).val().toLowerCase();
jQuery('#upkyk-documents-list tr').each(function() {
const text = jQuery(this).text().toLowerCase();
jQuery(this).toggle(text.indexOf(searchTerm) > -1);
});
});
}
// Function to render documents list
function renderDocumentsList(documents) {
console.log('Rendering documents list:', documents);
// Get the document list container
var $documentsList = jQuery('#upkyk-documents-list');
$documentsList.empty();
if (!documents || documents.length === 0) {
$documentsList.html('<tr><td colspan="6">' + (upkyk_admin_vars.i18n.no_documents || 'No documents uploaded yet.') + '</td></tr>');
return;
}
// Format and display each document
documents.forEach(function(doc) {
// Format file size
var size = parseInt(doc.size) || 0;
var formattedSize = size;
// Format date
var formattedDate = '';
if (doc.date_added) {
var date = new Date(doc.date_added);
formattedDate = date.toLocaleString();
}
// Create row
var row = '<tr data-id="' + doc.id + '">' +
'<td>' + (doc.name || '') + '</td>' +
'<td>' + (doc.file_type || '') + '</td>' +
'<td>' + formattedSize + '</td>' +
'<td>' + formattedDate + '</td>' +
'<td>' + (doc.status || 'pending') + '</td>' +
'<td><button class="button button-small delete-document" data-id="' + doc.id + '">' + (upkyk_admin_vars.i18n.delete || 'Delete') + '</button></td>' +
'</tr>';
$documentsList.append(row);
});
// Re-attach event handlers for delete buttons
jQuery('.delete-document').on('click', function() {
var id = jQuery(this).data('id');
if (confirm(upkyk_admin_vars.i18n.confirm_delete_document || 'Are you sure you want to delete this document?')) {
deleteDocument(id);
}
});
}
// Make functions globally available
window.bindDocumentEvents = bindDocumentEvents;
window.renderDocumentsList = renderDocumentsList;
// Function to reset training
function resetTraining() {
showNotification('Info', 'Resetting training...', 'info');
// Show reset in progress UI
const resetButton = jQuery('#upkyk-reset-button');
resetButton.prop('disabled', true).addClass('reset-in-progress');
resetButton.html('<span class="spinner is-active" style="float:none;margin:0 4px 0 0;"></span> Resetting...');
jQuery.ajax({
url: upkyk_admin_vars.ajax_url,
type: 'POST',
data: {
action: 'upkyk_reset_training',
nonce: upkyk_admin_vars.nonce
},
success: function(response) {
// Reset button
resetButton.prop('disabled', false).removeClass('reset-in-progress');
resetButton.html('<i class="dashicons dashicons-dismiss"></i> Reset Training');
if (response.success) {
showNotification('Success', 'Training reset successfully!', 'success');
// Force reload the page to reflect updated training status
setTimeout(function() {
window.location.reload();
}, 1500);
} else {
showNotification('Error', response.data?.message || 'Failed to reset training.', 'error');
}
},
error: function(xhr, status, error) {
// Reset button
resetButton.prop('disabled', false).removeClass('reset-in-progress');
resetButton.html('<i class="dashicons dashicons-dismiss"></i> Reset Training');
showNotification('Error', 'Server error: ' + error, 'error');
}
});
}
// Helper function to format file size
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
var k = 1024;
var sizes = ['Bytes', 'KB', 'MB', 'GB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// Helper function to format date
function formatDate(dateString) {
var date = new Date(dateString);
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
}
// Global function for notifications
function showNotification(title, message, type = 'info') {
console.log(`Notification (${type}): ${title} - ${message}`);
// Use WordPress admin notices
if (typeof jQuery !== 'undefined') {
const noticeClass = type === 'error' ? 'notice-error' :
type === 'success' ? 'notice-success' :
type === 'warning' ? 'notice-warning' : 'notice-info';
// First remove any existing notices with the same type
jQuery('#upkyk-admin-notices .notice.' + noticeClass).remove();
const $notice = jQuery(`
<div class="notice ${noticeClass} is-dismissible upkyk-admin-notice">
<p><strong>${title}:</strong> ${message}</p>
<button type="button" class="notice-dismiss"></button>
</div>
`);
// Ensure the notices container exists and is visible
const $noticesContainer = jQuery('#upkyk-admin-notices');
if ($noticesContainer.length === 0) {
jQuery('.upkyk-training-container').prepend('<div id="upkyk-admin-notices"></div>');
}
jQuery('#upkyk-admin-notices').append($notice);
// Initialize the dismissible functionality
$notice.find('.notice-dismiss').on('click', function() {
jQuery(this).closest('.notice').fadeOut(300, function() { jQuery(this).remove(); });
});
// Auto-dismiss after some time
setTimeout(function() {
$notice.fadeOut(500, function() {
jQuery(this).remove();
});
}, 5000);
} else {
// Fallback to alert if jQuery is not available
alert(`${title}: ${message}`);
}
}
// Function to show notification if not already defined
if (typeof window.showNotification !== 'function' && typeof showNotification !== 'function') {
function showNotification(title, message, type) {
console.log(`${type.toUpperCase()}: ${title} - ${message}`);
// Create a unique ID for the notification
const notificationId = 'notification-' + Date.now();
// Create notification element
const $notification = $(`
<div id="${notificationId}" class="upkyk-notification ${type}">
<strong>${title}</strong>: ${message}
<span class="upkyk-notification-close">×</span>
</div>
`);
// Add to notifications container
if ($('.upkyk-notifications-container').length === 0) {
$('body').append('<div class="upkyk-notifications-container"></div>');
}
$('.upkyk-notifications-container').append($notification);
// Add close handler
$notification.find('.upkyk-notification-close').on('click', function() {
$notification.fadeOut(300, function() {
$(this).remove();
});
});
// Auto-remove after 5 seconds
setTimeout(function() {
if ($notification.length) {
$notification.fadeOut(500, function() {
$(this).remove();
});
}
}, 5000);
// Return the notification for potential further use
return $notification;
}
}
// Override the loadDocuments and related functions to do nothing
function loadDocuments() {
console.log('Document loading disabled in core version');
// Do nothing - documents are only available in PRO
}
function loadTrainingDocuments() {
console.log('Training documents loading disabled in core version');
// Do nothing - documents are only available in PRO
}
function handleDocumentUpload() {
console.log('Document upload disabled in core version');
showProUpgradeNotification();
return false;
}
function showProUpgradeNotification() {
showNotification('PRO Feature', 'Document training is available in the PRO version.', 'info');
}
// Override the training buttons to show upgrade notifications
jQuery(document).ready(function($) {
$('.upkyk-pro-teaser button, .upkyk-pro-teaser input, .upkyk-pro-teaser .upkyk-choose-file').on('click', function(e) {
e.preventDefault();
showProUpgradeNotification();
});
// Attach click handler to the pro teaser links
$('.upkyk-pro-message a').on('click', function(e) {
e.preventDefault();
showProUpgradeNotification();
});
// Initialize the Add Phrase button - make this a clean simple handler
$('#add-phrase-button').on('click', function() {
window.addCustomPhrase();
});
});
// Make additional functions globally available
window.resetTraining = resetTraining;
window.formatFileSize = formatFileSize;
window.formatDate = formatDate;
window.showProUpgradeNotification = showProUpgradeNotification;
window.loadDocuments = loadDocuments;
window.loadTrainingDocuments = loadTrainingDocuments;
window.handleDocumentUpload = handleDocumentUpload;
// Document ready function for training page
jQuery(document).ready(function($) {
// Create notifications container if it doesn't exist
if ($('#upkyk-notifications').length === 0) {
$('body').append('<div id="upkyk-notifications" class="upkyk-notifications"></div>');
}
// Handle train button click
jQuery('#upkyk-train-button').on('click', function() {
console.log('Train button clicked');
if (confirm(upkyk_admin_vars.i18n.train_confirm_message || 'Are you sure you want to train the Assistant AI with the uploaded documents? This process may take some time.')) {
console.log('Training confirmed');
// Show training in progress UI
const trainButton = jQuery(this);
const resetButton = jQuery('#upkyk-reset-button');
// Disable both train and reset buttons during training
trainButton.prop('disabled', true).addClass('training-in-progress');
resetButton.prop('disabled', true);
trainButton.html('<span class="spinner is-active"></span> ' + (upkyk_admin_vars.i18n.training_in_progress || 'Training in Progress...'));
// Send AJAX request to start training
jQuery.ajax({
url: upkyk_admin_vars.ajax_url,
type: 'POST',
data: {
action: 'upkyk_train_assistant_ai',
nonce: upkyk_admin_vars.nonce
},
success: function(response) {
console.log('Training response:', response);
if (response.success) {
showNotification(upkyk_admin_vars.i18n.success || 'Success', upkyk_admin_vars.i18n.training_completed || 'Training completed successfully!', 'success');
// Reload page after a delay
setTimeout(function() {
location.reload();
}, 2000);
} else {
showNotification(upkyk_admin_vars.i18n.error || 'Error', response.data?.message || upkyk_admin_vars.i18n.training_failed || 'Training failed', 'error');
// Reset UI
trainButton.prop('disabled', false).removeClass('training-in-progress');
resetButton.prop('disabled', false);
trainButton.html(upkyk_admin_vars.i18n.train_button_text || 'Train Assistant AI');
}
},
error: function(xhr, status, error) {
console.error('Training error:', error);
console.error('Response:', xhr.responseText);
showNotification(upkyk_admin_vars.i18n.error || 'Error', (upkyk_admin_vars.i18n.server_error || 'Server error while training: ') + error, 'error');
// Reset UI
trainButton.prop('disabled', false).removeClass('training-in-progress');
resetButton.prop('disabled', false);
trainButton.html(upkyk_admin_vars.i18n.train_button_text || 'Train Assistant AI');
}
});
}
});
// File upload change handler - auto upload on selection
$('#upkyk-document-file').on('change', function(e) {
if (this.files && this.files[0]) {
$('#selected-file-name').text(this.files[0].name).addClass('file-selected');
$('#upkyk-document-upload-btn').show();
} else {
$('#selected-file-name').text(upkyk_admin_vars.i18n.no_file_selected || 'No file selected').removeClass('file-selected');
$('#upkyk-document-upload-btn').hide();
}
});
// Handle document upload button click
$('#upkyk-document-upload-btn').on('click', function(e) {
e.preventDefault();
uploadDocument(e);
});
// Document upload click handlers for Choose File button
$(document).on('click', '.upkyk-choose-file', function(e) {
e.preventDefault();
$('#upkyk-document-file').click();
});
$('#upkyk-reset-button').on('click', function() {
if (confirm(upkyk_admin_vars.i18n.reset_confirm || 'Are you sure you want to reset the training? This will delete all training data and cannot be undone.')) {
resetTraining();
}
});
$(document).on('click', '.delete-document', function() {
var id = $(this).data('id');
if (confirm(upkyk_admin_vars.i18n.confirm_delete_document || 'Are you sure you want to delete this document?')) {
deleteDocument(id);
}
});
// Load documents on page load
console.log('Document ready - calling loadTrainingDocuments');
// Ensure documents are loaded, with delay to ensure scripts are fully loaded
setTimeout(function() {
if (typeof window.loadTrainingDocuments === 'function') {
console.log('Calling global loadTrainingDocuments function');
window.loadTrainingDocuments();
} else if (typeof loadTrainingDocuments === 'function') {
console.log('Calling local loadTrainingDocuments function');
loadTrainingDocuments();
} else {
console.warn('No loadTrainingDocuments function found, falling back to direct AJAX call');
// Direct AJAX call as fallback
$.ajax({
url: upkyk_admin_vars.ajax_url,
type: 'POST',
data: {
action: 'upkyk_get_documents',
nonce: upkyk_admin_vars.nonce
},
success: function(response) {
console.log('Direct AJAX document load response:', response);
if (response.success && response.data && response.data.documents) {
renderDocumentsList(response.data.documents);
} else {
$('#upkyk-documents-list').html('<tr><td colspan="6">' + (upkyk_admin_vars.i18n.no_documents || 'No documents found.') + '</td></tr>');
}
},
error: function() {
$('#upkyk-documents-list').html('<tr><td colspan="6">' + (upkyk_admin_vars.i18n.error_loading_documents || 'Error loading documents.') + '</td></tr>');
}
});
}
}, 500);
// Initialize range sliders for configuration
$('#upkyk-intent-sensitivity').on('input', function() {
$('#intent-sensitivity-value').text($(this).val());
});
$('#upkyk-response-creativity').on('input', function() {
$('#response-creativity-value').text($(this).val());
});
$('#upkyk-confidence-threshold-enabled').on('change', function() {
if ($(this).is(':checked')) {
$('.upkyk-threshold-settings').show();
} else {
$('.upkyk-threshold-settings').hide();
}
});
});
// Function to handle document upload
function uploadDocument(event) {
event.preventDefault();
// Log for debugging
console.log('Upload document function called from training-page.js');
const fileInput = document.getElementById('upkyk-document-file');
if (!fileInput || !fileInput.files || !fileInput.files[0]) {
showNotification(upkyk_admin_vars.i18n.error || 'Error', upkyk_admin_vars.i18n.select_file || 'Please select a file to upload', 'error');
return;
}
const file = fileInput.files[0];
const fileName = file.name;
const fileType = fileName.split('.').pop().toLowerCase();
// Check file type
if (!['txt', 'csv', 'json'].includes(fileType)) {
showNotification(upkyk_admin_vars.i18n.error || 'Error', upkyk_admin_vars.i18n.invalid_file_type || 'Invalid file type. Please upload a TXT, CSV, or JSON file.', 'error');
return;
}
// Debug log
console.log('Uploading file:', fileName, 'Type:', fileType, 'Size:', file.size);
// Create form data
const formData = new FormData();
formData.append('action', 'upkyk_handle_document_upload');
formData.append('nonce', upkyk_admin_vars.nonce);
formData.append('document', file);
// Show loading state
showNotification(upkyk_admin_vars.i18n.info || 'Info', upkyk_admin_vars.i18n.uploading_document || 'Uploading document...', 'info');
// Perform AJAX request
jQuery.ajax({
url: upkyk_admin_vars.ajax_url,
type: 'POST',
data: formData,
contentType: false,
processData: false,
success: function(response) {
console.log('Upload response:', response);
if (response.success) {
showNotification(upkyk_admin_vars.i18n.success || 'Success', upkyk_admin_vars.i18n.document_uploaded || 'Document uploaded successfully!', 'success');
// Clear the file input
fileInput.value = '';
jQuery('#selected-file-name').text(upkyk_admin_vars.i18n.no_file_selected || 'No file selected').removeClass('file-selected');
jQuery('#upkyk-document-upload-btn').hide();
// Reload documents list using the best available function
console.log('Attempting to reload documents list after upload');
if (typeof window.loadDocuments === 'function') {
console.log('Using window.loadDocuments');
window.loadDocuments();
} else if (typeof loadDocuments === 'function') {
console.log('Using local loadDocuments');
loadDocuments();
} else if (typeof jQuery.fn.loadDocuments === 'function') {
console.log('Using jQuery.fn.loadDocuments');
jQuery.fn.loadDocuments();
} else {
console.log('No loadDocuments function found - reloading page');
// Last resort - refresh the page
location.reload();
}
} else {
showNotification(upkyk_admin_vars.i18n.error || 'Error', response.data?.message || upkyk_admin_vars.i18n.error_uploading || 'Error uploading document.', 'error');
}
},
error: function(xhr, status, error) {
console.error('Upload error:', error);
console.error('Upload response:', xhr.responseText);
showNotification(upkyk_admin_vars.i18n.error || 'Error', (upkyk_admin_vars.i18n.server_error || 'Server error while uploading document: ') + error, 'error');
}
});
}
// Function to handle document deletion
function deleteDocument(id) {
if (!id) {
showNotification(upkyk_admin_vars.i18n.error || 'Error', upkyk_admin_vars.i18n.invalid_document_id || 'Invalid document ID', 'error');
return;
}
// Show deletion in progress
showNotification(upkyk_admin_vars.i18n.info || 'Info', upkyk_admin_vars.i18n.deleting_document || 'Deleting document...', 'info');
// Perform deletion via AJAX
jQuery.ajax({
url: upkyk_admin_vars.ajax_url,
type: 'POST',
data: {
action: 'upkyk_delete_document',
nonce: upkyk_admin_vars.nonce,
document_id: id
},
success: function(response) {
console.log('Delete response:', response);
if (response.success) {
showNotification(upkyk_admin_vars.i18n.success || 'Success', upkyk_admin_vars.i18n.document_deleted || 'Document deleted successfully', 'success');
// Directly remove the row from the table without reload
jQuery(`#upkyk-documents-list tr[data-id="${id}"]`).fadeOut(300, function() {
jQuery(this).remove();
// Check if we need to show the "no documents" message
if (jQuery('#upkyk-documents-list tr').length === 0) {
jQuery('#upkyk-documents-list').html('<tr><td colspan="6">' + (upkyk_admin_vars.i18n.no_documents_uploaded || 'No documents uploaded yet.') + '</td></tr>');
}
});
} else {
showNotification(upkyk_admin_vars.i18n.error || 'Error', response.data?.message || upkyk_admin_vars.i18n.failed_delete_document || 'Failed to delete document', 'error');
}
},
error: function(xhr, status, error) {
console.error('Delete error:', error);
console.error('Delete response:', xhr.responseText);
showNotification(upkyk_admin_vars.i18n.error || 'Error', (upkyk_admin_vars.i18n.server_error || 'Server error while deleting document: ') + error, 'error');
}
});
}