const VersionHistoryPanel = ({ article, historyVersions, versions: versionsProp, onRestore, onClose, versioningMode, isOpen }) => { const [selectedVersion, setSelectedVersion] = React.useState(null); const [showRestoreConfirm, setShowRestoreConfirm] = React.useState(false); const versions = Array.isArray(versionsProp) ? versionsProp : (Array.isArray(historyVersions) ? historyVersions : []); const isHistoryMode = versioningMode === 'history'; const isParallelMode = versioningMode === 'parallel'; React.useEffect(() => { if (versions.length > 0 && !selectedVersion) { setSelectedVersion(versions[0]); } }, [versions.length]); const formatFileSize = (bytes) => { if (!bytes) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i]; }; const getAttachments = (version) => { if (version.attachments_snapshot) { try { return typeof version.attachments_snapshot === 'string' ? JSON.parse(version.attachments_snapshot) : version.attachments_snapshot; } catch (e) { return version.attachments || []; } } return version.attachments || []; }; const handleRestore = async () => { if (!selectedVersion || selectedVersion.is_current) return; try { await onRestore(selectedVersion.id); setShowRestoreConfirm(false); onClose(); } catch (error) { console.error('Restore error:', error); window.otoNotify?.toast('Failed to restore version', 'error'); } }; if (!isOpen) return null; return (
{/* Header with gradient */}

{isParallelMode ? 'Parallel Versions' : 'Version History'}

{isParallelMode ? 'All versions work together' : 'Track changes and restore previous versions'}

{/* Content Area */}
{/* Left Sidebar - Version List */}

{isParallelMode ? 'All Versions' : 'Timeline'}

{versions.length} version{versions.length !== 1 ? 's' : ''}

{versions.length === 0 ? (
📄

No versions found

) : ( versions.map((version, index) => { const isSelected = selectedVersion?.id === version.id || selectedVersion?.version === version.version; const isCurrent = version.is_current || index === 0; return (
setSelectedVersion(version)} className={`px-6 py-4 border-b border-gray-100 cursor-pointer transition-colors ${isSelected ? 'bg-primary/5 border-l-4 border-l-primary' : 'hover:bg-white border-l-4 border-l-transparent' }`} >
Version {version.version} {version.restored_from_version != null && ( Restored from v{version.restored_from_version} )} {isCurrent && ( CURRENT )}
{version.changed_by_name || version.changed_by}
{new Date(version.changed_at || version.modified_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' })}
); }) )}
{/* Right Panel - Version Details */}
{selectedVersion ? ( <>

Version {selectedVersion.version}

{selectedVersion.restored_from_version != null && ( Restored from v{selectedVersion.restored_from_version} )} {selectedVersion.is_current && ( CURRENT )}

{selectedVersion.changed_by_name || selectedVersion.changed_by} • {' '} {new Date(selectedVersion.changed_at || selectedVersion.modified_at).toLocaleString('en-US', { month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' })}

{isHistoryMode && !selectedVersion.is_current && ( )}
{selectedVersion.title}
{selectedVersion.content && (
{selectedVersion.content}
)}
{selectedVersion.category && (
{selectedVersion.category}
)} {selectedVersion.status && (
{selectedVersion.status}
)}
{selectedVersion.tags && selectedVersion.tags.length > 0 && (
{selectedVersion.tags.map((tag, i) => ( {tag} ))}
)} {(() => { const attachments = getAttachments(selectedVersion); if (!attachments || attachments.length === 0) return null; return (
{attachments.map((att, i) => (
📎
{att.original_filename}
{formatFileSize(att.file_size)}
{att.id && selectedVersion.kb_id && ( e.stopPropagation()} > View )}
))}
); })()}
) : (
📄

Select a version

Click on any version in the timeline

)}
{/* Restore Confirmation Modal */} {showRestoreConfirm && selectedVersion && !selectedVersion.is_current && (

Restore Version {selectedVersion.version}?

This will restore the content from Version {selectedVersion.version} and make it the new current version.

What will be restored:

  • • Title: {selectedVersion.title}
  • • Content ({(selectedVersion.content || '').length} characters)
  • • Tags ({(selectedVersion.tags || []).length})
  • {selectedVersion.category &&
  • • Category: {selectedVersion.category}
  • } {(() => { const attachments = getAttachments(selectedVersion); if (attachments.length > 0) { return
  • • Attachments ({attachments.length} file{attachments.length !== 1 ? 's' : ''})
  • ; } })()}
)}
); }; if (typeof window !== 'undefined') window.VersionHistoryPanel = VersionHistoryPanel;