From aaddd33e3bf9acac7621061dcd70989144292bd5 Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Tue, 3 Feb 2026 03:38:30 +0100 Subject: [PATCH] change popup --- config/current.ver | 2 +- public/assets/js/ui-editor.js | 79 +++++++++++++++++++++++++++++++--- public/assets/js/ui-list.js | 81 +++++++++++++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 10 deletions(-) diff --git a/config/current.ver b/config/current.ver index 725ffd4..d9e75ec 100644 --- a/config/current.ver +++ b/config/current.ver @@ -1 +1 @@ -1.2.27 \ No newline at end of file +1.2.28 \ No newline at end of file diff --git a/public/assets/js/ui-editor.js b/public/assets/js/ui-editor.js index 219d055..d76e79e 100644 --- a/public/assets/js/ui-editor.js +++ b/public/assets/js/ui-editor.js @@ -60,8 +60,65 @@ export function initEditor() { let currentVersionId = 0; let currentVersionMeta = null; -  const ok  = (m) => toast(m, true); -  const err = (m) => toast(m, false); + const ok  = (m) => toast(m, true); + const err = (m) => toast(m, false); + + const showConfirmDialog = (() => { + let dialog; + let titleEl; + let textEl; + let btnOk; + let btnCancel; + let pendingResolve = null; + + const ensure = () => { + if (dialog) return; + dialog = document.createElement('dialog'); + dialog.className = 'rounded-2xl p-0 w-[520px]'; + dialog.innerHTML = ` +
+

+

+
+ + +
+
+ `; + document.body.appendChild(dialog); + titleEl = dialog.querySelector('[data-confirm-title]'); + textEl = dialog.querySelector('[data-confirm-text]'); + btnOk = dialog.querySelector('[data-confirm-ok]'); + btnCancel = dialog.querySelector('[data-confirm-cancel]'); + + btnOk?.addEventListener('click', () => { + if (pendingResolve) pendingResolve(true); + pendingResolve = null; + dialog.close(); + }); + btnCancel?.addEventListener('click', () => { + if (pendingResolve) pendingResolve(false); + pendingResolve = null; + dialog.close(); + }); + dialog.addEventListener('close', () => { + if (pendingResolve) pendingResolve(false); + pendingResolve = null; + }); + }; + + return async ({ title, text, confirmLabel = 'Bestätigen', cancelLabel = 'Abbrechen' }) => { + ensure(); + if (titleEl) titleEl.textContent = title || 'Bestätigung'; + if (textEl) textEl.textContent = text || ''; + if (btnOk) btnOk.textContent = confirmLabel; + if (btnCancel) btnCancel.textContent = cancelLabel; + if (!dialog.open) dialog.showModal(); + return await new Promise(resolve => { + pendingResolve = resolve; + }); + }; + })();   // ---------- Hilfen ---------- function activeMode() { @@ -1107,13 +1164,21 @@ export function initEditor() { if (!current?.id || !isTemplateSection()) return true; const res = await apiAction('templates.references', { method: 'GET', data: { template_id: current.id } }).catch(() => null); if (!res || res.ok === false) { - return confirm(`Referenzen konnten nicht geprüft werden. ${actionLabel} trotzdem?`); + return await showConfirmDialog({ + title: 'Referenzen nicht geprüft', + text: `Referenzen konnten nicht geprüft werden. ${actionLabel} trotzdem?`, + confirmLabel: actionLabel, + }); } const refs = Array.isArray(res?.references) ? res.references : []; if (!refs.length) return true; const preview = refs.slice(0, 6).map(r => `${r.name || 'Template'} #${r.id}`).join(', '); const more = refs.length > 6 ? ` und ${refs.length - 6} weitere` : ''; - return confirm(`Dieses Template wird in ${refs.length} anderen Template(s) verwendet (${preview}${more}). ${actionLabel} trotzdem?`); + return await showConfirmDialog({ + title: 'Template wird verwendet', + text: `Dieses Template wird in ${refs.length} anderen Template(s) verwendet (${preview}${more}). ${actionLabel} trotzdem?`, + confirmLabel: actionLabel, + }); } // Buttons @@ -1146,7 +1211,11 @@ export function initEditor() { if (!okRefs) return; let res = await apiAction('content_versions.deactivate', { method: 'POST', data: { content_id: current.id } }); if (res && res.ok === false && Array.isArray(res.references) && res.references.length) { - const ok = confirm('Dieses Template wird in anderen Templates verwendet. Trotzdem deaktivieren?'); + const ok = await showConfirmDialog({ + title: 'Template wird verwendet', + text: 'Dieses Template wird in anderen Templates verwendet. Trotzdem deaktivieren?', + confirmLabel: 'Deaktivieren', + }); if (!ok) return; res = await apiAction('content_versions.deactivate', { method: 'POST', data: { content_id: current.id, force: 1 } }); } diff --git a/public/assets/js/ui-list.js b/public/assets/js/ui-list.js index 35a1dc7..e4045d7 100644 --- a/public/assets/js/ui-list.js +++ b/public/assets/js/ui-list.js @@ -9,6 +9,63 @@ function esc(s = '') { .replace(/'/g, '''); } +const showConfirmDialog = (() => { + let dialog; + let titleEl; + let textEl; + let btnOk; + let btnCancel; + let pendingResolve = null; + + const ensure = () => { + if (dialog) return; + dialog = document.createElement('dialog'); + dialog.className = 'rounded-2xl p-0 w-[520px]'; + dialog.innerHTML = ` +
+

+

+
+ + +
+
+ `; + document.body.appendChild(dialog); + titleEl = dialog.querySelector('[data-confirm-title]'); + textEl = dialog.querySelector('[data-confirm-text]'); + btnOk = dialog.querySelector('[data-confirm-ok]'); + btnCancel = dialog.querySelector('[data-confirm-cancel]'); + + btnOk?.addEventListener('click', () => { + if (pendingResolve) pendingResolve(true); + pendingResolve = null; + dialog.close(); + }); + btnCancel?.addEventListener('click', () => { + if (pendingResolve) pendingResolve(false); + pendingResolve = null; + dialog.close(); + }); + dialog.addEventListener('close', () => { + if (pendingResolve) pendingResolve(false); + pendingResolve = null; + }); + }; + + return async ({ title, text, confirmLabel = 'Bestätigen', cancelLabel = 'Abbrechen' }) => { + ensure(); + if (titleEl) titleEl.textContent = title || 'Bestätigung'; + if (textEl) textEl.textContent = text || ''; + if (btnOk) btnOk.textContent = confirmLabel; + if (btnCancel) btnCancel.textContent = cancelLabel; + if (!dialog.open) dialog.showModal(); + return await new Promise(resolve => { + pendingResolve = resolve; + }); + }; +})(); + function formatVersionDate(value) { if (!value) return ''; try { @@ -105,12 +162,20 @@ async function openTemplateManager(item, section) { if (!isTemplateSection()) return true; const refs = await fetchTemplateReferences(); if (refs === null) { - return confirm(`Referenzen konnten nicht geprüft werden. ${actionLabel} trotzdem?`); + return await showConfirmDialog({ + title: 'Referenzen nicht geprüft', + text: `Referenzen konnten nicht geprüft werden. ${actionLabel} trotzdem?`, + confirmLabel: actionLabel, + }); } if (!refs.length) return true; const preview = refs.slice(0, 6).map(r => `${r.name || 'Template'} #${r.id}`).join(', '); const more = refs.length > 6 ? ` und ${refs.length - 6} weitere` : ''; - return confirm(`Dieses Template wird in ${refs.length} anderen Template(s) verwendet (${preview}${more}). ${actionLabel} trotzdem?`); + return await showConfirmDialog({ + title: 'Template wird verwendet', + text: `Dieses Template wird in ${refs.length} anderen Template(s) verwendet (${preview}${more}). ${actionLabel} trotzdem?`, + confirmLabel: actionLabel, + }); }; const updateDeleteState = () => { @@ -262,7 +327,11 @@ async function openTemplateManager(item, section) { } let res = await apiAction('content_versions.deactivate', { method: 'POST', data: { content_id: item.id } }); if (res && res.ok === false && Array.isArray(res.references) && res.references.length) { - const ok = confirm('Dieses Template wird in anderen Templates verwendet. Trotzdem deaktivieren?'); + const ok = await showConfirmDialog({ + title: 'Template wird verwendet', + text: 'Dieses Template wird in anderen Templates verwendet. Trotzdem deaktivieren?', + confirmLabel: 'Deaktivieren', + }); if (!ok) return; res = await apiAction('content_versions.deactivate', { method: 'POST', data: { content_id: item.id, force: 1 } }); } @@ -277,7 +346,11 @@ async function openTemplateManager(item, section) { if (!confirm('Version wirklich löschen?')) return; let res = await apiAction('content_versions.delete', { method: 'POST', data: { id: vid, content_id: item.id } }); if (res && res.ok === false && Array.isArray(res.references) && res.references.length) { - const ok = confirm('Dieses Template wird in anderen Templates verwendet. Trotzdem löschen?'); + const ok = await showConfirmDialog({ + title: 'Template wird verwendet', + text: 'Dieses Template wird in anderen Templates verwendet. Trotzdem löschen?', + confirmLabel: 'Löschen', + }); if (!ok) return; res = await apiAction('content_versions.delete', { method: 'POST', data: { id: vid, content_id: item.id, force: 1 } }); }