el("p",{class:"mut",style:"margin-top:0;font-size:.85rem"},"Renders the template with sample data via WeasyPrint and stores it as a PDF attachment."), el("label",{},"Template"), sel), { buttons: [{ label:"Convert", kind:"btn", onClick: async (close) => { try { const d = await POST(`/attachments/convert-pdf?template_id=${sel.value}`); toast(`PDF created: ${d.name || d.filename} (${fmtBytes(d.size_bytes||0)})`, "ok"); close(); await load(); } catch (err) { toast("Conversion failed: " + err.message, "err"); } }}] }); }); $("#btnClear").addEventListener("click", () => confirmedAction( "Delete ALL attachments? Files are removed from disk and cannot be recovered.", async () => { const d = await POST("/attachments/clear-all"); toast(`Deleted ${d.deleted} attachments`, "ok"); await load(); })); $("#body").addEventListener("click", (e) => { const b = e.target.closest("button"); if (!b) return; const id = b.dataset.prev || b.dataset.dl || b.dataset.del; if (b.dataset.dl) window.open(`/attachments/${id}/download`, "_blank"); if (b.dataset.prev) { const a = state.data.find(x => x.id == id); if (a.kind === "html") { fetch(`/attachments/${id}/preview`).then(r => r.text()).then(t => { openModal("Preview — " + a.name, el("div",{class:"pv-frame"},el("iframe",{srcdoc:t})), {xw:true}); }); } else if (a.kind === "image") { openModal("Preview — " + a.name, el("div",{style:"text-align:center"}, el("img",{src:`/attachments/${id}/preview`, style:"max-width:100%;border-radius:8px"})), {xw:true}); } else if (a.kind === "text" || a.kind === "pdf") { window.open(`/attachments/${id}/preview`, "_blank"); } else toast("No inline preview for this file type", "info"); } if (b.dataset.del) confirmedAction(`Delete “${state.data.find(x=>x.id==id)?.name || id}”?`, async () => { await POST(`/attachments/${id}/delete`); toast("Deleted","ok"); await load(); }); }); $("#pager").addEventListener("click", (e) => { const b = e.target.closest("button"); if (!b || b.disabled) return; state.page = +b.dataset.pg; load();