From 3f3223f17c445ff31ec9ba2cc3e90550d5b76773 Mon Sep 17 00:00:00 2001 From: smueller Date: Fri, 3 Jul 2026 13:48:51 +0200 Subject: [PATCH] Implement newsletter preview copy functionality and UI enhancements - Add a new preview banner to indicate the live newsletter display. - Introduce `copyFromPreviewFrame` function to enable copying the newsletter preview directly. - Update copy status messages for clarity and improved user guidance. - Revise button labels in the dashboard for better usability. - Modify CSS for the newsletter preview frame and add styles for the new preview banner. --- app/static/css/main.css | 18 ++++++++++-- app/static/js/newsletter.js | 56 ++++++++++++++++++++++++++++-------- app/templates/base.html | 2 +- app/templates/dashboard.html | 17 +++++------ 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/app/static/css/main.css b/app/static/css/main.css index 167fda0..a2715a1 100644 --- a/app/static/css/main.css +++ b/app/static/css/main.css @@ -487,13 +487,27 @@ tbody tr:hover { background: #FAFAFA; } .copy-status.success { color: var(--tk-success); } .copy-status.error { color: var(--tk-error); } +.preview-banner { + margin-top: 0.5rem; + padding: 0.5rem 0.85rem; + background: var(--tk-orange-light); + border: 1px solid #F5D5BC; + border-bottom: none; + border-radius: var(--radius) var(--radius) 0 0; + font-size: 0.82rem; + font-weight: 600; + color: var(--tk-orange-dark); + text-align: center; +} + .newsletter-preview-frame { width: 100%; min-height: 640px; border: 1px solid var(--tk-border); - border-radius: var(--radius); - background: var(--tk-gray-light); + border-radius: 0 0 var(--radius) var(--radius); + background: #FFFFFF; box-shadow: var(--shadow-md); + display: block; } .textarea-actions { diff --git a/app/static/js/newsletter.js b/app/static/js/newsletter.js index 0a1a8ab..c7eea86 100644 --- a/app/static/js/newsletter.js +++ b/app/static/js/newsletter.js @@ -181,6 +181,39 @@ function showCopyDialog(text, title) { document.addEventListener("keydown", copyDialogKeyHandler); } +function copyFromPreviewFrame() { + const frame = document.getElementById("newsletter-preview-frame"); + const doc = frame?.contentDocument; + const win = frame?.contentWindow; + if (!doc?.body || !win || !doc.body.innerHTML.trim()) { + return false; + } + + const range = doc.createRange(); + range.selectNodeContents(doc.body); + const selection = win.getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + + let ok = false; + try { + ok = doc.execCommand("copy"); + } catch (err) { + console.warn("Copy from preview frame failed.", err); + } finally { + selection.removeAllRanges(); + } + return ok; +} + +function loadPreviewFrame() { + const frame = document.getElementById("newsletter-preview-frame"); + const html = getNewsletterOutlookHtml(); + if (frame && html) { + frame.srcdoc = html; + } +} + function copyViaIframe(html) { const iframe = document.createElement("iframe"); iframe.setAttribute("aria-hidden", "true"); @@ -247,8 +280,13 @@ async function copyForOutlook() { return; } - if (copyHtmlWithFallback(html)) { - setCopyStatus("Newsletter kopiert. In Outlook: Strg+V, dann ggf. Rechtsklick → „Format beibehalten“."); + if (copyFromPreviewFrame()) { + setCopyStatus("Vorschau kopiert – in Outlook mit Strg+V einfügen (Rechtsklick → „Format beibehalten“)."); + return; + } + + if (copyViaIframe(html)) { + setCopyStatus("Newsletter kopiert – in Outlook mit Strg+V einfügen (Rechtsklick → „Format beibehalten“)."); return; } @@ -261,14 +299,14 @@ async function copyForOutlook() { "text/plain": new Blob([plain], { type: "text/plain" }), }), ]); - setCopyStatus("Newsletter kopiert. In Outlook: Strg+V, dann ggf. Rechtsklick → „Format beibehalten“."); + setCopyStatus("Newsletter kopiert – in Outlook mit Strg+V einfügen."); return; } catch (err) { console.warn("Clipboard API HTML copy failed.", err); } } - setCopyStatus("Bitte „Im Browser öffnen“ nutzen und dort Strg+A → Strg+C.", true); + setCopyStatus("Kopieren fehlgeschlagen. Bitte „Im Browser öffnen“ nutzen.", true); } function copyHtmlSource() { @@ -332,17 +370,11 @@ function openOutlookInBrowser() { popup.document.write(html); popup.document.close(); popup.document.title = "Wiki-Newsletter – zum Kopieren"; - setCopyStatus("Newsletter im Browser geöffnet: Strg+A → Strg+C, dann in Outlook einfügen."); + setCopyStatus("Im neuen Tab: Alles markieren (Strg+A) → kopieren (Strg+C) → in Outlook einfügen."); } document.addEventListener("DOMContentLoaded", () => { - const outlookSource = document.getElementById("newsletter-outlook-source"); - const htmlSource = document.getElementById("newsletter-html-source"); - const frame = document.getElementById("newsletter-preview-frame"); - const previewHtml = outlookSource?.value.trim() || htmlSource?.value.trim() || ""; - if (frame && previewHtml) { - frame.srcdoc = previewHtml; - } + loadPreviewFrame(); const htmlDisplay = document.getElementById("newsletter-html-display"); htmlDisplay?.addEventListener("focus", () => selectTextarea(htmlDisplay)); diff --git a/app/templates/base.html b/app/templates/base.html index 1cad5c6..7e310f8 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -4,7 +4,7 @@ {% block title %}{{ title if title else "Wiki Newsletter Admin" }}{% endblock %} · Thomas-Krenn.AG - +
diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index b20d3d2..18f0b65 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -79,14 +79,15 @@

Formatierten Newsletter ansehen und für Outlook kopieren.

-

Empfohlen: „Im Browser öffnen“ → Strg+A, Strg+C → in Outlook Strg+V.

+

Die Vorschau unten zeigt exakt, wie der Newsletter aussieht. „Vorschau kopieren“ übernimmt dieses Layout 1:1 in die Zwischenablage.

- - + +
+
Live-Vorschau – so wird der Newsletter dargestellt
@@ -276,10 +277,10 @@ {% if user.role == "admin" %} @@ -297,5 +298,5 @@ {% endblock %} {% block scripts %} - + {% endblock %}