const lineupChangedEvent = new Event('bc:lineupChanged') document.querySelectorAll('.event-lineup').forEach(lineup=>{ lineup.addEventListener('bc:lineupChanged', (evt)=>{ console.log(`lineup changed`, evt.target) const lineup = evt.target colorPositions(lineup) lineup.querySelectorAll(".lineup-slot").forEach((slot, i) => { const lineup_segment = determineLineupSegment(slot) if (lineup_segment != 'bench' && lineup_segment != 'out'){ slot.querySelector("input[name=sequence]").value = i; } else { slot.querySelector("input[name=sequence]").value = null; } updateFlagInput(slot) updatePositionInput(slot) }); } ) }) document.querySelectorAll('[data-control=popup]').forEach(popup_control=>{ console.log(popup_control) popup_control.addEventListener('click', (evt)=>{ const popup = evt.target.closest(".Popup") const to_open = popup.querySelector(".Popup-toggle").dataset.open popup.querySelectorAll(`[data-popup=${to_open}]`).forEach(popup_container => { console.log(evt, evt.target, popup, popup_container) popup_container.classList.toggle('is-open') evt.stopPropagation() }) }) }) document.querySelectorAll('.position-label-flags input[type="checkbox"]').forEach(flagCheckbox => { const lineup = flagCheckbox.closest('.event-lineup') flagCheckbox.addEventListener('click', ()=>{lineup.dispatchEvent(lineupChangedEvent)}) }) function onPositionSelectChange(elem) { elem.querySelectorAll("option").forEach((option) => { if (option.innerText.trim() == elem.value) { option.setAttribute("selected", "selected"); } else { option.removeAttribute("selected"); } }); const lineup = elem.closest('.event-lineup') lineup.dispatchEvent(lineupChangedEvent) elem } function colorPositions(lineup) { const class_none = "u-colorNegative" const class_good = "u-colorPositive" const class_over = "u-colorHighlight" lineup.querySelectorAll('.position-status').forEach( position_status=>{ position_status.classList.remove(class_over, class_good, class_none); const occurences = lineup.querySelectorAll(`.position-select-box option:checked[value="${position_status.dataset.value}"]`) switch (occurences.length){ case 0: position_status.classList.add(class_none) break; case 1: position_status.classList.add(class_good) break; default: position_status.classList.add(class_over) break; } }) } function initFlagsCheckboxes(){ document.querySelectorAll(".lineup-slot").forEach(lineup_slot=>{ const possible_flags = ['DHd', 'DRd'] const flags_string = lineup_slot.querySelector("input[name=flags]")?.value const flags = flagSetFromString(flags_string) possible_flags.forEach(flag=>{ if (flags.has(flag)){ lineup_slot.querySelector(`input[type=checkbox][name=${flag}]`).checked = true } }) }) } const flagSetFromString = (s) => { if (!s) {return new Set()} const array = s.split(',').map(item=>item.trim()) return new Set(array) } const flagSetFromSlot = (slot) => { const inputs = slot.querySelectorAll('.position-label-flags input[type=checkbox]:checked') const set = new Set() inputs.forEach(i=>set.add(i.name)) return set } const flagSetToString = (set) => { return Array.from(set).join(","); } const updateFlagInput = (slot) => { const flags = flagSetFromSlot(slot) const lineup_segment = slot.closest('.lineup-segment') lineup_segment.classList.contains('position-only') ? flags.add('PO') : flags.delete('PO') slot.querySelector('input[name="flags"]').value = flagSetToString(flags); } const updatePositionInput = (slot) => { const selected_position = slot.querySelector(".position-select-box option:checked"); const lineup_segment = slot.closest('.lineup-segment') if (selected_position && selected_position.text != "--" && !lineup_segment.classList.contains('bench')) { slot.querySelector("input[name=label]").value = selected_position.text; } else { slot.querySelector("input[name=label]").value = null; } } const determineLineupSegment = (slot) => { const lineup_segments = ['starting', 'position-only', 'bench', 'out'] const lineup_segment = slot.closest('.lineup-segment') const classList = Array.from(lineup_segment.classList) const segments = classList.filter(c=>lineup_segments.includes(c)) if (segments.length == 1) { return segments[0] } else { return '' } } function openAvailabilityReminderModal (el, team_id, event_id) { const url = `/${team_id}/event/${event_id}/modal-confirm-availability-reminders/` const form = el.closest('form') const form_data = new FormData (form) fetch(url) .then((response) => { if (response.ok) { return response.text(); } else { return Promise.reject(response.text()); } }) .then((html) => { const parser = new DOMParser() const modal = parser.parseFromString(html, 'text/html') const modal_node = modal.firstElementChild.querySelector('#modal') modal_node.classList.add('is-open') const modal_node_accept = modal.querySelector('Button[data-confirm=yes]') const checked = Array.from(el.querySelectorAll('input:checked')).map const body = document.querySelector('body') body.appendChild(modal_node) modal_node_accept.addEventListener( "click", ()=>{ // const memberIds = form_data.getAll('memberId') const csrf_token = form_data.get('csrfToken') const selected_status_codes = Array.from(document.querySelectorAll('input:checked')).map(e=>e.value) const slots = Array.from(document.querySelectorAll('.lineup-slot')).filter( slot =>{ const slot_status_code = slot.querySelector('input[name=availabilityStatusCode]').value return selected_status_codes.includes(slot_status_code) } ) const memberIds = slots.map( slot => slot.querySelector('input[name=memberId]').value ) console.log("sending reminders", el, event_id, memberIds, csrf_token) sendAvailabilityReminder(el, event_id, memberIds, csrf_token) body.removeChild(modal_node) } ) }) } function confirmModal(el, prompt, fn, options) { const url = "/modal-confirm" const params = new URLSearchParams(prompt) url.search = params.toString() fetch(url+"?"+params.toString(), {method:"GET"}) .then((response) => { if (response.ok) { return response.text(); } else { return Promise.reject(response.text()); } }) .then((html) => { const parser = new DOMParser() const modal = parser.parseFromString(html, 'text/html') const modal_node = modal.firstElementChild.querySelector('#modal') modal_node.classList.add('is-open') const modal_node_accept = modal.querySelector('Button[data-confirm=yes]') const body = document.querySelector('body') body.appendChild(modal_node) modal_node_accept.addEventListener("click", ()=>{fn(modal_node, options)}) }) } const toggleShowAndHideLoading = (el) => { console.log(el) el.querySelectorAll('.hideOnLoading').forEach((element)=>{ element.classList.add('u-hidden') }) el.querySelectorAll('.showOnLoading').forEach((element)=>{ element.classList.remove('u-hidden') }) } const completeLoad = (el, success) => { el.querySelectorAll('.hideOnLoading, .showOnLoading, .showOnFailure, .showOnSuccess').forEach((element)=>{ element.classList.add('u-hidden') }) if (success) { el.querySelectorAll('.showOnSuccess').forEach((element) => { element.classList.remove('u-hidden') }) } else { el.querySelectorAll('.showOnFailure').forEach((element) => { element.classList.remove('u-hidden') }) } } function submitClearLineup(modal, options){ console.log('clearing lineup...') toggleShowAndHideLoading(modal) const {team_id, event_id, event_lineup_id} = options const url = `/${team_id}/event/${event_id}/lineup/${event_lineup_id}/delete` const form = document.querySelector(`#event-lineup-${event_id} form`); const data = new FormData(form); const memberIds = data.getAll('memberId') console.log(url) fetch(url, {method:"POST", body: JSON.stringify({memberIds, event_id}), headers: {"Content-Type": "application/json"}}) .then((response) => { if (response.ok) { completeLoad(modal, true); return response.text(); } else { completeLoad(modal, false); return Promise.reject(response.text()); } }) .finally(()=>{ setTimeout(function (){ location.reload() }, 500) });//refresh page } function submitResetAvailabilities(modal, options){ const {team_id, event_id} = options toggleShowAndHideLoading(modal) const url = `/${team_id}/event/${event_id}/reset_availabilities` const form = document.querySelector(`#event-lineup-${event_id} form`); const data = new FormData(form); const memberIds = data.getAll('memberId') console.log('submitting...', url) fetch(url, {method:"POST", body: JSON.stringify({memberIds, event_id}), headers: {"Content-Type": "application/json"}}) .then((response) => { if (response.ok) { completeLoad(modal, true); return response.text(); } else { completeLoad(modal, false); return Promise.reject(response.text()); } }) .finally(()=>{ setTimeout(function (){ location.reload() }, 500) });//refresh page } function emailModal(el, url) { form = el.closest("form"); console.log(form) data = new FormData(form); fetch(url, { method: "POST", body: data, headers: { 'CSRF-Token': data.get('_csrf') } }) .then((response) => { if (response.ok) { return response.text(); } else { return Promise.reject(response.text()); } }) .then((html) => { const parser = new DOMParser() const email_modal = parser.parseFromString(html, 'text/html') const email_modal_node = email_modal.firstElementChild.querySelector('#modal') email_modal_node.setAttribute('id', `lineup-email-data-${data.get('event_lineup_id')}`) const body = document.querySelector('body') email_modal_node.classList.add('is-open') body.appendChild(email_modal_node) tinymce.init({ selector:`textarea#email-editor`, content_css:"/css/application.css", plugins: 'image', menubar: false, toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | image', paste_data_images: true, statusbar:false}) tinymce.remove(); }); } async function submitEventLineup(form, event) { event.preventDefault(); console.log(event) teamsnap_icon = form.querySelector("#teamsnap-icon"); waiting_icon = form.querySelector("#waiting-icon"); success_icon = form.querySelector("#success-icon"); failure_icon = form.querySelector("#failure-icon"); data = new FormData(form); console.log(form) url = form.attributes.action.textContent; toggleShowAndHideLoading(form) await fetch(url, { method: "POST", body: data, headers: { 'CSRF-Token': data.get('_csrf') } }) .then((response) => { if (response.ok) { return response.text(); } else { return Promise.reject(response.text()); } }) .then((text) => { event.submitter.blur() completeLoad(form, true) console.log(text); }) .catch((error) => { event.submitter.blur() completeLoad(form, false) console.log(error); }) .finally(()=>{location.reload()});//refresh page setTimeout(() => { [waiting_icon, success_icon, failure_icon].forEach(e=>e.classList.add('u-hidden')) teamsnap_icon.classList.remove('u-hidden') }, 3000) } async function copyEmailTable (element) { // range=document.createRange(); // window.getSelection().removeAllRanges(); // // range.selectNode(document.querySelector('.Modal').querySelector('.Modal-body')); // tinymce.activeEditor.selection.select(tinymce.activeEditor.getBody()); // // window.getSelection().addRange(range); // document.execCommand('copy'); // window.getSelection().removeAllRanges(); const emailStyle = ` ` // html_content = emailStyle+tinymce.activeEditor.getContent() // console.log(html_content) const table = element.closest('form').querySelector('.lineup-table table') // navigator.clipboard.write( // [new ClipboardItem( // { // // 'text/plain': new Blob([tinymce.activeEditor.getContent({format: "text"})], {type: 'text/plain'}), // 'text/plain': new Blob([table.innerText], {type: 'text/plain'}), // 'text/html': new Blob([emailStyle+table.outerHTML], {type: 'text/html'}) // }) // ]) window.getSelection().removeAllRanges(); var range = document.createRange(); range.selectNode(table); window.getSelection().addRange(range); document.execCommand("copy"); window.getSelection().removeAllRanges(); } moveToLineupSegment = (slot, segment_name) => { if (!slot.classList.contains('lineup-slot')) { slot = slot.closest('.lineup-slot') if (!slot) {return} } const current_lineup_segment = slot.closest('.lineup-segment') if (current_lineup_segment.classList.contains(segment_name)) { return } const lineup = slot.closest('.event-lineup') const newParent = lineup.querySelector(`.lineup-segment.${segment_name} .slot-set`) newParent.append(slot) } function initSlots () { document.querySelectorAll('.lineup-slot').forEach(slot=>{ if (slot.dataset.initialLineupSegment) { moveToLineupSegment(slot, slot.dataset.initialLineupSegment) slot.removeAttribute('data-initial-lineup-segment') } }) } addToStarting = (el) => { const slot = el.closest('.lineup-slot') this.blur() } removeToBench = (el) => { const slot = el.closest('.lineup-slot') this.blue() } function insertLineup(direction, teamId, eventId, element) { const currentUrl = window.location.href; let search_params if (Number(direction) > 0) { search_params = new URLSearchParams({ page_size:1, index: 1 }) } else if (Number(direction) < 0) { search_params = new URLSearchParams({ page_size:1, index: -1 }) } else {throw new Error("Needs to be a negative number or a positive number")} fetch(`/${teamId}/event/${eventId}/lineup/adjacent?`+search_params, { method: "GET" }) .then((response) => { if (response.ok) { return response.text(); } else { return Promise.reject(response.text()); } }) .then((html) =>{ const parser = new DOMParser(); const new_lineup_doc = parser.parseFromString(html, 'text/html') const new_lineup_doc_node = new_lineup_doc.firstElementChild.querySelector('.event-lineup') const main = document.querySelector("main") const new_csrf_token = new_lineup_doc.querySelector('form input[name=csrfToken]').value direction > 0 ? main.appendChild(new_lineup_doc_node) : main.insertBefore(new_lineup_doc_node, element.closest('[id*=event-lineup]')) main.classList.remove(...main.classList) main.classList.add('scroll-horizontal', 'u-spaceSidesSm', 'u-flex') Array.from(document.querySelectorAll(".event-lineup")).forEach((bcLineup) => { // main.classList.remove('.u-max1200', 'u-flexExpandSides') bcLineup.classList.remove('u-spaceSidesNone', 'u-sm-spaceSidesAuto') } ) Array.from(document.querySelectorAll(".event-lineup .Panel")).forEach((bcLineupPanel) => { bcLineupPanel.classList.remove('Panel--full') }) for (input of document.querySelectorAll("form input[name=csrfToken]")){ input.value = new_csrf_token } initPage(); }) } function initPage (){ initSlots(); initFlagsCheckboxes(); for (bcLineup of document.querySelectorAll(".event-lineup")) { bcLineup.dispatchEvent(lineupChangedEvent) options = { animation: 150, handle: ".Panel-cell:has(.drag-handle), .Panel-cell:has(.sequence)", ghostClass: "ghost", group: { name: bcLineup.id, put: [bcLineup.id], pull: [bcLineup.id], }, onAdd: function (/**Event*/ evt) { bcLineup.dispatchEvent(lineupChangedEvent) }, onUpdate: function (/**Event*/ evt) { bcLineup.dispatchEvent(lineupChangedEvent) }, }; new Sortable.create(bcLineup.querySelector(".lineup-segment.starting .slot-set"), options); new Sortable.create(bcLineup.querySelector(".lineup-segment.position-only .slot-set"), options); new Sortable.create(bcLineup.querySelector(".lineup-segment.bench .slot-set"), {...options, sort:false}); new Sortable.create(bcLineup.querySelector(".lineup-segment.out .slot-set"), {...options, sort:false, group:{...options.group, put:[]}}); } // for (lineup_slot of document.querySelectorAll(".lineup-segment.out .lineup-slot")) { // const cells = lineup_slot.querySelectorAll('.Panel-cell:has(.sequence), .Panel-cell:has(.drag-handle), .Panel-cell:has(.position-select-box), button:has(+.position-label-flags)') // Array.from(cells).forEach(cell=>{ // cell.classList.add('u-hidden') // }) // } } function mailToLink(el, protocol) { const {to, bcc} = el.dataset const subject = document.getElementById('email-subject').value const email_body = document.getElementById('email-editor').value const url = `${protocol}://compose?recipient=${to}&bcc=${bcc}&subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(email_body)}` console.log(url) // location.href=`mailto:${to}${params}` const windowRef = window.open(url, '_blank'); windowRef.focus(); } function sendAvailabilityReminder(element, eventId, memberIds, csrf_token) { const icon = element.querySelector('svg') const button_text = element.querySelector('span') icon.classList.toggle('u-hidden') button_text.classList.toggle('u-hidden') const loader = '' const loader_node = new DOMParser().parseFromString(loader, "text/html").firstChild.querySelector('span'); element.appendChild(loader_node) element.blur(); const data = new FormData(); const url = "../availability_reminders" data.append('eventId', eventId) for (var i = 0; i < memberIds.length; i++) { data.append('memberIds[]', memberIds[i]); } console.log(data) fetch(url, { method: "POST", body: data, headers: { 'CSRF-Token': csrf_token } }) .then((response) => { if (response.ok) { console.log(response) return response.text(); } else { return Promise.reject(response.text()); } }) .finally(()=>{ loader_node.remove() icon.classList.toggle('u-hidden') button_text.classList.toggle('u-hidden') }) console.log(element, eventId, memberIds) } document.addEventListener('DOMContentLoaded', initPage)