mail send

This commit is contained in:
2025-12-07 01:40:21 +01:00
parent 98298e2b23
commit cb9deabe91
4 changed files with 208 additions and 7 deletions

View File

@@ -18,6 +18,7 @@ export function initEditor() {
  const sendForm     = document.getElementById('sendTestForm');
  const sendTo       = document.getElementById('send_to');
  const sendSubject  = document.getElementById('send_subject');
  const sendInfo     = document.getElementById('send_template_info');
  const btnCancelSend= document.getElementById('btn-cancel-send');
  const btnSendNow   = document.getElementById('btn-send-now');
  const prevFrame    = document.getElementById('previewFrame');
@@ -36,6 +37,27 @@ export function initEditor() {
    return (b?.dataset?.tab) || (current?.resource) || 'templates';
  }
  function setSendContext(id, name = '') {
    if (sendDlg) {
      if (id) {
        sendDlg.dataset.templateId = String(id);
      } else {
        delete sendDlg.dataset.templateId;
      }
      if (name) sendDlg.dataset.templateName = name;
    }
    if (sendInfo) {
      if (!id) {
        sendInfo.textContent = 'Kein Template ausgewählt.';
        sendInfo.classList.add('text-rose-600');
      } else {
        const label = name ? `${name} Template #${id}` : `Template #${id}`;
        sendInfo.textContent = label;
        sendInfo.classList.remove('text-rose-600');
      }
    }
  }
  function writeHtmlToFrame(html) {
    iframe.srcdoc = `<!doctype html><html>
      <head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>
@@ -246,6 +268,8 @@ export function initEditor() {
    // globaler Kontext
    window.__currentItemId    = current.id;
    window.__currentEditorCtx = { id: current.id, mode: current.resource };
    setSendContext(current.id, current.name);
    if (btnTest) btnTest.classList.toggle('hidden', current.resource !== 'templates');
    // Neuen Token erzeugen & alten Listener entfernen
    reqToken++;
@@ -388,24 +412,32 @@ export function initEditor() {
    prevDlg?.showModal?.();
  }
  
  async function openSend() {
    sendSubject.value = 'Testversand';
    sendTo.value = '';
  async function openSend(ctx = null) {
    const ctxId = ctx?.id ? Number(ctx.id) : (window.__currentItemId || current?.id || 0);
    if (!ctxId) {
      err('Kein Template geladen');
      return;
    }
    window.__currentItemId = ctxId;
    const ctxName = ctx?.name ?? sendDlg?.dataset?.templateName ?? current?.name ?? '';
    setSendContext(ctxId, ctxName);
    if (sendSubject) sendSubject.value = ctx?.subject || 'Testversand';
    if (sendTo) sendTo.value = ctx?.to || '';
    sendDlg?.showModal?.();
  }
  function closeSend(){ sendDlg?.close?.(); }
  async function doSend(ev){
    ev?.preventDefault?.();
    const to = sendTo.value.trim();
    if(!to){ toast("Bitte Empfänger angeben", false); return; }
    const to = (sendTo?.value || '').trim();
    if(!to){ err('Bitte Empfänger angeben'); return; }
    const win = iframe?.contentWindow;
    const ctx = (win && win.__currentEditorCtx) || {};
    const id  = (window.__currentItemId || ctx?.id || 0);
    if(!id){ toast("Kein Template geladen", false); return; }
    // Hier wird der gespeicherte HTML-Code verwendet, nicht der Live-HTML, da apiAction
    // keine Live-Daten erwartet. Es geht um template_id.
    const r = await apiAction('templates.test_send', { method:'POST', data:{ template_id: id, to, subject: sendSubject.value || 'Testversand' } });
    const r = await apiAction('templates.test_send', { method:'POST', data:{ template_id: id, to, subject: (sendSubject?.value || 'Testversand') } });
    if(r?.ok){ toast("Testversand ausgelöst"); closeSend(); } else { toast("Senden fehlgeschlagen", false); }
  }
  function closePreview(){ prevDlg?.close?.(); }
@@ -440,6 +472,18 @@ export function initEditor() {
  btnCancelSend&& (btnCancelSend.onclick= closeSend);
  sendForm     && (sendForm.onsubmit    = doSend);
  window.AdminTestSend = window.AdminTestSend || {};
  window.AdminTestSend.open = (opts = {}) => {
    const targetId = Number(opts.id || window.__currentItemId || 0);
    if (!targetId) {
      err('Testversand: Keine ID vorhanden');
      return;
    }
    window.__currentItemId = targetId;
    setSendContext(targetId, opts.name || '');
    openSend({ id: targetId, name: opts.name || '' });
  };
  // Public API
  window.EditorUI = { open, save, close, clear: clearEditor, preview: openPreview };
}

View File

@@ -97,6 +97,9 @@ export async function loadList(resource){
const editBtn = (resource==='snippets')
? `<button class='btn' data-edit='snippets:${item.id}'>Bearbeiten</button>` : '';
const testBtn = resource==='templates'
? `<button class='btn' data-test='${item.id}' data-name='${name}'>Testversand</button>` : '';
const prevBtn = `<button class='btn' data-preview='${resource}:${item.id}'>Vorschau</button>`;
const delBtn = `<button class='btn btn-danger' data-del='${resource}:${item.id}' data-name='${name}'>Löschen</button>`;
@@ -104,7 +107,7 @@ export async function loadList(resource){
<div class='min-w-48 font-medium truncate' title="${name}">${name || '(ohne Name)'}</div>
<div class='text-xs text-gray-500'>#${item.id}</div>
<div class='text-xs'>${parentBadge(resource,item)}</div>
<div class='ms-auto flex gap-2'>${[openBtn, editBtn, prevBtn, delBtn].filter(Boolean).join('')}</div>
<div class='ms-auto flex gap-2'>${[openBtn, editBtn, testBtn, prevBtn, delBtn].filter(Boolean).join('')}</div>
</div>`;
}).join('');
@@ -149,6 +152,21 @@ export async function loadList(resource){
prevDlg.showModal();
}));
// test send (templates only)
list.querySelectorAll('[data-test]').forEach(b=>b.addEventListener('click', ()=>{
const id = Number(b.dataset.test || '0');
const nm = b.dataset.name || '';
if (!id) {
toast('Testversand: Ungültige ID', false);
return;
}
if (window.AdminTestSend && typeof window.AdminTestSend.open === 'function') {
window.AdminTestSend.open({ id, name: nm });
} else {
toast('Testversand ist aktuell nicht verfügbar.', false);
}
}));
// delete
const delDlg=document.getElementById('deleteDialog'),
delText=document.getElementById('deleteText'),

