\n
The Golf DraftEmail Builder
Checking sign in…
Draft League Results Profile Rules Admin Hub Detailed Admin

Email Builder

Build, save, preview and send polished Golf Draft emails.

Back to AdminAutomationResults Email

Campaign


Newsletter images

Choose an image

Uploads are resized/compressed server-side into the newsletter folder. PNG transparency is preserved.

HTML Preview

`;}function refreshPreview(){$("preview").srcdoc=$("htmlInput").value||"";}function updateMode(){const m=$("mode").value;["testBox","leagueBox","userBox","manualBox"].forEach(id=>$(id).classList.remove("show"));if(m==="test")$("testBox").classList.add("show");if(m==="league")$("leagueBox").classList.add("show");if(m==="single")$("userBox").classList.add("show");if(m==="manual")$("manualBox").classList.add("show");}async function loadImages(){const d=await api("/api/email-builder/images");const sel=$("imagePicker");sel.innerHTML="";(d.images||[]).forEach(img=>{const o=document.createElement("option");o.value=img.absolute_url||img.url;o.textContent=img.filename;sel.appendChild(o);});if(!sel.options.length)sel.innerHTML='';updateImagePreview();}function selectedImage(){return $("imagePicker").value;}function updateImagePreview(){const u=selectedImage();$("imagePreview").innerHTML=u?``:"Choose an image";}async function uploadImage(){const file=$("uploadFile").files[0];if(!file){showStatus("Choose an image first.",true);return;}const done=busy($("uploadBtn"),"Uploading…");try{const fd=new FormData();fd.append("image",file);fd.append("filename",$("uploadName").value||file.name);const d=await api("/api/email-builder-direct-upload",{method:"POST",body:fd});showStatus("Uploaded "+d.filename);$("uploadFile").value="";$("uploadName").value="";await loadImages();[...$("imagePicker").options].forEach((o,i)=>{if(o.value===(d.absolute_url||d.url))$("imagePicker").selectedIndex=i;});updateImagePreview();}catch(e){showStatus(e.message,true);}finally{done();}}async function loadLeagues(){const d=await api("/api/email-builder/leagues");const sel=$("leagueSelect");sel.innerHTML="";(d.leagues||[]).forEach(l=>{const o=document.createElement("option");o.value=l.code;o.textContent=`${l.name||"League"} (${l.code}) - ${l.member_count||0} users`;sel.appendChild(o);});if(!sel.options.length)sel.innerHTML='';}async function loadUsers(){const d=await api("/api/email-builder/users");const sel=$("userSelect");sel.innerHTML="";(d.users||[]).forEach(u=>{const o=document.createElement("option");o.value=u.email;o.textContent=`${u.display_name||u.email} - ${u.email}`;sel.appendChild(o);});if(!sel.options.length)sel.innerHTML='';}async function loadTemplateStore(){const d=await api("/api/email-builder-v3/templates");templates=d.templates||{};lastCampaign=d.last_campaign||null;const sel=$("savedTemplates");sel.innerHTML="";Object.keys(templates).sort().forEach(name=>{const o=document.createElement("option");o.value=name;o.textContent=name;sel.appendChild(o);});if(!sel.options.length)sel.innerHTML='';}async function saveTemplate(){const done=busy($("saveTemplateBtn"),"Saving…");try{const d=await api("/api/email-builder-v3/templates",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:$("templateName").value,subject:$("subject").value,html:$("htmlInput").value})});showStatus("Template saved.");await loadTemplateStore();$("savedTemplates").value=d.template.name;}catch(e){showStatus(e.message,true);}finally{done();}}function loadTemplateItem(item){if(!item||!item.html){showStatus("No template selected.",true);return;}$("subject").value=item.subject||"The Golf Draft";$("htmlInput").value=item.html;refreshPreview();showStatus("Template loaded.");}async function sendEmail(){const done=busy($("sendBtn"),"Sending…");try{const mode=$("mode").value;if(mode!=="test"&&!confirm("Send this campaign using the selected recipient mode?"))return;const d=await api("/api/email-builder-v3/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({subject:$("subject").value,html:$("htmlInput").value,mode,test_to:$("testEmail").value,user_email:$("userSelect").value,league_code:$("leagueSelect").value,manual:$("manualEmails").value})});showStatus(`Sent: ${d.sent_count||0}. Failed: ${(d.failed||[]).length}.`);await loadTemplateStore();}catch(e){showStatus(e.message,true);}finally{done();}}document.addEventListener("DOMContentLoaded",async()=>{$("htmlInput").value=fancyTemplate();refreshPreview();updateMode();$("mode").addEventListener("change",updateMode);$("imagePicker").addEventListener("change",updateImagePreview);$("setHeroBtn").addEventListener("click",()=>{const u=selectedImage();if(!u)return;HERO=u;$("htmlInput").value=fancyTemplate();refreshPreview();showStatus("Hero image updated.");});$("setSecondBtn").addEventListener("click",()=>{const u=selectedImage();if(!u)return;SECOND=u;$("htmlInput").value=fancyTemplate();refreshPreview();showStatus("Second image updated.");});$("insertImageBtn").addEventListener("click",()=>{const u=selectedImage();if(!u)return;const snip=`\n
The Golf Draft
\n`;const ta=$("htmlInput");const s=ta.selectionStart||ta.value.length;ta.value=ta.value.slice(0,s)+snip+ta.value.slice(s);refreshPreview();});$("uploadBtn").addEventListener("click",uploadImage);$("loadTemplateBtn").addEventListener("click",()=>{$("htmlInput").value=fancyTemplate();refreshPreview();showStatus("Fancy launch email loaded.");});$("refreshBtn").addEventListener("click",refreshPreview);$("htmlInput").addEventListener("input",refreshPreview);$("saveTemplateBtn").addEventListener("click",saveTemplate);$("loadSavedBtn").addEventListener("click",()=>loadTemplateItem(templates[$("savedTemplates").value]));$("loadLastBtn").addEventListener("click",()=>loadTemplateItem(lastCampaign));$("sendBtn").addEventListener("click",sendEmail);try{await Promise.all([loadImages(),loadLeagues(),loadUsers(),loadTemplateStore()]);}catch(e){showStatus(e.message,true);}}); /* TGDF delete newsletter image */ async function tgdfDeleteSelectedImage(){ const sel = document.getElementById('imagePicker'); if(!sel || !sel.value){ if(typeof showStatus === 'function') showStatus('Choose an image to delete first.', true); else alert('Choose an image to delete first.'); return; } const label = sel.options[sel.selectedIndex]?.textContent || sel.value; if(!confirm('Delete this newsletter image?\n\n' + label)) return; const btn = document.getElementById('deleteImageBtn'); const old = btn ? btn.textContent : ''; if(btn){ btn.disabled = true; btn.textContent = 'Deleting…'; } try{ const res = await fetch('/api/email-builder/delete-image', { method:'POST', credentials:'include', headers:{'Content-Type':'application/json'}, body:JSON.stringify({url:sel.value, filename:label}) }); const data = await res.json().catch(()=>({})); if(!res.ok || data.error) throw new Error(data.error || 'Delete failed'); if(typeof showStatus === 'function') showStatus('Deleted ' + (data.filename || label)); else alert('Deleted ' + (data.filename || label)); if(typeof loadImages === 'function') await loadImages(); }catch(e){ if(typeof showStatus === 'function') showStatus(e.message || 'Delete failed', true); else alert(e.message || 'Delete failed'); }finally{ if(btn){ btn.disabled = false; btn.textContent = old || 'Delete Selected Image'; } } } document.addEventListener('DOMContentLoaded', function(){ const btn = document.getElementById('deleteImageBtn'); if(btn && !btn.dataset.tgdfDeleteBound){ btn.dataset.tgdfDeleteBound = '1'; btn.addEventListener('click', tgdfDeleteSelectedImage); } }); \n \n