refactor(Phase 17 follow-up): copyDraftToClipboard nutzt data-pm-id statt JSON.stringify im onclick

Vorher: `onclick="copyDraftToClipboard(this, ${JSON.stringify(...).replace(/"/g, '"')}, ...)"`
— funktional korrekt, aber Pattern-anfaellig (gleiche Klasse wie der
merkliste-bug aus Phase 17). Plus < und > waren nicht escaped.

Nachher: Button traegt nur eine numerische data-pm-id; der Handler
fetched den Draft per API und kopiert den Body. Robuster, weniger
Quote-Escaping, einheitlicher mit dem versionsHtml-Pattern oben in
derselben Datei.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dotty Dotter 2026-05-07 08:01:00 +02:00
parent c06de002ca
commit eeedf85d7e

View File

@ -683,7 +683,7 @@ async function showDraftFromData(d) {
const actionRow = `<div style="display:flex;gap:8px;margin:10px 0 12px;flex-wrap:wrap;"> const actionRow = `<div style="display:flex;gap:8px;margin:10px 0 12px;flex-wrap:wrap;">
${isMailtoTooLong ? '<span style="font-family:var(--font-mono);font-size:10px;opacity:0.6;">PM zu lang für Mail-Link — Clipboard nutzen.</span>' ${isMailtoTooLong ? '<span style="font-family:var(--font-mono);font-size:10px;opacity:0.6;">PM zu lang für Mail-Link — Clipboard nutzen.</span>'
: `<a href="${mailto}" style="font-family:var(--font-mono);font-size:11px;padding:5px 12px;border:1px solid var(--ecg-border);border-radius:3px;background:var(--ecg-card-bg);color:var(--ecg-dark);text-decoration:none;">📧 Per Mail versenden</a>`} : `<a href="${mailto}" style="font-family:var(--font-mono);font-size:11px;padding:5px 12px;border:1px solid var(--ecg-border);border-radius:3px;background:var(--ecg-card-bg);color:var(--ecg-dark);text-decoration:none;">📧 Per Mail versenden</a>`}
<button type="button" onclick="copyDraftToClipboard(this, ${JSON.stringify(d.titel).replace(/"/g, '&quot;')}, ${JSON.stringify(d.body).replace(/"/g, '&quot;')})" style="font-family:var(--font-mono);font-size:11px;padding:5px 12px;border:1px solid var(--ecg-border);border-radius:3px;background:var(--ecg-card-bg);color:var(--ecg-dark);cursor:pointer;">📋 In Zwischenablage kopieren</button> <button type="button" data-pm-id="${d.id}" onclick="copyDraftToClipboard(this)" style="font-family:var(--font-mono);font-size:11px;padding:5px 12px;border:1px solid var(--ecg-border);border-radius:3px;background:var(--ecg-card-bg);color:var(--ecg-dark);cursor:pointer;">📋 In Zwischenablage kopieren</button>
<a href="/api/aktuelle-themen/drafts/pdf/${d.id}" target="_blank" rel="noopener" style="font-family:var(--font-mono);font-size:11px;padding:5px 12px;border:1px solid var(--ecg-border);border-radius:3px;background:var(--ecg-card-bg);color:var(--ecg-dark);text-decoration:none;">📄 PDF</a> <a href="/api/aktuelle-themen/drafts/pdf/${d.id}" target="_blank" rel="noopener" style="font-family:var(--font-mono);font-size:11px;padding:5px 12px;border:1px solid var(--ecg-border);border-radius:3px;background:var(--ecg-card-bg);color:var(--ecg-dark);text-decoration:none;">📄 PDF</a>
</div>`; </div>`;
@ -745,7 +745,19 @@ async function loadVersion(draftId) {
} catch (e) { alert('Fehler: ' + e); } } catch (e) { alert('Fehler: ' + e); }
} }
async function copyDraftToClipboard(btn, titel, body) { async function copyDraftToClipboard(btn) {
// Daten aus dem Modal-State holen — vermeidet HTML-Attribut-Quoting-
// Probleme mit JSON.stringify (siehe ADR 0011 Folge-Erkenntnis).
const draftId = btn.dataset.pmId;
let titel = '', body = '';
try {
const r = await fetch(`/api/aktuelle-themen/drafts/${draftId}`);
if (r.ok) {
const d = await r.json();
titel = d.titel || '';
body = d.body || '';
}
} catch (_) {}
const text = titel + '\n\n' + body; const text = titel + '\n\n' + body;
try { try {
await navigator.clipboard.writeText(text); await navigator.clipboard.writeText(text);