Merge branch 'main' into docker
This commit is contained in:
@@ -169,9 +169,9 @@ app.use(function (err, req, res, next) {
|
||||
});
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
// app.use(function (req, res, next) {
|
||||
// next(createError(404));
|
||||
// });
|
||||
app.use(function (req, res, next) {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
app.set('trust proxy')
|
||||
|
||||
|
||||
@@ -67,3 +67,22 @@ exports.getEvent = async (req, res, next) => {
|
||||
};
|
||||
res.render("event/show", context);
|
||||
};
|
||||
|
||||
exports.sendAvailabilityReminders = async (req,res,next) => {
|
||||
await Promise.all(req.promises)
|
||||
if (req.params.event_id != req.body.eventId) {
|
||||
// Load actual event. Do I want this to be an error? probably
|
||||
res.status(500).send()
|
||||
}
|
||||
|
||||
const {event} = req
|
||||
const {eventId, memberIds} = req.body
|
||||
const sendingMember = req.members.find(m=>m.userId==req.user.id)
|
||||
try {
|
||||
await teamsnap.sendAvailabilityReminders(event, sendingMember, memberIds)
|
||||
res.status(200).send('OK')
|
||||
} catch (err) {
|
||||
res.status(500).send()
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -14,6 +14,22 @@ const statusCodeIcons = {
|
||||
undefined: embeddedSvgFromPath("/bootstrap-icons/question-lg.svg")
|
||||
}
|
||||
|
||||
const statusCodeClasses = {
|
||||
1: "u-colorPositive",
|
||||
0: "u-colorNegative",
|
||||
2: "u-colorPrimary",
|
||||
null: "u-colorGrey",
|
||||
undefined: "u-colorGrey"
|
||||
}
|
||||
|
||||
const statusCodeButtonClasses = {
|
||||
1: "Button--yes",
|
||||
0: "Button--no",
|
||||
2: "Button--maybe",
|
||||
null: "",
|
||||
undefined: ""
|
||||
}
|
||||
|
||||
exports.helpers = {
|
||||
flagsString: (flags) => {
|
||||
return flags != null ? Array.from(flags).join(",") : ''
|
||||
@@ -21,25 +37,8 @@ exports.helpers = {
|
||||
plus1: (i) => Number(i)+1,
|
||||
positions: () => ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH", "DR"],
|
||||
defense_positions: () => ["C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "P"],
|
||||
avail_status_code_icon: (status_code) => {
|
||||
const icon_classes = {
|
||||
1: "u-colorPositive",
|
||||
0: "u-colorNegative",
|
||||
2: "u-colorPrimary",
|
||||
null: "u-colorGrey",
|
||||
undefined: "u-colorGrey"
|
||||
}
|
||||
|
||||
const button_classes = {
|
||||
1: "Button--yes",
|
||||
0: "Button--no",
|
||||
2: "Button--maybe",
|
||||
null: "",
|
||||
undefined: ""
|
||||
}
|
||||
|
||||
return `<button class="Button Button--smallSquare ${button_classes[status_code]}" type="button"><span class="">${statusCodeIcons[status_code]}</span></button>`
|
||||
},
|
||||
avail_status_code_class: (status_code) => statusCodeButtonClasses[status_code],
|
||||
avail_status_code_icon: (status_code) => statusCodeIcons[status_code],
|
||||
positionLabelWithoutFlags: (label) => {
|
||||
const {positionLabelWithoutFlags} = parsePositionLabel(label);
|
||||
return positionLabelWithoutFlags
|
||||
@@ -92,6 +91,12 @@ exports.helpers = {
|
||||
statusShortLookup[NONE] = "UNK"
|
||||
statusShortLookup[undefined] = "UNK"
|
||||
return (statusShortLookup[availability?.statusCode])
|
||||
},
|
||||
filterNonPlayers: (members) => {
|
||||
return members.filter(m=>!m.isNonPlayer)
|
||||
},
|
||||
joinMemberEmailAddresses: (members) => {
|
||||
return members.map(m=>m.emailAddresses.join(',')).join(',')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,9 +126,13 @@ exports.getAdjacentEventLineup = async (req, res) => {
|
||||
} else {
|
||||
throw new Error('Index must be positive or negative number')
|
||||
}
|
||||
if (!event) {
|
||||
res.status(500).send()
|
||||
return
|
||||
}
|
||||
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 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)
|
||||
@@ -142,7 +151,7 @@ attachBenchcoachPropertiesToMember = (members, event_lineup_entries, availabilit
|
||||
// as far as I can tell, member_name should consistently be formulated from first and last name
|
||||
// perhaps could have some edge cases if first or last names change, but this *should be* exceedingly rare.
|
||||
const member_name = `${member.firstName} ${member.lastName}`
|
||||
const event_lineup_entry = event_lineup_entries.find(e=> e.memberId == member.id || e.memberName == member_name)
|
||||
const event_lineup_entry = event_lineup_entries?.find(e=> e.memberId == member.id || e.memberName == member_name)
|
||||
const availability = availabilities.find(e=>e.memberId == member.id)
|
||||
member.benchcoach.availability = availability
|
||||
if (event_lineup_entry != null) {
|
||||
|
||||
@@ -82,7 +82,7 @@ exports.getLineupCard = (req, res, next) => {
|
||||
availabilities: items.filter((i) => i.type == "availability").sort(tsUtils.teamsnapMembersSortLineupAvailabilityLastName),
|
||||
all_lineup_entries: items.filter((i) => i.type == "eventLineupEntry"),
|
||||
event_lineup_entries_offense: items
|
||||
.filter((i) => i.type == "eventLineupEntry" && i.eventId == event_id && !i.label.includes("[PO]"))
|
||||
.filter((i) => i.type == "eventLineupEntry" && i.eventId == event_id && !i.label.has("[PO]"))
|
||||
.sort((a, b) => a.sequence - b.sequence),
|
||||
event_lineup_entries: items
|
||||
.filter((i) => i.type == "eventLineupEntry" && i.eventId == event_id)
|
||||
|
||||
@@ -7,7 +7,7 @@ exports.offenseLineup = (number_of_slots, event_lineup_entries, members, options
|
||||
|
||||
for (let i = 0; i < number_of_slots; i++){
|
||||
const event_lineup_entry = event_lineup_entries ? event_lineup_entries[i] : null
|
||||
if (event_lineup_entry && !parsePositionLabel(event_lineup_entry.label).positionFlags.includes('PO')){
|
||||
if (event_lineup_entry && !parsePositionLabel(event_lineup_entry.label).positionFlags.has('PO')){
|
||||
results += options.fn({
|
||||
sequence: event_lineup_entry.sequence,
|
||||
member: members.find(member=> event_lineup_entry.memberId == member.id || event_lineup_entry.memberName == `${member.firstName} ${member.lastName}`),
|
||||
|
||||
@@ -50,17 +50,6 @@ teamsnapMembersSortAvailabilityLastName = (a, b) => {
|
||||
}
|
||||
exports.teamsnapMembersSortAvailabilityLastName = teamsnapMembersSortAvailabilityLastName
|
||||
|
||||
exports.initTeamsnap = (req, res, next) => {
|
||||
if (!teamsnap.isAuthed()) {
|
||||
teamsnap.init(process.env["TEAMSNAP_CLIENT_ID"]);
|
||||
teamsnap.auth(req.user.accessToken);
|
||||
}
|
||||
teamsnap.loadCollections((err) => {
|
||||
teamsnap.enablePersistence();
|
||||
next(req, res, next);
|
||||
});
|
||||
};
|
||||
|
||||
exports.teamsnapCallback = (err,result, d) => {
|
||||
if (Array.isArray(result)){
|
||||
types = new Set(result.map(i=>i.type))
|
||||
@@ -167,7 +156,19 @@ exports.compilePositionLabel = (label, flags) => {
|
||||
return label
|
||||
}
|
||||
else {
|
||||
const flags_set = new Set(flags.split(',').map(s=>s.trim()))
|
||||
const flags_set = toFlagsSet(flags)
|
||||
return `${label} [${Array.from(flags_set).sort().join(',')}]`
|
||||
}
|
||||
}
|
||||
|
||||
function toFlagsSet(flags) {
|
||||
let flags_set
|
||||
if (typeof(flags) == 'string'){
|
||||
const flags_set = new Set(flags.split(',').map(s=>s.trim()))
|
||||
} else if (flags.constructor === Array){
|
||||
flags_set = new Set(flags)
|
||||
} else if (flags.constructor === Set){
|
||||
flags_set = flags
|
||||
}
|
||||
return flags_set
|
||||
}
|
||||
@@ -1,25 +1,26 @@
|
||||
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 = ""
|
||||
var subject_date
|
||||
if (event_id) {
|
||||
const event = await teamsnap.loadEvents({id: event_id}).pop()
|
||||
subject_date = event.startDate.toISOString().slice(0,10)
|
||||
const new_date = new Date(event.startDate.getTime()+10000);
|
||||
subject_date = event.startDate
|
||||
}
|
||||
else {
|
||||
subject_date = new Date().toISOString().slice(0,10)
|
||||
subject_date = new Date()
|
||||
}
|
||||
req.promises.push(
|
||||
teamsnap.bulkLoad({
|
||||
teamId: team_id,
|
||||
types: ["event", "availabilitySummary"],
|
||||
scopeTo: "event",
|
||||
event__startedAfter: subject_date,
|
||||
event__pageSize: page_size + 1
|
||||
event__startedAfter: new Date(subject_date.getTime()+10000),
|
||||
event__pageSize: page_size
|
||||
})
|
||||
.then(items => tsUtils.groupTeamsnapItems(items))
|
||||
.then((items)=>{
|
||||
req.upcoming_events=items.events ? items.events.slice(1) : [];
|
||||
req.upcoming_events=items.events ? items.events : [];
|
||||
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) => {
|
||||
teamId: team_id,
|
||||
types: ["event", "availabilitySummary"],
|
||||
scopeTo: "event",
|
||||
event__startedBefore: subject_date,
|
||||
event__startedBefore: new Date(subject_date.getTime()-10000),
|
||||
event__pageSize: page_size,
|
||||
event__sortStartDate: "desc"
|
||||
})
|
||||
|
||||
@@ -1004,21 +1004,21 @@ h6 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.Button--blue {
|
||||
.Button--blue, button:has(+ .position-label-flags :checked) {
|
||||
background-color: #1A6BAF;
|
||||
border-color: #15568c;
|
||||
color: #ffffff;
|
||||
}
|
||||
.Button--blue:hover, .Button--blue:active, .Button--blue:focus {
|
||||
.Button--blue:hover, button:hover:has(+ .position-label-flags :checked), .Button--blue:active, button:active:has(+ .position-label-flags :checked), .Button--blue:focus, button:focus:has(+ .position-label-flags :checked) {
|
||||
background-color: #17609e;
|
||||
border-color: #134d7e;
|
||||
color: #ffffff;
|
||||
}
|
||||
.Button--blue.is-active {
|
||||
.Button--blue.is-active, button.is-active:has(+ .position-label-flags :checked) {
|
||||
background-color: #17609e;
|
||||
color: #ffffff;
|
||||
}
|
||||
.Button--blue.is-disabled, .Button--blue.is-disabled:hover, .Button--blue.is-disabled:active, .Button--blue:disabled, .Button--blue:disabled:hover, .Button--blue:disabled:active {
|
||||
.Button--blue.is-disabled, button.is-disabled:has(+ .position-label-flags :checked), .Button--blue.is-disabled:hover, button.is-disabled:hover:has(+ .position-label-flags :checked), .Button--blue.is-disabled:active, button.is-disabled:active:has(+ .position-label-flags :checked), .Button--blue:disabled, button:disabled:has(+ .position-label-flags :checked), .Button--blue:disabled:hover, button:disabled:hover:has(+ .position-label-flags :checked), .Button--blue:disabled:active, button:disabled:active:has(+ .position-label-flags :checked) {
|
||||
background-color: #1A6BAF;
|
||||
border-color: #15568c;
|
||||
color: #ffffff;
|
||||
@@ -7137,8 +7137,7 @@ div[id^=event-lineup] .Panel.position-only .Panel-cell:has(.sequence), div[id^=e
|
||||
}
|
||||
|
||||
.Panel .Panel {
|
||||
border: none;
|
||||
margin: 0;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.scroll-horizontal {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -774,6 +774,7 @@ td.is-present-checkbox.available-status-code-None > span {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
#front-cover .opponent img, #front-cover .team img {
|
||||
height: 115px;
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sourceRoot":"","sources":["../../scss/eventsheet.scss"],"names":[],"mappings":";AAAQ;AACA;AACA;AACA;AACA;AAER;EACE;EACA;EACA;EACA;;AAGF;EACE;;AAGF;AACA;EACE;IACE;IACA;;;AAIJ;AACA;EACE;IACE;;EAEF;IACE;;EAEF;IACE;IACA;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;AACA;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAKA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAQR;EACE;;;AAGF;EACE;;;AAOF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;AACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;AAAA;EAEE;EACA;EACA;EACA,qBACE;;;AAIJ;AAAA;EAEE;EACA;EACA;EACA,qBACE;;;AAIJ;AAAA;AAAA;AAAA;EAIE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAKF;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAQN;EACE;;;AAGF;AACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAKA;EACE;EACA;EACA;EACA,qBACE;;AAIJ;EACE;;AAGF;EACE;;AAGF;AACE;EACA;EACA;EACA;AACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;EACA;;AAGF;EACE;EACA;;AACA;EACE;;AAQJ;EACE;EACA;EACA;;AAEF;EACE;;;AAON;EACE;;AAGF;EACE;;AAIA;EACE;EACA;;AAMF;EACE;;AAGF;EAOE;EACA;EACA;EACA;;AATA;EACE;;AACA;EACE;;;AAeV;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAMI;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAUZ;EACE;EAEA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EAIE;EACA;EACA;;AALA;EACE;;AAKF;EACI;;;AASV;EACE;AACA;EACA;EAEA;EACA;AACA;;AAEA;EACE;EACA;;AAGF;EACE;;AACA;EACE;;;AAON;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;AACA;AACA;AACA;EACA;EAEA;EACA;EACA;EACA;EACA;;;AAKF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AASA;AACE;EACA;EACA;AACA;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACI;EACA;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;EAEE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAMN;EACE;EACA;EACA;;AAEF;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;;AAGF;EACE;EACA;EACA;;AAEA;EACE;;AAQJ;EACE;;AAGF;EACE;;AAGF;EACE;;;AAOJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;AACA;AAAA;;;AAIF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACI;EACA;EACA;EACA;;AAGJ;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE","file":"eventsheet.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["../../scss/eventsheet.scss"],"names":[],"mappings":";AAAQ;AACA;AACA;AACA;AACA;AAER;EACE;EACA;EACA;EACA;;AAGF;EACE;;AAGF;AACA;EACE;IACE;IACA;;;AAIJ;AACA;EACE;IACE;;EAEF;IACE;;EAEF;IACE;IACA;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;AACA;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAKA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAQR;EACE;;;AAGF;EACE;;;AAOF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;AACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;AAAA;EAEE;EACA;EACA;EACA,qBACE;;;AAIJ;AAAA;EAEE;EACA;EACA;EACA,qBACE;;;AAIJ;AAAA;AAAA;AAAA;EAIE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAKF;EACE;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAQN;EACE;;;AAGF;AACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAKA;EACE;EACA;EACA;EACA,qBACE;;AAIJ;EACE;;AAGF;EACE;;AAGF;AACE;EACA;EACA;EACA;AACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;EACA;;AAGF;EACE;EACA;;AACA;EACE;;AAQJ;EACE;EACA;EACA;;AAEF;EACE;;;AAON;EACE;;AAGF;EACE;;AAIA;EACE;EACA;;AAMF;EACE;;AAGF;EAOE;EACA;EACA;EACA;;AATA;EACE;;AACA;EACE;;;AAeV;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAMI;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAIR;EACE,SALM;;AAUZ;EACE;EAEA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EAIE;EACA;EACA;;AALA;EACE;;AAKF;EACI;;;AASV;EACE;AACA;EACA;EAEA;EACA;AACA;;AAEA;EACE;EACA;;AAGF;EACE;;AACA;EACE;;;AAON;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;AACA;AACA;AACA;EACA;EAEA;EACA;EACA;EACA;EACA;;;AAKF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AASA;AACE;EACA;EACA;AACA;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACI;EACA;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;EAEE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAMN;EACE;EACA;EACA;;AAEF;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;;AAGF;EACE;EACA;EACA;;AAEA;EACE;;AAQJ;EACE;;AAGF;EACE;;AAGF;EACE;;;AAOJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;AACA;AAAA;;;AAIF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACI;EACA;EACA;EACA;;AAGJ;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE","file":"eventsheet.css"}
|
||||
@@ -50,6 +50,7 @@ function initFlagsCheckboxes(){
|
||||
).forEach((slot, i) => {
|
||||
const flags = new Set(slot.querySelector("input[name*=flags]")?.value?.split(',')?.map(s=>s.trim())) || new Set()
|
||||
if (flags.has('DHd')) {
|
||||
console.log('dhd')
|
||||
slot.querySelector('[name=flag-dhd]').checked = true;
|
||||
}
|
||||
|
||||
@@ -509,14 +510,14 @@ function toggleChildSlots (element) {
|
||||
console.log(element.closest(".slot-set"))
|
||||
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
|
||||
console.log(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 ')
|
||||
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.toggle('u-hidden')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function submitEmail () {
|
||||
async function copyEmailTable (element) {
|
||||
// range=document.createRange();
|
||||
// window.getSelection().removeAllRanges();
|
||||
// // range.selectNode(document.querySelector('.Modal').querySelector('.Modal-body'));
|
||||
@@ -558,16 +559,25 @@ async function submitEmail () {
|
||||
margin: 0;
|
||||
}</style>
|
||||
`
|
||||
html_content = emailStyle+tinymce.activeEditor.getContent()
|
||||
console.log(html_content)
|
||||
// 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/html': new Blob([html_content], {type: 'text/html'})
|
||||
})
|
||||
])
|
||||
// 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();
|
||||
}
|
||||
|
||||
function insertLineup(direction, teamId, eventId, element) {
|
||||
@@ -657,11 +667,77 @@ function initPage (){
|
||||
}
|
||||
|
||||
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')
|
||||
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='mailto') {
|
||||
console.log(el)
|
||||
console.log(el.dataset)
|
||||
const {to, bcc, subject} = el.dataset
|
||||
const params = new URLSearchParams({
|
||||
bcc, subject: encodeURIComponent(subject),
|
||||
})
|
||||
const url = `${protocol}:${to}?${params}`
|
||||
console.log(url)
|
||||
// location.href=`mailto:${to}${params}`
|
||||
const windowRef = window.open(url, '_blank');
|
||||
windowRef.focus();
|
||||
}
|
||||
|
||||
function sparkMailToLink(el) {
|
||||
const protocol = 'readdle-spark'
|
||||
const {to, bcc, subject} = el.dataset
|
||||
const url = `${protocol}://compose?recipient=${to}&bcc=${bcc}&subject=${encodeURIComponent(subject)}`
|
||||
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)
|
||||
@@ -1,6 +1,7 @@
|
||||
var express = require("express");
|
||||
var passport = require("passport");
|
||||
var TeamsnapStrategy = require("passport-teamsnap");
|
||||
const express = require("express");
|
||||
const passport = require("passport");
|
||||
const TeamsnapStrategy = require("passport-teamsnap");
|
||||
const {teamsnapCallback} = require('../lib/utils')
|
||||
// const {teamsnap} = require("../app");
|
||||
// Configure the TeamSnap strategy for use by Passport.
|
||||
//
|
||||
@@ -21,20 +22,17 @@ passport.use(
|
||||
proxy: true
|
||||
},
|
||||
async function (req, accessToken, refreshToken, profile, done) {
|
||||
json = JSON.parse(profile._raw);
|
||||
field_from_collection = (field_name) => {
|
||||
return json.collection.items[0].data.filter(
|
||||
(e) => e.name == field_name
|
||||
)[0].value;
|
||||
}
|
||||
const new_profile = { access_token: accessToken };
|
||||
new_profile["id"] = field_from_collection("id")
|
||||
new_profile["email"] = field_from_collection("email")
|
||||
new_profile["first_name"] = field_from_collection("first_name")
|
||||
new_profile["last_name"] = field_from_collection("last_name")
|
||||
// json = JSON.parse(profile._raw);
|
||||
const new_profile = {
|
||||
access_token: accessToken,
|
||||
};
|
||||
['id', 'email', 'first_name', 'last_name', 'managed_team_ids'].forEach(
|
||||
k => {
|
||||
new_profile[k] = profile.data[0].get(k)
|
||||
})
|
||||
|
||||
req.session.teamsnap_access_token = accessToken;
|
||||
await initTeamsnap(process.env["TEAMSNAP_CLIENT_ID"], accessToken)
|
||||
await initTeamsnap(accessToken)
|
||||
return done(null, new_profile);
|
||||
}
|
||||
)
|
||||
@@ -59,6 +57,7 @@ passport.serializeUser(function (user, cb) {
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
accessToken: user.access_token,
|
||||
managed_team_ids: user.managed_team_ids
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -66,10 +65,12 @@ passport.serializeUser(function (user, cb) {
|
||||
passport.deserializeUser(function (user, cb) {
|
||||
process.nextTick(async function () {
|
||||
console.log("L#68 deserializing user id", user.id);
|
||||
if (!teamsnap.isAuthed()){
|
||||
await initTeamsnap(process.env["TEAMSNAP_CLIENT_ID"], user.accessToken)
|
||||
try {
|
||||
await initTeamsnap(user.accessToken)
|
||||
return cb(null, user);
|
||||
} catch (err) {
|
||||
return cb(err)
|
||||
}
|
||||
return cb(null, user);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -86,9 +87,11 @@ var router = express.Router();
|
||||
router.get("/login", function (req, res, next) {
|
||||
// https://stackoverflow.com/a/73056806/20522015
|
||||
returnTo = req.session.returnTo;
|
||||
// req.session.regenerate(); // this is not working right as of now...
|
||||
req.session.returnTo = returnTo;
|
||||
res.render("login", {layout:"layouts/main"});
|
||||
if (req.user?.accessToken){
|
||||
res.redirect(returnTo || "/");
|
||||
} else {
|
||||
res.render("login", {layout:"layouts/main"});
|
||||
}
|
||||
});
|
||||
|
||||
/* GET /login/federated/teamsnap
|
||||
@@ -125,10 +128,9 @@ router.get(
|
||||
})
|
||||
);
|
||||
|
||||
const initTeamsnap = async (clientID, accessToken) => {
|
||||
teamsnap.init(clientID);
|
||||
teamsnap.auth(accessToken);
|
||||
await teamsnap.loadCollections();
|
||||
const initTeamsnap = async (accessToken) => {
|
||||
await teamsnap.auth(accessToken);
|
||||
await teamsnap.loadCollections(teamsnapCallback);
|
||||
await teamsnap.enablePersistence();
|
||||
}
|
||||
|
||||
@@ -138,7 +140,7 @@ const ensureLoggedIn = (req, res, next) => {
|
||||
res.redirect("/login");
|
||||
// return next();
|
||||
}
|
||||
else{
|
||||
else {
|
||||
req.user = req.session.passport.user
|
||||
next();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ const eventsController = require("../controllers/event");
|
||||
const router = express.Router();
|
||||
const tsUtils = require("../lib/utils")
|
||||
const {teamsnapCallback} = require("../lib/utils")
|
||||
const multer = require("multer");
|
||||
const upload = multer()
|
||||
|
||||
// Middleware
|
||||
const loadEvent = (req,res,next) => {
|
||||
@@ -68,6 +70,7 @@ router.use("/:team_id([0-9]+)/event/:event_id([0-9]+)", loadEvent)
|
||||
// Routes
|
||||
router.get("/:team_id([0-9]+)/schedule", eventsController.getEvents);
|
||||
router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)", eventsController.getEvent);
|
||||
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/availability_reminders", upload.none(), eventsController.sendAvailabilityReminders)
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -354,12 +354,16 @@ div[id^="event-lineup"] .Panel {
|
||||
.Panel .Panel{
|
||||
// padding: 0;
|
||||
// border-radius: 0;
|
||||
border: none;
|
||||
// border: none;
|
||||
// border-top: 1px solid #d6d6d6;
|
||||
// border-bottom: 1px solid #d6d6d6;
|
||||
margin: 0;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.scroll-horizontal {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
button:has(+.position-label-flags :checked) {
|
||||
@extend .Button--blue
|
||||
}
|
||||
@@ -880,7 +880,8 @@ td.is-present-checkbox.available-status-code-None > span {
|
||||
font-family: 'Pacifico';
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
flex-grow:1
|
||||
flex-grow:1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.opponent img, .team img{
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
<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 class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="/{{team.id}}/event/{{event.id}}/sheet">
|
||||
<span>{{{embeddedSvgFromPath "/bootstrap-icons/file-earmark.svg"}}}</span>
|
||||
<span class="u-hidden u-xs-inline">Game Sheet</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)">
|
||||
@@ -39,6 +39,25 @@
|
||||
{{{embeddedSvgFromPath "/bootstrap-icons/caret-left.svg"}}}
|
||||
<span>Insert previous lineup</span>
|
||||
</a>
|
||||
<div class="u-hidden">
|
||||
<hr class="Divider u-spaceEndsNone">
|
||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
||||
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/send.svg"}}}
|
||||
<span>Availability Reminders</span>
|
||||
</span>
|
||||
<hr class="Divider u-spaceEndsNone">
|
||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
||||
<span>Reset All Availabilities</span>
|
||||
</span>
|
||||
<hr class="Divider u-spaceEndsNone">
|
||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
||||
<span>Clear Lineup</span>
|
||||
</span>
|
||||
<hr class="Divider u-spaceEndsNone">
|
||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
||||
<span>Publish</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<div id="modal" class="Modal Modal--clickableBg">
|
||||
<div class="Modal-bgDismiss" onclick="javascript:this.closest('.Modal').remove();tinymce.remove();"></div>
|
||||
<div class="Modal-content">
|
||||
<div onclick="javascript:this.closest('.Modal').remove();tinymce.remove();">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg" "Modal-iconDismiss"}}}</div>
|
||||
<div class="Modal-header">
|
||||
@@ -17,10 +16,21 @@
|
||||
</div>
|
||||
<div class="FieldGroup">
|
||||
<label class="FieldGroup-label">Lineup</label>
|
||||
<div class="lineup-email">{{>email_table}}</div>
|
||||
<div class="lineup-email lineup-table">{{>email_table}}</div>
|
||||
</div>
|
||||
<div class="FieldGroup">
|
||||
<button class="Button" role="button" onclick="submitEmail();">Submit</button>
|
||||
<button class="Button" role="button" type="button" onclick="copyEmailTable(this)">
|
||||
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-fill.svg"}}}
|
||||
{{{embeddedSvgFromPath "/bootstrap-icons/table.svg"}}}
|
||||
Copy Table
|
||||
</button>
|
||||
<button class="Button" role="button" type="button" onclick="sparkMailToLink(this);",
|
||||
data-to="{{user.email}}"
|
||||
data-bcc="{{joinMemberEmailAddresses (filterNonPlayers members)}}"
|
||||
data-subject="{{dateFormat event.startDate "ddd, MMM D, YYYY h:mm A" }}, {{ event.locationName }}, ({{#if (isAway event) }}@{{/if}}{{ event.opponentName }})">
|
||||
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/mail.svg"}}}
|
||||
Spark Mail
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -17,13 +17,39 @@
|
||||
</div>
|
||||
<div class="Panel-cell u-padXs u-sizeFill u-flex">
|
||||
<div
|
||||
class="availability-status-code-{{
|
||||
class="Popup availability-status-code-{{
|
||||
member.benchcoach.availability?.statusCode
|
||||
}}"
|
||||
>
|
||||
{{#if member.benchcoach.availability}}{{{avail_status_code_icon member.benchcoach.availability.statusCode}}}{{/if}}
|
||||
{{#if member.benchcoach.availability}}
|
||||
{{#with member.benchcoach.availability}}
|
||||
<button class="Popup-toggle Button Button--smallSquare {{avail_status_code_class statusCode}}"
|
||||
type="button"
|
||||
data-control="popup"
|
||||
data-open="availablility-popup-{{memberId}}-{{eventId}}"
|
||||
onclick="this.closest('div').querySelector('.Popup-container').classList.toggle('is-open')"
|
||||
>
|
||||
{{#if notes}}{{{embeddedSvgFromPath "/bootstrap-icons/asterisk.svg"}}}{{else}}{{{avail_status_code_icon statusCode}}}{{/if}}
|
||||
</button>
|
||||
<div class="Popup-container Popup-container--left" data-popup="availablility-popup-{{memberId}}-{{eventId}}">
|
||||
<div class="Popup-content u-padSm u-textCenter">
|
||||
<h3 class="u-spaceBottomSm">Availability</h3>
|
||||
{{#if notes}}
|
||||
<p class="u-textLeft">“ <i>{{notes}}</i> ”</p>
|
||||
{{else}}
|
||||
<p class="u-textLeft">No notes.</p>
|
||||
{{/if}}
|
||||
<button type="button" class="Button u-spaceTopSm" onclick="sendAvailabilityReminder(this, {{eventId}}, ['{{memberId}}'], {{csrfToken}})">
|
||||
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/send.svg"}}}
|
||||
<span>Send Reminder</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="u-fontSizeLg u-textNoWrap">
|
||||
|
||||
<div class="u-fontSizeLg u-textNoWrap">
|
||||
<span class="lastname">
|
||||
{{member.lastName}}
|
||||
</span>
|
||||
@@ -35,14 +61,21 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="u-flexGrow1"></div>
|
||||
<div class="position-label-flags u-textNoWrap">
|
||||
<div class="Checkbox Checkbox--inline">
|
||||
<input class="Checkbox-input" type="checkbox" name="flag-drd" id="flag-drd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}" onclick="refreshLineup()">
|
||||
<label class="Checkbox-label" for="flag-drd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}">DR<small>d</small></label>
|
||||
</div>
|
||||
<div class="Checkbox Checkbox--inline">
|
||||
<input class="Checkbox-input" type="checkbox" name="flag-dhd" id="flag-dhd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}" onclick="refreshLineup()">
|
||||
<label class="Checkbox-label" for="flag-dhd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}">DH<small>d</small></label>
|
||||
<div class="Popup">
|
||||
<button type="button" class="Popup-toggle Button Button--smallSquare" onclick="this.closest('div').querySelector('.Popup-container').classList.toggle('is-open');this.blur();" href="javascript:void(0)">
|
||||
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/flag.svg"}}}
|
||||
</button>
|
||||
<div class="Popup-container Popup-container--rightHang position-label-flags">
|
||||
<div class="Popup-content u-padSm u-textCenter">
|
||||
<div class="Checkbox Checkbox--inline">
|
||||
<input class="Checkbox-input" type="checkbox" name="flag-drd" id="flag-drd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}" onclick="refreshLineup()">
|
||||
<label class="Checkbox-label" for="flag-drd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}">DR<small>d</small></label>
|
||||
</div>
|
||||
<div class="Checkbox Checkbox--inline">
|
||||
<input class="Checkbox-input" type="checkbox" name="flag-dhd" id="flag-dhd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}" onclick="refreshLineup()">
|
||||
<label class="Checkbox-label" for="flag-dhd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}">DH<small>d</small></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -158,8 +158,9 @@
|
||||
<div>
|
||||
<span class="name">{{event.opponentName}}</span>
|
||||
</div>
|
||||
{{#if opponent_logo.mediumUrl }}
|
||||
<img src="{{opponent_logo.mediumUrl}}">
|
||||
{{!-- <%= ::Temple::Utils.escape_html((image_tag opponent_logos[event.opponent.id].medium_url)) %> --}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="">
|
||||
<table>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
{{> navbar }}
|
||||
{{{_sections.header}}}
|
||||
</header>
|
||||
<main class="">
|
||||
<main class="u-sm-spaceSidesMd">
|
||||
{{{ body }}}
|
||||
</main>
|
||||
</body>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<img src ="/teamsnap-ui/assets/icons/schedule.svg" class="Icon">
|
||||
<span class="span u-hidden u-xs-inline">Schedule</span>
|
||||
</a>
|
||||
<a class="Button" href="members">
|
||||
<a class="Button u-hidden" href="members">
|
||||
<img src ="/teamsnap-ui/assets/icons/roster.svg" class="Icon">
|
||||
<span class="span u-hidden u-xs-inline">Roster</span>
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user