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
|
// catch 404 and forward to error handler
|
||||||
// app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
// next(createError(404));
|
next(createError(404));
|
||||||
// });
|
});
|
||||||
|
|
||||||
app.set('trust proxy')
|
app.set('trust proxy')
|
||||||
|
|
||||||
|
|||||||
@@ -67,3 +67,22 @@ exports.getEvent = async (req, res, next) => {
|
|||||||
};
|
};
|
||||||
res.render("event/show", context);
|
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,15 +14,7 @@ const statusCodeIcons = {
|
|||||||
undefined: embeddedSvgFromPath("/bootstrap-icons/question-lg.svg")
|
undefined: embeddedSvgFromPath("/bootstrap-icons/question-lg.svg")
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.helpers = {
|
const statusCodeClasses = {
|
||||||
flagsString: (flags) => {
|
|
||||||
return flags != null ? Array.from(flags).join(",") : ''
|
|
||||||
},
|
|
||||||
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",
|
1: "u-colorPositive",
|
||||||
0: "u-colorNegative",
|
0: "u-colorNegative",
|
||||||
2: "u-colorPrimary",
|
2: "u-colorPrimary",
|
||||||
@@ -30,7 +22,7 @@ exports.helpers = {
|
|||||||
undefined: "u-colorGrey"
|
undefined: "u-colorGrey"
|
||||||
}
|
}
|
||||||
|
|
||||||
const button_classes = {
|
const statusCodeButtonClasses = {
|
||||||
1: "Button--yes",
|
1: "Button--yes",
|
||||||
0: "Button--no",
|
0: "Button--no",
|
||||||
2: "Button--maybe",
|
2: "Button--maybe",
|
||||||
@@ -38,8 +30,15 @@ exports.helpers = {
|
|||||||
undefined: ""
|
undefined: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return `<button class="Button Button--smallSquare ${button_classes[status_code]}" type="button"><span class="">${statusCodeIcons[status_code]}</span></button>`
|
exports.helpers = {
|
||||||
|
flagsString: (flags) => {
|
||||||
|
return flags != null ? Array.from(flags).join(",") : ''
|
||||||
},
|
},
|
||||||
|
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_class: (status_code) => statusCodeButtonClasses[status_code],
|
||||||
|
avail_status_code_icon: (status_code) => statusCodeIcons[status_code],
|
||||||
positionLabelWithoutFlags: (label) => {
|
positionLabelWithoutFlags: (label) => {
|
||||||
const {positionLabelWithoutFlags} = parsePositionLabel(label);
|
const {positionLabelWithoutFlags} = parsePositionLabel(label);
|
||||||
return positionLabelWithoutFlags
|
return positionLabelWithoutFlags
|
||||||
@@ -92,6 +91,12 @@ exports.helpers = {
|
|||||||
statusShortLookup[NONE] = "UNK"
|
statusShortLookup[NONE] = "UNK"
|
||||||
statusShortLookup[undefined] = "UNK"
|
statusShortLookup[undefined] = "UNK"
|
||||||
return (statusShortLookup[availability?.statusCode])
|
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 {
|
} else {
|
||||||
throw new Error('Index must be positive or negative number')
|
throw new Error('Index must be positive or negative number')
|
||||||
}
|
}
|
||||||
|
if (!event) {
|
||||||
|
res.status(500).send()
|
||||||
|
return
|
||||||
|
}
|
||||||
const availabilitySummary = event.availabilitySummary
|
const availabilitySummary = event.availabilitySummary
|
||||||
const event_lineup = req.timeline.event_lineups.find(i=>i.eventId==event.id)
|
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)
|
const availabilities = req.timeline.availabilities.filter(i=>i.eventId==event.id)
|
||||||
attachBenchcoachPropertiesToMember(members, event_lineup_entries, availabilities)
|
attachBenchcoachPropertiesToMember(members, event_lineup_entries, availabilities)
|
||||||
members.sort(tsUtils.teamsnapMembersSortLineupAvailabilityLastName)
|
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
|
// 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.
|
// 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 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)
|
const availability = availabilities.find(e=>e.memberId == member.id)
|
||||||
member.benchcoach.availability = availability
|
member.benchcoach.availability = availability
|
||||||
if (event_lineup_entry != null) {
|
if (event_lineup_entry != null) {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ exports.getLineupCard = (req, res, next) => {
|
|||||||
availabilities: items.filter((i) => i.type == "availability").sort(tsUtils.teamsnapMembersSortLineupAvailabilityLastName),
|
availabilities: items.filter((i) => i.type == "availability").sort(tsUtils.teamsnapMembersSortLineupAvailabilityLastName),
|
||||||
all_lineup_entries: items.filter((i) => i.type == "eventLineupEntry"),
|
all_lineup_entries: items.filter((i) => i.type == "eventLineupEntry"),
|
||||||
event_lineup_entries_offense: items
|
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),
|
.sort((a, b) => a.sequence - b.sequence),
|
||||||
event_lineup_entries: items
|
event_lineup_entries: items
|
||||||
.filter((i) => i.type == "eventLineupEntry" && i.eventId == event_id)
|
.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++){
|
for (let i = 0; i < number_of_slots; i++){
|
||||||
const event_lineup_entry = event_lineup_entries ? event_lineup_entries[i] : null
|
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({
|
results += options.fn({
|
||||||
sequence: event_lineup_entry.sequence,
|
sequence: event_lineup_entry.sequence,
|
||||||
member: members.find(member=> event_lineup_entry.memberId == member.id || event_lineup_entry.memberName == `${member.firstName} ${member.lastName}`),
|
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.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) => {
|
exports.teamsnapCallback = (err,result, d) => {
|
||||||
if (Array.isArray(result)){
|
if (Array.isArray(result)){
|
||||||
types = new Set(result.map(i=>i.type))
|
types = new Set(result.map(i=>i.type))
|
||||||
@@ -167,7 +156,19 @@ exports.compilePositionLabel = (label, flags) => {
|
|||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
else {
|
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(',')}]`
|
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) => {
|
exports.loadRecentAndUpcomingEvents = async (req, res, next) => {
|
||||||
const {team_id, event_id} = req.params
|
const {team_id, event_id} = req.params
|
||||||
const page_size = req.query.page_size ? Number(req.query.page_size) : 4
|
const page_size = req.query.page_size ? Number(req.query.page_size) : 4
|
||||||
var subject_date = ""
|
var subject_date
|
||||||
if (event_id) {
|
if (event_id) {
|
||||||
const event = await teamsnap.loadEvents({id: event_id}).pop()
|
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 {
|
else {
|
||||||
subject_date = new Date().toISOString().slice(0,10)
|
subject_date = new Date()
|
||||||
}
|
}
|
||||||
req.promises.push(
|
req.promises.push(
|
||||||
teamsnap.bulkLoad({
|
teamsnap.bulkLoad({
|
||||||
teamId: team_id,
|
teamId: team_id,
|
||||||
types: ["event", "availabilitySummary"],
|
types: ["event", "availabilitySummary"],
|
||||||
scopeTo: "event",
|
scopeTo: "event",
|
||||||
event__startedAfter: subject_date,
|
event__startedAfter: new Date(subject_date.getTime()+10000),
|
||||||
event__pageSize: page_size + 1
|
event__pageSize: page_size
|
||||||
})
|
})
|
||||||
.then(items => tsUtils.groupTeamsnapItems(items))
|
.then(items => tsUtils.groupTeamsnapItems(items))
|
||||||
.then((items)=>{
|
.then((items)=>{
|
||||||
req.upcoming_events=items.events ? items.events.slice(1) : [];
|
req.upcoming_events=items.events ? items.events : [];
|
||||||
const availabilitySummaries=items.availabilitySummaries;
|
const availabilitySummaries=items.availabilitySummaries;
|
||||||
req.upcoming_events.forEach((event) => {
|
req.upcoming_events.forEach((event) => {
|
||||||
event.link('availabilitySummary', availabilitySummaries.find(a=>a.eventId==event.id))
|
event.link('availabilitySummary', availabilitySummaries.find(a=>a.eventId==event.id))
|
||||||
@@ -32,7 +33,7 @@ exports.loadRecentAndUpcomingEvents = async (req, res, next) => {
|
|||||||
teamId: team_id,
|
teamId: team_id,
|
||||||
types: ["event", "availabilitySummary"],
|
types: ["event", "availabilitySummary"],
|
||||||
scopeTo: "event",
|
scopeTo: "event",
|
||||||
event__startedBefore: subject_date,
|
event__startedBefore: new Date(subject_date.getTime()-10000),
|
||||||
event__pageSize: page_size,
|
event__pageSize: page_size,
|
||||||
event__sortStartDate: "desc"
|
event__sortStartDate: "desc"
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1004,21 +1004,21 @@ h6 {
|
|||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Button--blue {
|
.Button--blue, button:has(+ .position-label-flags :checked) {
|
||||||
background-color: #1A6BAF;
|
background-color: #1A6BAF;
|
||||||
border-color: #15568c;
|
border-color: #15568c;
|
||||||
color: #ffffff;
|
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;
|
background-color: #17609e;
|
||||||
border-color: #134d7e;
|
border-color: #134d7e;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
.Button--blue.is-active {
|
.Button--blue.is-active, button.is-active:has(+ .position-label-flags :checked) {
|
||||||
background-color: #17609e;
|
background-color: #17609e;
|
||||||
color: #ffffff;
|
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;
|
background-color: #1A6BAF;
|
||||||
border-color: #15568c;
|
border-color: #15568c;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
@@ -7137,8 +7137,7 @@ div[id^=event-lineup] .Panel.position-only .Panel-cell:has(.sequence), div[id^=e
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Panel .Panel {
|
.Panel .Panel {
|
||||||
border: none;
|
margin: 8px;
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroll-horizontal {
|
.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;
|
display: inline-flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
#front-cover .opponent img, #front-cover .team img {
|
#front-cover .opponent img, #front-cover .team img {
|
||||||
height: 115px;
|
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) => {
|
).forEach((slot, i) => {
|
||||||
const flags = new Set(slot.querySelector("input[name*=flags]")?.value?.split(',')?.map(s=>s.trim())) || new Set()
|
const flags = new Set(slot.querySelector("input[name*=flags]")?.value?.split(',')?.map(s=>s.trim())) || new Set()
|
||||||
if (flags.has('DHd')) {
|
if (flags.has('DHd')) {
|
||||||
|
console.log('dhd')
|
||||||
slot.querySelector('[name=flag-dhd]').checked = true;
|
slot.querySelector('[name=flag-dhd]').checked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,14 +510,14 @@ function toggleChildSlots (element) {
|
|||||||
console.log(element.closest(".slot-set"))
|
console.log(element.closest(".slot-set"))
|
||||||
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
|
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
|
||||||
console.log(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=>{
|
Array.from(cells).forEach(cell=>{
|
||||||
cell.classList.toggle('u-hidden')
|
cell.classList.toggle('u-hidden')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitEmail () {
|
async function copyEmailTable (element) {
|
||||||
// range=document.createRange();
|
// range=document.createRange();
|
||||||
// window.getSelection().removeAllRanges();
|
// window.getSelection().removeAllRanges();
|
||||||
// // range.selectNode(document.querySelector('.Modal').querySelector('.Modal-body'));
|
// // range.selectNode(document.querySelector('.Modal').querySelector('.Modal-body'));
|
||||||
@@ -558,16 +559,25 @@ async function submitEmail () {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}</style>
|
}</style>
|
||||||
`
|
`
|
||||||
html_content = emailStyle+tinymce.activeEditor.getContent()
|
// html_content = emailStyle+tinymce.activeEditor.getContent()
|
||||||
console.log(html_content)
|
// console.log(html_content)
|
||||||
|
const table = element.closest('form').querySelector('.lineup-table table')
|
||||||
|
|
||||||
navigator.clipboard.write(
|
// navigator.clipboard.write(
|
||||||
[new ClipboardItem(
|
// [new ClipboardItem(
|
||||||
{
|
// {
|
||||||
'text/plain': new Blob([tinymce.activeEditor.getContent({format: "text"})], {type: 'text/plain'}),
|
// // 'text/plain': new Blob([tinymce.activeEditor.getContent({format: "text"})], {type: 'text/plain'}),
|
||||||
'text/html': new Blob([html_content], {type: 'text/html'})
|
// '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) {
|
function insertLineup(direction, teamId, eventId, element) {
|
||||||
@@ -657,11 +667,77 @@ function initPage (){
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
|
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=>{
|
Array.from(cells).forEach(cell=>{
|
||||||
cell.classList.add('u-hidden')
|
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)
|
document.addEventListener('DOMContentLoaded', initPage)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
var express = require("express");
|
const express = require("express");
|
||||||
var passport = require("passport");
|
const passport = require("passport");
|
||||||
var TeamsnapStrategy = require("passport-teamsnap");
|
const TeamsnapStrategy = require("passport-teamsnap");
|
||||||
|
const {teamsnapCallback} = require('../lib/utils')
|
||||||
// const {teamsnap} = require("../app");
|
// const {teamsnap} = require("../app");
|
||||||
// Configure the TeamSnap strategy for use by Passport.
|
// Configure the TeamSnap strategy for use by Passport.
|
||||||
//
|
//
|
||||||
@@ -21,20 +22,17 @@ passport.use(
|
|||||||
proxy: true
|
proxy: true
|
||||||
},
|
},
|
||||||
async function (req, accessToken, refreshToken, profile, done) {
|
async function (req, accessToken, refreshToken, profile, done) {
|
||||||
json = JSON.parse(profile._raw);
|
// json = JSON.parse(profile._raw);
|
||||||
field_from_collection = (field_name) => {
|
const new_profile = {
|
||||||
return json.collection.items[0].data.filter(
|
access_token: accessToken,
|
||||||
(e) => e.name == field_name
|
};
|
||||||
)[0].value;
|
['id', 'email', 'first_name', 'last_name', 'managed_team_ids'].forEach(
|
||||||
}
|
k => {
|
||||||
const new_profile = { access_token: accessToken };
|
new_profile[k] = profile.data[0].get(k)
|
||||||
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")
|
|
||||||
|
|
||||||
req.session.teamsnap_access_token = accessToken;
|
req.session.teamsnap_access_token = accessToken;
|
||||||
await initTeamsnap(process.env["TEAMSNAP_CLIENT_ID"], accessToken)
|
await initTeamsnap(accessToken)
|
||||||
return done(null, new_profile);
|
return done(null, new_profile);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -59,6 +57,7 @@ passport.serializeUser(function (user, cb) {
|
|||||||
first_name: user.first_name,
|
first_name: user.first_name,
|
||||||
last_name: user.last_name,
|
last_name: user.last_name,
|
||||||
accessToken: user.access_token,
|
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) {
|
passport.deserializeUser(function (user, cb) {
|
||||||
process.nextTick(async function () {
|
process.nextTick(async function () {
|
||||||
console.log("L#68 deserializing user id", user.id);
|
console.log("L#68 deserializing user id", user.id);
|
||||||
if (!teamsnap.isAuthed()){
|
try {
|
||||||
await initTeamsnap(process.env["TEAMSNAP_CLIENT_ID"], user.accessToken)
|
await initTeamsnap(user.accessToken)
|
||||||
}
|
|
||||||
return cb(null, user);
|
return cb(null, user);
|
||||||
|
} catch (err) {
|
||||||
|
return cb(err)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,9 +87,11 @@ var router = express.Router();
|
|||||||
router.get("/login", function (req, res, next) {
|
router.get("/login", function (req, res, next) {
|
||||||
// https://stackoverflow.com/a/73056806/20522015
|
// https://stackoverflow.com/a/73056806/20522015
|
||||||
returnTo = req.session.returnTo;
|
returnTo = req.session.returnTo;
|
||||||
// req.session.regenerate(); // this is not working right as of now...
|
if (req.user?.accessToken){
|
||||||
req.session.returnTo = returnTo;
|
res.redirect(returnTo || "/");
|
||||||
|
} else {
|
||||||
res.render("login", {layout:"layouts/main"});
|
res.render("login", {layout:"layouts/main"});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* GET /login/federated/teamsnap
|
/* GET /login/federated/teamsnap
|
||||||
@@ -125,10 +128,9 @@ router.get(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const initTeamsnap = async (clientID, accessToken) => {
|
const initTeamsnap = async (accessToken) => {
|
||||||
teamsnap.init(clientID);
|
await teamsnap.auth(accessToken);
|
||||||
teamsnap.auth(accessToken);
|
await teamsnap.loadCollections(teamsnapCallback);
|
||||||
await teamsnap.loadCollections();
|
|
||||||
await teamsnap.enablePersistence();
|
await teamsnap.enablePersistence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ const eventsController = require("../controllers/event");
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const tsUtils = require("../lib/utils")
|
const tsUtils = require("../lib/utils")
|
||||||
const {teamsnapCallback} = require("../lib/utils")
|
const {teamsnapCallback} = require("../lib/utils")
|
||||||
|
const multer = require("multer");
|
||||||
|
const upload = multer()
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
const loadEvent = (req,res,next) => {
|
const loadEvent = (req,res,next) => {
|
||||||
@@ -68,6 +70,7 @@ router.use("/:team_id([0-9]+)/event/:event_id([0-9]+)", loadEvent)
|
|||||||
// Routes
|
// Routes
|
||||||
router.get("/:team_id([0-9]+)/schedule", eventsController.getEvents);
|
router.get("/:team_id([0-9]+)/schedule", eventsController.getEvents);
|
||||||
router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)", eventsController.getEvent);
|
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", eventsController.getLineup);
|
||||||
// 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_card", eventsController.getLineupCard);
|
||||||
|
|
||||||
|
|||||||
@@ -354,12 +354,16 @@ div[id^="event-lineup"] .Panel {
|
|||||||
.Panel .Panel{
|
.Panel .Panel{
|
||||||
// padding: 0;
|
// padding: 0;
|
||||||
// border-radius: 0;
|
// border-radius: 0;
|
||||||
border: none;
|
// border: none;
|
||||||
// border-top: 1px solid #d6d6d6;
|
// border-top: 1px solid #d6d6d6;
|
||||||
// border-bottom: 1px solid #d6d6d6;
|
// border-bottom: 1px solid #d6d6d6;
|
||||||
margin: 0;
|
margin: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroll-horizontal {
|
.scroll-horizontal {
|
||||||
overflow-x: scroll;
|
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';
|
font-family: 'Pacifico';
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-grow:1
|
flex-grow:1;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.opponent img, .team img{
|
.opponent img, .team img{
|
||||||
|
|||||||
@@ -25,9 +25,9 @@
|
|||||||
<span>Generate Email</span>
|
<span>Generate Email</span>
|
||||||
</a>
|
</a>
|
||||||
<hr class="Divider u-spaceEndsNone">
|
<hr class="Divider u-spaceEndsNone">
|
||||||
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="../sheet">
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="/{{team.id}}/event/{{event.id}}/sheet">
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/book.svg"}}}
|
<span>{{{embeddedSvgFromPath "/bootstrap-icons/file-earmark.svg"}}}</span>
|
||||||
<span>Lineup Card</span>
|
<span class="u-hidden u-xs-inline">Game Sheet</span>
|
||||||
</a>
|
</a>
|
||||||
<hr class="Divider u-spaceEndsNone">
|
<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)">
|
<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"}}}
|
{{{embeddedSvgFromPath "/bootstrap-icons/caret-left.svg"}}}
|
||||||
<span>Insert previous lineup</span>
|
<span>Insert previous lineup</span>
|
||||||
</a>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<div id="modal" class="Modal Modal--clickableBg">
|
<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 class="Modal-content">
|
||||||
<div onclick="javascript:this.closest('.Modal').remove();tinymce.remove();">{{{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-header">
|
||||||
@@ -17,10 +16,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="FieldGroup">
|
<div class="FieldGroup">
|
||||||
<label class="FieldGroup-label">Lineup</label>
|
<label class="FieldGroup-label">Lineup</label>
|
||||||
<div class="lineup-email">{{>email_table}}</div>
|
<div class="lineup-email lineup-table">{{>email_table}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="FieldGroup">
|
<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>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,12 +17,38 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="Panel-cell u-padXs u-sizeFill u-flex">
|
<div class="Panel-cell u-padXs u-sizeFill u-flex">
|
||||||
<div
|
<div
|
||||||
class="availability-status-code-{{
|
class="Popup availability-status-code-{{
|
||||||
member.benchcoach.availability?.statusCode
|
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>
|
||||||
|
</div>
|
||||||
|
{{/with}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="u-fontSizeLg u-textNoWrap">
|
<div class="u-fontSizeLg u-textNoWrap">
|
||||||
<span class="lastname">
|
<span class="lastname">
|
||||||
{{member.lastName}}
|
{{member.lastName}}
|
||||||
@@ -35,7 +61,12 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="u-flexGrow1"></div>
|
<div class="u-flexGrow1"></div>
|
||||||
<div class="position-label-flags u-textNoWrap">
|
<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">
|
<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()">
|
<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>
|
<label class="Checkbox-label" for="flag-drd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}">DR<small>d</small></label>
|
||||||
@@ -46,6 +77,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="Panel-cell u-padXs u-sizeFit">
|
<div class="Panel-cell u-padXs u-sizeFit">
|
||||||
<div class="SelectBox position-selection">
|
<div class="SelectBox position-selection">
|
||||||
<select name="positionLabelSelectBox" class="position-select-box SelectBox-options" onchange="onPositionSelectChange(this)" >
|
<select name="positionLabelSelectBox" class="position-select-box SelectBox-options" onchange="onPositionSelectChange(this)" >
|
||||||
|
|||||||
@@ -158,8 +158,9 @@
|
|||||||
<div>
|
<div>
|
||||||
<span class="name">{{event.opponentName}}</span>
|
<span class="name">{{event.opponentName}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{{#if opponent_logo.mediumUrl }}
|
||||||
<img src="{{opponent_logo.mediumUrl}}">
|
<img src="{{opponent_logo.mediumUrl}}">
|
||||||
{{!-- <%= ::Temple::Utils.escape_html((image_tag opponent_logos[event.opponent.id].medium_url)) %> --}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="">
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
{{> navbar }}
|
{{> navbar }}
|
||||||
{{{_sections.header}}}
|
{{{_sections.header}}}
|
||||||
</header>
|
</header>
|
||||||
<main class="">
|
<main class="u-sm-spaceSidesMd">
|
||||||
{{{ body }}}
|
{{{ body }}}
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<img src ="/teamsnap-ui/assets/icons/schedule.svg" class="Icon">
|
<img src ="/teamsnap-ui/assets/icons/schedule.svg" class="Icon">
|
||||||
<span class="span u-hidden u-xs-inline">Schedule</span>
|
<span class="span u-hidden u-xs-inline">Schedule</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="Button" href="members">
|
<a class="Button u-hidden" href="members">
|
||||||
<img src ="/teamsnap-ui/assets/icons/roster.svg" class="Icon">
|
<img src ="/teamsnap-ui/assets/icons/roster.svg" class="Icon">
|
||||||
<span class="span u-hidden u-xs-inline">Roster</span>
|
<span class="span u-hidden u-xs-inline">Roster</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user