// Revisions dropdown for a page: lists page_revisions; clicking one opens a modal // with the rendered old content + a Restore action (PATCH body_md). import { el } from '../dom.js'; import { api } from '../api.js'; import { marked } from '../vendor/marked.esm.js'; import DOMPurify from '../vendor/purify.es.mjs'; export function revisionsMenu(pageId, onRestore) { const wrap = el('div', { class: 'exp-menu' }); const list = el('div', { class: 'exp-list rev-list' }); const btn = el('button', { class: 'ghost', onclick: async (e) => { e.stopPropagation(); if (wrap.classList.toggle('open')) await load(); } }, 'Revisions ▾'); async function load() { list.replaceChildren(el('div', { class: 'muted', style: { padding: '7px 10px' } }, 'Loading…')); let revs = []; try { revs = await api.get('/api/pages/' + pageId + '/revisions'); } catch { /* */ } list.replaceChildren(); if (!revs.length) { list.appendChild(el('div', { class: 'muted', style: { padding: '7px 10px' } }, 'No earlier revisions.')); return; } revs.forEach(r => list.appendChild(el('button', { onclick: () => view(r) }, new Date(r.created_at).toLocaleString() + (r.edited_by ? ` · ${r.edited_by}` : '')))); } function view(rev) { wrap.classList.remove('open'); const body = el('div', { class: 'md-preview' }); body.innerHTML = DOMPurify.sanitize(marked.parse(rev.body_md || '')); const modal = el('div', { class: 'rev-overlay', onclick: (e) => { if (e.target === modal) modal.remove(); } }, el('div', { class: 'rev-modal' }, el('div', { class: 'rev-modal-head' }, el('span', {}, 'Revision · ' + new Date(rev.created_at).toLocaleString()), el('button', { class: 'ghost', onclick: () => modal.remove() }, 'Close')), body, el('div', { class: 'rev-modal-foot' }, el('button', { class: 'primary', onclick: async () => { try { await api.patch('/api/pages/' + pageId, { body_md: rev.body_md }); if (onRestore) onRestore(rev.body_md); modal.remove(); } catch (e) { alert('Restore failed: ' + e.message); } } }, 'Restore this version')))); document.body.appendChild(modal); } wrap.append(btn, list); document.addEventListener('click', () => wrap.classList.remove('open')); return wrap; }