add insert lineup before and after

This commit is contained in:
2024-03-15 14:19:14 -05:00
parent dc17ca76ba
commit f2371c6b5a
12 changed files with 305 additions and 221 deletions

View File

@@ -96,12 +96,40 @@ exports.helpers = {
}
exports.getEventLineup = async (req, res)=>{
// res.send(req.event_lineup)
await Promise.all(req.promises)
const {user, team, members, event, layout, event_lineup, event_lineup_entries, availabilities, availabilitySummary, csrfToken} = req
attachBenchcoachPropertiesToMember(members, event_lineup_entries, availabilities)
members.sort(tsUtils.teamsnapMembersSortLineupAvailabilityLastName)
res.render("eventlineup/edit", {user, team, members, event, layout, event_lineup, event_lineup_entries, availabilitySummary, csrfToken})
const scripts = [
"https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js",
"/js/eventlineup.js",
"/js/tinymce.min.js"
]
res.render("eventlineup/edit", {user, team, members, event, scripts, layout, event_lineup, event_lineup_entries, availabilitySummary, csrfToken})
}
exports.getAdjacentEventLineup = async (req, res) => {
await Promise.all(req.promises)
const index = Number(req.query.index)
const {user, team, members, csrfToken} = req
let event
if (index > 0) {
event = req.upcoming_events[index-1]
}
else if (index < 0){
event = req.recent_events[Math.abs(index)-1]
} else {
throw new Error('Index must be positive or negative number')
}
const availabilitySummary = event.availabilitySummary
const event_lineup = req.timeline.event_lineups.find(i=>i.eventId==event.id)
const event_lineup_entries = req.timeline.event_lineup_entries.filter(i=>i.eventId==event.id)
const availabilities = req.timeline.availabilities.filter(i=>i.eventId==event.id)
attachBenchcoachPropertiesToMember(members, event_lineup_entries, availabilities)
members.sort(tsUtils.teamsnapMembersSortLineupAvailabilityLastName)
console.log()
// res.status(200).send('Received')
res.render("eventlineup/edit", {user, team, members, event, layout: null, event_lineup, event_lineup_entries, availabilitySummary, csrfToken})
}
attachBenchcoachPropertiesToMember = (members, event_lineup_entries, availabilities) => {
@@ -141,7 +169,7 @@ exports.getEventLineupEmail = async (req, res)=>{
const {newEventLineupEntries} = processPostedEventLineupEntries(body, eventLineupEntries, event_lineup)
attachBenchcoachPropertiesToMember(members, newEventLineupEntries, availabilities)
members.sort(tsUtils.teamsnapMembersSortLineupAvailabilityLastName)
res.status(200).render("eventlineup/partials/email_table", {user, team, members, event, event_lineup, event_lineup_entries: newEventLineupEntries, availabilities, availabilitySummary})
res.status(200).render("eventlineup/partials/email_modal.hbs", {layout:null, user, team, members, event, event_lineup, event_lineup_entries: newEventLineupEntries, availabilities, availabilitySummary})
}
exports.getEventLineupEntries = async (req, res)=>{

View File

@@ -3,7 +3,7 @@ const { teamsnapCallback } = require("../lib/utils");
utils = require("../lib/utils");
exports.getTeams = async (req, res, next) => {
const {layout} = req
const {layout, user} = req
const {user_id} = req.params
req.session.current_team_id = null
promise = teamsnap.loadTeams({'userId':user_id},
@@ -17,7 +17,7 @@ exports.getTeams = async (req, res, next) => {
req.promises.push(promise)
await Promise.all(req.promises)
try {
const context = { layout, title: "Teams", teams: req.teams.filter(t=>!t.isRetired) };
const context = { layout, title: "Teams", user, teams: req.teams.filter(t=>!t.isRetired) };
res.render("team/list", context);
} catch (e){
next(e);

View File

@@ -1,5 +1,6 @@
exports.loadRecentAndUpcomingEvents = async (req, res, next) => {
const {team_id, event_id} = req.params
const page_size = req.query.page_size ? Number(req.query.page_size) : 4
var subject_date = ""
if (event_id) {
const event = await teamsnap.loadEvents({id: event_id}).pop()
@@ -14,11 +15,11 @@ exports.loadRecentAndUpcomingEvents = async (req, res, next) => {
types: ["event", "availabilitySummary"],
scopeTo: "event",
event__startedAfter: subject_date,
event__pageSize: 4
event__pageSize: page_size + 1
})
.then(items => tsUtils.groupTeamsnapItems(items))
.then((items)=>{
req.upcoming_events=items.events || [];
req.upcoming_events=items.events ? items.events.slice(1) : [];
const availabilitySummaries=items.availabilitySummaries;
req.upcoming_events.forEach((event) => {
event.link('availabilitySummary', availabilitySummaries.find(a=>a.eventId==event.id))
@@ -32,7 +33,7 @@ exports.loadRecentAndUpcomingEvents = async (req, res, next) => {
types: ["event", "availabilitySummary"],
scopeTo: "event",
event__startedBefore: subject_date,
event__pageSize: 4,
event__pageSize: page_size,
event__sortStartDate: "desc"
})
.then(items => tsUtils.groupTeamsnapItems(items))

View File

@@ -7017,6 +7017,8 @@ a.Panel-row {
div[id^=event-lineup] {
max-width: 576px;
counter-reset: lineup-sequence-counter 0;
margin-left: 8px;
margin-right: 9px;
}
.lineup-slot {

File diff suppressed because one or more lines are too long

View File

@@ -49,7 +49,6 @@ function initFlagsCheckboxes(){
)
).forEach((slot, i) => {
const flags = new Set(slot.querySelector("input[name*=flags]")?.value?.split(',')?.map(s=>s.trim())) || new Set()
console.log(slot, flags)
if (flags.has('DHd')) {
slot.querySelector('[name=flag-dhd]').checked = true;
}
@@ -106,44 +105,6 @@ function refreshLineup() {
});
}
for (bcLineup of document.querySelectorAll("[id^=event-lineup]")) {
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) {
console.log("added to lineup");
// Add to Lineup
var itemEl = evt.item; // dragged HTMLElement
refreshLineup();
},
onUpdate: function (/**Event*/ evt) {
console.log("update to lineup");
// var itemEl = evt.item; // dragged HTMLElement
// refresh_lineup_order(itemEl);
refreshLineup();
},
};
new Sortable.create(bcLineup.querySelector("[id^=lineup-starting] .slot-set"), options);
new Sortable.create(bcLineup.querySelector("[id^=lineup-positiononly] .slot-set"), options);
options["sort"] = false;
new Sortable.create(bcLineup.querySelector("[id^=lineup-bench] .slot-set"), options);
new Sortable.create(bcLineup.querySelector("[id^=lineup-out] .slot-set"), {...options, group:{...options.group, put:[]}});
}
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
const cells = lineup_slot.querySelectorAll('.Panel-cell:has(.sequence), .Panel-cell:has(.drag-handle), .Panel-cell:has(.position-select-box), div.position-label-flags')
Array.from(cells).forEach(cell=>{
cell.classList.add('u-hidden')
})
}
function refreshFlags(){
}
@@ -293,8 +254,6 @@ function emailModal(el, url) {
form = el.closest("form");
data = new FormData(form);
email_modal = document.querySelector("#modal");
fetch(url, {
method: "POST",
body: data,
@@ -309,12 +268,25 @@ function emailModal(el, url) {
return Promise.reject(response.text());
}
})
.then((lineup_table) => {
const email_textarea = document.querySelector('#email-editor')
const lineup_table_div = document.querySelector(".FieldGroup .lineup-email")
tinymce.activeEditor.setContent("Team,")
lineup_table_div.innerHTML = lineup_table
email_modal.classList.add("is-open");
.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:`#lineup-email-data-${data.get('event_lineup_id')} #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.activeEditor.setContent("Team,")
// lineup_table_div.innerHTML = lineup_table
// email_modal.classList.add("is-open");
// email_modal.querySelector(".Modal-body").innerHTML = html;
});
}
@@ -596,3 +568,86 @@ async function submitEmail () {
})
])
}
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('[id*=event-lineup]')
const lineup_container = document.querySelector("#lineup-container")
direction > 0 ? lineup_container.appendChild(new_lineup_doc_node) : lineup_container.insertBefore(new_lineup_doc_node, element.closest('[id*=event-lineup]'))
initPage();
})
}
function initPage (){
colorPositions();
initFlagsCheckboxes();
refreshLineup();
for (bcLineup of document.querySelectorAll("[id^=event-lineup]")) {
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) {
console.log("added to lineup");
// Add to Lineup
var itemEl = evt.item; // dragged HTMLElement
refreshLineup();
},
onUpdate: function (/**Event*/ evt) {
console.log("update to lineup");
// var itemEl = evt.item; // dragged HTMLElement
// refresh_lineup_order(itemEl);
refreshLineup();
},
};
new Sortable.create(bcLineup.querySelector("[id^=lineup-starting] .slot-set"), options);
new Sortable.create(bcLineup.querySelector("[id^=lineup-positiononly] .slot-set"), options);
options["sort"] = false;
new Sortable.create(bcLineup.querySelector("[id^=lineup-bench] .slot-set"), options);
new Sortable.create(bcLineup.querySelector("[id^=lineup-out] .slot-set"), {...options, group:{...options.group, put:[]}});
}
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
const cells = lineup_slot.querySelectorAll('.Panel-cell:has(.sequence), .Panel-cell:has(.drag-handle), .Panel-cell:has(.position-select-box), div.position-label-flags')
Array.from(cells).forEach(cell=>{
cell.classList.add('u-hidden')
})
}
}
document.addEventListener('DOMContentLoaded', initPage)

View File

@@ -23,6 +23,46 @@ const loadEvent = (req,res,next) => {
next();
}
// Middleware
const loadEvents = async (req,res,next) => {
const {team_id, event_id} = req.params
req.timeline = {}
await Promise.all(req.promises)
const {recent_events, upcoming_events} = req
const eventIds = [...recent_events.map(e=>e.id), event_id, ...upcoming_events.map(e=>e.id)]
// if (!req.event_lineup){
bulkLoadTypes = ['event','eventLineup', 'eventLineupEntry']
req.promises.push(
teamsnap.bulkLoad(
{teamId: team_id, types: bulkLoadTypes, scopeTo:'event', event__id:eventIds},
null,
(err, items) => {teamsnapCallback(err, items, {req, source:"loadEvents", method:'bulkLoad'})}
)
.then(items => tsUtils.groupTeamsnapItems(items, bulkLoadTypes))
.then(items => {
req.timeline.events = items.events;
req.timeline.event_lineups = items.eventLineups;
req.timeline.event_lineup_entries = items.eventLineupEntries;
})
)
req.promises.push(
teamsnap.loadAvailabilities(
{eventId: eventIds},
(err, items) => {teamsnapCallback(err, items, {req, source:"loadEvents", method:'loadAvailabilities'})}
).then(availabilities => {
req.timeline.availabilities = availabilities
}
)
)
// }
// else {
// // const {event_lineup} = req
// }
const {event_lineup} = req
next();
}
router.use("/:team_id([0-9]+)/event/:event_id([0-9]+)", loadEvent)
// Routes
@@ -31,4 +71,4 @@ router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)", eventsController.getEven
// router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup", eventsController.getLineup);
// router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup_card", eventsController.getLineupCard);
module.exports = {router, loadEvent}
module.exports = {router, loadEvent, loadEvents}

View File

@@ -5,6 +5,8 @@ const tsUtils = require('../lib/utils')
const multer = require("multer");
const upload = multer()
const { doubleCsrfProtection } = require('../middlewares/csrf');
const {loadRecentAndUpcomingEvents} = require('../middlewares/bulkload')
const {loadEvents} = require('./event')
const {teamsnapCallback} = require("../lib/utils")
@@ -51,10 +53,10 @@ router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup", async (req,res) =
}
)
router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/adjacent", doubleCsrfProtection, loadRecentAndUpcomingEvents, loadEvents, eventsLineupController.getAdjacentEventLineup);
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)/email", upload.none(), doubleCsrfProtection, eventsLineupController.getEventLineupEmail )
router.get ("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)", upload.none(), doubleCsrfProtection, eventsLineupController.getEventLineup);
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)", upload.none(), doubleCsrfProtection, eventsLineupController.postEventLineup);
// router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup_card", eventsController.getLineupCard);
router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)/entries", eventsLineupController.getEventLineupEntries)
module.exports = {router, loadEventLineup}

View File

@@ -1,7 +1,7 @@
const express = require("express");
const eventsSheetController = require("../controllers/eventsheet");
const {loadEventLineup} = require("./eventlineup");
const {loadEvent} = require("./event");
const {loadEvent, loadEvents} = require("./event");
const {loadRecentAndUpcomingEvents} = require("../middlewares/bulkload")
const router = express.Router();
const tsUtils = require('../lib/utils')
@@ -10,46 +10,6 @@ const multer = require("multer");
const upload = multer()
// Middleware
const loadEvents = async (req,res,next) => {
const {team_id, event_id} = req.params
req.timeline = {}
await Promise.all(req.promises)
const {recent_events, upcoming_events} = req
const eventIds = [...recent_events.map(e=>e.id), event_id, ...upcoming_events.map(e=>e.id)]
// if (!req.event_lineup){
bulkLoadTypes = ['event','eventLineup', 'eventLineupEntry']
req.promises.push(
teamsnap.bulkLoad(
{teamId: team_id, types: bulkLoadTypes, scopeTo:'event', event__id:eventIds},
null,
(err, items) => {teamsnapCallback(err, items, {req, source:"loadEvents", method:'bulkLoad'})}
)
.then(items => tsUtils.groupTeamsnapItems(items, bulkLoadTypes))
.then(items => {
req.timeline.events = items.events;
req.timeline.event_lineups = items.eventLineups;
req.timeline.event_lineup_entries = items.eventLineupEntries;
})
)
req.promises.push(
teamsnap.loadAvailabilities(
{eventId: eventIds},
(err, items) => {teamsnapCallback(err, items, {req, source:"loadEvents", method:'loadAvailabilities'})}
).then(availabilities => {
req.timeline.availabilities = availabilities
}
)
)
// }
// else {
// // const {event_lineup} = req
// }
const {event_lineup} = req
next();
}
const linksForEventSheet = async (req, res, next) => {
await Promise.all(req.promises)
const events = [...req.recent_events, req.event, ...req.upcoming_events]

View File

@@ -192,6 +192,8 @@ a.Panel-row {
div[id^="event-lineup"] {
max-width: 576px;
counter-reset: lineup-sequence-counter 0;
margin-left: 8px;
margin-right: 9px;
}
.lineup-slot {

View File

@@ -1,131 +1,124 @@
{{>emailmodal}}
<div class="u-spaceAuto" id="event-lineup-{{event.id}}" data-event-lineup-id="{{event_lineup.id}}" data-event-id="{{event.id}}">
<form onsubmit="onSubmit(this,event)" action="#">
<input type="hidden" name="event_lineup_id" value="{{event_lineup.id}}">
{{!-- <input type="hidden" name="_csrf" value="{{csrfToken}}"> --}}
<input type="hidden" name="csrfToken" value="{{csrfToken}}">
<div class="Panel Panel--full">
<div class="Panel-header u-padEndsSm">
<h3 style="flex: 1 1 0%;">{{event.formattedTitle}}</h3>
<div class="ButtonGroup">
<button class="Button Button--orange" type="submit" formmethod="post">
<div>
<span id="teamsnap-icon">{{{embeddedSvgFromPath "/media/teamsnap_star.svg"}}}</span>
<span id="waiting-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/loader.svg" "Icon--loader"}}}</span>
<span id="success-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/check.svg"}}}</span>
<span id="failure-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg"}}}</span>
Save
<div class="u-flex" id="lineup-container">
<div class="u-spaceSidessAuto" id="event-lineup-{{event.id}}" data-event-lineup-id="{{event_lineup.id}}" data-event-id="{{event.id}}">
<form onsubmit="onSubmit(this,event)" action="#">
<input type="hidden" name="event_lineup_id" value="{{event_lineup.id}}">
{{!-- <input type="hidden" name="_csrf" value="{{csrfToken}}"> --}}
<input type="hidden" name="csrfToken" value="{{csrfToken}}">
<div class="Panel Panel--full">
<div class="Panel-header u-padEndsSm">
<h3 style="flex: 1 1 0%;">{{event.formattedTitle}}</h3>
<div class="ButtonGroup">
<button class="Button Button--orange" type="submit" formmethod="post">
<div>
<span id="teamsnap-icon">{{{embeddedSvgFromPath "/media/teamsnap_star.svg"}}}</span>
<span id="waiting-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/loader.svg" "Icon--loader"}}}</span>
<span id="success-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/check.svg"}}}</span>
<span id="failure-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg"}}}</span>
Save
</div>
</button>
<div class="Button Button--orange .u-padSidesXs Popup" onclick="togglePopup(this)">
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/caret-down.svg"}}}
<div class="Popup-container Popup-container--down Popup-container--right" style="width: 200px">
<div class="Popup-content u-textDecorationNone">
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="emailModal(this, '{{event_lineup.id}}/email')">
{{{embeddedSvgFromPath "/bootstrap-icons/envelope.svg"}}}
<span>Generate Email</span>
</a>
<hr class="Divider u-spaceEndsNone">
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="../sheet">
{{{embeddedSvgFromPath "/bootstrap-icons/book.svg"}}}
<span>Lineup Card</span>
</a>
<hr class="Divider u-spaceEndsNone">
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="insertLineup(1, {{team.id}}, {{event.id}}, this)">
{{{embeddedSvgFromPath "/bootstrap-icons/caret-right.svg"}}}
<span>Insert next lineup</span>
</a>
<hr class="Divider u-spaceEndsNone">
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="insertLineup(-1, {{team.id}}, {{event.id}}, this)">
{{{embeddedSvgFromPath "/bootstrap-icons/caret-left.svg"}}}
<span>Insert previous lineup</span>
</a>
</div>
</div>
</button>
<div class="Button Button--orange .u-padSidesXs Popup" onclick="togglePopup(this)">
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/caret-down.svg"}}}
<div class="Popup-container Popup-container--down Popup-container--right" style="width: 200px">
<div class="Popup-content u-textDecorationNone">
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="emailModal(this, '{{event_lineup.id}}/email')">
{{{embeddedSvgFromPath "/bootstrap-icons/envelope.svg"}}}
<span>Generate Email</span>
</a>
<hr class="Divider u-spaceEndsNone">
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="../sheet">
{{{embeddedSvgFromPath "/bootstrap-icons/book.svg"}}}
<span>Lineup Card</span>
</a>
</div>
</div>
</div>
<div class=" Panel-body u-padEndsSm">
<div class=" u-padSidesSm">
<div class="date">{{dateFormat event.startDate "ddd, MMM D h:mm A" }}</div>
<div class="location">{{event.locationName}}</div>
</div>
<div class=" availability-bar fullwidth">
</div>
</div>
</div>
<div class=" Panel-body u-padEndsSm">
<div class=" u-padSidesSm">
<div class="date">{{dateFormat event.startDate "ddd, MMM D h:mm A" }}</div>
<div class="location">{{event.locationName}}</div>
<div id="lineup-starting-{{event.id}}" class="Panel u-maxWidthSm starting Panel--fullWidthMobile Panel--full">
<div class="Panel-body">
<div class="Panel-row Panel-title u-padXs">
<i>{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}</i>
<span>Starting Lineup</span>
</div>
<div class=" availability-bar fullwidth">
<div class=" Panel-row Grid Grid--fit u-textBold u-textCenter u-padXs">
{{#each (positions)}}
<div class="Grid-cell position-status">{{this}}</div>
{{/each}}
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInStartingLineup this)}}
{{> slot member=this}}
{{/if}}
{{/each}}
</div>
</div>
</div>
</div>
<div id="lineup-starting-{{event.id}}" class="Panel u-maxWidthSm starting Panel--fullWidthMobile Panel--full">
<div class="Panel-body">
<div id="lineup-positiononly-{{event.id}}" class="Panel u-maxWidthSm position-only Panel--full">
<div class="Panel-row Panel-title u-padXs">
<i>{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}</i>
<span>Starting Lineup</span>
</div>
<div class=" Panel-row Grid Grid--fit u-textBold u-textCenter u-padXs">
{{#each (positions)}}
<div class="Grid-cell position-status">{{this}}</div>
{{/each}}
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInStartingLineup this)}}
{{> slot member=this}}
{{/if}}
{{/each}}
</div>
</div>
</div>
<div id="lineup-positiononly-{{event.id}}" class="Panel u-maxWidthSm position-only Panel--full">
<div class="Panel-row Panel-title u-padXs">
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}
<span>Position Only</span>
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInPositionOnly this)}}
{{> slot member=this}}
{{/if}}
{{/each}}
</div>
</div>
<div id="lineup-bench-{{event.id}}" class="Panel u-maxWidthSm bench Panel--full">
<div class="Panel-row Panel-title u-padXs">
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-minus.svg"}}}
<span>Bench</span>
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInBench this)}}
{{> slot member=this event=../event}}
{{/if}}
{{/each}}
</div>
</div>
<div id="lineup-out-{{event.id}}" class="Panel u-maxWidthSm out Panel--full">
<div class="Panel-row Panel-title u-padXs u-flex">
<div><span style="flex: 1 1 0%;">{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-x.svg"}}}Out</span></div>
<div class="u-flexGrow1"></div>
<div class="Toggle">
<input class="Toggle-input" type="checkbox" id="enable-slots" onclick="toggleChildSlots(this);">
<label class="Toggle-label" for="enable-slots"></label>
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}
<span>Position Only</span>
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInPositionOnly this)}}
{{> slot member=this}}
{{/if}}
{{/each}}
</div>
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInOut this)}}
{{> slot member=this}}
{{/if}}
{{/each}}
</div>
<div id="lineup-bench-{{event.id}}" class="Panel u-maxWidthSm bench Panel--full">
<div class="Panel-row Panel-title u-padXs">
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-minus.svg"}}}
<span>Bench</span>
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInBench this)}}
{{> slot member=this event=../event}}
{{/if}}
{{/each}}
</div>
</div>
<div id="lineup-out-{{event.id}}" class="Panel u-maxWidthSm out Panel--full">
<div class="Panel-row Panel-title u-padXs u-flex">
<div><span style="flex: 1 1 0%;">{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-x.svg"}}}Out</span></div>
<div class="u-flexGrow1"></div>
<div class="Toggle">
<input class="Toggle-input" type="checkbox" id="enable-slots" onclick="toggleChildSlots(this);">
<label class="Toggle-label" for="enable-slots"></label>
</div>
</div>
<div class="slot-set">
{{#each members}}
{{#if (isInOut this)}}
{{> slot member=this}}
{{/if}}
{{/each}}
</div>
</div>
</form>
</div>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
<script src="/js/eventlineup.js"></script>
<script src="/js/tinymce.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
colorPositions();
initFlagsCheckboxes();
refreshLineup();
tinymce.init({
selector:"#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})
})
</script>

View File

@@ -1,7 +1,7 @@
<div id="modal" class="Modal Modal--clickableBg">
<div class="Modal-bgDismiss" onclick="javascript:this.closest('.Modal').classList.toggle('is-open')"></div>
<div class="Modal-bgDismiss" onclick="javascript:this.closest('.Modal').remove();tinymce.remove();"></div>
<div class="Modal-content">
<div onclick="javascript:this.closest('.Modal').classList.toggle('is-open')">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg" "Modal-iconDismiss"}}}</div>
<div onclick="javascript:this.closest('.Modal').remove();tinymce.remove();">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg" "Modal-iconDismiss"}}}</div>
<div class="Modal-header">
<div class="Modal-title">Email</div>
</div>
@@ -17,7 +17,7 @@
</div>
<div class="FieldGroup">
<label class="FieldGroup-label">Lineup</label>
<div class="lineup-email"></div>
<div class="lineup-email">{{>email_table}}</div>
</div>
<div class="FieldGroup">
<button class="Button" role="button" onclick="submitEmail();">Submit</button>
@@ -26,3 +26,4 @@
</div>
</div>
</div>
</script>