reorganize start...
This commit is contained in:
2
bin/www
2
bin/www
@@ -4,7 +4,7 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var app = require("../app");
|
||||
var app = require("../src/app");
|
||||
var http = require("http");
|
||||
var https = require("https");
|
||||
var fs = require("fs");
|
||||
|
||||
137
package-lock.json
generated
137
package-lock.json
generated
@@ -7,7 +7,6 @@
|
||||
"": {
|
||||
"name": "teamsnap-benchcoach",
|
||||
"version": "0.0.0",
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"@teamsnap/teamsnap-ui": "^3.12.3",
|
||||
"bootstrap": "^5.3.1",
|
||||
@@ -22,11 +21,13 @@
|
||||
"http-errors": "~1.6.3",
|
||||
"mkdirp": "^1.0.4",
|
||||
"morgan": "~1.9.1",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"papaparse": "^5.4.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-teamsnap": "^1.1.1",
|
||||
"pluralize": "^8.0.0",
|
||||
"pug": "^3.0.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
"teamsnap.js": "^1.62.1",
|
||||
"xhr2": "^0.2.1"
|
||||
},
|
||||
@@ -704,6 +705,11 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/append-field": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
|
||||
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
|
||||
},
|
||||
"node_modules/array-buffer-byte-length": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
|
||||
@@ -962,6 +968,17 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
||||
"dependencies": {
|
||||
"streamsearch": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
@@ -1101,6 +1118,20 @@
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
|
||||
},
|
||||
"node_modules/concat-stream": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
|
||||
"engines": [
|
||||
"node >= 0.8"
|
||||
],
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^2.2.2",
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/connect-ensure-login": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/connect-ensure-login/-/connect-ensure-login-0.1.1.tgz",
|
||||
@@ -1197,6 +1228,11 @@
|
||||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||
},
|
||||
"node_modules/csrf": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz",
|
||||
@@ -2345,6 +2381,14 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
@@ -2376,6 +2420,34 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/multer": {
|
||||
"version": "1.4.5-lts.1",
|
||||
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
|
||||
"integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
|
||||
"dependencies": {
|
||||
"append-field": "^1.0.0",
|
||||
"busboy": "^1.0.0",
|
||||
"concat-stream": "^1.5.2",
|
||||
"mkdirp": "^0.5.4",
|
||||
"object-assign": "^4.1.1",
|
||||
"type-is": "^1.6.4",
|
||||
"xtend": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/multer/node_modules/mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -2687,6 +2759,11 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"node_modules/promise": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||
@@ -2925,6 +3002,25 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream/node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
|
||||
@@ -3198,6 +3294,11 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sortablejs": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -3223,6 +3324,22 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string.prototype.trim": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
|
||||
@@ -3391,6 +3508,11 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typedarray": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||
},
|
||||
"node_modules/uid-safe": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||
@@ -3464,6 +3586,11 @@
|
||||
"browserslist": ">= 4.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
@@ -3561,6 +3688,14 @@
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,13 @@
|
||||
"http-errors": "~1.6.3",
|
||||
"mkdirp": "^1.0.4",
|
||||
"morgan": "~1.9.1",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"papaparse": "^5.4.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-teamsnap": "^1.1.1",
|
||||
"pluralize": "^8.0.0",
|
||||
"pug": "^3.0.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
"teamsnap.js": "^1.62.1",
|
||||
"xhr2": "^0.2.1"
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
event_id = "292333461";
|
||||
event_id_2 = "292333462";
|
||||
team_id = "6882652";
|
||||
|
||||
function format_stat(number) {
|
||||
const zeroPad = (num, places) => String(num).padStart(3, "0");
|
||||
return zeroPad(Math.round(number * 1000), 3);
|
||||
}
|
||||
|
||||
async function load_data_xxx() {
|
||||
const event_id = document.querySelector('input[name="event_id"]').value;
|
||||
const team_id = document.querySelector('input[name="team_id"]').value;
|
||||
update_card(team_id, event_id);
|
||||
}
|
||||
|
||||
async function update_card(team_id, event_id) {
|
||||
fetch(`/${team_id}/event/${event_id}/gamecard/data`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(function (items) {
|
||||
console.log(items);
|
||||
events = items.filter(function (item) {
|
||||
return item.type == "event";
|
||||
});
|
||||
event_index = events.findIndex(function (e) {
|
||||
return e.id == event_id;
|
||||
});
|
||||
event = events[event_index];
|
||||
document.title = event.formattedTitle;
|
||||
|
||||
document.querySelectorAll(".event-title").forEach(function (element) {
|
||||
element.innerText = event.formattedTitle;
|
||||
});
|
||||
|
||||
document.querySelectorAll(".event-label").forEach(function (element) {
|
||||
element.innerText = event.label;
|
||||
});
|
||||
|
||||
document
|
||||
.querySelectorAll(".event-location-name")
|
||||
.forEach(function (element) {
|
||||
element.innerText = event.locationName;
|
||||
});
|
||||
|
||||
document.querySelectorAll(".opponent").forEach(function (element) {
|
||||
element.innerText = event.opponentName;
|
||||
});
|
||||
|
||||
document.querySelectorAll(".homeaway").forEach(function (element) {
|
||||
element.innerText = event.gameType;
|
||||
});
|
||||
|
||||
document.querySelectorAll(".event-date").forEach(function (element) {
|
||||
element.innerText = new Date(event.startDate).toLocaleDateString(
|
||||
"en-us",
|
||||
{
|
||||
weekday: "short",
|
||||
day: "numeric",
|
||||
// year: "numeric",
|
||||
month: "short",
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
document.querySelectorAll(".event-time").forEach(function (element) {
|
||||
element.innerText = new Date(event.startDate).toLocaleTimeString(
|
||||
"en-us",
|
||||
{
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
document.getElementById("todays-game-header").innerText =
|
||||
event.formattedTitle +
|
||||
" - " +
|
||||
new Date(event.startDate).toLocaleDateString("en-us", {
|
||||
weekday: "short",
|
||||
day: "numeric",
|
||||
// year: "numeric",
|
||||
month: "short",
|
||||
}) +
|
||||
" " +
|
||||
new Date(event.startDate).toLocaleTimeString("en-us", {
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
});
|
||||
|
||||
for (let j = -4; j < 5; j++) {
|
||||
if (j < 0) {
|
||||
plus_minus = "minus";
|
||||
} else if (j > 0) {
|
||||
plus_minus = "plus";
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
document.querySelector(
|
||||
`th.today-${plus_minus}-${Math.abs(j)} div`
|
||||
).textContent = new Date(
|
||||
events[event_index + j].startDate
|
||||
).toLocaleDateString("en-us", {
|
||||
weekday: "short",
|
||||
});
|
||||
}
|
||||
console.log({
|
||||
0: events[event_index],
|
||||
1: events[event_index + 1],
|
||||
});
|
||||
});
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,9 +8,9 @@ var session = require("express-session");
|
||||
var csrf = require("csurf");
|
||||
var passport = require("passport");
|
||||
var logger = require("morgan");
|
||||
var bodyParser = require("body-parser");
|
||||
global.XMLHttpRequest = require("xhr2");
|
||||
var teamsnap = require("teamsnap.js");
|
||||
|
||||
var indexRouter = require("./routes/index");
|
||||
var authRouter = require("./routes/auth");
|
||||
|
||||
@@ -22,6 +22,8 @@ app.set("view engine", "pug");
|
||||
|
||||
app.locals.pluralize = require("pluralize");
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.json());
|
||||
app.use(logger("dev"));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
@@ -29,17 +31,21 @@ app.use(cookieParser());
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
app.use(
|
||||
"/css",
|
||||
express.static(path.join(__dirname, "node_modules/bootstrap/dist/css"))
|
||||
express.static(path.join(__dirname, "../node_modules/bootstrap/dist/css"))
|
||||
);
|
||||
app.use(
|
||||
"/css",
|
||||
express.static(
|
||||
path.join(__dirname, "node_modules/@teamsnap/teamsnap-ui/dist/css")
|
||||
path.join(__dirname, "../node_modules/@teamsnap/teamsnap-ui/dist/css")
|
||||
)
|
||||
);
|
||||
app.use(
|
||||
"/font",
|
||||
express.static(path.join(__dirname, "node_modules/bootstrap-icons/font"))
|
||||
express.static(path.join(__dirname, "../node_modules/bootstrap-icons/font"))
|
||||
);
|
||||
app.use(
|
||||
"/js",
|
||||
express.static(path.join(__dirname, "../node_modules/sortablejs"))
|
||||
);
|
||||
app.use(
|
||||
session({
|
||||
42
src/controllers/events.js
Normal file
42
src/controllers/events.js
Normal file
@@ -0,0 +1,42 @@
|
||||
utils = require("../lib/utils");
|
||||
|
||||
exports.getEvents = (req, res, next) => {
|
||||
team_id = req.params.team_id;
|
||||
utils.initTeamsnap(req, res, () => {
|
||||
teamsnap
|
||||
.bulkLoad(team_id, ["team", "event", "availabilitySummary"])
|
||||
.then(() => {
|
||||
items = teamsnap.getAllItems();
|
||||
context = {
|
||||
title: "Events",
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
availabilitySummaries: items.filter(
|
||||
(i) => i.type == "availabilitySummary"
|
||||
),
|
||||
events: items.filter((i) => i.type == "event"),
|
||||
};
|
||||
res.render("events", context);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.getEvent = (req, res, next) => {
|
||||
team_id = req.params.team_id;
|
||||
event_id = req.params.event_id;
|
||||
utils.initTeamsnap(req, res, () => {
|
||||
teamsnap
|
||||
.bulkLoad(team_id, ["team", "event", "availabilitySummary"])
|
||||
.then(() => {
|
||||
items = teamsnap.getAllItems();
|
||||
context = {
|
||||
title: "Event",
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
availabilitySummary: items.find(
|
||||
(i) => i.type == "availabilitySummary" && i.id == event_id
|
||||
),
|
||||
event: items.find((i) => i.type == "event" && i.id == event_id),
|
||||
};
|
||||
res.render("event", context);
|
||||
});
|
||||
});
|
||||
};
|
||||
20
src/controllers/teams.js
Normal file
20
src/controllers/teams.js
Normal file
@@ -0,0 +1,20 @@
|
||||
utils = require("../lib/utils");
|
||||
|
||||
exports.getTeams = (req, res, next) => {
|
||||
utils.initTeamsnap(req, res, () => {
|
||||
teamsnap.loadTeams().then((teams) => {
|
||||
context = { title: "Teams", teams: teams };
|
||||
res.render("teams", context);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.getTeamHome = (req, res, next) => {
|
||||
team_id = req.params.team_id;
|
||||
utils.initTeamsnap(req, res, () => {
|
||||
teamsnap.loadTeam(team_id).then((team) => {
|
||||
context = { title: "Home", team: team };
|
||||
res.render("team", context);
|
||||
});
|
||||
});
|
||||
};
|
||||
35
src/lib/utils.js
Normal file
35
src/lib/utils.js
Normal file
@@ -0,0 +1,35 @@
|
||||
exports.teamsnapAvailabilitiesSort = (a, b) => {
|
||||
status_code_sort = [
|
||||
teamsnap.AVAILABILITIES.YES,
|
||||
teamsnap.AVAILABILITIES.MAYBE,
|
||||
teamsnap.AVAILABILITIES.NO,
|
||||
teamsnap.AVAILABILITIES.NONE,
|
||||
];
|
||||
a_sort = status_code_sort.indexOf(a.statusCode);
|
||||
b_sort = status_code_sort.indexOf(b.statusCode);
|
||||
if (a_sort > b_sort) {
|
||||
return 1;
|
||||
}
|
||||
if (a_sort < b_sort) {
|
||||
return -1;
|
||||
}
|
||||
if (a_sort == b_sort) {
|
||||
if (a.member.lastName < b.member.lastName) {
|
||||
return -1;
|
||||
}
|
||||
if (a.member.lastName > b.member.lastName) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
});
|
||||
};
|
||||
71
src/public/css/lineup.css
Normal file
71
src/public/css/lineup.css
Normal file
@@ -0,0 +1,71 @@
|
||||
@import url("/font/bootstrap-icons.css");
|
||||
|
||||
:root {
|
||||
--bc-text-muted: #6c757d;
|
||||
}
|
||||
|
||||
#label_13_5_0 span {
|
||||
display: none !important;
|
||||
}
|
||||
#label_13_5_0:after {
|
||||
font-family: FontAwesome;
|
||||
content: "\f005";
|
||||
}
|
||||
.lineup-slot .Panel-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lineup-slot .Panel-cell:has(.drag-handle) {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.lineup-slot [class*="availability-status-code"]::before {
|
||||
padding-right: 6px;
|
||||
font-family: "bootstrap-icons";
|
||||
}
|
||||
|
||||
.lineup-slot .availability-status-code-1::before {
|
||||
content: "\F26A";
|
||||
color: var(--bs-success);
|
||||
}
|
||||
|
||||
.lineup-slot .availability-status-code-2::before {
|
||||
content: "\F504";
|
||||
color: var(--bs-primary);
|
||||
}
|
||||
|
||||
.lineup-slot .availability-status-code-0::before {
|
||||
content: "\F622";
|
||||
color: var(--bs-danger);
|
||||
}
|
||||
|
||||
.lineup-slot .availability-status-code-null::before {
|
||||
content: "\F505";
|
||||
color: var(--bs-secondary);
|
||||
}
|
||||
|
||||
.lineup-slot .lastname {
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.lineup-slot .jerseynumber {
|
||||
text-transform: uppercase;
|
||||
font-weight: light;
|
||||
color: var(--bc-text-muted);
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.lineup-slot .jerseynumber::before {
|
||||
content: " - ";
|
||||
}
|
||||
|
||||
/* if lineup_entry.availabilityStatusCode == 2
|
||||
i.bi.bi-question-circle-fill.text-info.u-spaceRightXs
|
||||
else if lineup_entry.availabilityStatusCode == 1
|
||||
i.bi.bi-check-circle-fill.text-success.u-spaceRightXs
|
||||
else if lineup_entry.availabilityStatusCode == 0
|
||||
i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs
|
||||
else
|
||||
i.bi.bi-question-circle.u-spaceRightXs */
|
||||
@@ -1,5 +1,6 @@
|
||||
/* These styles are generated from project.scss. */
|
||||
@import url("https://fonts.googleapis.com/css2?family=Open+Sans&display=swap");
|
||||
@import url("../fonts/helvetica-now/stylesheet.css");
|
||||
.alert-debug {
|
||||
color: black;
|
||||
background-color: white;
|
||||
@@ -55,3 +56,17 @@
|
||||
border-color: #1b73bc;
|
||||
background-color: #1b73bc;
|
||||
}
|
||||
|
||||
.benchcoach-nav {
|
||||
background-color: #323669;
|
||||
margin-bottom: 2em;
|
||||
padding: 0.5em;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.benchcoach-nav h3 {
|
||||
font-family: "Helvetica Now";
|
||||
font-weight: bolder;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
1
src/public/media/teamsnap.svg
Normal file
1
src/public/media/teamsnap.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.8 KiB |
9
src/public/media/teamsnap_star.svg
Normal file
9
src/public/media/teamsnap_star.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.0 KiB |
@@ -17,6 +17,7 @@ passport.use(
|
||||
clientSecret: process.env["TEAMSNAP_CLIENT_SECRET"],
|
||||
callbackURL: "/auth/teamsnap/callback",
|
||||
passReqToCallback: true,
|
||||
scope: ["read", "write"],
|
||||
},
|
||||
function (req, accessToken, refreshToken, profile, done) {
|
||||
json = JSON.parse(profile._raw);
|
||||
@@ -30,8 +31,7 @@ passport.use(
|
||||
new_profile["first_name"] = json.collection.items[0].data.filter(
|
||||
(e) => e.name == "first_name"
|
||||
)[0].value;
|
||||
console.log("LI#35 session is ", req.session);
|
||||
console.log("LI#35 session id is ", req.session.id);
|
||||
|
||||
req.session.teamsnap_access_token = accessToken;
|
||||
teamsnap.init(process.env["TEAMSNAP_CLIENT_ID"]);
|
||||
teamsnap.auth(accessToken);
|
||||
@@ -79,6 +79,10 @@ var router = express.Router();
|
||||
* will be sent to the `GET /login/federated/teamsnap` route.
|
||||
*/
|
||||
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");
|
||||
});
|
||||
|
||||
@@ -107,22 +111,13 @@ router.get(
|
||||
passport.authenticate("teamsnap", function (err, user, info, status) {})
|
||||
);
|
||||
|
||||
router.get("/auth/teamsnap/callback", function (req, res, next) {
|
||||
passport.authenticate("teamsnap", function (err, user, info, status) {
|
||||
if (err) {
|
||||
// do something with the error
|
||||
console.error("error: ", err);
|
||||
}
|
||||
// success
|
||||
console.log("L#105 user is ", user);
|
||||
req.logIn(user, function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
return res.redirect("/");
|
||||
});
|
||||
})(req, res, next);
|
||||
});
|
||||
router.get(
|
||||
"/auth/teamsnap/callback",
|
||||
passport.authenticate("teamsnap", {
|
||||
successReturnToOrRedirect: "/",
|
||||
failureRedirect: "/login",
|
||||
keepSessionInfo: true,
|
||||
})
|
||||
);
|
||||
|
||||
module.exports = router;
|
||||
@@ -6,176 +6,19 @@ var ensureLoggedIn = ensureLogIn();
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
function authTeamsnap(user) {
|
||||
if (!teamsnap.isAuthed()) {
|
||||
teamsnap.init(process.env["TEAMSNAP_CLIENT_ID"]);
|
||||
teamsnap.auth(user.accessToken);
|
||||
}
|
||||
}
|
||||
|
||||
function availabilitiesSort(a, b) {
|
||||
status_code_sort = [
|
||||
teamsnap.AVAILABILITIES.YES,
|
||||
teamsnap.AVAILABILITIES.MAYBE,
|
||||
teamsnap.AVAILABILITIES.NO,
|
||||
teamsnap.AVAILABILITIES.NONE,
|
||||
];
|
||||
a_sort = status_code_sort.indexOf(a.statusCode);
|
||||
b_sort = status_code_sort.indexOf(b.statusCode);
|
||||
if (a_sort > b_sort) {
|
||||
return 1;
|
||||
}
|
||||
if (a_sort < b_sort) {
|
||||
return -1;
|
||||
}
|
||||
if (a_sort == b_sort) {
|
||||
if (a.member.lastName < b.member.lastName) {
|
||||
return -1;
|
||||
}
|
||||
if (a.member.lastName > b.member.lastName) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function fetch_stats(resolve, reject) {
|
||||
url =
|
||||
"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv&gid={tab_id}";
|
||||
papaparse.Papa.parse(url, {
|
||||
download: true,
|
||||
complete: function (results) {
|
||||
results.data.forEach((row, i) => {
|
||||
if (i == 0 || row[2] == "Totals" || row[2] == "") {
|
||||
return;
|
||||
}
|
||||
d = {
|
||||
first_name: row[3],
|
||||
last_name: row[2],
|
||||
jersey_number: row[1],
|
||||
pa: row[5],
|
||||
ab: row[6],
|
||||
avg: row[20],
|
||||
obp: row[21],
|
||||
slg: row[22],
|
||||
};
|
||||
});
|
||||
resolve(d);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/* GET home page. */
|
||||
router.get("/", ensureLoggedIn, function (req, res, next) {
|
||||
if (req.user) {
|
||||
authTeamsnap(req.user);
|
||||
teamsnap.loadCollections(function (err) {
|
||||
if (err) {
|
||||
alert("Error loading TeamSnap SDK");
|
||||
return;
|
||||
}
|
||||
teamsnap.loadTeams(function onTeamsLoad(err, teams) {
|
||||
teams = teams.sort((a, b) => b.seasonName - a.seasonName);
|
||||
res.render("home", { req: req, teams: teams });
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.render("home", { req: req });
|
||||
}
|
||||
});
|
||||
|
||||
router.get(
|
||||
"/teams",
|
||||
ensureLoggedIn,
|
||||
function (req, res, next) {
|
||||
console.log("teamsnap authed?: ", teamsnap.isAuthed());
|
||||
console.log("user is", req.user);
|
||||
|
||||
authTeamsnap(req.user);
|
||||
teamsnap.loadCollections(function (err) {
|
||||
if (err) {
|
||||
alert("Error loading TeamSnap SDK");
|
||||
return;
|
||||
}
|
||||
teamsnap.loadTeams(function onTeamsLoad(err, teams) {
|
||||
teams = teams.sort((a, b) => b.seasonName - a.seasonName);
|
||||
res.render("teams", { teams: teams });
|
||||
});
|
||||
});
|
||||
|
||||
next();
|
||||
},
|
||||
function (req, res, next) {
|
||||
// res.send(`${me.firstName} ${me.lastName}`);
|
||||
}
|
||||
);
|
||||
|
||||
router.get("/:team_id([0-9]+)", ensureLoggedIn, function (req, res, next) {
|
||||
authTeamsnap(req.user);
|
||||
team_id = req.params.team_id;
|
||||
console.log("team_id", team_id);
|
||||
teamsnap.loadCollections(function (err) {
|
||||
if (err) {
|
||||
alert("Error loading TeamSnap SDK");
|
||||
return;
|
||||
}
|
||||
teamsnap.enablePersistence();
|
||||
|
||||
teamsnap.bulkLoad(
|
||||
team_id,
|
||||
["team", "member", "event", "opponent", "availability_summary"],
|
||||
function onBulkLoad(err, items) {
|
||||
team = items.find((i) => (i.type == "team") & (i.id == team_id));
|
||||
console.log(team);
|
||||
res.set("Content-Type", "text/html");
|
||||
res.render("team", { team: team });
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
var multer = require("multer");
|
||||
const storage = multer.memoryStorage();
|
||||
const upload = multer({ storage: storage });
|
||||
const teamsController = require("../controllers/teams");
|
||||
const eventsController = require("../controllers/events");
|
||||
|
||||
router.get("/", ensureLoggedIn, teamsController.getTeams);
|
||||
router.get("/:team_id/home", ensureLoggedIn, teamsController.getTeamHome);
|
||||
router.get("/:team_id/events", ensureLoggedIn, eventsController.getEvents);
|
||||
router.get(
|
||||
"/:team_id/event/:event_id",
|
||||
ensureLoggedIn,
|
||||
function (req, res, next) {
|
||||
authTeamsnap(req.user);
|
||||
var team_id = req.params.team_id;
|
||||
var event_id = req.params.event_id;
|
||||
teamsnap.loadCollections(function (err) {
|
||||
console.log();
|
||||
teamsnap.enablePersistence();
|
||||
|
||||
teamsnap.bulkLoad(
|
||||
team_id,
|
||||
["team", "event", "availabilitySummary"],
|
||||
function (err, items) {
|
||||
if (err) {
|
||||
res.code = 500;
|
||||
res.send(err);
|
||||
}
|
||||
|
||||
availabilitySummaries = items.filter(
|
||||
(i) => i.type == "availabilitySummary" && i.id == event_id
|
||||
);
|
||||
events = items.filter((i) => i.type == "event" && i.id == event_id);
|
||||
|
||||
if (events) {
|
||||
event = events[0];
|
||||
availabilitySummary = availabilitySummaries[0];
|
||||
console.log("A_S", availabilitySummaries);
|
||||
res.render("event", {
|
||||
event: event,
|
||||
team_id: team_id,
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
availabilitySummary: availabilitySummary,
|
||||
});
|
||||
} else {
|
||||
res.code = 500;
|
||||
res.send("error");
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
eventsController.getEvent
|
||||
);
|
||||
|
||||
router.get(
|
||||
@@ -234,6 +77,7 @@ router.get(
|
||||
current_event_index = events.findIndex((e) => e.id == event_id);
|
||||
|
||||
context = {
|
||||
title: "Gamecard",
|
||||
team_id: req.params.team_id,
|
||||
event_id: req.params.event_id,
|
||||
current_event_index: current_event_index,
|
||||
@@ -328,6 +172,8 @@ router.get(
|
||||
current_event_index = events.findIndex((e) => e.id == event_id);
|
||||
|
||||
context = {
|
||||
title: "Lineup",
|
||||
team: items.find((e) => e.type == "team" && e.id == team_id),
|
||||
team_id: req.params.team_id,
|
||||
event_id: req.params.event_id,
|
||||
current_event_index: current_event_index,
|
||||
@@ -360,30 +206,27 @@ router.get(
|
||||
.sort((a, b) => a.sequence - b.sequence),
|
||||
};
|
||||
|
||||
res.render("lineup", context);
|
||||
res.render("lineup/lineup", context);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
router.get("/:team_id/events", ensureLoggedIn, function (req, res, next) {
|
||||
router.get("/:team_id/events", ensureLoggedIn);
|
||||
|
||||
router.get("/:team_id/opponents", ensureLoggedIn, function (req, res, next) {
|
||||
authTeamsnap(req.user);
|
||||
team_id = req.params.team_id;
|
||||
event_id = req.params.event_id;
|
||||
teamsnap.loadCollections(function (err) {
|
||||
teamsnap
|
||||
.bulkLoad(team_id, ["team", "event", "availability_summary"])
|
||||
.then((items) => {
|
||||
res.set("Content-Type", "text/html");
|
||||
res.render("events", {
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
events: items.filter((i) => i.type == "event"),
|
||||
availabilitySummaries: items.filter(
|
||||
(i) => i.type == "availabilitySummary"
|
||||
),
|
||||
team_id: team_id,
|
||||
});
|
||||
teamsnap.bulkLoad(team_id, ["team", "opponent"]).then((items) => {
|
||||
res.set("Content-Type", "text/html");
|
||||
res.render("opponents", {
|
||||
title: "Opponents",
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
opponents: items.filter((i) => i.type == "opponent"),
|
||||
team_id: team_id,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -394,6 +237,7 @@ router.get("/:team_id/opponents", ensureLoggedIn, function (req, res, next) {
|
||||
teamsnap.bulkLoad(team_id, ["team", "opponent"]).then((items) => {
|
||||
res.set("Content-Type", "text/html");
|
||||
res.render("opponents", {
|
||||
title: "Opponents",
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
opponents: items.filter((i) => i.type == "opponent"),
|
||||
team_id: team_id,
|
||||
@@ -402,38 +246,72 @@ router.get("/:team_id/opponents", ensureLoggedIn, function (req, res, next) {
|
||||
});
|
||||
});
|
||||
|
||||
router.get("/:team_id/roster", ensureLoggedIn, function (req, res, next) {
|
||||
authTeamsnap(req.user);
|
||||
team_id = req.params.team_id;
|
||||
teamsnap.loadCollections(function (err) {
|
||||
teamsnap.enablePersistence();
|
||||
teamsnap.bulkLoad(team_id, ["team", "members"]).then(() => {
|
||||
items = teamsnap.getAllItems();
|
||||
res.set("Content-Type", "text/html");
|
||||
res.render("roster", {
|
||||
title: `Roster`,
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
members: items.find((i) => i.type == "member" && team.id == team_id),
|
||||
team_id: team_id,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
router.get(
|
||||
"/:team_id/opponent/:opponent_id",
|
||||
"/:team_id/opponent/:opponent_id/upload-logo",
|
||||
ensureLoggedIn,
|
||||
function (req, res, next) {
|
||||
authTeamsnap(req.user);
|
||||
team_id = req.params.team_id;
|
||||
opponent_id = req.params.opponent_id;
|
||||
teamsnap.loadCollections(function (err) {
|
||||
teamsnap.enablePersistence();
|
||||
teamsnap
|
||||
.bulkLoad(team_id, ["team", "opponent"])
|
||||
.then(() => {
|
||||
teamsnap.loadTeamMedia(team_id);
|
||||
})
|
||||
.then(() => {
|
||||
items = teamsnap.getAllItems();
|
||||
res.set("Content-Type", "text/html");
|
||||
res.render("opponent", {
|
||||
team: items.find((i) => i.type == "team" && i.id == team_id),
|
||||
opponent: items.find(
|
||||
(i) => i.type == "opponent" && i.id == opponent_id
|
||||
),
|
||||
opponent_logo: items.find(
|
||||
(i) =>
|
||||
i.type == "teamMedium" &&
|
||||
i.description == `team-logo-${opponent_id}.png`
|
||||
),
|
||||
team_id: team_id,
|
||||
});
|
||||
});
|
||||
team_id = req.params.team_id;
|
||||
res.set("Content-Type", "text/html");
|
||||
res.render("upload-logo", {
|
||||
title: "Upload Logo",
|
||||
csrf_token: req.csrfToken(),
|
||||
team_id: team_id,
|
||||
opponent_id: opponent_id,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/:team_id/opponent/:opponent_id/upload-logo",
|
||||
ensureLoggedIn,
|
||||
upload.single("file"),
|
||||
function (req, res, next) {
|
||||
opponent_id = req.body.opponent_id;
|
||||
team_id = req.body.team_id;
|
||||
member_id = req.user.id;
|
||||
file = new File(req.file.buffer, `team-logo-${opponent_id}.png`, {
|
||||
type: "image/png",
|
||||
});
|
||||
authTeamsnap(req.user);
|
||||
teamsnap
|
||||
.loadCollections()
|
||||
.then(() => {
|
||||
return teamsnap.createTeamMedium({
|
||||
file: file,
|
||||
mediaFormat: "file",
|
||||
memberId: member_id,
|
||||
teamId: team_id,
|
||||
teamMediaGroupId: "4927028",
|
||||
description: `team-logo-${opponent_id}.png`,
|
||||
});
|
||||
})
|
||||
.then((item) => {
|
||||
return teamsnap.uploadTeamMedium(item);
|
||||
})
|
||||
.then((item) => {
|
||||
res.send("Data Received: " + JSON.stringify(item));
|
||||
})
|
||||
.fail((err) => console.log(err));
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = router;
|
||||
42
src/views/base.pug
Normal file
42
src/views/base.pug
Normal file
@@ -0,0 +1,42 @@
|
||||
html
|
||||
head
|
||||
block meta
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title BenchCoach - #{title}
|
||||
block styles
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/font/bootstrap-icons.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
link(rel='stylesheet' href='/css/project.css')
|
||||
block pre-scripts
|
||||
script(type='text/javascript', src='/js/Sortable.js')
|
||||
|
||||
body.bg-light
|
||||
block navbar
|
||||
.benchcoach-nav.u-flex.u-flexJustifyBetween.u-flexAlignItemsCenter
|
||||
.u-flex.u-flexAlignItemsCenter
|
||||
img(src='/media/benchcoach.svg' alt='TeamSnap Logo' width='30' height='30')
|
||||
h3.u-padLeft.u-colorWhite.u-noMarginBottom BenchCoach
|
||||
|
||||
.u-spaceSm.u-md-spaceLg
|
||||
block content
|
||||
.Panel
|
||||
.Panel-header
|
||||
h2.Panel-title Panel
|
||||
.Panel-body
|
||||
.Panel-row Panel Row
|
||||
.Panel-row Roster
|
||||
.Panel-row Opponents
|
||||
|
||||
block footer
|
||||
.u-padMd.u-borderTop
|
||||
.u-max1200.u-flexExpandSides.Grid
|
||||
.Grid-cell.u-md-size1of2
|
||||
p.u-textCenter.u-md-textLeft
|
||||
| Copyright © 2023 BenchCoach. BenchCoach is not affiliated with TeamSnap, inc.
|
||||
.Grid-cell.u-md-size1of2
|
||||
p.u-textCenter.u-md-textRight
|
||||
|
||||
block scripts
|
||||
|
||||
63
src/views/event-lineup.pug
Normal file
63
src/views/event-lineup.pug
Normal file
@@ -0,0 +1,63 @@
|
||||
extends ../base.pug
|
||||
include lineup-slot.pug
|
||||
include ../widgets/availability-progress-bar.pug
|
||||
|
||||
block append styles
|
||||
link(rel='stylesheet' href='/css/lineup.css')
|
||||
|
||||
block pre-scripts
|
||||
script(type='text/javascript', src='/js/Sortable.js')
|
||||
|
||||
block content
|
||||
div(id=`event-lineup-${event.id}`).event-lineup
|
||||
.Panel
|
||||
.panel-header
|
||||
.Panel-title #{event.formattedTitle}
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
p.text-muted.mb-2 #{event.startDate}
|
||||
p #{event.locationName}
|
||||
+availability-progress-bar(availabilitySummary, team)
|
||||
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard-check.me-1
|
||||
span Starting Lineup
|
||||
.Panel-row.Grid.Grid--fit.fw-bold.text-center.u-padXs
|
||||
each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"]
|
||||
.Grid-cell.position-status #{pos}
|
||||
.slot-set
|
||||
each lineup_entry, i in event_lineup_entries_offense
|
||||
+lineup-slot(lineup_entry, i)
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard-minus.me-1
|
||||
span Starting Lineup (Position Only)
|
||||
.slot-set
|
||||
each lineup_entry, i in event_lineup_entries
|
||||
if lineup_entry.label.includes("[PO]")
|
||||
+lineup-slot(lineup_entry, i)
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard.me-1
|
||||
span Bench
|
||||
.slot-set
|
||||
each availability, i in availabilities.filter((a)=>a.eventId==event_id && !context.event_lineup_entries.map((lue)=>lue.memberId).includes(a.memberId) && !a.member.isNonPlayer && a.statusCode!=0 && a.statusCode!==null)
|
||||
+lineup-slot(availability, i)
|
||||
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard-x.me-1
|
||||
span Out
|
||||
.slot-set
|
||||
each availability, i in availabilities.filter((a)=>a.eventId==event_id && !context.event_lineup_entries.map((lue)=>lue.memberId).includes(a.memberId) && !a.member.isNonPlayer && (a.statusCode==0 || a.statusCode===null))
|
||||
+lineup-slot(availability, i)
|
||||
block scripts
|
||||
script
|
||||
include lineup.js
|
||||
script.
|
||||
colorPositions();
|
||||
27
src/views/event.pug
Normal file
27
src/views/event.pug
Normal file
@@ -0,0 +1,27 @@
|
||||
extends base.pug
|
||||
include mixin-availability-progress-bar.pug
|
||||
|
||||
block content
|
||||
.Panel
|
||||
.Panel-header
|
||||
h3.Panel-title #{event.formattedTitle}
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
h6.card-text.text-muted.mb-2
|
||||
|#{event.startDate}
|
||||
br
|
||||
|#{event.locationName}
|
||||
.Panel-row
|
||||
h4 Availability
|
||||
+availability-progress-bar(availabilitySummary, team)
|
||||
.Panel-row
|
||||
div.d-flex
|
||||
a(class="Button m-auto" href=`/${team_id}/event/${event.id}/lineup`)
|
||||
i(class="bi bi-clipboard")
|
||||
span.mx-1 Lineup
|
||||
a(class="Button m-auto" href=`/${team_id}/event/${event.id}/gamecard`)
|
||||
i(class="bi bi-book")
|
||||
span.mx-1 Game Card
|
||||
a(class="Button m-auto" href=`https://go.teamsnap.com/${team_id}/schedule/view_game/${event.id}`)
|
||||
i(class="bi bi-asterisk")
|
||||
span.mx-1 TeamSnap
|
||||
21
src/views/events.pug
Normal file
21
src/views/events.pug
Normal file
@@ -0,0 +1,21 @@
|
||||
extends base.pug
|
||||
include mixin-availability-progress-bar.pug
|
||||
|
||||
block content
|
||||
.Panel
|
||||
.Panel-header
|
||||
.Panel-title Schedule
|
||||
.Panel-body
|
||||
each event in events
|
||||
- var availabilitySummary = availabilitySummaries.find((a)=>a.eventId==event.id)
|
||||
a(class="event list-group-item" href=`/${team_id}/event/${event.id}`).Panel-row--withCells
|
||||
.Panel-cell
|
||||
h4 #{event.formattedTitle}
|
||||
+availability-progress-bar(availabilitySummary, team)
|
||||
.Panel-cell
|
||||
|#{event.startDate.toLocaleDateString("en-us",{weekday: "short", day: "numeric",month: "short"})}
|
||||
.Panel-cell
|
||||
|#{event.startDate.toLocaleTimeString("en-us",{hour: "numeric", minute: "2-digit"})}
|
||||
.Panel-cell
|
||||
|#{event.locationName}
|
||||
|
||||
24
src/views/home.pug
Normal file
24
src/views/home.pug
Normal file
@@ -0,0 +1,24 @@
|
||||
extends base.pug
|
||||
|
||||
block content
|
||||
.row
|
||||
.text-center.my-2
|
||||
.row
|
||||
h1
|
||||
img.mx-auto(src="media/benchcoach.svg" style="width: 2.5em;")
|
||||
.row
|
||||
h1
|
||||
strong
|
||||
| Welcome to
|
||||
span.text-nowrap BenchCoach
|
||||
.text-center.lead.fst-italic.fw-light
|
||||
| An assistant coach for TeamSnap
|
||||
.row
|
||||
.col.text-center
|
||||
if req.user
|
||||
ul.list-group
|
||||
each team in teams
|
||||
a(class='team list-group-item' href=`/${team.id}/home`) #{team.name} [#{team.seasonName}]
|
||||
else
|
||||
a.btn.btn-outline-primary(href="login")
|
||||
| Login
|
||||
356
src/views/lineup.js
Normal file
356
src/views/lineup.js
Normal file
@@ -0,0 +1,356 @@
|
||||
/* Project specific Javascript goes here. */
|
||||
function onPositionSelectChange(elem) {
|
||||
elem.querySelectorAll("option").forEach((option) => {
|
||||
if (option.innerText == elem.value) {
|
||||
option.setAttribute("selected", "selected");
|
||||
} else {
|
||||
option.removeAttribute("selected");
|
||||
}
|
||||
});
|
||||
colorPositions();
|
||||
}
|
||||
|
||||
function colorPositions() {
|
||||
console.log("Coloring Positions");
|
||||
for (bcLineup of document.getElementsByClassName("event-lineup")) {
|
||||
selected_lineup_positions = Array.from(
|
||||
bcLineup.querySelectorAll(
|
||||
".Panel-row .SelectBox.position-selection option[selected='selected']"
|
||||
)
|
||||
).map((el) => el.value);
|
||||
console.log(selected_lineup_positions);
|
||||
for (position_status of bcLineup.querySelectorAll(".position-status")) {
|
||||
for (class_name of ["text-danger", "text-warning", "text-success"]) {
|
||||
if (position_status.classList.contains(class_name)) {
|
||||
position_status.classList.remove(class_name);
|
||||
}
|
||||
}
|
||||
|
||||
occurrences = selected_lineup_positions.filter(
|
||||
(s) => s == position_status.innerText
|
||||
).length;
|
||||
|
||||
if (occurrences == 1) {
|
||||
position_status.classList.add("text-success");
|
||||
} else if (occurrences > 1) {
|
||||
position_status.classList.add("text-warning");
|
||||
} else {
|
||||
position_status.classList.add("text-danger");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function refresh_lineup_order(itemEl) {
|
||||
let bcLineup = itemEl.closest(".benchcoach-lineup");
|
||||
var player_rows = [];
|
||||
for (tbody of bcLineup.querySelectorAll(
|
||||
"[class*='tbody-benchcoach-starting']"
|
||||
)) {
|
||||
for (row of tbody.rows) {
|
||||
player_rows.push(row);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < player_rows.length; i++) {
|
||||
var player_order = player_rows[i].querySelector('[id^="sequence"]');
|
||||
var form_element_order = player_rows[i].querySelector('[id$="sequence"]');
|
||||
player_order.innerText = parseInt(player_rows[i].dataset.order);
|
||||
player_rows[i].dataset.order = i;
|
||||
form_element_order.value = i;
|
||||
player_order.innerHTML = i + 1;
|
||||
}
|
||||
var player_rows = bcLineup.getElementsByClassName("tbody-benchcoach-bench")[0]
|
||||
.rows;
|
||||
for (let i = 0; i < player_rows.length; i++) {
|
||||
var player_order = player_rows[i].querySelector('[id^="sequence"]');
|
||||
var form_element_order = player_rows[i].querySelector('[id$="sequence"]');
|
||||
player_rows[i].dataset.order = null;
|
||||
form_element_order.value = null;
|
||||
player_order.innerHTML = null;
|
||||
}
|
||||
}
|
||||
|
||||
function sendToClipboard(itemEl) {
|
||||
let bcLineup = itemEl.closest(".benchcoach-lineup");
|
||||
player_rows = bcLineup.querySelectorAll("[data-position=P]");
|
||||
lineup_export = [];
|
||||
if (player_rows.length > 0) {
|
||||
lineup_export.push(player_rows[0].dataset.playerName);
|
||||
lineup_export.push("", "");
|
||||
} else {
|
||||
lineup_export.push("", "", "");
|
||||
}
|
||||
|
||||
lineup_export.push("");
|
||||
for (position of ["C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "DH"]) {
|
||||
var player_rows = bcLineup.querySelectorAll(
|
||||
`[data-position=${CSS.escape(position)}]`
|
||||
);
|
||||
if (player_rows.length > 0) {
|
||||
lineup_export.push(player_rows[0].dataset.playerName);
|
||||
} else {
|
||||
lineup_export.push("");
|
||||
}
|
||||
}
|
||||
for (position of ["EH"]) {
|
||||
var player_rows = bcLineup.querySelectorAll(
|
||||
`[data-position=${CSS.escape(position)}]`
|
||||
);
|
||||
for (var i = 0; i < 2; i++) {
|
||||
if (i < player_rows.length) {
|
||||
lineup_export.push(player_rows[i].dataset.playerName);
|
||||
} else {
|
||||
lineup_export.push("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (position of ["DR"]) {
|
||||
let player_rows = bcLineup.querySelectorAll(
|
||||
`[data-position=${CSS.escape(position)}]`
|
||||
);
|
||||
if (player_rows.length > 0) {
|
||||
lineup_export.push(player_rows[0].dataset.playerName);
|
||||
} else {
|
||||
lineup_export.push("");
|
||||
}
|
||||
}
|
||||
|
||||
lineup_export.push("");
|
||||
lineup_export.push("", "");
|
||||
lineup_export.push("");
|
||||
|
||||
for (var i = 0; i < 11; i++) {
|
||||
let player_rows = bcLineup
|
||||
.querySelector(".table-benchcoach-startinglineup")
|
||||
.querySelectorAll(`[data-order=${CSS.escape(i)}]`);
|
||||
if (player_rows.length > 0) {
|
||||
lineup_export.push(player_rows[0].dataset.playerName);
|
||||
} else {
|
||||
lineup_export.push("");
|
||||
}
|
||||
}
|
||||
|
||||
console.dir(lineup_export);
|
||||
var textArea = document.createElement("textarea");
|
||||
textArea.value = lineup_export.join("\n");
|
||||
|
||||
// Avoid scrolling to bottom
|
||||
textArea.style.top = "0";
|
||||
textArea.style.left = "0";
|
||||
textArea.style.position = "fixed";
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
var successful = document.execCommand("copy");
|
||||
var msg = successful ? "successful" : "unsuccessful";
|
||||
console.log("Copying text command was " + msg);
|
||||
} catch (err) {
|
||||
console.error("Oops, unable to copy", err);
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
for (bcLineup of document.querySelectorAll(".Panel:has(.lineup-slot)")) {
|
||||
var startinglineup = new Sortable.create(
|
||||
bcLineup.querySelector(".slot-set"),
|
||||
{
|
||||
animation: 150,
|
||||
handle: ".drag-handle",
|
||||
ghostClass: "ghost",
|
||||
group: {
|
||||
name: bcLineup.id,
|
||||
put: [bcLineup.id],
|
||||
pull: [bcLineup.id],
|
||||
},
|
||||
onAdd: function (/**Event*/ evt) {
|
||||
// Add to Lineup
|
||||
var itemEl = evt.item; // dragged HTMLElement
|
||||
var player_order = itemEl.querySelector('[id^="sequence-member"]');
|
||||
var player_available = itemEl.querySelector(
|
||||
'[class^="member-availability-status"]'
|
||||
);
|
||||
refresh_lineup_order(itemEl);
|
||||
if (player_order.classList.contains("d-none")) {
|
||||
player_order.classList.remove("d-none");
|
||||
}
|
||||
// player_available.classList.add('d-none')
|
||||
},
|
||||
onUpdate: function (/**Event*/ evt) {
|
||||
console.log("update to lineup");
|
||||
var itemEl = evt.item; // dragged HTMLElement
|
||||
refresh_lineup_order(itemEl);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function copyEmailTable(itemEl, subject, recipients) {
|
||||
// Create container for the HTML
|
||||
// [1]
|
||||
let bcLineup = itemEl.closest(".benchcoach-lineup");
|
||||
var container = document.createElement("div");
|
||||
var tbl = document.createElement("table");
|
||||
|
||||
let thead = tbl.createTHead();
|
||||
let thead_row = thead.insertRow();
|
||||
let thead_row_cell = thead_row.insertCell();
|
||||
thead_row_cell.appendChild(
|
||||
document
|
||||
.createElement("h3")
|
||||
.appendChild(document.createTextNode("STARTING LINEUP"))
|
||||
);
|
||||
thead_row_cell.colSpan = 3;
|
||||
thead_row_cell.classList.add("title-cell");
|
||||
var tbody = tbl.createTBody();
|
||||
for (row of bcLineup.querySelector(".table-benchcoach-startinglineup").rows) {
|
||||
let tr = tbody.insertRow();
|
||||
cell = tr.insertCell();
|
||||
cell.classList.add("sequence-cell");
|
||||
cell.appendChild(document.createTextNode(parseInt(row.dataset.order) + 1));
|
||||
cell = tr.insertCell();
|
||||
cell.appendChild(document.createTextNode(row.dataset.playerName));
|
||||
cell.classList.add("name-cell");
|
||||
tr.insertCell().appendChild(document.createTextNode(row.dataset.position));
|
||||
}
|
||||
|
||||
if (
|
||||
bcLineup.querySelector(".table-benchcoach-startingpositionalonly").rows
|
||||
.length > 0
|
||||
) {
|
||||
var tr = tbody.insertRow();
|
||||
cell = tr.insertCell();
|
||||
cell.colSpan = 3;
|
||||
cell.appendChild(document.createTextNode("STARTING (POS. ONLY)"));
|
||||
cell.classList.add("title-cell");
|
||||
|
||||
for (row of bcLineup.querySelector(
|
||||
".table-benchcoach-startingpositionalonly"
|
||||
).rows) {
|
||||
var tr = tbody.insertRow();
|
||||
cell = tr.insertCell();
|
||||
cell.classList.add("sequence-cell");
|
||||
cell.appendChild(document.createTextNode(""));
|
||||
cell = tr.insertCell();
|
||||
cell.appendChild(document.createTextNode(row.dataset.playerName));
|
||||
cell.classList.add("name-cell");
|
||||
tr.insertCell().appendChild(
|
||||
document.createTextNode(row.dataset.position)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (bcLineup.querySelector(".table-benchcoach-bench").rows.length > 0) {
|
||||
var tr = tbody.insertRow();
|
||||
cell = tr.insertCell();
|
||||
cell.colSpan = 3;
|
||||
cell.appendChild(document.createTextNode("SUBS"));
|
||||
cell.classList.add("title-cell");
|
||||
|
||||
for (row of bcLineup.querySelector(".table-benchcoach-bench").rows) {
|
||||
var tr = tbody.insertRow();
|
||||
cell = tr.insertCell();
|
||||
cell.classList.add("sequence-cell");
|
||||
availability_status = {
|
||||
None: "UNK",
|
||||
0: "NO",
|
||||
2: "MAY",
|
||||
1: "YES",
|
||||
}[row.dataset.availabilityStatuscode];
|
||||
cell.appendChild(document.createTextNode(availability_status));
|
||||
cell = tr.insertCell();
|
||||
cell.appendChild(document.createTextNode(row.dataset.playerName));
|
||||
cell.classList.add("name-cell");
|
||||
tr.insertCell().appendChild(document.createTextNode(""));
|
||||
}
|
||||
}
|
||||
|
||||
if (bcLineup.querySelector(".table-benchcoach-out").rows.length > 0) {
|
||||
var tr = tbody.insertRow();
|
||||
cell = tr.insertCell();
|
||||
cell.colSpan = 3;
|
||||
cell.appendChild(document.createTextNode("OUT"));
|
||||
cell.classList.add("title-cell");
|
||||
|
||||
for (row of bcLineup.querySelector(".table-benchcoach-out").rows) {
|
||||
var tr = tbody.insertRow();
|
||||
cell = tr.insertCell();
|
||||
cell.classList.add("sequence-cell");
|
||||
availability_status = {
|
||||
None: "UNK",
|
||||
0: "NO",
|
||||
1: "MAY",
|
||||
2: "YES",
|
||||
}[row.dataset.availabilityStatuscode];
|
||||
cell.appendChild(document.createTextNode(availability_status));
|
||||
tr.insertCell().appendChild(
|
||||
document.createTextNode(row.dataset.playerName)
|
||||
);
|
||||
tr.insertCell().appendChild(document.createTextNode(""));
|
||||
}
|
||||
}
|
||||
|
||||
container.appendChild(tbl);
|
||||
for (cell of container.getElementsByClassName("title-cell")) {
|
||||
cell.setAttribute(
|
||||
"style",
|
||||
"font-weight:bold;background-color:#323669;color:#fff;padding:2px 5px;"
|
||||
);
|
||||
}
|
||||
|
||||
for (cell of container.getElementsByClassName("sequence-cell")) {
|
||||
cell.setAttribute("style", "font-weight:bold;padding:2px 5px;");
|
||||
}
|
||||
|
||||
for (cell of container.getElementsByClassName("name-cell")) {
|
||||
cell.setAttribute("style", "width:200px;");
|
||||
}
|
||||
|
||||
// Detect all style sheets of the page
|
||||
var activeSheets = Array.prototype.slice
|
||||
.call(document.styleSheets)
|
||||
.filter(function (sheet) {
|
||||
return !sheet.disabled;
|
||||
});
|
||||
|
||||
// Mount the container to the DOM to make `contentWindow` available
|
||||
// [3]
|
||||
document.body.appendChild(container);
|
||||
|
||||
// Copy to clipboard
|
||||
// [4]
|
||||
window.getSelection().removeAllRanges();
|
||||
|
||||
var range = document.createRange();
|
||||
range.selectNode(container);
|
||||
window.getSelection().addRange(range);
|
||||
|
||||
// [5.1]
|
||||
document.execCommand("copy");
|
||||
|
||||
// [5.2]
|
||||
for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = true;
|
||||
|
||||
// [5.3]
|
||||
// document.execCommand('copy')
|
||||
|
||||
// [5.4]
|
||||
for (var i = 0; i < activeSheets.length; i++)
|
||||
activeSheets[i].disabled = false;
|
||||
|
||||
// Remove the container
|
||||
// [6]
|
||||
document.body.removeChild(container);
|
||||
subject_encoded = encodeURIComponent(subject);
|
||||
window.open(
|
||||
"readdle-spark://compose?recipient=manager@chihounds.com&subject=" +
|
||||
subject +
|
||||
"&bcc=" +
|
||||
recipients
|
||||
);
|
||||
}
|
||||
19
src/views/login.pug
Normal file
19
src/views/login.pug
Normal file
@@ -0,0 +1,19 @@
|
||||
extends base.pug
|
||||
|
||||
block content
|
||||
.Grid.Grid--fit.Grid--withGutter.u-max1200.u-flexExpandSides.u-xs-size5of6.u-sm-size2of3.u-md-sizeFull.u-padBottomMd.u-xs-padEndsLg.u-sm-padEndsXl
|
||||
.Grid-cell.u-size5of12
|
||||
.Panel.u-padLg.u-spaceSidesAuto
|
||||
h1.u-spaceSidesAuto.u-spaceBottomLg Sign in
|
||||
a(class="Button Button--large Button--orange" href="/login/federated/teamsnap").u-spaceSidesAuto
|
||||
img(src="/media/teamsnap_star.svg").icon.u-spaceRightSm
|
||||
span TeamSnap
|
||||
.Grid-cell.u-size7of12.u-textCenter
|
||||
h1
|
||||
img(src="media/benchcoach.svg" style="width: 2.5em;")
|
||||
h1
|
||||
strong
|
||||
| Welcome to
|
||||
span.text-nowrap BenchCoach
|
||||
.lead.fst-italic.fw-light
|
||||
| An assistant coach for TeamSnap
|
||||
15
src/views/mixin-availability-progress-bar.pug
Normal file
15
src/views/mixin-availability-progress-bar.pug
Normal file
@@ -0,0 +1,15 @@
|
||||
mixin availability-progress-bar(availabilitySummary, team)
|
||||
.progress
|
||||
div(class="progress-bar bg-success fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerGoingCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerGoingCount}
|
||||
div(class="progress-bar bg-info fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerMaybeCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerMaybeCount}
|
||||
div(class="progress-bar bg-danger fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerNotGoingCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerNotGoingCount}
|
||||
div(class="progress-bar text-secondary fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerUnknownCount/team.playerMemberCount)*100).toString() + "%"};
|
||||
background-color: var(--bs-gray-200)`)
|
||||
|#{availabilitySummary.playerUnknownCount}
|
||||
22
src/views/mixin-lineup-slot.pug
Normal file
22
src/views/mixin-lineup-slot.pug
Normal file
@@ -0,0 +1,22 @@
|
||||
mixin lineup-slot(item, index)
|
||||
-
|
||||
if (item.type == "eventLineupEntry") {
|
||||
var availability_status_code = item.availabilityStatusCode
|
||||
} else if (item.type == "availability") {
|
||||
var availability_status_code = item.statusCode
|
||||
}
|
||||
.Panel-row.Panel-row--withCells.lineup-slot
|
||||
.Panel-cell.Panel-cell--header.u-padXs.u-size1of12
|
||||
.u-flexAlignSelfCenter
|
||||
|#{index+1}
|
||||
div(class=`Panel-cell availability-status-code-${availability_status_code}`).u-padXs.u-size8of12
|
||||
span.lastname #{item.member.lastName}
|
||||
span.jerseynumber ##{item.member.jerseyNumber}
|
||||
.Panel-cell.u-padXs.u-size2of12
|
||||
.SelectBox.position-selection
|
||||
select(onchange="onPositionSelectChange(this)").position-select-box.SelectBox-options
|
||||
each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"]
|
||||
option(selected=item.label==pos) #{pos}
|
||||
.Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12
|
||||
.drag-handle
|
||||
i.bi.bi-grip-vertical.text-secondary.drag-handle
|
||||
@@ -13,6 +13,11 @@ body
|
||||
.Panel-header
|
||||
.Panel-title #{opponent.name}
|
||||
.Panel-body
|
||||
.Panel-row.Panel-row--withCells
|
||||
.Panel-cell.Panel-cell--header ID
|
||||
.panel-cell #{opponent.id}
|
||||
Button(onclick=`navigator.clipboard.writeText("${opponent.id}");`).Button
|
||||
i.bi.bi-clipboard.Icon
|
||||
.Panel-row.Panel-row--withCells
|
||||
.Panel-cell.Panel-cell--header Contact Name
|
||||
.panel-cell #{opponent.contactsName}
|
||||
@@ -27,8 +32,16 @@ body
|
||||
.panel-cell
|
||||
if opponent_logo
|
||||
img(src=`${opponent_logo.mediumUrl}` width="64" height="64")
|
||||
a.Button(target="_blank" rel="noopener noreferrer" href=`https://go.teamsnap.com/${team_id}/files/view/${opponent_logo.id}`).Button
|
||||
i.bi.bi-asterisk.Icon
|
||||
else
|
||||
button.Button Upload
|
||||
if team_media_group
|
||||
a.Button(target="_blank" rel="noopener noreferrer" href=`https://go.teamsnap.com/${team_id}/files/list/${team_media_group.id}`) Upload
|
||||
else
|
||||
a.Button(target="_blank" rel="noopener noreferrer" href=`https://go.teamsnap.com/${team_id}/files/`) Upload
|
||||
Button(onclick=`navigator.clipboard.writeText("team-logo-${opponent.id}.png");`).Button
|
||||
i.bi.bi-clipboard.Icon
|
||||
span Copy Filename
|
||||
.Panel-row.Panel-row--withCells
|
||||
.Panel-cell.Panel-cell--header Notes
|
||||
.panel-cell #{opponent.Notes}
|
||||
17
src/views/roster.pug
Normal file
17
src/views/roster.pug
Normal file
@@ -0,0 +1,17 @@
|
||||
extends base.pug
|
||||
include widgets/availability-progress-bar.pug
|
||||
|
||||
block content
|
||||
.Panel
|
||||
.Panel-header
|
||||
.Panel-title roster
|
||||
.Panel-body
|
||||
each member in members
|
||||
- var availabilitySummary = availabilitySummaries.find((a)=>a.eventId==event.id)
|
||||
a(class="event list-group-item" href=`/${team_id}/event/${event.id}`).Panel-row--withCells
|
||||
.Panel-cell
|
||||
|#{member.firstName}
|
||||
.Panel-cell
|
||||
|#{event.lastName}
|
||||
|
||||
|
||||
24
src/views/team.pug
Normal file
24
src/views/team.pug
Normal file
@@ -0,0 +1,24 @@
|
||||
extends base.pug
|
||||
|
||||
block content
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
h2.Panel-title #{team.name}
|
||||
p #{team.seasonName}
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
a(href=`/${team.id}/events`).u-fontSizeXl-
|
||||
<svg viewBox="0 0 960 960" role="presentation" class="Icon">
|
||||
<path d="M890 131c11.3 2.7 20.5 8.3 27.5 17s10.5 18.7 10.5 30v699c0 11.3-3.5 21.3-10.5 30s-16.2 14.3-27.5 17l-8 2c-4.7.7-11 1.7-19 3s-17.7 3-29 5-24.3 3.8-39 5.5-30.5 3.5-47.5 5.5-35.7 4-56 6-41.3 3.7-63 5-45.3 2.3-71 3-51.5 1-77.5 1-51.8-.3-77.5-1-49.3-1.7-71-3-42.7-3-63-5-39-4-56-6-32.8-3.8-47.5-5.5-27.7-3.5-39-5.5-21-3.7-29-5-14.3-2.3-19-3l-8-2c-11.3-2.7-20.5-8.3-27.5-17S32 888.3 32 877V178c0-11.3 3.5-21.3 10.5-30s16.2-14.3 27.5-17c.7 0 4.5-.7 11.5-2s17.8-3.2 32.5-5.5 30-4.5 46-6.5v43c0 23.3 8.3 42.5 25 57.5s36.7 22.5 60 22.5c-14-12.7-21-28.7-21-48V64c0-17.3 6.3-32.3 19-45s27.7-19 45-19 32.3 6.3 45 19 19 27.7 19 45v35c40-2 82.7-3 128-3 28.7 0 50 .3 64 1v63c0 23.3 8.3 42.5 25 57.5s36.7 22.5 60 22.5c-14-12.7-21-28.7-21-48V64c0-17.3 6.3-32.3 19-45s27.7-19 45-19 32.3 6.3 45 19 19 27.7 19 45v45c64 6.7 115.3 14 154 22zM480 869c122.7 0 240-9.3 352-28V384H128v457c112 18.7 229.3 28 352 28zm256-421v128H608V448h128zm-192 0v128H416V448h128zm0 320H416V640h128v128zm-192 0H224V640h128v128zm384 0H608V640h128v128z"></path>
|
||||
</svg>
|
||||
| Events
|
||||
.Panel-row
|
||||
a(href=`/${team.id}/roster`)
|
||||
<svg viewBox="0 0 960 960" class="Icon"><path d="M959 714c2 8 .7 16-4 24-5.3 7.3-12.3 11.7-21 13-9.3 4.7-66.7 8.3-172 11-28.7-60.7-73.3-109.7-134-147-17.3-10-39-19.7-65-29-6.7-3.3-12-5.7-16-7 31.3-49.3 52.3-97 63-143s13.5-84.3 8.5-115-15.2-58.3-30.5-83c-28-47.3-63.3-80.7-106-100 18.7-24 37.2-41.7 55.5-53S579 68 607 68c33.3 0 63.7 7.7 91 23s49.3 36.7 66 64c43.3 71.3 32.3 157.7-33 259-20 28.7-27.7 50.7-23 66 2 7.3 8 14.5 18 21.5s18.7 12.2 26 15.5 19.3 8.3 36 15c26 10.7 43.7 18.7 53 24 64.7 39.3 104 92 118 158zM352 892c-70 0-132-1-186-3s-90.2-4-108.5-6-28.8-3.3-31.5-4c-8.7-.7-15.7-5-21-13-4.7-6.7-6-14.7-4-24 14-66 53-118.7 117-158 8-4.7 25.7-12.7 53-24 16.7-6.7 28.7-11.7 36-15s16-8.5 26-15.5 16-14.2 18-21.5c4.7-14.7-2.7-36.7-22-66-65.3-102-76.7-188.3-34-259 16.7-27.3 38.8-48.7 66.5-64s57.8-23 90.5-23c33.3 0 63.8 7.7 91.5 23s49.8 36.7 66.5 64c42.7 70.7 31.3 157-34 259-19.3 29.3-26.7 51.3-22 66 2 7.3 8 14.5 18 21.5s18.7 12.2 26 15.5 19.3 8.3 36 15c27.3 11.3 45 19.3 53 24 63.3 39.3 102.7 92 118 158 2 8.7.3 16.7-5 24-5.3 8-12.3 12.3-21 13-2.7.7-13.3 2-32 4s-55 4-109 6-116 3-186 3z"></path></svg>
|
||||
| Roster
|
||||
.Panel-row
|
||||
a(href=`/${team.id}/opponents`)
|
||||
<svg viewBox="0 0 960 960" class="Icon"><path d="M959 628c2 6.7.7 13.7-4 21s-10.7 11.3-18 12l-7 1c-4.7.7-11.8 1.5-21.5 2.5s-21.5 2-35.5 3-33.2 1.8-57.5 2.5-50.8 1.3-79.5 2c-6-4.7-12.7-9.2-20-13.5s-15.2-9-23.5-14S678 635.7 674 633c-10.7-5.3-21-11.3-31-18 70-92.7 84-184.7 42-276-16.7-36-40-64-70-84s-62.7-32.3-98-37c0-23.3 5.3-47.3 16-72 12.7-28 32-48.7 58-62s53-20 81-20 55 6.7 81 20 45.3 34 58 62c32 70 16.3 141.7-47 215-19.3 22.7-18 46.3 4 71 6.7 8 26.2 21.3 58.5 40s55.2 32.7 68.5 42c7.3 5.3 13.8 10.2 19.5 14.5s10.5 9.3 14.5 15 7.2 10 9.5 13 4.7 8.2 7 15.5 3.8 12.3 4.5 15 2.2 9.2 4.5 19.5 3.8 17.5 4.5 21.5zm-673 5c-4 2.7-10.2 6.5-18.5 11.5s-16.2 9.7-23.5 14-14 8.8-20 13.5c-20.7 0-40.3-.3-59-1s-34.7-1.3-48-2-25.3-1.3-36-2-19.5-1.3-26.5-2-12.8-1.3-17.5-2-8.3-1-11-1l-3-1c-7.3-.7-13.3-4.7-18-12-4.7-6-6-13-4-21 1.3-4.7 3-11.8 5-21.5s3.3-16.2 4-19.5 2.2-8.5 4.5-15.5 4.7-12 7-15S27 549.3 31 544s8.7-10.3 14-15 12-9.7 20-15c14-10 37-24.3 69-43s51.3-31.7 58-39c22-24.7 23.3-48.3 4-71-63.3-73.3-79-145-47-215 12.7-28 32-48.7 58-62s53-20 81-20 55 6.7 81 20 45.3 34 58 62c10.7 24.7 16 48.7 16 72-80 11.3-136.3 51.7-169 121-41.3 91.3-27 183.3 43 276-2.7 2-5.7 4-9 6s-7.2 4.2-11.5 6.5-7.5 4.2-9.5 5.5h-1zm194 263c-28 0-54.5-.2-79.5-.5s-46.2-.8-63.5-1.5-33-1.5-47-2.5-25.5-1.8-34.5-2.5-16.5-1.3-22.5-2-10.3-1-13-1l-5-1c-7.3-.7-13.3-4.7-18-12-4.7-6-6-13-4-21 1.3-4.7 3-11.8 5-21.5s3.3-16.2 4-19.5 2.2-8.5 4.5-15.5 4.7-12 7-15 5.5-7.2 9.5-12.5 8.7-10.3 14-15 12-9.7 20-15c14-10 37-24.3 69-43s51.3-31.7 58-39c22-24.7 23.3-48.3 4-71-63.3-73.3-79-145-47-215 12.7-28 32-48.7 58-62s53-20 81-20 55 6.7 81 20 45.3 34 58 62c32 70 16.3 141.7-47 215-19.3 22.7-18 46.3 4 71 6.7 8 26.2 21.3 58.5 40s55.2 32.7 68.5 42c16.7 12 29 23.2 37 33.5s13.5 21.7 16.5 34S763 833.3 767 852c2 7.3.7 14.3-4 21-4.7 7.3-10.7 11.3-18 12l-5 1c-2.7 0-7 .3-13 1s-13.5 1.3-22.5 2-20.7 1.5-35 2.5-30.2 1.8-47.5 2.5-38.3 1.2-63 1.5-51 .5-79 .5z"></path></svg>
|
||||
| Opponents
|
||||
20
src/views/teams.pug
Normal file
20
src/views/teams.pug
Normal file
@@ -0,0 +1,20 @@
|
||||
extends base.pug
|
||||
|
||||
block content
|
||||
.row
|
||||
.text-center.my-2
|
||||
.row
|
||||
h1
|
||||
img.mx-auto(src="media/benchcoach.svg" style="width: 2.5em;")
|
||||
.row
|
||||
h1
|
||||
strong
|
||||
| Welcome to
|
||||
span.text-nowrap BenchCoach
|
||||
.text-center.lead.fst-italic.fw-light
|
||||
| An assistant coach for TeamSnap
|
||||
.row
|
||||
.col.text-center
|
||||
ul.list-group
|
||||
each team in teams
|
||||
a(class='team list-group-item' href=`/${team.id}/home`) #{team.name} [#{team.seasonName}]
|
||||
84
src/views/upload-logo.pug
Normal file
84
src/views/upload-logo.pug
Normal file
@@ -0,0 +1,84 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title BenchCoach - Teams
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/font/bootstrap-icons.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
script(type='text/javascript', src='/js/teamsnap.js')
|
||||
|
||||
body
|
||||
.container
|
||||
.Panel
|
||||
.Panel-header
|
||||
.Panel-title Upload
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
.input-group
|
||||
label(for='file') Select file
|
||||
input(id='file' type="file")
|
||||
input(id="csrf_token", type="hidden" name="csrf_token" value=`${csrf_token}`)
|
||||
input(id='team_id', type="hidden", value=`${team_id}`)
|
||||
input(id='opponent_id', type="hidden", value=`${opponent_id}`)
|
||||
input(id='token', type="hidden", value=`${token}`)
|
||||
input(id='clientId', type="hidden", value=`${clientId}`)
|
||||
button(type='submit' onClick="submitForm()") Upload
|
||||
|
||||
script.
|
||||
function submitForm(e) {
|
||||
console.log(document.getElementById("opponent_id").value)
|
||||
const file = document.getElementById("file");
|
||||
const csrf_token = document.getElementById("csrf_token").value;
|
||||
const team_id = document.getElementById("team_id").value;
|
||||
const opponent_id = document.getElementById("opponent_id").value;
|
||||
const formData = new FormData();
|
||||
formData.append("file", file.files[0]);
|
||||
formData.append("team_id", team_id);
|
||||
formData.append("opponent_id", opponent_id);
|
||||
for (var key of formData.entries()) {
|
||||
console.log(key[0] + ', ' + key[1]);
|
||||
}
|
||||
fetch(`/${team_id}/opponent/${opponent_id}/upload-logo`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
"X-CSRF-Token": csrf_token,
|
||||
|
||||
}
|
||||
})
|
||||
.then((res) => console.log(res))
|
||||
.catch((err) => ("Error occured", err));
|
||||
}
|
||||
|
||||
function uploadImageForm(e) {
|
||||
const file = document.getElementById("file");
|
||||
const csrf_token = document.getElementById("csrf_token").value;
|
||||
const team_id = document.getElementById("team_id").value;
|
||||
const opponent_id = document.getElementById("opponent_id").value;
|
||||
const token = document.getElementById("token").value;
|
||||
const clientId = document.getElementById("clientId").value;
|
||||
const formData = new FormData();
|
||||
teamsnap.init(clientId);
|
||||
teamsnap.auth(token)
|
||||
console.log(teamsnap.isAuthed())
|
||||
teamsnap
|
||||
.loadCollections()
|
||||
.then(() => {
|
||||
return teamsnap.createTeamMedium({
|
||||
file: file.files[0],
|
||||
mediaFormat: "file",
|
||||
memberId: member_id,
|
||||
teamId: team_id,
|
||||
teamMediaGroupId: "4927028",
|
||||
description: `team-logo-${opponent_id}.png`,
|
||||
});
|
||||
})
|
||||
.then((item) => {
|
||||
return teamsnap.uploadTeamMedium(item);
|
||||
})
|
||||
.then((item) => {
|
||||
res.send("Data Received: " + JSON.stringify(item));
|
||||
})
|
||||
.fail((err) => console.log(err));
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title #{event.formattedTitle}
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/font/bootstrap-icons.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
body
|
||||
.container
|
||||
.Panel
|
||||
.Panel-header
|
||||
h3.Panel-title #{event.formattedTitle}
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
h6.card-text.text-muted.mb-2
|
||||
|#{event.startDate}
|
||||
br
|
||||
|#{event.locationName}
|
||||
.Panel-row
|
||||
h4 Availability
|
||||
.progress
|
||||
div(class="progress-bar bg-success fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerGoingCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerGoingCount}
|
||||
div(class="progress-bar bg-info fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerMaybeCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerMaybeCount}
|
||||
div(class="progress-bar bg-danger fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerNotGoingCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerNotGoingCount}
|
||||
div(class="progress-bar text-secondary fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerUnknownCount/team.playerMemberCount)*100).toString() + "%"};
|
||||
background-color: var(--bs-gray-200)`)
|
||||
|#{availabilitySummary.playerUnknownCount}
|
||||
hr
|
||||
div.d-flex
|
||||
a(class="Button m-auto" href=`/${team_id}/event/${event.id}/lineup`)
|
||||
i(class="bi bi-clipboard")
|
||||
span.mx-1 Lineup
|
||||
a(class="Button m-auto" href=`/${team_id}/event/${event.id}/gamecard`)
|
||||
i(class="bi bi-book")
|
||||
span.mx-1 Game Card
|
||||
a(class="Button m-auto" href=`https://go.teamsnap.com/${team_id}/schedule/view_game/${event.id}`)
|
||||
i(class="bi bi-asterisk")
|
||||
span.mx-1 TeamSnap
|
||||
@@ -1,37 +0,0 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title BenchCoach - Teams
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
body
|
||||
.container
|
||||
.Panel
|
||||
.Panel-header
|
||||
.Panel-title Schedule
|
||||
.Panel-body
|
||||
each event in events
|
||||
- var availabilitySummary = availabilitySummaries.find((a)=>a.eventId==event.id)
|
||||
.Panel-row
|
||||
a(class="event list-group-item" href=`/${team_id}/event/${event.id}`)
|
||||
h4 #{event.formattedTitle}
|
||||
p.small
|
||||
| #{event.startDate.toLocaleDateString("en-us",{weekday: "short", day: "numeric",month: "short"})}
|
||||
| #{event.startDate.toLocaleTimeString("en-us",{hour: "numeric", minute: "2-digit"})}
|
||||
p #{event.locationName}
|
||||
.progress
|
||||
div(class="progress-bar bg-success fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerGoingCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerGoingCount}
|
||||
div(class="progress-bar bg-info fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerMaybeCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerMaybeCount}
|
||||
div(class="progress-bar bg-danger fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerNotGoingCount/team.playerMemberCount)*100).toString() + "%"}`)
|
||||
|#{availabilitySummary.playerNotGoingCount}
|
||||
div(class="progress-bar text-secondary fw-bold" role="progressbar" style=`
|
||||
width: ${((availabilitySummary.playerUnknownCount/team.playerMemberCount)*100).toString() + "%"};
|
||||
background-color: var(--bs-gray-200)`)
|
||||
|#{availabilitySummary.playerUnknownCount}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title BenchCoach - Home
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/css/project.css')
|
||||
body.bg-light
|
||||
.container
|
||||
.row
|
||||
.text-center.my-2
|
||||
.row
|
||||
h1
|
||||
img.mx-auto(src="media/benchcoach.svg" style="width: 2.5em;")
|
||||
.row
|
||||
h1
|
||||
strong
|
||||
| Welcome to
|
||||
span.text-nowrap BenchCoach
|
||||
.text-center.lead.fst-italic.fw-light
|
||||
| An assistant coach for TeamSnap
|
||||
.row
|
||||
.col.text-center
|
||||
if req.user
|
||||
ul.list-group
|
||||
each team in teams
|
||||
a(class='team list-group-item' href=`/${team.id}`) #{team.name} [#{team.seasonName}]
|
||||
else
|
||||
a.btn.btn-outline-primary(href="login")
|
||||
| Login
|
||||
139
views/lineup.pug
139
views/lineup.pug
@@ -1,139 +0,0 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
title #{event.formattedTitle}
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/font/bootstrap-icons.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
|
||||
body.bg-light
|
||||
.container
|
||||
div(style="max-width: 455px")
|
||||
.Panel
|
||||
.panel-header
|
||||
.Panel-title #{event.formattedTitle}
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
p.text-muted.mb-2 #{event.startDate}
|
||||
p #{event.locationName}
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard-check.me-1
|
||||
span Starting Lineup
|
||||
.Panel-row.Grid.Grid--fit.fw-bold.text-center.u-padXs
|
||||
each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"]
|
||||
if event_lineup_entries.map((lue)=>lue.label).includes(pos)
|
||||
.Grid-cell.text-success
|
||||
|#{pos}
|
||||
else
|
||||
.Grid-cell.text-danger
|
||||
|#{pos}
|
||||
each lineup_entry, i in event_lineup_entries_offense
|
||||
.Panel-row.Panel-row--withCells
|
||||
.Panel-cell.Panel-cell--header.u-padXs.u-size1of12
|
||||
.u-flexAlignSelfCenter
|
||||
|#{i+1}
|
||||
.Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase
|
||||
if lineup_entry.availabilityStatusCode == 2
|
||||
i.bi.bi-question-circle-fill.text-info.u-spaceRightXs
|
||||
else if lineup_entry.availabilityStatusCode == 1
|
||||
i.bi.bi-check-circle-fill.text-success.u-spaceRightXs
|
||||
else if lineup_entry.availabilityStatusCode == 0
|
||||
i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs
|
||||
else
|
||||
i.bi.bi-question-circle.u-spaceRightXs
|
||||
|#{lineup_entry.member.lastName}
|
||||
.Panel-cell.u-padXs.u-size2of12
|
||||
.SelectBox
|
||||
select.SelectBox-options
|
||||
each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"]
|
||||
option(selected=lineup_entry.label==pos) #{pos}
|
||||
.Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12
|
||||
.drag-handle
|
||||
i.bi.bi-grip-vertical.text-secondary
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard-minus.me-1
|
||||
span Starting Lineup (Position Only)
|
||||
each lineup_entry, i in event_lineup_entries
|
||||
if lineup_entry.label.includes("[PO]")
|
||||
.Panel-row.Panel-row--withCells
|
||||
.Panel-cell.Panel-cell--header.u-padXs.u-size1of12
|
||||
.u-flexAlignSelfCenter
|
||||
|#{i+1}
|
||||
.Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase
|
||||
if lineup_entry.availabilityStatusCode == 2
|
||||
i.bi.bi-question-circle-fill.text-info.u-spaceRightXs
|
||||
else if lineup_entry.availabilityStatusCode == 1
|
||||
i.bi.bi-check-circle-fill.text-success.u-spaceRightXs
|
||||
else if lineup_entry.availabilityStatusCode == 0
|
||||
i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs
|
||||
else
|
||||
i.bi.bi-question-circle.u-spaceRightXs
|
||||
|#{lineup_entry.member.lastName}
|
||||
.Panel-cell.u-padXs.u-size2of12
|
||||
.SelectBox
|
||||
select.SelectBox-options
|
||||
each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"]
|
||||
option(selected=lineup_entry.label==pos) #{pos}
|
||||
.Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12
|
||||
.drag-handle
|
||||
i.bi.bi-grip-vertical.text-secondary
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard.me-1
|
||||
span Bench
|
||||
each availability, i in availabilities.filter((a)=>a.eventId==event_id && !context.event_lineup_entries.map((lue)=>lue.memberId).includes(a.memberId) && !a.member.isNonPlayer && a.statusCode!=0 && a.statusCode!==null)
|
||||
.Panel-row.Panel-row--withCells
|
||||
.Panel-cell.Panel-cell--header.u-padXs.u-size1of12
|
||||
.u-flexAlignSelfCenter
|
||||
.Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase
|
||||
if availability.statusCode == 2
|
||||
i.bi.bi-question-circle-fill.text-info.u-spaceRightXs
|
||||
else if availability.statusCode == 1
|
||||
i.bi.bi-check-circle-fill.text-success.u-spaceRightXs
|
||||
else if availability.statusCode == 0
|
||||
i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs
|
||||
else
|
||||
i.bi.bi-question-circle.u-spaceRightXs
|
||||
|#{availability.member.lastName}
|
||||
.Panel-cell.u-padXs.u-size2of12
|
||||
.SelectBox
|
||||
select.SelectBox-options
|
||||
each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"]
|
||||
option #{pos}
|
||||
.Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12
|
||||
.drag-handle
|
||||
i.bi.bi-grip-vertical.text-secondary
|
||||
|
||||
.Panel
|
||||
.Panel-body
|
||||
.Panel-row.Panel-title.u-padXs
|
||||
i.bi.bi-clipboard-x.me-1
|
||||
span Out
|
||||
each availability, i in availabilities.filter((a)=>a.eventId==event_id && !context.event_lineup_entries.map((lue)=>lue.memberId).includes(a.memberId) && !a.member.isNonPlayer && (a.statusCode==0 || a.statusCode===null))
|
||||
.Panel-row.Panel-row--withCells
|
||||
.Panel-cell.Panel-cell--header.u-padXs.u-size1of12
|
||||
.u-flexAlignSelfCenter
|
||||
.Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase
|
||||
if availability.statusCode == 2
|
||||
i.bi.bi-question-circle-fill.text-info.u-spaceRightXs
|
||||
else if availability.statusCode == 1
|
||||
i.bi.bi-check-circle-fill.text-success.u-spaceRightXs
|
||||
else if availability.statusCode == 0
|
||||
i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs
|
||||
else
|
||||
i.bi.bi-question-circle.u-spaceRightXs
|
||||
|#{availability.member.lastName}
|
||||
.Panel-cell.u-padXs.u-size2of12
|
||||
.SelectBox
|
||||
select.SelectBox-options
|
||||
each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"]
|
||||
option #{pos}
|
||||
.Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12
|
||||
.drag-handle
|
||||
i.bi.bi-grip-vertical.text-secondary
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title BenchCoach - Login
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/font/bootstrap-icons.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
body
|
||||
.u-padSidesMd.u-xs-padSidesLg
|
||||
.Panel.u-padLg
|
||||
h3 BenchCoach
|
||||
p Sign in
|
||||
|
||||
a(class="Button Button--large Button--orange" href="/login/federated/teamsnap")
|
||||
i(class="bi bi-asterisk")/
|
||||
span Sign in with TeamSnap
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title BenchCoach - #{team.name}
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/font/bootstrap-icons.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
|
||||
body
|
||||
.container
|
||||
.Panel
|
||||
.Panel-header
|
||||
h2.Panel-title #{team.name}
|
||||
p #{team.seasonName}
|
||||
.Panel-body
|
||||
.Panel-row
|
||||
a(class="list-group-item" href=`${team.id}/events`) Events
|
||||
.Panel-row
|
||||
a(class="list-group-item" href=`${team.id}/roster`) Roster
|
||||
.Panel-row
|
||||
a(class="list-group-item" href=`${team.id}/opponents`) Opponents
|
||||
@@ -1,14 +0,0 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||
title BenchCoach - Teams
|
||||
link(rel='stylesheet' href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/font/bootstrap-icons.min.css')
|
||||
link(rel='stylesheet' href='/css/teamsnap-ui.css')
|
||||
|
||||
body
|
||||
ul
|
||||
each team in teams
|
||||
li
|
||||
a(class='team' href=`/${team.id}`) #{team.name} [#{team.seasonName}]
|
||||
Reference in New Issue
Block a user