| @@ -272,14 +272,8 @@ | ||
| 272 | 272 | <?php |
| 273 | 273 | // Render the Content Selector Modal |
| 274 | 274 | mxchat_render_content_selector_modal(); |
| 275 | 275 | |
| 276 | - // Render the Edit Entry Modal | |
| 277 | - mxchat_render_edit_entry_modal(); | |
| 278 | - | |
| 279 | - // Render the read-only Knowledge Inspector modal (plan-d8cb4b) | |
| 280 | - mxchat_render_inspect_entry_modal(); | |
| 281 | - | |
| 282 | 276 | // Render the navigation JavaScript |
| 283 | 277 | mxchat_render_knowledge_page_scripts(); |
| 284 | 278 | } |
| 285 | 279 | |
| @@ -851,39 +845,15 @@ | ||
| 851 | 845 | </form> |
| 852 | 846 | <!-- Delete Button Container - transforms between Delete All and Delete Selected --> |
| 853 | 847 | <div class="mxchat-delete-container" id="mxchat-delete-container"> |
| 854 | 848 | <!-- Delete All Form (shown when nothing selected) --> |
| 855 | - <?php | |
| 856 | - // Build confirm message and button text based on active filter | |
| 857 | - $delete_all_label = __('Delete All', 'mxchat'); | |
| 858 | - $delete_all_confirm = __('Are you sure you want to delete all knowledge?', 'mxchat'); | |
| 859 | - if (!empty($content_type_filter)) { | |
| 860 | - $filter_display = $content_type_filter; | |
| 861 | - // Try to get a human-readable label | |
| 862 | - $pt_obj = get_post_type_object($content_type_filter); | |
| 863 | - if ($pt_obj) { | |
| 864 | - $filter_display = $pt_obj->label; | |
| 865 | - } elseif ($content_type_filter === 'pdf') { | |
| 866 | - $filter_display = 'PDFs'; | |
| 867 | - } elseif ($content_type_filter === 'url') { | |
| 868 | - $filter_display = 'URLs'; | |
| 869 | - } | |
| 870 | - /* translators: %s: content type label (e.g. "Pages", "PDFs") */ | |
| 871 | - $delete_all_label = sprintf(__('Delete All %s', 'mxchat'), $filter_display); | |
| 872 | - /* translators: %s: content type label */ | |
| 873 | - $delete_all_confirm = sprintf(__('Are you sure you want to delete all %s from the knowledge base?', 'mxchat'), $filter_display); | |
| 874 | - } | |
| 875 | - ?> | |
| 876 | - <form method="post" action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_delete_all_prompts')); ?>" id="mxchat-delete-all-form" onsubmit="return confirm('<?php echo esc_attr($delete_all_confirm); ?>');"> | |
| 849 | + <form method="post" action="<?php echo esc_url(admin_url('admin-post.php?action=mxchat_delete_all_prompts')); ?>" id="mxchat-delete-all-form" onsubmit="return confirm('<?php esc_attr_e('Are you sure you want to delete all knowledge?', 'mxchat'); ?>');"> | |
| 877 | 850 | <?php wp_nonce_field('mxchat_delete_all_prompts_action', 'mxchat_delete_all_prompts_nonce'); ?> |
| 878 | 851 | <input type="hidden" name="data_source" value="<?php echo esc_attr($data_source); ?>" /> |
| 879 | 852 | <input type="hidden" name="bot_id" value="<?php echo esc_attr($current_bot_id); ?>" /> |
| 880 | - <?php if (!empty($content_type_filter)) : ?> | |
| 881 | - <input type="hidden" name="content_type_filter" value="<?php echo esc_attr($content_type_filter); ?>" /> | |
| 882 | - <?php endif; ?> | |
| 883 | 853 | <button type="submit" class="mxch-btn mxch-btn-secondary mxch-btn-sm" style="color: var(--mxch-error);"> |
| 884 | 854 | <span class="dashicons dashicons-trash" style="font-size: 14px;"></span> |
| 885 | - <?php echo esc_html($delete_all_label); ?> | |
| 855 | + <?php esc_html_e('Delete All', 'mxchat'); ?> | |
| 886 | 856 | </button> |
| 887 | 857 | </form> |
| 888 | 858 | <!-- Delete Selected Button (shown when items selected) --> |
| 889 | 859 | <button type="button" |
| @@ -991,32 +961,10 @@ | ||
| 991 | 961 | <?php else : ?> |
| 992 | 962 | <span style="color: var(--mxch-text-muted);"><?php esc_html_e('Manual Content', 'mxchat'); ?></span> |
| 993 | 963 | <?php endif; ?> |
| 994 | 964 | </td> |
| 995 | - <td class="mxchat-actions-cell" style="padding: 12px 16px; white-space: nowrap;"> | |
| 965 | + <td class="mxchat-actions-cell" style="padding: 12px 16px;"> | |
| 996 | 966 | <button type="button" |
| 997 | - class="mxch-btn mxch-btn-ghost mxch-btn-sm mxchat-inspect-entry-btn" | |
| 998 | - data-source-url="<?php echo esc_attr($source_url); ?>" | |
| 999 | - data-entry-id="<?php echo esc_attr($first_prompt->id); ?>" | |
| 1000 | - data-data-source="<?php echo esc_attr($data_source); ?>" | |
| 1001 | - data-bot-id="<?php echo esc_attr($current_bot_id); ?>" | |
| 1002 | - data-nonce="<?php echo wp_create_nonce('mxchat_inspect_entry_nonce'); ?>" | |
| 1003 | - title="<?php esc_attr_e('View indexed content', 'mxchat'); ?>"> | |
| 1004 | - <span class="dashicons dashicons-visibility" style="font-size: 14px;"></span> | |
| 1005 | - </button> | |
| 1006 | - <?php if ($data_source !== 'pinecone') : ?> | |
| 1007 | - <button type="button" | |
| 1008 | - class="mxch-btn mxch-btn-ghost mxch-btn-sm mxchat-edit-entry-btn" | |
| 1009 | - data-source-url="<?php echo esc_attr($source_url); ?>" | |
| 1010 | - data-entry-id="<?php echo esc_attr($first_prompt->id); ?>" | |
| 1011 | - data-data-source="<?php echo esc_attr($data_source); ?>" | |
| 1012 | - data-bot-id="<?php echo esc_attr($current_bot_id); ?>" | |
| 1013 | - data-nonce="<?php echo wp_create_nonce('mxchat_edit_entry_nonce'); ?>" | |
| 1014 | - title="<?php esc_attr_e('Edit content', 'mxchat'); ?>"> | |
| 1015 | - <span class="dashicons dashicons-edit" style="font-size: 14px;"></span> | |
| 1016 | - </button> | |
| 1017 | - <?php endif; ?> | |
| 1018 | - <button type="button" | |
| 1019 | 967 | class="mxch-btn mxch-btn-ghost mxch-btn-sm delete-button-group" |
| 1020 | 968 | data-source-url="<?php echo esc_attr($source_url); ?>" |
| 1021 | 969 | data-chunk-count="<?php echo esc_attr($chunk_count); ?>" |
| 1022 | 970 | data-data-source="<?php echo esc_attr($data_source); ?>" |
| @@ -1151,31 +1099,9 @@ | ||
| 1151 | 1099 | <?php else : ?> |
| 1152 | 1100 | <span style="color: var(--mxch-text-muted);"><?php esc_html_e('Manual', 'mxchat'); ?></span> |
| 1153 | 1101 | <?php endif; ?> |
| 1154 | 1102 | </td> |
| 1155 | - <td style="padding: 12px 16px; white-space: nowrap;"> | |
| 1156 | - <button type="button" | |
| 1157 | - class="mxch-btn mxch-btn-ghost mxch-btn-sm mxchat-inspect-entry-btn" | |
| 1158 | - data-source-url="<?php echo esc_attr($prompt->source_url ?? ''); ?>" | |
| 1159 | - data-entry-id="<?php echo esc_attr($prompt->id); ?>" | |
| 1160 | - data-data-source="<?php echo esc_attr($data_source); ?>" | |
| 1161 | - data-bot-id="<?php echo esc_attr($current_bot_id); ?>" | |
| 1162 | - data-nonce="<?php echo wp_create_nonce('mxchat_inspect_entry_nonce'); ?>" | |
| 1163 | - title="<?php esc_attr_e('View indexed content', 'mxchat'); ?>"> | |
| 1164 | - <span class="dashicons dashicons-visibility" style="font-size: 14px;"></span> | |
| 1165 | - </button> | |
| 1166 | - <?php if ($data_source !== 'pinecone') : ?> | |
| 1167 | - <button type="button" | |
| 1168 | - class="mxch-btn mxch-btn-ghost mxch-btn-sm mxchat-edit-entry-btn" | |
| 1169 | - data-source-url="<?php echo esc_attr($prompt->source_url ?? ''); ?>" | |
| 1170 | - data-entry-id="<?php echo esc_attr($prompt->id); ?>" | |
| 1171 | - data-data-source="<?php echo esc_attr($data_source); ?>" | |
| 1172 | - data-bot-id="<?php echo esc_attr($current_bot_id); ?>" | |
| 1173 | - data-nonce="<?php echo wp_create_nonce('mxchat_edit_entry_nonce'); ?>" | |
| 1174 | - title="<?php esc_attr_e('Edit content', 'mxchat'); ?>"> | |
| 1175 | - <span class="dashicons dashicons-edit" style="font-size: 14px;"></span> | |
| 1176 | - </button> | |
| 1177 | - <?php endif; ?> | |
| 1103 | + <td style="padding: 12px 16px;"> | |
| 1178 | 1104 | <?php if ($data_source === 'pinecone') : ?> |
| 1179 | 1105 | <button type="button" class="mxch-btn mxch-btn-ghost mxch-btn-sm delete-button-ajax" data-vector-id="<?php echo esc_attr($prompt->id); ?>" data-bot-id="<?php echo esc_attr($current_bot_id); ?>" data-nonce="<?php echo wp_create_nonce('mxchat_delete_pinecone_prompt_nonce'); ?>" style="color: var(--mxch-error);"> |
| 1180 | 1106 | <span class="dashicons dashicons-trash" style="font-size: 14px;"></span> |
| 1181 | 1107 | </button> |
| @@ -1269,19 +1195,8 @@ | ||
| 1269 | 1195 | <span style="font-weight: 500;"><?php esc_html_e('Auto-sync Pages', 'mxchat'); ?></span> |
| 1270 | 1196 | </div> |
| 1271 | 1197 | </div> |
| 1272 | 1198 | |
| 1273 | - <div class="mxch-field" style="margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--mxch-card-border);"> | |
| 1274 | - <div style="display: flex; align-items: center; gap: 12px;"> | |
| 1275 | - <label class="mxchat-toggle-switch"> | |
| 1276 | - <input type="checkbox" name="mxchat_auto_sync_acf_pdfs" class="mxchat-autosave-field" value="1" data-nonce="<?php echo wp_create_nonce('mxchat_prompts_setting_nonce'); ?>" <?php checked(get_option('mxchat_auto_sync_acf_pdfs', '0'), '1'); ?>> | |
| 1277 | - <span class="mxchat-toggle-slider"></span> | |
| 1278 | - </label> | |
| 1279 | - <span style="font-weight: 500;"><?php esc_html_e('Extract text from PDFs in ACF fields on save', 'mxchat'); ?></span> | |
| 1280 | - </div> | |
| 1281 | - <p class="mxch-field-description" style="margin-top: 8px;"><?php esc_html_e('When ON, editor saves re-extract every PDF referenced in ACF fields. Default OFF — saves stay fast and don\'t re-parse the same PDFs on every edit. The manual content selector has its own per-batch checkbox; this setting only controls the auto-sync path.', 'mxchat'); ?></p> | |
| 1282 | - </div> | |
| 1283 | - | |
| 1284 | 1199 | <div style="margin-top: 24px;"> |
| 1285 | 1200 | <button id="mxchat-custom-post-types-toggle" class="mxch-btn mxch-btn-secondary"> |
| 1286 | 1201 | <?php esc_html_e('Advanced Custom Post Sync Settings', 'mxchat'); ?> |
| 1287 | 1202 | <span style="margin-left: 5px;">▼</span> |
| @@ -1389,11 +1304,10 @@ | ||
| 1389 | 1304 | |
| 1390 | 1305 | <h4 style="margin: 0 0 16px 0;"><?php esc_html_e('Add Tag-Role Mapping', 'mxchat'); ?></h4> |
| 1391 | 1306 | <div style="display: flex; gap: 15px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 24px;"> |
| 1392 | 1307 | <div class="mxch-field" style="flex: 1; min-width: 200px; margin-bottom: 0;"> |
| 1393 | - <label class="mxch-field-label" for="mxchat-tag-input"><?php esc_html_e('Tag (name or slug)', 'mxchat'); ?></label> | |
| 1394 | - <input type="text" id="mxchat-tag-input" class="mxch-input" placeholder="<?php esc_attr_e('e.g., Premium Content or premium-content', 'mxchat'); ?>"> | |
| 1395 | - <span class="mxch-field-hint"><?php esc_html_e('Enter an existing post tag by its display name or its slug.', 'mxchat'); ?></span> | |
| 1308 | + <label class="mxch-field-label" for="mxchat-tag-input"><?php esc_html_e('Tag Name', 'mxchat'); ?></label> | |
| 1309 | + <input type="text" id="mxchat-tag-input" class="mxch-input" placeholder="<?php esc_attr_e('e.g., premium, members-only', 'mxchat'); ?>"> | |
| 1396 | 1310 | </div> |
| 1397 | 1311 | <div class="mxch-field" style="flex: 1; min-width: 200px; margin-bottom: 0;"> |
| 1398 | 1312 | <label class="mxch-field-label" for="mxchat-role-select"><?php esc_html_e('Required Role', 'mxchat'); ?></label> |
| 1399 | 1313 | <select id="mxchat-role-select" class="mxch-select"> |
| @@ -1532,28 +1446,8 @@ | ||
| 1532 | 1446 | <svg class="mxch-notice-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg> |
| 1533 | 1447 | <span><?php esc_html_e('Enter post meta keys to include in embeddings. This is useful for OptionTree fields, theme meta boxes, or any custom post meta that is not managed by ACF.', 'mxchat'); ?></span> |
| 1534 | 1448 | </div> |
| 1535 | 1449 | |
| 1536 | - <!-- Meta-key discovery scanner (plan-mxchat-20260709-fe8e4e): mirror the ACF picker's | |
| 1537 | - discover-for-you UX for non-ACF meta, so owners click keys instead of typing them blind. --> | |
| 1538 | - <div class="mxch-field mxchat-meta-scan"> | |
| 1539 | - <label class="mxch-field-label"><?php esc_html_e('Discover meta keys', 'mxchat'); ?></label> | |
| 1540 | - <p class="mxch-field-description" style="margin-top: 0;"> | |
| 1541 | - <?php esc_html_e('Scan your published content for custom meta keys, then click any you want to include. This gives non-ACF meta the same discover-and-click experience as the ACF picker.', 'mxchat'); ?> | |
| 1542 | - </p> | |
| 1543 | - <div class="mxchat-meta-scan-controls"> | |
| 1544 | - <button type="button" id="mxchat-scan-meta-btn" class="mxch-btn mxch-btn-secondary" data-nonce="<?php echo esc_attr(wp_create_nonce('mxchat_prompts_setting_nonce')); ?>"> | |
| 1545 | - <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> | |
| 1546 | - <span class="mxchat-scan-label"><?php esc_html_e('Scan my content for meta keys', 'mxchat'); ?></span> | |
| 1547 | - </button> | |
| 1548 | - <label class="mxchat-meta-scan-internal"> | |
| 1549 | - <input type="checkbox" id="mxchat-scan-internal"> | |
| 1550 | - <?php esc_html_e('Include internal keys (underscore-prefixed)', 'mxchat'); ?> | |
| 1551 | - </label> | |
| 1552 | - </div> | |
| 1553 | - <div id="mxchat-meta-scan-results" class="mxchat-meta-scan-results" aria-live="polite"></div> | |
| 1554 | - </div> | |
| 1555 | - | |
| 1556 | 1450 | <div class="mxch-field"> |
| 1557 | 1451 | <label class="mxch-field-label" for="mxchat_custom_meta_whitelist"> |
| 1558 | 1452 | <?php esc_html_e('Meta Key Whitelist', 'mxchat'); ?> |
| 1559 | 1453 | </label> |
| @@ -1566,9 +1460,9 @@ | ||
| 1566 | 1460 | data-nonce="<?php echo wp_create_nonce('mxchat_prompts_setting_nonce'); ?>" |
| 1567 | 1461 | style="font-family: monospace;" |
| 1568 | 1462 | ><?php echo esc_textarea($whitelist); ?></textarea> |
| 1569 | 1463 | <p class="mxch-field-description"> |
| 1570 | - <?php esc_html_e('Enter one meta key per line. These fields will be appended to the content during embedding. Text values are added as-is; array or repeater values are flattened into a comma-separated list. Empty values are skipped.', 'mxchat'); ?> | |
| 1464 | + <?php esc_html_e('Enter one meta key per line. These fields will be appended to the content during embedding. Only string values are included.', 'mxchat'); ?> | |
| 1571 | 1465 | </p> |
| 1572 | 1466 | </div> |
| 1573 | 1467 | |
| 1574 | 1468 | <div style="margin-top: 20px; padding: 16px; background: #f8fafc; border-radius: var(--mxch-radius-md);"> |
| @@ -1575,9 +1469,9 @@ | ||
| 1575 | 1469 | <h4 style="margin: 0 0 12px 0; font-size: 14px;"><?php esc_html_e('How to find meta keys:', 'mxchat'); ?></h4> |
| 1576 | 1470 | <ul style="margin: 0; padding-left: 20px; color: var(--mxch-text-secondary); font-size: 13px;"> |
| 1577 | 1471 | <li><?php esc_html_e('Check your theme documentation for meta key names', 'mxchat'); ?></li> |
| 1578 | 1472 | <li><?php esc_html_e('Look in the wp_postmeta database table', 'mxchat'); ?></li> |
| 1579 | - <li><?php esc_html_e('Use the Scan my content for meta keys button above to discover the keys on your published content automatically', 'mxchat'); ?></li> | |
| 1473 | + <li><?php esc_html_e('Use a plugin like "Show Post Meta" to view meta keys on any post', 'mxchat'); ?></li> | |
| 1580 | 1474 | <li><?php esc_html_e('Meta keys starting with underscore (_) are usually hidden/internal', 'mxchat'); ?></li> |
| 1581 | 1475 | </ul> |
| 1582 | 1476 | </div> |
| 1583 | 1477 | </div> |
| @@ -1820,15 +1714,8 @@ | ||
| 1820 | 1714 | </div> |
| 1821 | 1715 | </div> |
| 1822 | 1716 | <div class="mxchat-kb-modal-footer"> |
| 1823 | 1717 | <div class="mxchat-kb-pagination"></div> |
| 1824 | - <div class="mxchat-kb-acf-pdf-option" style="display:flex; align-items:flex-start; gap:8px; padding:8px 0; font-size:12px; color: var(--mxch-text-secondary, #64748b);"> | |
| 1825 | - <input type="checkbox" id="mxchat-kb-acf-pdf-extract" style="margin-top:2px;"> | |
| 1826 | - <label for="mxchat-kb-acf-pdf-extract" style="cursor:pointer; line-height:1.4;"> | |
| 1827 | - <strong style="color: var(--mxch-text-primary, #1a1a2e);"><?php esc_html_e('Also extract text from PDFs linked in ACF File/Image fields', 'mxchat'); ?></strong><br> | |
| 1828 | - <span><?php esc_html_e('Adds 200-500ms per post and ~30 KB to each KB entry. Recommended only if your ACF setup uses PDF attachments for primary content.', 'mxchat'); ?></span> | |
| 1829 | - </label> | |
| 1830 | - </div> | |
| 1831 | 1718 | <div class="mxchat-kb-footer-actions"> |
| 1832 | 1719 | <button type="button" id="mxchat-kb-process-selected" class="mxchat-kb-button-primary" disabled> |
| 1833 | 1720 | <?php esc_html_e('Process Selected Content', 'mxchat'); ?> |
| 1834 | 1721 | <span class="mxchat-kb-selected-count">(0)</span> |
| @@ -1843,248 +1730,8 @@ | ||
| 1843 | 1730 | <?php |
| 1844 | 1731 | } |
| 1845 | 1732 | |
| 1846 | 1733 | /** |
| 1847 | - * Render Edit Entry Modal | |
| 1848 | - */ | |
| 1849 | -function mxchat_render_edit_entry_modal() { | |
| 1850 | - ?> | |
| 1851 | - <div id="mxchat-kb-edit-modal" class="mxchat-kb-modal"> | |
| 1852 | - <div class="mxchat-kb-modal-content mxchat-kb-edit-modal-content"> | |
| 1853 | - <div class="mxchat-kb-modal-header"> | |
| 1854 | - <h3 id="mxchat-kb-edit-title"><?php esc_html_e('Edit Knowledge Entry', 'mxchat'); ?></h3> | |
| 1855 | - <span class="mxchat-kb-modal-close" id="mxchat-kb-edit-close">×</span> | |
| 1856 | - </div> | |
| 1857 | - <div class="mxchat-kb-edit-body"> | |
| 1858 | - <div class="mxchat-kb-edit-source" id="mxchat-kb-edit-source"></div> | |
| 1859 | - <textarea id="mxchat-kb-edit-textarea" class="mxchat-kb-edit-textarea" placeholder="<?php esc_attr_e('Loading content...', 'mxchat'); ?>"></textarea> | |
| 1860 | - <div class="mxchat-kb-edit-meta"> | |
| 1861 | - <span id="mxchat-kb-edit-charcount"></span> | |
| 1862 | - <span id="mxchat-kb-edit-chunkinfo"></span> | |
| 1863 | - </div> | |
| 1864 | - </div> | |
| 1865 | - <div class="mxchat-kb-edit-footer"> | |
| 1866 | - <div class="mxchat-kb-edit-notice" id="mxchat-kb-edit-notice"></div> | |
| 1867 | - <div class="mxchat-kb-edit-actions"> | |
| 1868 | - <button type="button" id="mxchat-kb-edit-cancel" class="mxch-btn mxch-btn-ghost"> | |
| 1869 | - <?php esc_html_e('Cancel', 'mxchat'); ?> | |
| 1870 | - </button> | |
| 1871 | - <button type="button" id="mxchat-kb-edit-save" class="mxch-btn mxch-btn-primary"> | |
| 1872 | - <span class="mxchat-kb-edit-save-text"><?php esc_html_e('Save & Re-embed', 'mxchat'); ?></span> | |
| 1873 | - <span class="mxchat-kb-edit-save-spinner" style="display:none;"> | |
| 1874 | - <span class="mxchat-kb-spinner is-active" style="margin: 0;"></span> | |
| 1875 | - <?php esc_html_e('Saving...', 'mxchat'); ?> | |
| 1876 | - </span> | |
| 1877 | - </button> | |
| 1878 | - </div> | |
| 1879 | - </div> | |
| 1880 | - </div> | |
| 1881 | - </div> | |
| 1882 | - <?php | |
| 1883 | -} | |
| 1884 | - | |
| 1885 | -/** | |
| 1886 | - * Render the read-only Knowledge Inspector modal (plan-mxchat-20260628-d8cb4b). | |
| 1887 | - * Shows exactly what was indexed for an entry: the per-chunk stored text + lengths | |
| 1888 | - * and (for Pinecone) the stored metadata fields, rendered with the Testing tab's | |
| 1889 | - * own card components so the two surfaces feel like one system. Self-contained | |
| 1890 | - * markup + JS so it doesn't entangle the edit-modal init. | |
| 1891 | - */ | |
| 1892 | -function mxchat_render_inspect_entry_modal() { | |
| 1893 | - ?> | |
| 1894 | - <div id="mxchat-kb-inspect-modal" class="mxchat-kb-modal"> | |
| 1895 | - <div class="mxchat-kb-modal-content mxchat-kb-inspect-modal-content"> | |
| 1896 | - <div class="mxchat-kb-modal-header"> | |
| 1897 | - <h3 id="mxchat-kb-inspect-title"><?php esc_html_e('Indexed Content', 'mxchat'); ?></h3> | |
| 1898 | - <span class="mxchat-kb-modal-close" id="mxchat-kb-inspect-close">×</span> | |
| 1899 | - </div> | |
| 1900 | - <div class="mxchat-kb-inspect-body"> | |
| 1901 | - <div class="mxchat-kb-edit-source" id="mxchat-kb-inspect-source"></div> | |
| 1902 | - <div class="mxch-testing-results" id="mxchat-kb-inspect-results"> | |
| 1903 | - <div class="mxch-testing-no-data"><?php esc_html_e('Loading indexed content…', 'mxchat'); ?></div> | |
| 1904 | - </div> | |
| 1905 | - </div> | |
| 1906 | - <div class="mxchat-kb-edit-footer"> | |
| 1907 | - <div class="mxchat-kb-edit-notice" id="mxchat-kb-inspect-notice"></div> | |
| 1908 | - <div class="mxchat-kb-edit-actions"> | |
| 1909 | - <button type="button" id="mxchat-kb-inspect-close-btn" class="mxch-btn mxch-btn-primary"> | |
| 1910 | - <?php esc_html_e('Close', 'mxchat'); ?> | |
| 1911 | - </button> | |
| 1912 | - </div> | |
| 1913 | - </div> | |
| 1914 | - </div> | |
| 1915 | - </div> | |
| 1916 | - <script> | |
| 1917 | - (function() { | |
| 1918 | - 'use strict'; | |
| 1919 | - document.addEventListener('DOMContentLoaded', function() { | |
| 1920 | - var modal = document.getElementById('mxchat-kb-inspect-modal'); | |
| 1921 | - if (!modal) return; | |
| 1922 | - var closeX = document.getElementById('mxchat-kb-inspect-close'); | |
| 1923 | - var closeBtn = document.getElementById('mxchat-kb-inspect-close-btn'); | |
| 1924 | - var sourceEl = document.getElementById('mxchat-kb-inspect-source'); | |
| 1925 | - var resultsEl= document.getElementById('mxchat-kb-inspect-results'); | |
| 1926 | - var titleEl = document.getElementById('mxchat-kb-inspect-title'); | |
| 1927 | - var noticeEl = document.getElementById('mxchat-kb-inspect-notice'); | |
| 1928 | - | |
| 1929 | - var I18N = { | |
| 1930 | - title: <?php echo wp_json_encode( esc_html__('Indexed Content', 'mxchat') ); ?>, | |
| 1931 | - loading: <?php echo wp_json_encode( esc_html__('Loading indexed content…', 'mxchat') ); ?>, | |
| 1932 | - manual: <?php echo wp_json_encode( esc_html__('Manual Content', 'mxchat') ); ?>, | |
| 1933 | - source: <?php echo wp_json_encode( esc_html__('Source', 'mxchat') ); ?>, | |
| 1934 | - store: <?php echo wp_json_encode( esc_html__('Storage', 'mxchat') ); ?>, | |
| 1935 | - type: <?php echo wp_json_encode( esc_html__('Content type', 'mxchat') ); ?>, | |
| 1936 | - chunksLbl:<?php echo wp_json_encode( esc_html__('Chunks', 'mxchat') ); ?>, | |
| 1937 | - totalLen: <?php echo wp_json_encode( esc_html__('Total indexed length', 'mxchat') ); ?>, | |
| 1938 | - chunk: <?php echo wp_json_encode( esc_html__('Chunk', 'mxchat') ); ?>, | |
| 1939 | - indexed: <?php echo wp_json_encode( esc_html__('Indexed', 'mxchat') ); ?>, | |
| 1940 | - chars: <?php echo wp_json_encode( esc_html__('chars', 'mxchat') ); ?>, | |
| 1941 | - showText: <?php echo wp_json_encode( esc_html__('Show indexed text', 'mxchat') ); ?>, | |
| 1942 | - hideText: <?php echo wp_json_encode( esc_html__('Hide indexed text', 'mxchat') ); ?>, | |
| 1943 | - wpStore: <?php echo wp_json_encode( esc_html__('Local WordPress database', 'mxchat') ); ?>, | |
| 1944 | - pcStore: <?php echo wp_json_encode( esc_html__('Pinecone', 'mxchat') ); ?>, | |
| 1945 | - meta: <?php echo wp_json_encode( esc_html__('Vector metadata', 'mxchat') ); ?>, | |
| 1946 | - loadFail: <?php echo wp_json_encode( esc_html__('Failed to load indexed content.', 'mxchat') ); ?>, | |
| 1947 | - netErr: <?php echo wp_json_encode( esc_html__('Network error: ', 'mxchat') ); ?> | |
| 1948 | - }; | |
| 1949 | - | |
| 1950 | - function esc(str) { | |
| 1951 | - var d = document.createElement('div'); | |
| 1952 | - d.textContent = (str === null || str === undefined) ? '' : String(str); | |
| 1953 | - return d.innerHTML; | |
| 1954 | - } | |
| 1955 | - function fmt(n) { try { return Number(n).toLocaleString(); } catch (e) { return n; } } | |
| 1956 | - | |
| 1957 | - document.addEventListener('click', function(e) { | |
| 1958 | - var btn = e.target.closest('.mxchat-inspect-entry-btn'); | |
| 1959 | - if (btn) { e.preventDefault(); open(btn); } | |
| 1960 | - }); | |
| 1961 | - if (closeX) closeX.addEventListener('click', close); | |
| 1962 | - if (closeBtn) closeBtn.addEventListener('click', close); | |
| 1963 | - modal.addEventListener('click', function(e) { if (e.target === modal) close(); }); | |
| 1964 | - document.addEventListener('keydown', function(e) { | |
| 1965 | - if (e.key === 'Escape' && modal.classList.contains('active')) close(); | |
| 1966 | - }); | |
| 1967 | - | |
| 1968 | - function close() { modal.classList.remove('active'); } | |
| 1969 | - | |
| 1970 | - function open(btn) { | |
| 1971 | - var entry = { | |
| 1972 | - sourceUrl: btn.getAttribute('data-source-url') || '', | |
| 1973 | - entryId: btn.getAttribute('data-entry-id') || '', | |
| 1974 | - dataSource: btn.getAttribute('data-data-source') || 'wordpress', | |
| 1975 | - botId: btn.getAttribute('data-bot-id') || 'default', | |
| 1976 | - nonce: btn.getAttribute('data-nonce') || '' | |
| 1977 | - }; | |
| 1978 | - | |
| 1979 | - titleEl.textContent = I18N.title; | |
| 1980 | - noticeEl.textContent = ''; | |
| 1981 | - noticeEl.className = 'mxchat-kb-edit-notice'; | |
| 1982 | - resultsEl.innerHTML = '<div class="mxch-testing-no-data">' + esc(I18N.loading) + '</div>'; | |
| 1983 | - | |
| 1984 | - if (entry.sourceUrl && entry.sourceUrl.indexOf('mxchat://') !== 0 && entry.sourceUrl.indexOf('_ungrouped_') !== 0) { | |
| 1985 | - sourceEl.innerHTML = esc(I18N.source) + ': <a href="' + esc(entry.sourceUrl) + '" target="_blank" rel="noopener">' + esc(entry.sourceUrl) + '</a>'; | |
| 1986 | - } else { | |
| 1987 | - sourceEl.textContent = I18N.manual; | |
| 1988 | - } | |
| 1989 | - | |
| 1990 | - modal.classList.add('active'); | |
| 1991 | - | |
| 1992 | - var fd = new FormData(); | |
| 1993 | - fd.append('action', 'mxchat_inspect_entry'); | |
| 1994 | - fd.append('nonce', entry.nonce); | |
| 1995 | - fd.append('source_url', entry.sourceUrl); | |
| 1996 | - fd.append('entry_id', entry.entryId); | |
| 1997 | - fd.append('data_source', entry.dataSource); | |
| 1998 | - fd.append('bot_id', entry.botId); | |
| 1999 | - | |
| 2000 | - fetch(ajaxurl, { method: 'POST', body: fd }) | |
| 2001 | - .then(function(r) { return r.json(); }) | |
| 2002 | - .then(function(resp) { | |
| 2003 | - if (resp && resp.success) { | |
| 2004 | - render(resp.data); | |
| 2005 | - } else { | |
| 2006 | - var msg = (resp && resp.data && resp.data.message) || I18N.loadFail; | |
| 2007 | - resultsEl.innerHTML = ''; | |
| 2008 | - showNotice(msg, 'error'); | |
| 2009 | - } | |
| 2010 | - }) | |
| 2011 | - .catch(function(err) { | |
| 2012 | - resultsEl.innerHTML = ''; | |
| 2013 | - showNotice(I18N.netErr + err.message, 'error'); | |
| 2014 | - }); | |
| 2015 | - } | |
| 2016 | - | |
| 2017 | - function render(data) { | |
| 2018 | - var storeLabel = data.store === 'pinecone' ? I18N.pcStore : I18N.wpStore; | |
| 2019 | - var html = ''; | |
| 2020 | - | |
| 2021 | - // Summary card — what this entry is + how much was indexed. | |
| 2022 | - html += '<div class="match-card above-threshold">' + | |
| 2023 | - '<div class="match-header">' + | |
| 2024 | - '<div class="match-title"><span class="status-icon">📦</span> ' + esc(data.chunk_count) + ' ' + esc(I18N.chunksLbl.toLowerCase()) + '</div>' + | |
| 2025 | - '<span class="context-label">' + esc(storeLabel) + '</span>' + | |
| 2026 | - '</div>' + | |
| 2027 | - '<div class="mxch-testing-field"><label>' + esc(I18N.type) + '</label><code>' + esc(data.content_type || '—') + '</code> ' + | |
| 2028 | - ' <label style="display:inline; text-transform:none; letter-spacing:0; font-weight:600;">' + esc(I18N.totalLen) + ':</label> ' + esc(fmt(data.assembled_length)) + ' ' + esc(I18N.chars) + '</div>'; | |
| 2029 | - if (data.metadata_note) { | |
| 2030 | - html += '<div class="match-source"><span class="source-icon">ℹ️</span> ' + esc(data.metadata_note) + '</div>'; | |
| 2031 | - } | |
| 2032 | - html += '</div>'; | |
| 2033 | - | |
| 2034 | - // One card per stored chunk — the actual embedded text. | |
| 2035 | - var chunks = data.chunks || []; | |
| 2036 | - chunks.forEach(function(chunk, i) { | |
| 2037 | - var num = (chunk.index !== null && chunk.index !== undefined) ? (chunk.index + 1) : (i + 1); | |
| 2038 | - var metaRows = ''; | |
| 2039 | - if (chunk.metadata && typeof chunk.metadata === 'object') { | |
| 2040 | - var keys = Object.keys(chunk.metadata); | |
| 2041 | - if (keys.length) { | |
| 2042 | - metaRows += '<div class="chunk-detail-row chunk-used" style="display:block;"><span class="chunk-detail-num">' + esc(I18N.meta) + '</span></div>'; | |
| 2043 | - keys.forEach(function(k) { | |
| 2044 | - metaRows += '<div class="chunk-detail-row"><span class="chunk-detail-num">' + esc(k) + '</span><span class="chunk-detail-score">' + esc(chunk.metadata[k]) + '</span></div>'; | |
| 2045 | - }); | |
| 2046 | - } | |
| 2047 | - } | |
| 2048 | - html += '<div class="match-card above-threshold">' + | |
| 2049 | - '<div class="match-header">' + | |
| 2050 | - '<div class="match-title"><span class="status-icon">✓</span> ' + esc(I18N.chunk) + ' ' + esc(num) + | |
| 2051 | - '<span class="chunk-summary">' + esc(fmt(chunk.length)) + ' ' + esc(I18N.chars) + '</span>' + | |
| 2052 | - '</div>' + | |
| 2053 | - '<span class="context-label">' + esc(I18N.indexed) + '</span>' + | |
| 2054 | - '</div>' + | |
| 2055 | - '<span class="chunk-expand-toggle" data-chunk="' + i + '">▶ ' + esc(I18N.showText) + '</span>' + | |
| 2056 | - '<div class="chunk-details" data-chunk="' + i + '">' + | |
| 2057 | - '<pre class="mxch-kb-inspect-chunk-text">' + esc(chunk.text) + '</pre>' + | |
| 2058 | - metaRows + | |
| 2059 | - '</div>' + | |
| 2060 | - '</div>'; | |
| 2061 | - }); | |
| 2062 | - | |
| 2063 | - resultsEl.innerHTML = html; | |
| 2064 | - | |
| 2065 | - resultsEl.querySelectorAll('.chunk-expand-toggle').forEach(function(toggle) { | |
| 2066 | - toggle.addEventListener('click', function() { | |
| 2067 | - var id = this.getAttribute('data-chunk'); | |
| 2068 | - var details = resultsEl.querySelector('.chunk-details[data-chunk="' + id + '"]'); | |
| 2069 | - if (!details) return; | |
| 2070 | - var expanded = details.classList.toggle('expanded'); | |
| 2071 | - this.innerHTML = (expanded ? '▼ ' + esc(I18N.hideText) : '▶ ' + esc(I18N.showText)); | |
| 2072 | - }); | |
| 2073 | - }); | |
| 2074 | - } | |
| 2075 | - | |
| 2076 | - function showNotice(msg, type) { | |
| 2077 | - noticeEl.textContent = msg; | |
| 2078 | - noticeEl.className = 'mxchat-kb-edit-notice' + (type ? ' ' + type : ''); | |
| 2079 | - } | |
| 2080 | - }); | |
| 2081 | - })(); | |
| 2082 | - </script> | |
| 2083 | - <?php | |
| 2084 | -} | |
| 2085 | - | |
| 2086 | -/** | |
| 2087 | 1734 | * Render Knowledge Page Navigation Scripts |
| 2088 | 1735 | */ |
| 2089 | 1736 | function mxchat_render_knowledge_page_scripts() { |
| 2090 | 1737 | ?> |
| @@ -2259,197 +1906,8 @@ | ||
| 2259 | 1906 | } |
| 2260 | 1907 | |
| 2261 | 1908 | // Sitemap detection is now handled by knowledge-processing.js |
| 2262 | 1909 | // It will be initialized when user clicks "Sitemap Import" option |
| 2263 | - | |
| 2264 | - // ─── Edit Entry Modal ──────────────────────────────────── | |
| 2265 | - initEditModal(); | |
| 2266 | - | |
| 2267 | - function initEditModal() { | |
| 2268 | - var modal = document.getElementById('mxchat-kb-edit-modal'); | |
| 2269 | - var textarea = document.getElementById('mxchat-kb-edit-textarea'); | |
| 2270 | - var saveBtn = document.getElementById('mxchat-kb-edit-save'); | |
| 2271 | - var cancelBtn = document.getElementById('mxchat-kb-edit-cancel'); | |
| 2272 | - var closeBtn = document.getElementById('mxchat-kb-edit-close'); | |
| 2273 | - var notice = document.getElementById('mxchat-kb-edit-notice'); | |
| 2274 | - var charCount = document.getElementById('mxchat-kb-edit-charcount'); | |
| 2275 | - var chunkInfo = document.getElementById('mxchat-kb-edit-chunkinfo'); | |
| 2276 | - var sourceEl = document.getElementById('mxchat-kb-edit-source'); | |
| 2277 | - var titleEl = document.getElementById('mxchat-kb-edit-title'); | |
| 2278 | - var saveText = saveBtn ? saveBtn.querySelector('.mxchat-kb-edit-save-text') : null; | |
| 2279 | - var saveSpin = saveBtn ? saveBtn.querySelector('.mxchat-kb-edit-save-spinner') : null; | |
| 2280 | - | |
| 2281 | - if (!modal) return; | |
| 2282 | - | |
| 2283 | - var currentEntry = {}; | |
| 2284 | - | |
| 2285 | - // Bind edit buttons (delegated) | |
| 2286 | - document.addEventListener('click', function(e) { | |
| 2287 | - var btn = e.target.closest('.mxchat-edit-entry-btn'); | |
| 2288 | - if (btn) { | |
| 2289 | - e.preventDefault(); | |
| 2290 | - openEditModal(btn); | |
| 2291 | - } | |
| 2292 | - }); | |
| 2293 | - | |
| 2294 | - // Close handlers | |
| 2295 | - if (closeBtn) closeBtn.addEventListener('click', closeModal); | |
| 2296 | - if (cancelBtn) cancelBtn.addEventListener('click', closeModal); | |
| 2297 | - modal.addEventListener('click', function(e) { | |
| 2298 | - if (e.target === modal) closeModal(); | |
| 2299 | - }); | |
| 2300 | - | |
| 2301 | - // Character count | |
| 2302 | - if (textarea) { | |
| 2303 | - textarea.addEventListener('input', function() { | |
| 2304 | - updateCharCount(); | |
| 2305 | - }); | |
| 2306 | - } | |
| 2307 | - | |
| 2308 | - // Save handler | |
| 2309 | - if (saveBtn) saveBtn.addEventListener('click', saveContent); | |
| 2310 | - | |
| 2311 | - function openEditModal(btn) { | |
| 2312 | - currentEntry = { | |
| 2313 | - sourceUrl: btn.getAttribute('data-source-url') || '', | |
| 2314 | - entryId: btn.getAttribute('data-entry-id') || '', | |
| 2315 | - dataSource: btn.getAttribute('data-data-source') || 'wordpress', | |
| 2316 | - botId: btn.getAttribute('data-bot-id') || 'default', | |
| 2317 | - nonce: btn.getAttribute('data-nonce') || '' | |
| 2318 | - }; | |
| 2319 | - | |
| 2320 | - // Reset state | |
| 2321 | - textarea.value = ''; | |
| 2322 | - textarea.placeholder = 'Loading content...'; | |
| 2323 | - textarea.disabled = true; | |
| 2324 | - saveBtn.disabled = true; | |
| 2325 | - notice.textContent = ''; | |
| 2326 | - notice.className = 'mxchat-kb-edit-notice'; | |
| 2327 | - charCount.textContent = ''; | |
| 2328 | - chunkInfo.textContent = ''; | |
| 2329 | - | |
| 2330 | - // Show source | |
| 2331 | - if (currentEntry.sourceUrl && currentEntry.sourceUrl.indexOf('mxchat://') !== 0) { | |
| 2332 | - sourceEl.innerHTML = 'Source: <a href="' + escapeHtml(currentEntry.sourceUrl) + '" target="_blank">' + escapeHtml(truncate(currentEntry.sourceUrl, 60)) + '</a>'; | |
| 2333 | - } else { | |
| 2334 | - sourceEl.textContent = 'Manual Content'; | |
| 2335 | - } | |
| 2336 | - | |
| 2337 | - // Show modal | |
| 2338 | - modal.classList.add('active'); | |
| 2339 | - | |
| 2340 | - // Fetch content | |
| 2341 | - var formData = new FormData(); | |
| 2342 | - formData.append('action', 'mxchat_get_entry_content'); | |
| 2343 | - formData.append('nonce', currentEntry.nonce); | |
| 2344 | - formData.append('source_url', currentEntry.sourceUrl); | |
| 2345 | - formData.append('entry_id', currentEntry.entryId); | |
| 2346 | - formData.append('data_source', currentEntry.dataSource); | |
| 2347 | - formData.append('bot_id', currentEntry.botId); | |
| 2348 | - | |
| 2349 | - fetch(ajaxurl, { method: 'POST', body: formData }) | |
| 2350 | - .then(function(r) { return r.json(); }) | |
| 2351 | - .then(function(resp) { | |
| 2352 | - if (resp.success) { | |
| 2353 | - textarea.value = resp.data.content || ''; | |
| 2354 | - textarea.disabled = false; | |
| 2355 | - textarea.placeholder = 'Edit your content here...'; | |
| 2356 | - saveBtn.disabled = false; | |
| 2357 | - currentEntry.contentType = resp.data.content_type || 'content'; | |
| 2358 | - | |
| 2359 | - updateCharCount(); | |
| 2360 | - | |
| 2361 | - if (resp.data.is_chunked) { | |
| 2362 | - chunkInfo.textContent = resp.data.chunk_count + ' chunks — will be re-chunked on save'; | |
| 2363 | - titleEl.textContent = 'Edit Knowledge Entry (' + resp.data.chunk_count + ' chunks)'; | |
| 2364 | - } else { | |
| 2365 | - chunkInfo.textContent = ''; | |
| 2366 | - titleEl.textContent = 'Edit Knowledge Entry'; | |
| 2367 | - } | |
| 2368 | - | |
| 2369 | - textarea.focus(); | |
| 2370 | - } else { | |
| 2371 | - textarea.placeholder = ''; | |
| 2372 | - showNotice((resp.data && resp.data.message) || 'Failed to load content.', 'error'); | |
| 2373 | - } | |
| 2374 | - }) | |
| 2375 | - .catch(function(err) { | |
| 2376 | - textarea.placeholder = ''; | |
| 2377 | - showNotice('Network error: ' + err.message, 'error'); | |
| 2378 | - }); | |
| 2379 | - } | |
| 2380 | - | |
| 2381 | - function saveContent() { | |
| 2382 | - if (!textarea.value.trim()) { | |
| 2383 | - showNotice('Content cannot be empty.', 'error'); | |
| 2384 | - return; | |
| 2385 | - } | |
| 2386 | - | |
| 2387 | - saveBtn.disabled = true; | |
| 2388 | - if (saveText) saveText.style.display = 'none'; | |
| 2389 | - if (saveSpin) saveSpin.style.display = ''; | |
| 2390 | - showNotice('Saving and re-embedding...', ''); | |
| 2391 | - | |
| 2392 | - var formData = new FormData(); | |
| 2393 | - formData.append('action', 'mxchat_save_entry_content'); | |
| 2394 | - formData.append('nonce', currentEntry.nonce); | |
| 2395 | - formData.append('source_url', currentEntry.sourceUrl); | |
| 2396 | - formData.append('entry_id', currentEntry.entryId); | |
| 2397 | - formData.append('content', textarea.value); | |
| 2398 | - formData.append('data_source', currentEntry.dataSource); | |
| 2399 | - formData.append('bot_id', currentEntry.botId); | |
| 2400 | - formData.append('content_type', currentEntry.contentType || 'content'); | |
| 2401 | - | |
| 2402 | - fetch(ajaxurl, { method: 'POST', body: formData }) | |
| 2403 | - .then(function(r) { return r.json(); }) | |
| 2404 | - .then(function(resp) { | |
| 2405 | - if (saveText) saveText.style.display = ''; | |
| 2406 | - if (saveSpin) saveSpin.style.display = 'none'; | |
| 2407 | - saveBtn.disabled = false; | |
| 2408 | - | |
| 2409 | - if (resp.success) { | |
| 2410 | - showNotice('Saved successfully!', 'success'); | |
| 2411 | - setTimeout(function() { | |
| 2412 | - closeModal(); | |
| 2413 | - window.location.reload(); | |
| 2414 | - }, 1000); | |
| 2415 | - } else { | |
| 2416 | - showNotice((resp.data && resp.data.message) || 'Save failed.', 'error'); | |
| 2417 | - } | |
| 2418 | - }) | |
| 2419 | - .catch(function(err) { | |
| 2420 | - if (saveText) saveText.style.display = ''; | |
| 2421 | - if (saveSpin) saveSpin.style.display = 'none'; | |
| 2422 | - saveBtn.disabled = false; | |
| 2423 | - showNotice('Network error: ' + err.message, 'error'); | |
| 2424 | - }); | |
| 2425 | - } | |
| 2426 | - | |
| 2427 | - function closeModal() { | |
| 2428 | - modal.classList.remove('active'); | |
| 2429 | - } | |
| 2430 | - | |
| 2431 | - function updateCharCount() { | |
| 2432 | - var len = textarea.value.length; | |
| 2433 | - charCount.textContent = len.toLocaleString() + ' characters'; | |
| 2434 | - } | |
| 2435 | - | |
| 2436 | - function showNotice(msg, type) { | |
| 2437 | - notice.textContent = msg; | |
| 2438 | - notice.className = 'mxchat-kb-edit-notice' + (type ? ' ' + type : ''); | |
| 2439 | - } | |
| 2440 | - | |
| 2441 | - function escapeHtml(str) { | |
| 2442 | - var div = document.createElement('div'); | |
| 2443 | - div.textContent = str; | |
| 2444 | - return div.innerHTML; | |
| 2445 | - } | |
| 2446 | - | |
| 2447 | - function truncate(str, max) { | |
| 2448 | - return str.length > max ? str.substring(0, max) + '...' : str; | |
| 2449 | - } | |
| 2450 | - } | |
| 2451 | - | |
| 2452 | 1910 | })(); |
| 2453 | 1911 | </script> |
| 2454 | 1912 | <?php |
| 2455 | 1913 | } |