PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.0.6
MxChat – AI Chatbot & Content Generation for WordPress v3.0.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
← All changes | js/mxchat-admin.js +21 -277 3.2.23.0.6 View file →
@@ -897,27 +897,14 @@
897 897 // Toggle visibility handlers
898 898 function toggleVisibility(selector) {
899 899 $(selector).on('click', function() {
900 900 var inputField = $(this).prev('input');
901 - // Check if this is a CSS-masked field (type="text" with mxchat-api-key-field class)
902 - if (inputField.hasClass('mxchat-api-key-field')) {
903 - // Use CSS class toggle for CSS-masked fields
904 - if (inputField.hasClass('mxchat-show-key')) {
905 - inputField.removeClass('mxchat-show-key');
906 - $(this).text('Show');
907 - } else {
908 - inputField.addClass('mxchat-show-key');
909 - $(this).text('Hide');
910 - }
901 + if (inputField.attr('type') === 'password') {
902 + inputField.attr('type', 'text');
903 + $(this).text('Hide');
911 904 } else {
912 - // Legacy type toggle for password fields
913 - if (inputField.attr('type') === 'password') {
914 - inputField.attr('type', 'text');
915 - $(this).text('Hide');
916 - } else {
917 - inputField.attr('type', 'password');
918 - $(this).text('Show');
919 - }
905 + inputField.attr('type', 'password');
906 + $(this).text('Show');
920 907 }
921 908 });
922 909 }
923 910
@@ -1027,12 +1014,8 @@
1027 1014 { value: 'gemini-1.5-pro', label: 'Gemini 1.5 Pro', description: 'Deprecated September 2025' },
1028 1015 { value: 'gemini-1.5-flash', label: 'Gemini 1.5 Flash', description: 'Deprecated September 2025' },
1029 1016 ],
1030 1017 openai: [
1031 - { value: 'gpt-5.4', label: 'GPT-5.4', description: 'Flagship reasoning and coding model' },
1032 - { value: 'gpt-5.4-mini', label: 'GPT-5.4 Mini', description: 'Fast and affordable with 400K context' },
1033 - { value: 'gpt-5.4-nano', label: 'GPT-5.4 Nano', description: 'Fastest and cheapest for lightweight tasks' },
1034 - { value: 'gpt-5.3-chat-latest', label: 'GPT-5.3 Chat', description: 'Optimized for natural conversations with reduced hallucinations' },
1035 1018 { value: 'gpt-5.2', label: 'GPT-5.2', description: 'Best general-purpose & agentic model with fast responses' },
1036 1019 { value: 'gpt-5.1-chat-latest', label: 'GPT-5.1 Chat Latest', description: 'Recommended for most use cases' },
1037 1020 { value: 'gpt-5.1-2025-11-13', label: 'GPT-5.1', description: 'Flagship for coding & agentic tasks with low reasoning (400K context)' },
1038 1021 { value: 'gpt-5', label: 'GPT-5', description: 'Flagship for coding, reasoning, and agentic tasks across domains' },
@@ -1040,9 +1023,8 @@
1040 1023 { value: 'gpt-5-nano', label: 'GPT-5 Nano', description: 'Fastest and cheapest; ideal for summarization and classification' },
1041 1024 ],
1042 1025 claude: [
1043 1026 { value: 'claude-opus-4-6', label: 'Claude Opus 4.6', description: 'Most capable Claude model - recommended' },
1044 - { value: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6', description: 'Latest Sonnet - excellent balance of speed and capability' },
1045 1027 { value: 'claude-opus-4-5', label: 'Claude Opus 4.5', description: 'Highly capable for complex tasks' },
1046 1028 { value: 'claude-sonnet-4-5-20250929', label: 'Claude Sonnet 4.5', description: 'Best for complex agents and coding' },
1047 1029 { value: 'claude-opus-4-1-20250805', label: 'Claude Opus 4.1', description: 'Exceptional for specialized complex tasks' },
1048 1030 { value: 'claude-haiku-4-5-20251001', label: 'Claude Haiku 4.5', description: 'Fastest and most intelligent Haiku' },
@@ -2115,14 +2097,24 @@
2115 2097 const actionLabel = this.dataset.label;
2116 2098 const actionIcon = this.querySelector('.dashicons').getAttribute('class').replace('dashicons dashicons-', '');
2117 2099 const actionDescription = this.querySelector('p').textContent;
2118 2100
2119 - // Check if this is a promotional card (add-on not installed)
2120 - const isPromo = this.dataset.promo === 'true';
2121 -
2122 - if (isPromo || (addonName && !isInstalled)) {
2123 - // Add-on required but not installed — show informational notice
2124 - const addonDisplayName = this.querySelector('.mxchat-addon-info')?.textContent?.replace('Requires ', '').replace('— Get Add-on', '').trim() || addonName + ' Add-on';
2101 + // Pro check using the proper detection method
2102 + const proIsActivated = typeof mxchatAdmin !== 'undefined' &&
2103 + (mxchatAdmin.is_activated === '1' ||
2104 + mxchatAdmin.is_activated === 'true' ||
2105 + mxchatAdmin.is_activated === true);
2106 +
2107 + // Handle different states
2108 + if (isPro && !proIsActivated) {
2109 + // Pro feature but no Pro license
2110 + showProFeatureNotice();
2111 + return;
2112 + }
2113 +
2114 + if (addonName && !isInstalled) {
2115 + // Add-on required but not installed
2116 + const addonDisplayName = this.querySelector('.mxchat-addon-info')?.textContent?.replace('Requires ', '') || addonName + ' Add-on';
2125 2117 showAddonRequiredNotice(addonDisplayName);
2126 2118 return;
2127 2119 }
2128 2120
@@ -3284,253 +3276,5 @@
3284 3276 var div = document.createElement('div');
3285 3277 div.appendChild(document.createTextNode(text));
3286 3278 return div.innerHTML;
3287 3279 }
3288 -
3289 - // ========================================
3290 - // DEBUG & OPTIMIZATION TOOLS
3291 - // ========================================
3292 -
3293 - // Debug Mode Toggle
3294 - $('#mxchat_debug_mode').on('change', function() {
3295 - var $toggle = $(this);
3296 - var enabled = $toggle.is(':checked') ? 'on' : 'off';
3297 - var $label = $toggle.closest('label');
3298 -
3299 - // Add loading indicator next to the toggle label
3300 - var $indicator = $label.find('.mxchat-save-indicator');
3301 - if ($indicator.length === 0) {
3302 - $indicator = $('<span class="mxchat-save-indicator" style="margin-left: 10px;"></span>');
3303 - $label.append($indicator);
3304 - }
3305 - $indicator.html('<span class="mxchat-saving-spinner"></span>').show();
3306 -
3307 - $.ajax({
3308 - url: ajaxurl,
3309 - type: 'POST',
3310 - data: {
3311 - action: 'mxchat_toggle_debug_mode',
3312 - enabled: enabled,
3313 - _ajax_nonce: mxchatAdmin.setting_nonce
3314 - },
3315 - success: function(response) {
3316 - if (response.success) {
3317 - // Show success indicator
3318 - $indicator.html('<span class="mxchat-save-success">✓</span>');
3319 - setTimeout(function() {
3320 - $indicator.fadeOut(300);
3321 - }, 2000);
3322 -
3323 - // Always refresh the log after toggling
3324 - refreshDebugLog();
3325 - } else {
3326 - $indicator.html('<span class="mxchat-save-error">✗</span>');
3327 - alert(response.data.message || 'Error toggling debug mode');
3328 - $toggle.prop('checked', !$toggle.is(':checked'));
3329 - }
3330 - },
3331 - error: function() {
3332 - $indicator.html('<span class="mxchat-save-error">✗</span>');
3333 - alert('Error toggling debug mode');
3334 - $toggle.prop('checked', !$toggle.is(':checked'));
3335 - }
3336 - });
3337 - });
3338 -
3339 - // Refresh Debug Log
3340 - function refreshDebugLog() {
3341 - var $container = $('#mxchat-debug-log');
3342 - var $countBadge = $('#mxchat-log-count');
3343 -
3344 - $.ajax({
3345 - url: ajaxurl,
3346 - type: 'POST',
3347 - data: {
3348 - action: 'mxchat_get_debug_log',
3349 - _ajax_nonce: mxchatAdmin.setting_nonce
3350 - },
3351 - success: function(response) {
3352 - if (response.success) {
3353 - var log = response.data.log;
3354 - var count = response.data.count;
3355 -
3356 - if (count > 0) {
3357 - $countBadge.text(count + ' entries').show();
3358 - var html = '<div class="mxchat-debug-log-entries">';
3359 - log.forEach(function(entry) {
3360 - var typeClass = 'mxchat-log-type-' + entry.type;
3361 - var typeLabel = entry.type.replace(/_/g, ' ').toUpperCase();
3362 - html += '<div class="mxchat-debug-log-entry ' + typeClass + '">';
3363 - html += '<div class="mxchat-log-header">';
3364 - html += '<span class="mxchat-log-type">' + escapeHtml(typeLabel) + '</span>';
3365 - html += '<span class="mxchat-log-time">' + escapeHtml(entry.time) + '</span>';
3366 - html += '</div>';
3367 - html += '<div class="mxchat-log-message">' + escapeHtml(entry.message) + '</div>';
3368 - if (entry.data) {
3369 - html += '<div class="mxchat-log-data">' + escapeHtml(JSON.stringify(entry.data, null, 2)) + '</div>';
3370 - }
3371 - html += '</div>';
3372 - });
3373 - html += '</div>';
3374 - $container.html(html);
3375 - } else {
3376 - $countBadge.hide();
3377 - $container.html(
3378 - '<div class="mxchat-debug-log-empty">' +
3379 - '<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" style="opacity: 0.3;"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>' +
3380 - '<p>No log entries yet. Enable debug mode to start logging.</p>' +
3381 - '</div>'
3382 - );
3383 - }
3384 - }
3385 - }
3386 - });
3387 - }
3388 -
3389 - // Load debug log on page load
3390 - if ($('#mxchat-debug-log').length) {
3391 - refreshDebugLog();
3392 - }
3393 -
3394 - // Refresh Log Button
3395 - $('#mxchat-refresh-log').on('click', function() {
3396 - var $btn = $(this);
3397 - $btn.prop('disabled', true);
3398 - refreshDebugLog();
3399 - setTimeout(function() {
3400 - $btn.prop('disabled', false);
3401 - }, 500);
3402 - });
3403 -
3404 - // Clear Log Button
3405 - $('#mxchat-clear-log').on('click', function() {
3406 - if (!confirm('Are you sure you want to clear the debug log?')) {
3407 - return;
3408 - }
3409 -
3410 - var $btn = $(this);
3411 - $btn.prop('disabled', true);
3412 -
3413 - $.ajax({
3414 - url: ajaxurl,
3415 - type: 'POST',
3416 - data: {
3417 - action: 'mxchat_clear_debug_log',
3418 - _ajax_nonce: mxchatAdmin.setting_nonce
3419 - },
3420 - success: function(response) {
3421 - if (response.success) {
3422 - refreshDebugLog();
3423 - } else {
3424 - alert(response.data.message || 'Error clearing log');
3425 - }
3426 - },
3427 - error: function() {
3428 - alert('Error clearing log');
3429 - },
3430 - complete: function() {
3431 - $btn.prop('disabled', false);
3432 - }
3433 - });
3434 - });
3435 -
3436 - // Export Settings Button
3437 - $('#mxchat-export-settings').on('click', function() {
3438 - var $btn = $(this);
3439 - var originalHtml = $btn.html();
3440 - $btn.prop('disabled', true).html(
3441 - '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="animation: spin 1s linear infinite;"><circle cx="12" cy="12" r="10" stroke-dasharray="32" stroke-dashoffset="12"/></svg> Exporting...'
3442 - );
3443 -
3444 - $.ajax({
3445 - url: ajaxurl,
3446 - type: 'POST',
3447 - data: {
3448 - action: 'mxchat_export_settings',
3449 - _ajax_nonce: mxchatAdmin.setting_nonce
3450 - },
3451 - success: function(response) {
3452 - if (response.success) {
3453 - // Create and download the JSON file
3454 - var dataStr = JSON.stringify(response.data.settings, null, 2);
3455 - var blob = new Blob([dataStr], { type: 'application/json' });
3456 - var url = URL.createObjectURL(blob);
3457 - var a = document.createElement('a');
3458 - a.href = url;
3459 - a.download = response.data.filename;
3460 - document.body.appendChild(a);
3461 - a.click();
3462 - document.body.removeChild(a);
3463 - URL.revokeObjectURL(url);
3464 - } else {
3465 - alert(response.data.message || 'Error exporting settings');
3466 - }
3467 - },
3468 - error: function() {
3469 - alert('Error exporting settings');
3470 - },
3471 - complete: function() {
3472 - $btn.prop('disabled', false).html(originalHtml);
3473 - }
3474 - });
3475 - });
3476 -
3477 - // Reset Settings Modal
3478 - var $resetModal = $('#mxchat-reset-modal');
3479 - var $resetConfirmInput = $('#mxchat-reset-confirmation');
3480 - var $resetConfirmBtn = $('#mxchat-reset-confirm');
3481 -
3482 - $('#mxchat-reset-settings').on('click', function() {
3483 - $resetModal.fadeIn(200);
3484 - $resetConfirmInput.val('').focus();
3485 - $resetConfirmBtn.prop('disabled', true);
3486 - });
3487 -
3488 - $('#mxchat-reset-modal-close, #mxchat-reset-cancel, .mxch-modal-backdrop').on('click', function() {
3489 - $resetModal.fadeOut(200);
3490 - });
3491 -
3492 - $resetConfirmInput.on('input', function() {
3493 - var value = $(this).val().toUpperCase();
3494 - $resetConfirmBtn.prop('disabled', value !== 'RESET');
3495 - });
3496 -
3497 - $resetConfirmBtn.on('click', function() {
3498 - var $btn = $(this);
3499 - var confirmation = $resetConfirmInput.val();
3500 -
3501 - $btn.prop('disabled', true).text('Resetting...');
3502 -
3503 - $.ajax({
3504 - url: ajaxurl,
3505 - type: 'POST',
3506 - data: {
3507 - action: 'mxchat_reset_all_settings',
3508 - confirmation: confirmation,
3509 - _ajax_nonce: mxchatAdmin.setting_nonce
3510 - },
3511 - success: function(response) {
3512 - if (response.success) {
3513 - alert(response.data.message);
3514 - window.location.reload();
3515 - } else {
3516 - alert(response.data.message || 'Error resetting settings');
3517 - $btn.prop('disabled', false).text('Reset All Settings');
3518 - }
3519 - },
3520 - error: function() {
3521 - alert('Error resetting settings');
3522 - $btn.prop('disabled', false).text('Reset All Settings');
3523 - }
3524 - });
3525 - });
3526 -
3527 - // Load debug log on page load if we're on the optimization section
3528 - if ($('#optimization').hasClass('active') || window.location.hash === '#optimization') {
3529 - refreshDebugLog();
3530 - }
3531 -
3532 - // Also refresh when switching to optimization tab
3533 - $(document).on('click', '[data-section="optimization"]', function() {
3534 - setTimeout(refreshDebugLog, 100);
3535 - });
3536 3280 });