612 lines
20 KiB
JavaScript
612 lines
20 KiB
JavaScript
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 = `
|
|
<style>.lineup-email {
|
|
font-family: "Helvetica", sans-serif;
|
|
}
|
|
.lineup-email .title-cell {
|
|
font-weight: bold;
|
|
background-color: #323669;
|
|
color: #fff;
|
|
padding: 2px 5px;
|
|
text-transform: uppercase;
|
|
}
|
|
.lineup-email .title-cell.out {
|
|
background-color: rgb(244, 199, 195);
|
|
color: black;
|
|
}
|
|
.lineup-email .sequence-cell {
|
|
font-weight: bold;
|
|
padding: 1px 5px;
|
|
text-align: left;
|
|
}
|
|
.lineup-email .name-cell {
|
|
width: 200px;
|
|
text-align: left;
|
|
}
|
|
.lineup-email .position-label-cell {
|
|
font-weight: bold;
|
|
text-align: right;
|
|
}
|
|
|
|
.Panel .Panel {
|
|
border: none;
|
|
margin: 0;
|
|
}</style>
|
|
`
|
|
// 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 = '<span class="PulseAnimation"><span class="PulseAnimation-dot"></span><span class="PulseAnimation-dot"></span><span class="PulseAnimation-dot"></span></span>'
|
|
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) |