| @@ -1375,8 +1375,11 @@ | ||
| 1375 | 1375 | |
| 1376 | 1376 | // Check for in-progress cloud indexing auto-refresh (survives page reloads) |
| 1377 | 1377 | this.checkForumIndexingAutoRefresh(); |
| 1378 | 1378 | |
| 1379 | + // Load indexing breakdown asynchronously (cached 1 day) | |
| 1380 | + this.loadIndexingBreakdown(); | |
| 1381 | + | |
| 1379 | 1382 | // Note: Polling is started from PHP inline script based on server-side $is_indexing status |
| 1380 | 1383 | // No need to start it here to avoid duplicate polling |
| 1381 | 1384 | }, |
| 1382 | 1385 | |
| @@ -1634,8 +1637,91 @@ | ||
| 1634 | 1637 | $icon.removeClass('wpforo-spin'); |
| 1635 | 1638 | $button.prop('disabled', false); |
| 1636 | 1639 | } |
| 1637 | 1640 | }); |
| 1641 | + }, | |
| 1642 | + | |
| 1643 | + /** | |
| 1644 | + * Load indexing breakdown via AJAX (private/unapproved topic counts) | |
| 1645 | + * Data is cached server-side for 1 day to avoid slow GROUP BY queries | |
| 1646 | + */ | |
| 1647 | + loadIndexingBreakdown: function() { | |
| 1648 | + const $container = $('#wpforo-ai-indexing-breakdown-container'); | |
| 1649 | + if (!$container.length) { | |
| 1650 | + return; | |
| 1651 | + } | |
| 1652 | + | |
| 1653 | + const self = this; | |
| 1654 | + const loadingText = $container.data('loading-text') || 'Loading...'; | |
| 1655 | + | |
| 1656 | + // Show small loading spinner | |
| 1657 | + $container.html('<span class="wpforo-ai-breakdown-loading"><span class="dashicons dashicons-update wpforo-spin"></span> ' + loadingText + '</span>'); | |
| 1658 | + | |
| 1659 | + $.ajax({ | |
| 1660 | + url: wpforoAIAdmin.ajaxUrl, | |
| 1661 | + type: 'POST', | |
| 1662 | + data: { | |
| 1663 | + action: 'wpforo_ai_get_indexing_breakdown', | |
| 1664 | + nonce: wpforoAIAdmin.nonce | |
| 1665 | + }, | |
| 1666 | + success: function(response) { | |
| 1667 | + if (response.success && response.data) { | |
| 1668 | + self.renderIndexingBreakdown($container, response.data); | |
| 1669 | + } else { | |
| 1670 | + $container.empty(); | |
| 1671 | + } | |
| 1672 | + }, | |
| 1673 | + error: function() { | |
| 1674 | + $container.empty(); | |
| 1675 | + } | |
| 1676 | + }); | |
| 1677 | + }, | |
| 1678 | + | |
| 1679 | + /** | |
| 1680 | + * Render the indexing breakdown HTML | |
| 1681 | + */ | |
| 1682 | + renderIndexingBreakdown: function($container, data) { | |
| 1683 | + const privateCount = parseInt(data.private, 10) || 0; | |
| 1684 | + const unapprovedCount = parseInt(data.unapproved, 10) || 0; | |
| 1685 | + | |
| 1686 | + if (privateCount === 0 && unapprovedCount === 0) { | |
| 1687 | + $container.empty(); | |
| 1688 | + return; | |
| 1689 | + } | |
| 1690 | + | |
| 1691 | + const excludedCount = privateCount + unapprovedCount; | |
| 1692 | + const excludedText = $container.data('excluded-text') || '%s topics are excluded from indexing'; | |
| 1693 | + const introText = $container.data('intro-text') || 'The following topics are automatically excluded from AI indexing:'; | |
| 1694 | + const privateText = $container.data('private-text') || 'private topics - these are only visible to their authors'; | |
| 1695 | + const unapprovedText = $container.data('unapproved-text') || 'unapproved topics - these will be indexed once approved by moderators'; | |
| 1696 | + const noteText = $container.data('note-text') || 'Private topics are never indexed to protect user privacy. Unapproved topics will be automatically indexed when approved.'; | |
| 1697 | + | |
| 1698 | + let html = '<div class="wpforo-ai-indexing-breakdown">'; | |
| 1699 | + html += '<details class="wpforo-ai-breakdown-details">'; | |
| 1700 | + html += '<summary class="wpforo-ai-breakdown-summary">'; | |
| 1701 | + html += '<span class="dashicons dashicons-info-outline"></span>'; | |
| 1702 | + html += excludedText.replace('%s', '<strong>' + this.formatNumber(excludedCount) + '</strong>'); | |
| 1703 | + html += '<span class="dashicons dashicons-arrow-down-alt2 wpforo-ai-breakdown-arrow"></span>'; | |
| 1704 | + html += '</summary>'; | |
| 1705 | + html += '<div class="wpforo-ai-breakdown-content">'; | |
| 1706 | + html += '<p class="wpforo-ai-breakdown-intro">' + introText + '</p>'; | |
| 1707 | + html += '<ul class="wpforo-ai-breakdown-list">'; | |
| 1708 | + | |
| 1709 | + if (privateCount > 0) { | |
| 1710 | + html += '<li><span class="dashicons dashicons-lock"></span>'; | |
| 1711 | + html += '<strong>' + this.formatNumber(privateCount) + '</strong> ' + privateText + '</li>'; | |
| 1712 | + } | |
| 1713 | + | |
| 1714 | + if (unapprovedCount > 0) { | |
| 1715 | + html += '<li><span class="dashicons dashicons-clock"></span>'; | |
| 1716 | + html += '<strong>' + this.formatNumber(unapprovedCount) + '</strong> ' + unapprovedText + '</li>'; | |
| 1717 | + } | |
| 1718 | + | |
| 1719 | + html += '</ul>'; | |
| 1720 | + html += '<p class="wpforo-ai-breakdown-note"><em>' + noteText + '</em></p>'; | |
| 1721 | + html += '</div></details></div>'; | |
| 1722 | + | |
| 1723 | + $container.html(html); | |
| 1638 | 1724 | }, |
| 1639 | 1725 | |
| 1640 | 1726 | // WordPress Content Indexing Methods have been moved to |
| 1641 | 1727 | // ai-features-wp-indexing.js for the dedicated WordPress Indexing tab. |