// ================================================================================== // HISTORY VERSIONS BUTTON COMPONENT // Smart button that only shows when history exists // ================================================================================== const HistoryVersionsButton = ({ doc, currentUser, onOpenModal, variant = 'default' }) => { const { useState, useEffect } = React; const [hasHistory, setHasHistory] = useState(false); const [isChecking, setIsChecking] = useState(true); // Check if history exists on mount useEffect(() => { let mounted = true; const checkHistory = async () => { try { const res = await fetch(`/api/knowledge-base/${doc.id}/history`, { headers: window.getApiHeaders ? window.getApiHeaders(currentUser.Username) : { 'X-OTO-User': currentUser.Username } }); if (!mounted) return; if (res.ok) { const data = await res.json(); const historyCount = (data.history || []).length; setHasHistory(historyCount > 0); } } catch (error) { console.error('Error checking history:', error); } finally { if (mounted) setIsChecking(false); } }; // Only check if versioning is enabled if (doc.versioning_mode === 'history' || doc.versioning_mode === 'parallel') { checkHistory(); } else { setIsChecking(false); } return () => { mounted = false; }; }, [doc.id, doc.versioning_mode, currentUser.Username]); // Don't show button if checking, no versioning, or no history if (isChecking) return null; if (doc.versioning_mode !== 'history' && doc.versioning_mode !== 'parallel') return null; if (!hasHistory) return null; const handleClick = async () => { try { // Fetch fresh article data const articleRes = await fetch(`/api/knowledge-base/${doc.id}`, { headers: window.getApiHeaders ? window.getApiHeaders(currentUser.Username) : { 'X-OTO-User': currentUser.Username } }); let freshArticle = doc; if (articleRes.ok) { const articleData = await articleRes.json(); freshArticle = articleData.article || doc; } // Fetch history const historyRes = await fetch(`/api/knowledge-base/${doc.id}/history`, { headers: window.getApiHeaders ? window.getApiHeaders(currentUser.Username) : { 'X-OTO-User': currentUser.Username } }); if (!historyRes.ok) { window.otoNotify?.toast('Could not load version history', 'error'); return; } const historyData = await historyRes.json(); const history = historyData.history || []; if (history.length === 0) { return; } // Get max version number const maxVersion = Math.max(...history.map(h => h.version)); // Check if current article was updated after last history entry const lastHistoryDate = new Date(history[0].changed_at || history[0].modified_at); const articleUpdateDate = new Date(freshArticle.updated_at || freshArticle.created_at); let allVersions = []; if (articleUpdateDate > lastHistoryDate) { // Article was modified after last history save - add current version const currentVersion = { id: `current-${freshArticle.id}`, kb_id: freshArticle.id, version: maxVersion + 1, title: freshArticle.title, content: freshArticle.content, category: freshArticle.category, status: freshArticle.status, visibility: freshArticle.visibility, tags: freshArticle.tags || [], attachments: freshArticle.attachments || [], attachments_snapshot: JSON.stringify(freshArticle.attachments || []), changed_by: freshArticle.modified_by || currentUser.Username, changed_by_name: freshArticle.modified_by_name || (currentUser.FirstName + ' ' + currentUser.LastName), changed_at: freshArticle.updated_at || freshArticle.created_at, modified_at: freshArticle.updated_at || freshArticle.created_at, is_current: true }; allVersions = [currentVersion, ...history]; } else { // Last history IS current - just use history allVersions = history; } // Open modal with versions onOpenModal(doc.id, allVersions, freshArticle); } catch (error) { console.error('Error loading history:', error); window.otoNotify?.toast('Error loading version history', 'error'); } }; const label = doc.versioning_mode === 'parallel' ? '📂 Versions' : '📚 History'; // Menu variant: used inside dropdown menus (e.g. Actions menu). Full-width, aligned with other items. if (variant === 'menu') { return ( ); } // Default standalone button (e.g. inline in forms or detail views) return ( ); }; if (typeof window !== 'undefined') window.HistoryVersionsButton = HistoryVersionsButton;