PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.1.4
MxChat – AI Chatbot & Content Generation for WordPress v3.1.4
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/knowledge-processing.js +22 -140 3.2.213.1.4 View file →
@@ -495,18 +495,20 @@
495 495 if (status.failed > 0 && status.failed_items && status.failed_items.length > 0) {
496 496 detailsHtml += '<div class="mxchat-error-summary" style="background: #fff3cd; border-left: 4px solid #ffc107; padding: 15px; margin-top: 15px;">';
497 497 detailsHtml += '<h4 style="margin: 0 0 10px 0; color: #856404;">⚠️ Failed Pages</h4>';
498 498
499 + detailsHtml += '<details style="cursor: pointer;">';
500 + detailsHtml += '<summary style="font-weight: bold; color: #856404; padding: 5px 0;">Click to view ' + status.failed_items.length + ' failed pages</summary>';
501 +
499 502 detailsHtml += '<div style="margin-top: 10px; max-height: 400px; overflow-y: auto;">';
500 503 detailsHtml += '<table style="width: 100%; border-collapse: collapse;">';
501 504 detailsHtml += '<thead><tr style="background: #f5f5f5;"><th style="padding: 8px; text-align: left;">Page</th><th style="padding: 8px; text-align: left;">Error</th><th style="padding: 8px; text-align: left;">Attempts</th></tr></thead>';
502 505 detailsHtml += '<tbody>';
503 -
506 +
504 507 status.failed_items.forEach(function(item) {
505 - let data;
506 - try { data = JSON.parse(item.item_data); } catch(e) { data = {}; }
508 + const data = JSON.parse(item.item_data);
507 509 const pageNum = data.page_number || 'Unknown';
508 -
510 +
509 511 detailsHtml += '<tr style="border-bottom: 1px solid #ddd;">';
510 512 detailsHtml += '<td style="padding: 8px;">Page ' + pageNum + '</td>';
511 513 detailsHtml += '<td style="padding: 8px; word-break: break-word;">' + (item.error_message || 'Unknown error') + '</td>';
512 514 detailsHtml += '<td style="padding: 8px;">' + item.attempts + '</td>';
@@ -511,12 +513,13 @@
511 513 detailsHtml += '<td style="padding: 8px; word-break: break-word;">' + (item.error_message || 'Unknown error') + '</td>';
512 514 detailsHtml += '<td style="padding: 8px;">' + item.attempts + '</td>';
513 515 detailsHtml += '</tr>';
514 516 });
515 -
517 +
516 518 detailsHtml += '</tbody></table>';
517 519 detailsHtml += '</div>';
518 -
520 + detailsHtml += '</details>';
521 +
519 522 detailsHtml += '</div>';
520 523 }
521 524
522 525 $card.find('.mxchat-status-details').html(detailsHtml);
@@ -571,20 +574,21 @@
571 574 if (status.failed > 0 && status.failed_items && status.failed_items.length > 0) {
572 575 detailsHtml += '<div class="mxchat-error-summary" style="background: #fff3cd; border-left: 4px solid #ffc107; padding: 15px; margin-top: 15px;">';
573 576 detailsHtml += '<h4 style="margin: 0 0 10px 0; color: #856404;">⚠️ Failed URLs</h4>';
574 577
578 + detailsHtml += '<details style="cursor: pointer;">';
579 + detailsHtml += '<summary style="font-weight: bold; color: #856404; padding: 5px 0;">Click to view ' + status.failed_items.length + ' failed URLs</summary>';
580 +
575 581 detailsHtml += '<div style="margin-top: 10px; max-height: 400px; overflow-y: auto;">';
576 582 detailsHtml += '<table style="width: 100%; border-collapse: collapse;">';
577 583 detailsHtml += '<thead><tr style="background: #f5f5f5;"><th style="padding: 8px; text-align: left;">URL</th><th style="padding: 8px; text-align: left;">Error</th><th style="padding: 8px; text-align: left;">Attempts</th></tr></thead>';
578 584 detailsHtml += '<tbody>';
579 -
585 +
580 586 status.failed_items.forEach(function(item) {
581 - let data;
582 - try { data = JSON.parse(item.item_data); } catch(e) { data = {}; }
583 - const url = data.url || data.pdf_url || 'Unknown URL';
584 - const pageInfo = data.page_number ? ' (page ' + data.page_number + ')' : '';
585 - const displayUrl = (url.length > 60 ? url.substring(0, 57) + '...' : url) + pageInfo;
586 -
587 + const data = JSON.parse(item.item_data);
588 + const url = data.url || 'Unknown URL';
589 + const displayUrl = url.length > 60 ? url.substring(0, 57) + '...' : url;
590 +
587 591 detailsHtml += '<tr style="border-bottom: 1px solid #ddd;">';
588 592 detailsHtml += '<td style="padding: 8px;"><a href="' + url + '" target="_blank" style="color: #0073aa; text-decoration: none;">' + displayUrl + '</a></td>';
589 593 detailsHtml += '<td style="padding: 8px; word-break: break-word;">' + (item.error_message || 'Unknown error') + '</td>';
590 594 detailsHtml += '<td style="padding: 8px;">' + item.attempts + '</td>';
@@ -589,15 +593,16 @@
589 593 detailsHtml += '<td style="padding: 8px; word-break: break-word;">' + (item.error_message || 'Unknown error') + '</td>';
590 594 detailsHtml += '<td style="padding: 8px;">' + item.attempts + '</td>';
591 595 detailsHtml += '</tr>';
592 596 });
593 -
597 +
594 598 detailsHtml += '</tbody></table>';
595 599 detailsHtml += '</div>';
596 -
600 + detailsHtml += '</details>';
601 +
597 602 detailsHtml += '</div>';
598 603 }
599 -
604 +
600 605 $card.find('.mxchat-status-details').html(detailsHtml);
601 606 }
602 607
603 608 /**
@@ -1929,9 +1934,9 @@
1929 1934 const sourceHtml = entry.has_link
1930 1935 ? '<a href="' + entry.source_url + '" target="_blank" style="color: var(--mxch-primary); text-decoration: none;"><span class="dashicons dashicons-external" style="font-size: 14px;"></span> View</a>'
1931 1936 : '<span style="color: var(--mxch-text-muted);">Manual</span>';
1932 1937
1933 - const deleteUrl = mxchatAdmin.admin_url + 'admin-post.php?action=mxchat_delete_prompt&id=' + entry.id + '&bot_id=' + encodeURIComponent(mxchatAdmin.bot_id || 'default') + '&_wpnonce=' + entry.delete_nonce;
1938 + const deleteUrl = mxchatAdmin.admin_url + 'admin-post.php?action=mxchat_delete_prompt&id=' + entry.id + '&_wpnonce=' + entry.delete_nonce;
1934 1939
1935 1940 // Check if content needs expand button (content longer than preview)
1936 1941 const needsExpand = entry.content_length > entry.preview_length;
1937 1942
@@ -2271,129 +2276,6 @@
2271 2276 $(document).on('DOMNodeInserted', function(e) {
2272 2277 if ($(e.target).hasClass('notice') && $(e.target).hasClass('is-dismissible')) {
2273 2278 setTimeout(initDismissibleNotices, 10);
2274 2279 }
2275 - });
2276 -
2277 - // ========================================
2278 - // CUSTOM META-KEY DISCOVERY PICKER (plan-mxchat-20260709-fe8e4e)
2279 - // Mirror the ACF picker's discover-and-click UX for non-ACF post meta: scan
2280 - // published content for meta keys, render clickable chips, and append chosen
2281 - // keys into the existing whitelist textarea (its autosave then persists them).
2282 - // ========================================
2283 - (function() {
2284 - var $scanBtn = $('#mxchat-scan-meta-btn');
2285 - if (!$scanBtn.length) { return; }
2286 -
2287 - var $results = $('#mxchat-meta-scan-results');
2288 - var $textarea = $('#mxchat_custom_meta_whitelist');
2289 - var $internal = $('#mxchat-scan-internal');
2290 - var $label = $scanBtn.find('.mxchat-scan-label');
2291 - var defaultLabel = $label.text();
2292 -
2293 - function currentKeys() {
2294 - return ($textarea.val() || '')
2295 - .split('\n')
2296 - .map(function(k) { return k.trim(); })
2297 - .filter(function(k) { return k.length; });
2298 - }
2299 -
2300 - function addKey(key) {
2301 - var keys = currentKeys();
2302 - if (keys.indexOf(key) !== -1) { return false; }
2303 - keys.push(key);
2304 - $textarea.val(keys.join('\n'));
2305 - // Fire the existing autosave (bound on 'change' in mxchat-admin.js).
2306 - $textarea.trigger('change');
2307 - return true;
2308 - }
2309 -
2310 - function escapeHtml(s) {
2311 - return String(s).replace(/[&<>"']/g, function(c) {
2312 - return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
2313 - });
2314 - }
2315 -
2316 - function humanize(key) {
2317 - var h = key.replace(/^_+/, '').replace(/[_-]+/g, ' ').trim();
2318 - return h.length ? h.charAt(0).toUpperCase() + h.slice(1) : key;
2319 - }
2320 -
2321 - function renderChips(keys) {
2322 - if (!keys || !keys.length) {
2323 - $results.html('<p class="mxchat-meta-scan-empty">' +
2324 - 'No custom meta keys found on your published content. Try enabling internal keys, or add keys manually below.' +
2325 - '</p>');
2326 - return;
2327 - }
2328 - var existing = currentKeys();
2329 - var html = '<div class="mxchat-meta-chip-grid">';
2330 - keys.forEach(function(item) {
2331 - var already = existing.indexOf(item.key) !== -1;
2332 - html += '<button type="button" class="mxchat-meta-chip' + (already ? ' is-added' : '') +
2333 - '" data-key="' + escapeHtml(item.key) + '"' + (already ? ' aria-pressed="true"' : '') + '>' +
2334 - '<span class="mxchat-meta-chip-main">' +
2335 - '<span class="mxchat-meta-chip-name">' + escapeHtml(humanize(item.key)) + '</span>' +
2336 - '<span class="mxchat-meta-chip-key">' + escapeHtml(item.key) + '</span>' +
2337 - '</span>' +
2338 - '<span class="mxchat-meta-chip-meta">on ' + item.count + ' post' + (item.count === 1 ? '' : 's') +
2339 - (item.sample ? ' · e.g. ' + escapeHtml(item.sample) : '') + '</span>' +
2340 - '<span class="mxchat-meta-chip-tick">' + (already ? '✓ Added' : '+ Add') + '</span>' +
2341 - '</button>';
2342 - });
2343 - html += '</div>';
2344 - $results.html(html);
2345 - }
2346 -
2347 - $scanBtn.on('click', function() {
2348 - var nonce = $scanBtn.data('nonce') ||
2349 - (window.mxchatAdmin && mxchatAdmin.settings_nonce) || '';
2350 - var ajaxUrl = (window.mxchatAdmin && (mxchatAdmin.ajax_url || mxchatAdmin.ajaxurl)) ||
2351 - window.ajaxurl || '/wp-admin/admin-ajax.php';
2352 -
2353 - $scanBtn.prop('disabled', true);
2354 - $label.text('Scanning…');
2355 - $results.html('<p class="mxchat-meta-scan-loading">Scanning your content for meta keys…</p>');
2356 -
2357 - $.post(ajaxUrl, {
2358 - action: 'mxchat_scan_custom_meta_keys',
2359 - _ajax_nonce: nonce,
2360 - include_internal: $internal.is(':checked') ? '1' : '0'
2361 - }).done(function(resp) {
2362 - if (resp && resp.success && resp.data && resp.data.keys) {
2363 - renderChips(resp.data.keys);
2364 - } else {
2365 - var msg = (resp && resp.data && resp.data.message) ? resp.data.message : 'Scan failed. Please try again.';
2366 - $results.html('<p class="mxchat-meta-scan-empty">' + escapeHtml(msg) + '</p>');
2367 - }
2368 - }).fail(function() {
2369 - $results.html('<p class="mxchat-meta-scan-empty">Scan request failed. Please try again.</p>');
2370 - }).always(function() {
2371 - $scanBtn.prop('disabled', false);
2372 - $label.text(defaultLabel);
2373 - });
2374 - });
2375 -
2376 - // Chip click -> add the raw key to the whitelist textarea (dedup) + autosave.
2377 - $results.on('click', '.mxchat-meta-chip', function() {
2378 - var $chip = $(this);
2379 - if ($chip.hasClass('is-added')) { return; }
2380 - var key = String($chip.data('key'));
2381 - if (addKey(key)) {
2382 - $chip.addClass('is-added').attr('aria-pressed', 'true');
2383 - $chip.find('.mxchat-meta-chip-tick').text('✓ Added');
2384 - }
2385 - });
2386 - })();
2387 -
2388 - // ========================================
2389 - // VIDEO CARDS — threshold follows the master switch (plan f52492)
2390 - // ========================================
2391 - // Presentation only. The server gate does NOT consult the threshold when
2392 - // the switch is off, so hiding the field never changes behavior — it just
2393 - // stops the page offering a number that is currently inert. Mirrors the
2394 - // YouTube import form's own show/hide idiom on this same page. Autosave is
2395 - // untouched: both fields keep their own change handler in mxchat-admin.js.
2396 - $('#mxchat_video_embed_enabled').on('change', function() {
2397 - $('#mxchat-video-embed-threshold-field').toggle($(this).is(':checked'));
2398 2280 });
2399 2281 });