View File

@@ -91,6 +91,8 @@ $assetVersion = defined('ASSET_VERSION') ? ASSET_VERSION : time();
<div class="px-4 py-2 border-b flex items-center gap-2 bg-white/80 backdrop-blur">
<strong class="me-auto">E-Mail Editor</strong>
<button id="btn-clear-main" type="button" class="btn" title="Leeren">🧹</button>
<button id="btn-preview" type="button" class="btn">Vorschau</button>
<button id="btn-test" type="button" class="btn">Testversand</button>
<button id="btn-save" type="button" class="btn">Speichern</button>
<button id="btn-close" type="button" class="btn">Schließen</button>
</div>
@@ -109,6 +111,26 @@ $assetVersion = defined('ASSET_VERSION') ? ASSET_VERSION : time();
</div>
</dialog>
<!-- Test Send Dialog -->
<dialog id="sendTestDialog" class="rounded-2xl p-0 w-[480px]">
<form id="sendTestForm" method="dialog" class="p-4 bg-white rounded-2xl space-y-4">
<h3 class="text-lg font-semibold">Testversand</h3>
<p id="send_template_info" class="text-sm text-slate-600">Kein Template ausgewählt.</p>
<label class="block">
<span class="text-sm text-slate-600">Empfänger (E-Mail)</span>
<input id="send_to" type="email" required class="mt-1 w-full border rounded-lg px-3 py-2" placeholder="name@example.com" />
</label>
<label class="block">
<span class="text-sm text-slate-600">Betreff</span>
<input id="send_subject" type="text" class="mt-1 w-full border rounded-lg px-3 py-2" value="Testversand" />
</label>
<div class="flex justify-end gap-2">
<button type="button" id="btn-cancel-send" class="btn">Abbrechen</button>
<button type="submit" id="btn-send-now" class="btn">Senden</button>
</div>
</form>
</dialog>
<!-- Edit Snippet Dialog -->
<dialog id="editSnippetDialog" class="rounded-2xl p-0 w-[700px]">
<form id="editSnippetForm" method="dialog" class="p-4 bg-white rounded-2xl">