diff --git a/backend/src/tools/snippets/routes.js b/backend/src/tools/snippets/routes.js index 7e5b5f5..8897a4c 100644 --- a/backend/src/tools/snippets/routes.js +++ b/backend/src/tools/snippets/routes.js @@ -98,6 +98,13 @@ router.put('/:id', authenticate, (req, res) => { }); // ── Löschen ────────────────────────────────────────────────────────────────── +router.delete('/:id/history/:hid', authenticate, (req, res) => { + const s = db.prepare('SELECT * FROM snippets WHERE id=? AND user_id=?').get(req.params.id, uid(req)); + if (!s) return res.status(403).json({ error: 'Kein Zugriff' }); + db.prepare('DELETE FROM snippet_history WHERE id=? AND snippet_id=?').run(req.params.hid, s.id); + res.json({ ok: true }); +}); + router.delete('/:id', authenticate, (req, res) => { const r = db.prepare('DELETE FROM snippets WHERE id=? AND user_id=?').run(req.params.id, uid(req)); if (!r.changes) return res.status(404).json({ error: 'Nicht gefunden' }); diff --git a/frontend/src/tools/codeschnipsel.jsx b/frontend/src/tools/codeschnipsel.jsx index 94f5a73..99c7801 100644 --- a/frontend/src/tools/codeschnipsel.jsx +++ b/frontend/src/tools/codeschnipsel.jsx @@ -140,66 +140,124 @@ function DiffView({ oldCode, newCode }) { } function HistoryModal({ snippet, onClose, onRestore, toast }) { const [history, setHistory] = useState([]); - const [selected, setSelected] = useState(null); + const [selectedIdx, setSelectedIdx] = useState(0); // 0 = Aktuell (current) const [showDiff, setShowDiff] = useState(true); - useEffect(()=>{ - api(`/tools/snippets/${snippet.id}/history`).then(h=>{ setHistory(h); if(h.length) setSelected(h[0]); }).catch(()=>{}); - },[]); const isMob = window.innerWidth < 768; - const getOlderCode = (h) => { - const idx = history.indexOf(h); - // Newest history entry (idx=0) compares against CURRENT snippet code - if (idx === 0) return snippet.code; - // Older entries compare against the next newer history entry - return history[idx - 1].code; + + const load = () => api(`/tools/snippets/${snippet.id}/history`).then(setHistory).catch(()=>{}); + useEffect(()=>{ load(); },[]); + + // Entries: [current, ...history] where index 0 = current + // entries[i].code, entries[i].label + const entries = [ + { id:'current', code: snippet.code, language: snippet.language, + saved_at: snippet.updated_at, label:'Aktuell', isCurrent: true }, + ...history.map((h,i) => ({ ...h, label:`v${history.length - i}`, isCurrent: false })), + ]; + + const selected = entries[selectedIdx]; + // Diff: what changed FROM previous version TO selected (selected is newer) + const prevEntry = entries[selectedIdx + 1]; // one step older + const oldCode = prevEntry?.code ?? null; // null = älteste, kein Diff + + const delHistory = async (hid) => { + try { + await api(`/tools/snippets/${snippet.id}/history/${hid}`, { method:'DELETE' }); + await load(); + // If deleted entry was selected, jump to current + setSelectedIdx(0); + toast('Version gelöscht'); + } catch(e) { toast(e.message,'error'); } }; + return (