/** * Revision Sidebar — slide-in panel listing file revisions * Ball Studios */ import React, { useEffect, useState } from 'react'; import http from '@/api/http'; import DiffViewer from './DiffViewer'; import RestoreModal from './RestoreModal'; interface Revision { id: number; revision_number: number; size_bytes: number; change_summary: string; created_at: string; author: { username: string } | null; } interface Props { serverUuid: string; filePath: string; onClose: () => void; } export default function RevisionSidebar({ serverUuid, filePath, onClose }: Props) { const [revisions, setRevisions] = useState([]); const [loading, setLoading] = useState(true); const [viewing, setViewing] = useState(null); const [restoring, setRestoring] = useState(null); useEffect(() => { http.get(`/api/client/servers/${serverUuid}/addons/files/revisions`, { params: { path: filePath }, }) .then(({ data }) => setRevisions(data.data ?? [])) .finally(() => setLoading(false)); }, [serverUuid, filePath]); return (
e.stopPropagation()}>
🕐 File History — {filePath}
{loading &&
Loading revisions…
} {!loading && revisions.length === 0 && (
No revisions recorded for this file yet.
)}
    {revisions.map(rev => (
  • #{rev.revision_number} {rev.author?.username ?? 'Unknown'} {new Date(rev.created_at).toLocaleString()} {(rev.size_bytes / 1024).toFixed(1)} KB

    {rev.change_summary}

    Download
  • ))}
{viewing && ( setViewing(null)} /> )} {restoring && ( setRestoring(null)} onRestored={() => { setRestoring(null); onClose(); }} /> )}
); }