#16: trim the schedule form when scheduling from a group

A group's members are automatically the meeting's participants, so the
Invite-participants, Invite-by-email and "Guests must be admitted by host"
sections are noise there. openScheduleModal now omits them when a group id is
present (inviteBlock is empty), and the email/participant/lobby handlers are
null-guarded so the save path still works without those fields.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 22:47:15 +05:30
parent 276c5e0929
commit c1b67d38d3
+16 -10
View File
@@ -4846,6 +4846,18 @@ function openScheduleModal(gid, editMtg){
const label12=m=>{ let h=Math.floor(m/60),mm=m%60; const ap=h<12?'AM':'PM'; let h12=h%12||12; return h12+':'+pad(mm)+' '+ap; }; const label12=m=>{ let h=Math.floor(m/60),mm=m%60; const ap=h<12?'AM':'PM'; let h12=h%12||12; return h12+':'+pad(mm)+' '+ap; };
const dateLabel=d=>d.toLocaleDateString([],{weekday:'short',month:'short',day:'numeric'}); const dateLabel=d=>d.toLocaleDateString([],{weekday:'short',month:'short',day:'numeric'});
const invitedIds=new Set(editing&&Array.isArray(editMtg.invitedIds)?editMtg.invitedIds:[]); const invitedIds=new Set(editing&&Array.isArray(editMtg.invitedIds)?editMtg.invitedIds:[]);
// #16: scheduling FROM a group doesn't need the invite-participants / invite-by-email / admit-by-host
// sections — the group's members are automatically the meeting's participants. Drop them for a group.
const fromGroup=!!gid;
const inviteBlock = fromGroup ? '' : (
'<label class="flbl">Invite participants</label>'
+ (CONTACTS.length>6?'<div class="gi-search" style="margin:.15rem 0 .35rem"><input id="schPplSearch" placeholder="Search people…" autocomplete="off"></div>':'')
+ '<div class="gi-list" id="schPeople" style="max-height:20vh;overflow:auto">'+(CONTACTS.length?CONTACTS.map(c=>'<label class="chk" data-nm="'+pEsc((c.name||'').toLowerCase())+'"><input type="checkbox" value="'+pEsc(c.id)+'"'+(invitedIds.has(c.id)?' checked':'')+'><span class="mini-av" style="background:'+avColor(c.name)+'">'+pEsc(initials(c.name))+'</span><span class="mn">'+pEsc(c.name)+'</span></label>').join(''):'<div class="gi-noresult">No contacts to invite</div>')+'</div>'
+ '<label class="flbl" style="margin-top:.7rem">Invite by email <span class="opt">(guests — no Connect account needed)</span></label>'
+ '<div class="email-invite"><input id="schEmail" class="finput" type="email" placeholder="name@example.com" autocomplete="off"><button type="button" class="email-add" id="schEmailAdd">'+ic('userPlus',15)+' Add</button></div>'
+ '<div class="email-chips" id="schEmailChips"></div>'
+ '<label class="chk2 switch-row" style="margin-top:.6rem"><span>'+ic('users',15)+' Guests must be admitted by the host</span><span class="switch"><input type="checkbox" id="schLobby" checked><span class="slider"></span></span></label>'
);
const ov=document.createElement('div'); ov.className='modal-ov'; ov.id='schedModal'; const ov=document.createElement('div'); ov.className='modal-ov'; ov.id='schedModal';
ov.innerHTML='<div class="modal sched">' ov.innerHTML='<div class="modal sched">'
+'<div class="gi-head" style="margin-bottom:.6rem"><div class="avatar grp" style="width:40px;height:40px;flex:0 0 40px;background:var(--blue)">'+ic('calendarClock',20)+'</div>' +'<div class="gi-head" style="margin-bottom:.6rem"><div class="avatar grp" style="width:40px;height:40px;flex:0 0 40px;background:var(--blue)">'+ic('calendarClock',20)+'</div>'
@@ -4860,13 +4872,7 @@ function openScheduleModal(gid, editMtg){
+'<label class="chk2 switch-row"><span>'+ic('calendarClock',15)+' Repeat weekly</span><span class="switch"><input type="checkbox" id="schRepeat"><span class="slider"></span></span></label>' +'<label class="chk2 switch-row"><span>'+ic('calendarClock',15)+' Repeat weekly</span><span class="switch"><input type="checkbox" id="schRepeat"><span class="slider"></span></span></label>'
+'<div class="sch-days hidden" id="schDays">'+DAY1.map((d,i)=>'<button type="button" class="day-chip" data-d="'+i+'" title="'+DAYW[i]+'">'+d+'</button>').join('')+'<button type="button" class="day-all" data-all="1">Everyday</button></div>' +'<div class="sch-days hidden" id="schDays">'+DAY1.map((d,i)=>'<button type="button" class="day-chip" data-d="'+i+'" title="'+DAYW[i]+'">'+d+'</button>').join('')+'<button type="button" class="day-all" data-all="1">Everyday</button></div>'
+'<label class="flbl">Description <span class="opt">(optional)</span></label><textarea id="schDesc" class="finput" rows="2" placeholder="What\'s this call about?"></textarea>' +'<label class="flbl">Description <span class="opt">(optional)</span></label><textarea id="schDesc" class="finput" rows="2" placeholder="What\'s this call about?"></textarea>'
+'<label class="flbl">Invite participants</label>' +inviteBlock // #16: empty when scheduling from a group — the members are the invitees (no invite/email/admit section)
+(CONTACTS.length>6?'<div class="gi-search" style="margin:.15rem 0 .35rem"><input id="schPplSearch" placeholder="Search people…" autocomplete="off"></div>':'')
+'<div class="gi-list" id="schPeople" style="max-height:20vh;overflow:auto">'+(CONTACTS.length?CONTACTS.map(c=>'<label class="chk" data-nm="'+pEsc((c.name||'').toLowerCase())+'"><input type="checkbox" value="'+pEsc(c.id)+'"'+(invitedIds.has(c.id)?' checked':'')+'><span class="mini-av" style="background:'+avColor(c.name)+'">'+pEsc(initials(c.name))+'</span><span class="mn">'+pEsc(c.name)+'</span></label>').join(''):'<div class="gi-noresult">No contacts to invite</div>')+'</div>'
+'<label class="flbl" style="margin-top:.7rem">Invite by email <span class="opt">(guests — no Connect account needed)</span></label>'
+'<div class="email-invite"><input id="schEmail" class="finput" type="email" placeholder="name@example.com" autocomplete="off"><button type="button" class="email-add" id="schEmailAdd">'+ic('userPlus',15)+' Add</button></div>'
+'<div class="email-chips" id="schEmailChips"></div>'
+'<label class="chk2 switch-row" style="margin-top:.6rem"><span>'+ic('users',15)+' Guests must be admitted by the host</span><span class="switch"><input type="checkbox" id="schLobby" checked><span class="slider"></span></span></label>'
+'<button class="gobtn" id="schSave" style="width:100%;margin-top:.9rem;background:var(--blue);color:#fff">'+(editing?'Save changes':'Schedule & invite')+'</button>' +'<button class="gobtn" id="schSave" style="width:100%;margin-top:.9rem;background:var(--blue);color:#fff">'+(editing?'Save changes':'Schedule & invite')+'</button>'
+'<div class="hint" id="schErr"></div></div>'; +'<div class="hint" id="schErr"></div></div>';
document.body.appendChild(ov); document.body.appendChild(ov);
@@ -4916,8 +4922,8 @@ function openScheduleModal(gid, editMtg){
const emailList=(editing&&Array.isArray(editMtg.guestEmails))?editMtg.guestEmails.slice():[]; const emailList=(editing&&Array.isArray(editMtg.guestEmails))?editMtg.guestEmails.slice():[];
function renderEmailChips(){ const w=$('schEmailChips'); if(!w) return; w.innerHTML=emailList.map((e,i)=>'<span class="echip">'+pEsc(e)+'<button type="button" data-i="'+i+'" title="Remove">'+ic('x',12)+'</button></span>').join(''); w.querySelectorAll('.echip button').forEach(b=>b.onclick=()=>{ emailList.splice(+b.dataset.i,1); renderEmailChips(); }); } function renderEmailChips(){ const w=$('schEmailChips'); if(!w) return; w.innerHTML=emailList.map((e,i)=>'<span class="echip">'+pEsc(e)+'<button type="button" data-i="'+i+'" title="Remove">'+ic('x',12)+'</button></span>').join(''); w.querySelectorAll('.echip button').forEach(b=>b.onclick=()=>{ emailList.splice(+b.dataset.i,1); renderEmailChips(); }); }
function addEmail(){ const inp=$('schEmail'); const v=(inp.value||'').trim().toLowerCase(); if(!v) return; if(!EMAIL_RE.test(v)){ err.textContent='Enter a valid email address.'; return; } if(!emailList.includes(v)) emailList.push(v); inp.value=''; err.textContent=''; renderEmailChips(); } function addEmail(){ const inp=$('schEmail'); const v=(inp.value||'').trim().toLowerCase(); if(!v) return; if(!EMAIL_RE.test(v)){ err.textContent='Enter a valid email address.'; return; } if(!emailList.includes(v)) emailList.push(v); inp.value=''; err.textContent=''; renderEmailChips(); }
$('schEmailAdd').onclick=addEmail; { const ea=$('schEmailAdd'); if(ea) ea.onclick=addEmail; } // #16: absent when scheduling from a group
$('schEmail').addEventListener('keydown',e=>{ if(e.key==='Enter'){ e.preventDefault(); addEmail(); } }); { const em=$('schEmail'); if(em) em.addEventListener('keydown',e=>{ if(e.key==='Enter'){ e.preventDefault(); addEmail(); } }); }
renderEmailChips(); renderEmailChips();
// #10: filter the participant list as you type. // #10: filter the participant list as you type.
{ const ps=$('schPplSearch'); if(ps) ps.addEventListener('input',()=>{ const q=ps.value.trim().toLowerCase(); ov.querySelectorAll('#schPeople .chk').forEach(l=>{ l.style.display=(!q||(l.dataset.nm||'').includes(q))?'':'none'; }); }); } { const ps=$('schPplSearch'); if(ps) ps.addEventListener('input',()=>{ const q=ps.value.trim().toLowerCase(); ov.querySelectorAll('#schPeople .chk').forEach(l=>{ l.style.display=(!q||(l.dataset.nm||'').includes(q))?'':'none'; }); }); }
@@ -4926,7 +4932,7 @@ function openScheduleModal(gid, editMtg){
const desc=$('schDesc').value.trim(); const desc=$('schDesc').value.trim();
const durationMins=parseInt($('schDur').value,10)||30; const durationMins=parseInt($('schDur').value,10)||30;
const participants=[...ov.querySelectorAll('#schPeople input:checked')].map(i=>i.value); const participants=[...ov.querySelectorAll('#schPeople input:checked')].map(i=>i.value);
{ const pend=($('schEmail').value||'').trim().toLowerCase(); if(pend && EMAIL_RE.test(pend) && !emailList.includes(pend)) emailList.push(pend); } // include a typed-but-not-added email { const em=$('schEmail'); const pend=((em&&em.value)||'').trim().toLowerCase(); if(pend && EMAIL_RE.test(pend) && !emailList.includes(pend)) emailList.push(pend); } // include a typed-but-not-added email (#16: absent for group schedules)
clearErrAll(); clearErrAll();
if(!title){ err.textContent='Please add a title.'; $('schTitle').classList.add('field-err'); $('schTitle').focus(); return; } if(!title){ err.textContent='Please add a title.'; $('schTitle').classList.add('field-err'); $('schTitle').focus(); return; }
const ts=new Date(selDate.getFullYear(),selDate.getMonth(),selDate.getDate(),Math.floor(selMin/60),selMin%60,0,0).getTime(); const ts=new Date(selDate.getFullYear(),selDate.getMonth(),selDate.getDate(),Math.floor(selMin/60),selMin%60,0,0).getTime();