?> (function(){ function ready(fn){ if(document.readyState!=='loading'){ fn(); } else { document.addEventListener('DOMContentLoaded', fn); } } function qs(sel, ctx){ return (ctx||document).querySelector(sel); } function qsa(sel, ctx){ return Array.from((ctx||document).querySelectorAll(sel)); } function showModal(dlg){ try { if (dlg.showModal) dlg.showModal(); else dlg.setAttribute('open',''); } catch(e){ console.error('Dialog show error', e); alert('Unable to open modal: '+e.message); } } function closeModal(dlg){ if (dlg.open) dlg.close(); else dlg.removeAttribute('open'); } function getEventId(){ try{ return new URL(location.href).searchParams.get('id'); }catch(e){ return null; } } // Try hard to find a stage_id for the clicked Assign control function resolveStageId(el){ if (!el) return null; // data-* direct var id = el.getAttribute('data-stage-id') || (el.dataset ? el.dataset.stageId : ''); if (id) return id; // href variant var href = el.getAttribute('href') || ''; if (href && /stage_assign\.php\?/.test(href)) { try { var u = new URL(href, location.href); return u.searchParams.get('stage_id'); } catch(e){} } // ancestors var a = el.closest('[data-stage-id], a[href*="stage_assign.php?stage_id="]'); if (a && a !== el) return resolveStageId(a); // table row with data-stage-id? var tr = el.closest('tr'); if (tr && tr.getAttribute('data-stage-id')) return tr.getAttribute('data-stage-id'); return null; } // Build (or reuse) a dialog function ensureDialog(){ var dlg = document.getElementById('assignDlg'); if (!dlg) { dlg = document.createElement('dialog'); dlg.id = 'assignDlg'; dlg.innerHTML = '
\
\ Assign Users to Stage\ \
\
\
\ \
\
'; document.body.appendChild(dlg); var closeBtn = dlg.querySelector('#dlgClose'); if (closeBtn) closeBtn.addEventListener('click', function(e){ e.preventDefault(); closeModal(dlg); }); } return dlg; } // Render stage chooser when we can't infer stage_id function renderStageChooser(dlg, assignBody, eventId, afterPick){ assignBody.innerHTML = '
Select a stage…
'; fetch('/tools/stages_for_event.php?event_id='+encodeURIComponent(eventId)) .then(function(r){ if(!r.ok) throw new Error('HTTP '+r.status); return r.json(); }) .then(function(list){ if (!Array.isArray(list) || list.length===0) { assignBody.innerHTML = '
No stages found for this event.
'; return; } var html = ['
']; html.push('
Click a stage to assign users:
'); list.forEach(function(s){ var due = s.due_date ? (' — due '+s.due_date) : ''; html.push(''); }); html.push('
'); assignBody.innerHTML = html.join(''); assignBody.addEventListener('click', function(e){ var b = e.target.closest('[data-pick-stage]'); if(!b) return; afterPick(b.getAttribute('data-pick-stage')); }, { once: true }); }) .catch(function(err){ assignBody.innerHTML = '
Failed to load stages: '+err.message+'
'; }); } function openAssignForStage(dlg, assignBody, stageId){ var title = document.getElementById('assignTitle'); title.textContent = 'Assign Users to Stage #'+stageId; assignBody.innerHTML = '
Loading…
'; // Prefer iframe if the classic page exists and we have permission var iframeUrl = '/stage_assign.php?stage_id='+encodeURIComponent(stageId); fetch(iframeUrl, { method:'HEAD' }) .then(function(r){ if (r.ok) { assignBody.innerHTML = ''; } else { // JSON tools fallback loadJsonAssign(dlg, assignBody, stageId); } }) .catch(function(){ loadJsonAssign(dlg, assignBody, stageId); }); } function loadJsonAssign(dlg, assignBody, stageId){ fetch('/tools/stage_assign_get.php?stage_id='+encodeURIComponent(stageId)) .then(function(r){ if(!r.ok) throw new Error('HTTP '+r.status); return r.json(); }) .then(function(data){ assignBody.innerHTML = '
\ \
Stage:
\
\ \ \
\
\ \
\
\
\ \
\
'; qs('#assignStageLabel', assignBody).textContent = data.stage_label || ('Stage #'+stageId); var usersDiv = qs('#assignUsers', assignBody); var slaInput = qs('#assignSla', assignBody); if (data.sla_days != null) slaInput.value = data.sla_days; usersDiv.innerHTML = (data.users||[]).map(function(u){ var checked = (data.assigned||[]).indexOf(u.id) >= 0 ? 'checked' : ''; return ''; }).join('') || '
No users available.
'; qs('#assignSave', assignBody).addEventListener('click', function(){ var ids = qsa('input[type="checkbox"]:checked', usersDiv).map(function(cb){ return cb.value; }); var body = new URLSearchParams(); body.set('stage_id', stageId); ids.forEach(function(id){ body.append('user_ids[]', id); }); if (slaInput.value !== '') body.set('sla_days', slaInput.value); fetch('/tools/stage_assign_save.php', { method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body: body.toString() }) .then(function(r){ if(!r.ok) return r.text().then(function(t){ throw new Error('HTTP '+r.status+' '+t); }); }) .then(function(){ closeModal(dlg); location.reload(); }) .catch(function(err){ var ed=qs('#assignErr', assignBody); ed.textContent = 'Save failed: '+err.message; ed.style.display='block'; }); }); }) .catch(function(err){ assignBody.innerHTML = '
Failed to load assignment dialog: '+err.message+'
'; }); } ready(function(){ // Move Fundraising to the right of Stages on desktop (no /assets needed) try{ var cards = qsa('div.card'); var fund = cards.find(function(c){ var h=c.querySelector('h1,h2,h3,h4,h5,h6'); return h && /fundraising/i.test((h.textContent||'').trim()); }); var stages = cards.find(function(c){ var h=c.querySelector('h1,h2,h3,h4,h5,h6'); return h && /stages/i.test((h.textContent||'').trim()); }); if (fund && stages && !fund.closest('.col-lg-4')) { var row = document.createElement('div'); row.className='row g-3'; var left=document.createElement('div'); left.className='col-lg-8'; var right=document.createElement('div'); right.className='col-lg-4'; stages.parentNode.insertBefore(row, stages); row.appendChild(left); row.appendChild(right); left.appendChild(stages); right.appendChild(fund); console.log('[eventfix] Fundraising moved next to Stages'); } }catch(e){ console.warn('[eventfix] layout move failed:', e); } var dlg = ensureDialog(); var assignBody = document.getElementById('assignBody'); // One unified click handler: document.addEventListener('click', function(e){ var el = e.target.closest('a,button'); if(!el) return; var label = (el.textContent||'').trim().toLowerCase(); var isAssign = el.matches('[data-role="assign-stage"], .btn-assign-stage, a[href*="stage_assign.php?stage_id="]') || label === 'assign'; if(!isAssign) return; e.preventDefault(); var stageId = resolveStageId(el); showModal(dlg); if (stageId) { openAssignForStage(dlg, assignBody, stageId); return; } // Fallback: let user pick a stage by event id from URL var eventId = getEventId(); if (!eventId) { assignBody.innerHTML = '
Can’t detect event id in the URL, and this Assign control has no stage id.
'; return; } renderStageChooser(dlg, assignBody, eventId, function(pickedId){ openAssignForStage(dlg, assignBody, pickedId); }); }, true); console.log('[eventfix] loaded'); }); })();