src/components/VersionHistory.jsx (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import { useCallback, useEffect, useState } from 'react';
import {
fetchDocumentVersions,
friendlyErrorMessage,
restoreDocumentVersion,
} from '../lib/api.js';
import { STR, formatVersionDate } from '../lib/strings.js';
export default function VersionHistory({
editToken,
clientId,
lockToken,
onRestored,
}) {
const [open, setOpen] = useState(false);
const [versions, setVersions] = useState([]);
const [loading, setLoading] = useState(false);
const [restoringId, setRestoringId] = useState('');
const [error, setError] = useState('');
const loadVersions = useCallback(async () => {
setLoading(true);
setError('');
try {
const data = await fetchDocumentVersions(editToken, { clientId, lockToken });
setVersions(data.versions ?? []);
} catch (err) {
setError(friendlyErrorMessage(err));
} finally {
setLoading(false);
}
}, [editToken, clientId, lockToken]);
useEffect(() => {
if (!open) return;
loadVersions();
}, [open, loadVersions]);
const handleRestore = async (versionId) => {
const confirmed = window.confirm(STR.VERSION_RESTORE_CONFIRM);
if (!confirmed) return;
setRestoringId(versionId);
setError('');
try {
const data = await restoreDocumentVersion(editToken, versionId, {
clientId,
lockToken,
});
onRestored(data);
await loadVersions();
} catch (err) {
setError(friendlyErrorMessage(err));
} finally {
setRestoringId('');
}
};
return (
<>
<button
type="button"
className="btn btn-ghost"
onClick={() => setOpen(true)}
>
{STR.VERSION_HISTORY}
</button>
{open && (
<div className="modal-backdrop" role="presentation" onClick={() => setOpen(false)}>
<div
className="modal share-panel version-panel"
role="dialog"
aria-labelledby="version-history-title"
aria-modal="true"
onClick={(e) => e.stopPropagation()}
>
<h2 id="version-history-title" className="modal__title">
{STR.VERSION_HISTORY}
</h2>
{loading && <p className="version-panel__status">{STR.VERSION_LOADING}</p>}
{!loading && versions.length === 0 && (
<p className="version-panel__status">{STR.VERSION_EMPTY}</p>
)}
{!loading && versions.length > 0 && (
<ul className="version-list">
{versions.map((version) => (
<li key={version.id} className="version-list__item">
<span className="version-list__date">
{formatVersionDate(version.createdAt)}
</span>
<button
type="button"
className="btn btn-ghost version-list__restore"
disabled={restoringId === version.id}
onClick={() => handleRestore(version.id)}
>
{restoringId === version.id
? STR.VERSION_RESTORING
: STR.VERSION_RESTORE}
</button>
</li>
))}
</ul>
)}
{error && (
<p className="share-error" role="alert">
{error}
</p>
)}
<div className="modal__actions">
<button type="button" className="btn" onClick={() => setOpen(false)}>
{STR.CLOSE}
</button>
</div>
</div>
</div>
)}
</>
);
}
|