From 5e76717a93b97fac650be002e873b3475ca315fb Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Wed, 21 Jan 2026 00:15:32 +0100 Subject: [PATCH] asdasd --- public/assets/js/ui-editor.js | 95 ++++++++++++++++++++++++++--------- public/index.php | 1 - 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/public/assets/js/ui-editor.js b/public/assets/js/ui-editor.js index 443b4c2..da9d8ff 100644 --- a/public/assets/js/ui-editor.js +++ b/public/assets/js/ui-editor.js @@ -15,7 +15,6 @@ export function initEditor() { const btnClear = document.getElementById('btn-clear-main'); const editorSelect = document.getElementById('editorTypeSelect'); const versionSelect = document.getElementById('versionSelect'); - const btnRestoreVersion = document.getElementById('btn-restore-version'); const craftEditor = initCraftEditor();   const prevDlg      = document.getElementById('previewDialog'); @@ -44,6 +43,9 @@ export function initEditor() { let versionItems = []; let savedSnapshot = ''; let lastVersionSelection = ''; + let isDirty = false; + let dirtyCleanup = null; + let dialogCancelBound = false;   const ok  = (m) => toast(m, true);   const err = (m) => toast(m, false); @@ -88,7 +90,7 @@ export function initEditor() { function setVersionUiVisible(show) { if (versionSelect) versionSelect.classList.toggle('hidden', !show); - if (btnRestoreVersion) btnRestoreVersion.classList.toggle('hidden', !show); + // restore button removed } setVersionUiVisible(false); @@ -117,6 +119,38 @@ export function initEditor() { }; } + function markDirty() { + isDirty = true; + } + + function clearDirty() { + isDirty = false; + } + + function attachGjsDirtyTracker(editor) { + if (!editor || typeof editor.on !== 'function') return () => {}; + const onUpdate = () => markDirty(); + editor.on('update', onUpdate); + editor.on('component:update', onUpdate); + return () => { + try { + editor.off('update', onUpdate); + editor.off('component:update', onUpdate); + } catch {} + }; + } + + function attachCraftDirtyTracker() { + const host = document.getElementById('craftEditor'); + if (!host) return () => {}; + const handler = () => markDirty(); + const events = ['input', 'keydown', 'paste', 'drop']; + events.forEach(evt => host.addEventListener(evt, handler, true)); + return () => { + events.forEach(evt => host.removeEventListener(evt, handler, true)); + }; + } + async function buildCurrentSnapshot() { if (currentEditorType === 'craftjs') { return buildSnapshot({ @@ -150,9 +184,11 @@ export function initEditor() { function setSavedSnapshotFromData(payload) { const fields = extractContentFields(payload); savedSnapshot = buildSnapshot(fields); + clearDirty(); } async function hasUnsavedChanges() { + if (isDirty) return true; if (!savedSnapshot) return false; const currentSnapshot = await buildCurrentSnapshot(); return currentSnapshot !== savedSnapshot; @@ -245,6 +281,8 @@ export function initEditor() { if (targetType === 'craftjs') { craftEditor?.setContent(data.html || '', data.craftJson || ''); setSavedSnapshotFromData(payload); + if (dirtyCleanup) dirtyCleanup(); + dirtyCleanup = attachCraftDirtyTracker(); return; } const editor = await waitForEditor(3000); @@ -254,12 +292,16 @@ export function initEditor() { const project = JSON.parse(jsonRaw); editor.loadProjectData(project); setSavedSnapshotFromData(payload); + if (dirtyCleanup) dirtyCleanup(); + dirtyCleanup = attachGjsDirtyTracker(editor); return; } catch {} } const html = normalizeSnapshotValue(data.html); editor.setComponents(html); setSavedSnapshotFromData(payload); + if (dirtyCleanup) dirtyCleanup(); + dirtyCleanup = attachGjsDirtyTracker(editor); } async function loadLatestContentFromServer() { @@ -553,6 +595,8 @@ export function initEditor() { if (editorType === 'craftjs') { const craftHtml = extractCraftHtml(craftJson, fresh); craftEditor?.setContent(craftHtml, craftJson); + if (dirtyCleanup) dirtyCleanup(); + dirtyCleanup = attachCraftDirtyTracker(); hideVeil(); if (dlg && typeof dlg.showModal === 'function') dlg.showModal(); if (!looksCraftSerialized(craftJson) && craftEditor?.serializeFromHtml) { @@ -633,10 +677,24 @@ export function initEditor() { };     // Jetzt den Editor-Core laden (erst NACH about:blank) -    iframe.src = `editor/editor-core.php?mode=${encodeURIComponent(current.section.slug)}&id=${current.id}§ion_id=${current.section.id}&t=${Date.now()}`; + iframe.src = `editor/editor-core.php?mode=${encodeURIComponent(current.section.slug)}&id=${current.id}§ion_id=${current.section.id}&t=${Date.now()}`; -    dlg?.showModal?.(); -  } + dlg?.showModal?.(); + if (dlg && !dialogCancelBound) { + dlg.addEventListener('cancel', async (ev) => { + ev.preventDefault(); + await close(); + }); + dialogCancelBound = true; + } + + waitForEditor(6000) + .then((ed) => { + if (dirtyCleanup) dirtyCleanup(); + dirtyCleanup = attachGjsDirtyTracker(ed); + }) + .catch(() => {}); + } // ---------- Speichern (DELEGIERT) ---------- // 🚨 KORRIGIERT: Delegiert Speichern an den iFrame, der die JSON-Daten holt! @@ -740,6 +798,8 @@ export function initEditor() { async function close() { const decision = await confirmUnsavedChanges(); if (decision === 'cancel') return; + if (dirtyCleanup) dirtyCleanup(); + dirtyCleanup = null; // nächstes Öffnen invalidiert laufende asyncs reqToken++; @@ -754,9 +814,10 @@ export function initEditor() {     iframe.src = 'about:blank#' + Date.now();     // Kontext leeren -    current = null; -    window.__currentItemId = undefined; -    window.__currentEditorCtx = undefined; + current = null; + window.__currentItemId = undefined; + window.__currentEditorCtx = undefined; + clearDirty(); } async function switchEditor(nextType) { @@ -841,23 +902,7 @@ export function initEditor() { versionSelect.value = previousSelection; } }); - btnRestoreVersion && (btnRestoreVersion.onclick = async () => { - if (!current?.id) return; - const versionId = Number(versionSelect?.value || 0); - if (!versionId) { - err('Bitte eine Version auswählen'); - return; - } - if (!confirm('Version wiederherstellen? Der aktuelle Stand wird überschrieben.')) return; - try { - const res = await apiAction('content_versions.restore', { method: 'POST', data: { id: versionId, content_id: current.id } }); - if (!res?.ok) throw new Error(res?.error || 'Wiederherstellen fehlgeschlagen'); - ok('Version wiederhergestellt'); - await open({ id: current.id, name: current.name, section: current.section }, null, current.section); - } catch (e) { - err(e.message || 'Wiederherstellen fehlgeschlagen'); - } - }); + // restore button removed window.AdminTestSend = window.AdminTestSend || {}; window.AdminTestSend.open = (opts = {}) => { diff --git a/public/index.php b/public/index.php index b3ca15b..83cb2d0 100644 --- a/public/index.php +++ b/public/index.php @@ -62,7 +62,6 @@ require __DIR__ . '/../partials/structure/layout_start.php'; -