Compare commits
65 Commits
d484f8cfdf
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
87b2abbd80
|
|||
|
b0de3fb221
|
|||
|
149f0a411b
|
|||
|
e6d1d5a697
|
|||
|
bf9d0c1a78
|
|||
|
64fa16740b
|
|||
|
f273677ba7
|
|||
|
ca194d516d
|
|||
|
ed18389bb2
|
|||
|
b346710496
|
|||
|
6d1588e80f
|
|||
|
858cb24e3f
|
|||
|
196eb5f51d
|
|||
|
07446570c1
|
|||
|
a5c47ff9a7
|
|||
|
aa2ebf0b2e
|
|||
|
5f02ea4d5c
|
|||
|
39380eaf03
|
|||
|
cb131353dc
|
|||
|
e1c9a7b81b
|
|||
|
c495b265ee
|
|||
|
49864874fc
|
|||
|
e9fd60e619
|
|||
|
84da372330
|
|||
|
c696ffb4bc
|
|||
|
a06807b028
|
|||
|
07be459781
|
|||
|
769fa60196
|
|||
|
d377399c10
|
|||
|
fa50ab93dc
|
|||
|
73e3afcecc
|
|||
|
af9fa3bd9b
|
|||
|
7e803cc8e3
|
|||
|
339d4c7923
|
|||
|
58825b5bcd
|
|||
|
6b9e6734fe
|
|||
|
03a9ac3aae
|
|||
|
da159f2b13
|
|||
|
c2c192bdc6
|
|||
|
c2b1898b91
|
|||
|
4ee466e7cb
|
|||
|
6592f2eeae
|
|||
|
1f2ba45e54
|
|||
|
588c23ec3f
|
|||
|
1c3cafdcda
|
|||
|
fb0ca76c29
|
|||
|
bdb6a77371
|
|||
|
e4b981d676
|
|||
|
c4c0d0fb7d
|
|||
|
3695cd8975
|
|||
|
bcade85182
|
|||
|
d50f94acc8
|
|||
|
5e1facf24a
|
|||
|
cf01bf9fff
|
|||
|
83e722cdb9
|
|||
|
dd48aeca8d
|
|||
|
f421089eb9
|
|||
|
84cc1f651c
|
|||
|
39e6c2b5af
|
|||
|
9f9da4e191
|
|||
|
7c5630c5ba
|
|||
|
d72ff726a5
|
|||
|
05c948fd16
|
|||
|
7a1dfa3165
|
|||
|
c8d0221247
|
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
@@ -4,10 +4,22 @@
|
|||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Attach",
|
||||||
|
"port": 9229,
|
||||||
|
"request": "attach",
|
||||||
|
"restart": true,
|
||||||
|
"skipFiles": [
|
||||||
|
"<node_internals>/**"
|
||||||
|
],
|
||||||
|
"type": "node",
|
||||||
|
"localRoot": "${workspaceFolder}/src",
|
||||||
|
"remoteRoot": "/home/node/app/src"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"internalConsoleOptions": "neverOpen",
|
"internalConsoleOptions": "neverOpen",
|
||||||
"name": "nodemon",
|
"name": "nodemon (dev)",
|
||||||
"program": "dev",
|
"program": "dev",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"restart": true,
|
"restart": true,
|
||||||
@@ -16,8 +28,8 @@
|
|||||||
"<node_internals>/**"
|
"<node_internals>/**"
|
||||||
],
|
],
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"env": {"NODE_ENV": "development"},
|
"env": {"NODE_ENV": "development", "DEBUG": "app"},
|
||||||
"preLaunchTask": "npm: scss"
|
"preLaunchTask": "npm: build-css"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
16
.vscode/tasks.json
vendored
16
.vscode/tasks.json
vendored
@@ -3,17 +3,21 @@
|
|||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"type": "npm",
|
"type": "npm",
|
||||||
"script": "scss",
|
"script": "watch-scss",
|
||||||
"problemMatcher": [],
|
"problemMatcher": [],
|
||||||
"label": "npm: scss watch",
|
"label": "npm: watch-scss",
|
||||||
"detail": "sass --watch src/scss/application.scss public/css/application.css src/scss/eventsheet.scss:public/css/eventsheet.css"
|
"detail": "npm run watch-css",
|
||||||
|
"icon": {
|
||||||
|
"id": "eye",
|
||||||
|
"color": "terminal.ansiBlue"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "npm",
|
"type": "npm",
|
||||||
"script": "scss",
|
"script": "build-css",
|
||||||
"problemMatcher": [],
|
"problemMatcher": [],
|
||||||
"label": "npm: scss",
|
"label": "npm: build-css",
|
||||||
"detail": "sass src/scss/application.scss:public/css/application.css src/scss/eventsheet.scss:public/css/eventsheet.css"
|
"detail": "npm build-css"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
FROM node:21
|
||||||
|
|
||||||
|
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
|
||||||
|
RUN mkdir -p /home/node/app/var/db && chown -R node:node /home/node/app
|
||||||
|
WORKDIR /home/node/app
|
||||||
|
|
||||||
|
USER node
|
||||||
|
COPY --chown=node:node package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY --chown=node:node src src
|
||||||
|
COPY --chown=node:node bin bin
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD [ "npm", "start" ]
|
||||||
21
bin/www
21
bin/www
@@ -10,8 +10,7 @@ var https = require("https");
|
|||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var debug = require("debug")("https");
|
var debug = require("debug")("https");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
var livereload = require("livereload");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get port from environment and store in Express.
|
* Get port from environment and store in Express.
|
||||||
@@ -19,32 +18,18 @@ const path = require("path");
|
|||||||
|
|
||||||
var port = normalizePort(process.env.PORT || "3000");
|
var port = normalizePort(process.env.PORT || "3000");
|
||||||
app.set("port", port);
|
app.set("port", port);
|
||||||
|
var server = http.createServer(app);
|
||||||
/**
|
|
||||||
* Create HTTPS server.
|
|
||||||
*/
|
|
||||||
const https_options = {
|
|
||||||
key: fs.readFileSync("certs/key.pem"),
|
|
||||||
cert: fs.readFileSync("certs/cert.pem"),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
// console.log(`starting livereload, watching ${path.join(__dirname, "../src/views")}`)
|
const liveReloadServer = livereload.createServer({port:35729});
|
||||||
var livereload = require("livereload");
|
|
||||||
var connectLiveReload = require("connect-livereload");
|
|
||||||
|
|
||||||
const liveReloadServer = livereload.createServer({https: https_options, extraExts: ['pug']});
|
|
||||||
liveReloadServer.watch(path.join(__dirname, "../src/views"));
|
liveReloadServer.watch(path.join(__dirname, "../src/views"));
|
||||||
liveReloadServer.server.once("connection", () => {
|
liveReloadServer.server.once("connection", () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
liveReloadServer.refresh("/");
|
liveReloadServer.refresh("/");
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var server = https.createServer(https_options, app);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen on provided port, on all network interfaces.
|
* Listen on provided port, on all network interfaces.
|
||||||
*/
|
*/
|
||||||
|
|||||||
26
caddy/Caddyfile
Normal file
26
caddy/Caddyfile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
{$LOG_LEVEL} # Set via environment variable
|
||||||
|
}
|
||||||
|
|
||||||
|
localhost {
|
||||||
|
# Development configuration
|
||||||
|
@notProd {
|
||||||
|
expression {env.ENVIRONMENT} == 'development'
|
||||||
|
}
|
||||||
|
handle @notProd {
|
||||||
|
# Configuration that only applies when not in production
|
||||||
|
reverse_proxy app-dev:3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{$DOMAIN} {
|
||||||
|
# Production configuration
|
||||||
|
@prod {
|
||||||
|
expression {env.ENVIRONMENT} == 'production'
|
||||||
|
}
|
||||||
|
handle @prod {
|
||||||
|
# Configuration that only applies in production
|
||||||
|
# header Strict-Transport-Security "max-age=31536000;"
|
||||||
|
reverse_proxy app:3000
|
||||||
|
}
|
||||||
|
}
|
||||||
50
docker-compose.yml
Normal file
50
docker-compose.yml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
services:
|
||||||
|
app: &app
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
build: .
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
profiles:
|
||||||
|
- production
|
||||||
|
expose:
|
||||||
|
- 3000
|
||||||
|
|
||||||
|
app-dev:
|
||||||
|
<<: *app
|
||||||
|
ports:
|
||||||
|
- 9229:9229 #debugger
|
||||||
|
- 35729:35729 #livereload
|
||||||
|
profiles:
|
||||||
|
- development
|
||||||
|
command: npm run dev
|
||||||
|
volumes:
|
||||||
|
- ./src:/home/node/app/src
|
||||||
|
- ./package.json:/home/node/app/package.json
|
||||||
|
- ./package-lock.json:/home/node/app/package-lock.json
|
||||||
|
- ./certs:/home/node/app/certs
|
||||||
|
- ./bin/www:/home/node/app/bin/www
|
||||||
|
environment:
|
||||||
|
DEBUG: "app"
|
||||||
|
NODE_ENV: "development"
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
volumes:
|
||||||
|
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
71
package-lock.json
generated
71
package-lock.json
generated
@@ -9,7 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@teamsnap/teamsnap-ui": "^3.12.3",
|
"@teamsnap/teamsnap-ui": "^3.12.3",
|
||||||
"better-sqlite3": "^9.4.1",
|
"better-sqlite3": "^9.6.0",
|
||||||
"better-sqlite3-session-store": "^0.1.0",
|
"better-sqlite3-session-store": "^0.1.0",
|
||||||
"bootstrap": "^5.3.1",
|
"bootstrap": "^5.3.1",
|
||||||
"bootstrap-icons": "^1.10.5",
|
"bootstrap-icons": "^1.10.5",
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"passport-teamsnap": "^1.1.1",
|
"passport-teamsnap": "^1.1.1",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
|
"sass": "^1.77.2",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"teamsnap.js": "github:anthonyscorrea/teamsnap-javascript-sdk#link-with-null-link",
|
"teamsnap.js": "github:anthonyscorrea/teamsnap-javascript-sdk#link-with-null-link",
|
||||||
"tinymce": "^6.8.3",
|
"tinymce": "^6.8.3",
|
||||||
@@ -663,7 +664,6 @@
|
|||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"picomatch": "^2.0.4"
|
"picomatch": "^2.0.4"
|
||||||
@@ -813,9 +813,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/better-sqlite3": {
|
"node_modules/better-sqlite3": {
|
||||||
"version": "9.4.1",
|
"version": "9.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.6.0.tgz",
|
||||||
"integrity": "sha512-QpqiQeMI4WkE+dQ68zTMX5OzlPGc7lXIDP1iKUt4Omt9PdaVgzKYxHIJRIzt1E+RUBQoFmkip/IbvzyrxehAIg==",
|
"integrity": "sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bindings": "^1.5.0",
|
"bindings": "^1.5.0",
|
||||||
@@ -834,7 +834,6 @@
|
|||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@@ -997,7 +996,6 @@
|
|||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fill-range": "^7.0.1"
|
"fill-range": "^7.0.1"
|
||||||
},
|
},
|
||||||
@@ -1169,7 +1167,6 @@
|
|||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "~3.1.2",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
@@ -1618,9 +1615,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/detect-libc": {
|
"node_modules/detect-libc": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||||
"integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
|
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@@ -2040,7 +2037,6 @@
|
|||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
},
|
},
|
||||||
@@ -2195,7 +2191,6 @@
|
|||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
"dev": true,
|
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2304,7 +2299,6 @@
|
|||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-glob": "^4.0.1"
|
"is-glob": "^4.0.1"
|
||||||
},
|
},
|
||||||
@@ -2564,6 +2558,11 @@
|
|||||||
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/immutable": {
|
||||||
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ=="
|
||||||
|
},
|
||||||
"node_modules/inherits": {
|
"node_modules/inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
@@ -2632,7 +2631,6 @@
|
|||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"binary-extensions": "^2.0.0"
|
"binary-extensions": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -2704,7 +2702,6 @@
|
|||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -2722,7 +2719,6 @@
|
|||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-extglob": "^2.1.1"
|
"is-extglob": "^2.1.1"
|
||||||
},
|
},
|
||||||
@@ -2745,7 +2741,6 @@
|
|||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
@@ -3270,9 +3265,9 @@
|
|||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
||||||
},
|
},
|
||||||
"node_modules/node-abi": {
|
"node_modules/node-abi": {
|
||||||
"version": "3.54.0",
|
"version": "3.62.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.62.0.tgz",
|
||||||
"integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==",
|
"integrity": "sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"semver": "^7.3.5"
|
"semver": "^7.3.5"
|
||||||
},
|
},
|
||||||
@@ -3373,7 +3368,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -3667,7 +3661,6 @@
|
|||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
},
|
},
|
||||||
@@ -3719,9 +3712,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prebuild-install": {
|
"node_modules/prebuild-install": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
|
||||||
"integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
|
"integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-libc": "^2.0.0",
|
"detect-libc": "^2.0.0",
|
||||||
"expand-template": "^2.0.3",
|
"expand-template": "^2.0.3",
|
||||||
@@ -4078,7 +4071,6 @@
|
|||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"picomatch": "^2.2.1"
|
"picomatch": "^2.2.1"
|
||||||
},
|
},
|
||||||
@@ -4228,6 +4220,22 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/sass": {
|
||||||
|
"version": "1.77.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.2.tgz",
|
||||||
|
"integrity": "sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA==",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": ">=3.0.0 <4.0.0",
|
||||||
|
"immutable": "^4.0.0",
|
||||||
|
"source-map-js": ">=0.6.2 <2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"sass": "sass.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.6.0",
|
"version": "7.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||||
@@ -4466,6 +4474,14 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/source-map-js": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-support": {
|
"node_modules/source-map-support": {
|
||||||
"version": "0.5.21",
|
"version": "0.5.21",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||||
@@ -4735,7 +4751,6 @@
|
|||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
13
package.json
13
package.json
@@ -24,13 +24,17 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./bin/www",
|
"start": "node ./bin/www",
|
||||||
"dev": "nodemon . & npm run scss",
|
"dev": "nodemon --inspect=0.0.0.0 ./bin/www",
|
||||||
"scss": "sass src/scss/application.scss:src/public/css/application.css src/scss/eventsheet.scss:src/public/css/eventsheet.css",
|
"build-css": "sass src/scss:src/public/css",
|
||||||
"scss watch": "sass --watch src/scss/application.scss:src/public/css/application.css src/scss/eventsheet.scss:src/public/css/eventsheet.css"
|
"watch-scss": "nodemon -e scss -x \"npm run build-css\""
|
||||||
|
},
|
||||||
|
"nodemonConfig": {
|
||||||
|
"ext": "js,hbs,scss",
|
||||||
|
"watch": ["src"]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@teamsnap/teamsnap-ui": "^3.12.3",
|
"@teamsnap/teamsnap-ui": "^3.12.3",
|
||||||
"better-sqlite3": "^9.4.1",
|
"better-sqlite3": "^9.6.0",
|
||||||
"better-sqlite3-session-store": "^0.1.0",
|
"better-sqlite3-session-store": "^0.1.0",
|
||||||
"bootstrap": "^5.3.1",
|
"bootstrap": "^5.3.1",
|
||||||
"bootstrap-icons": "^1.10.5",
|
"bootstrap-icons": "^1.10.5",
|
||||||
@@ -54,6 +58,7 @@
|
|||||||
"passport-teamsnap": "^1.1.1",
|
"passport-teamsnap": "^1.1.1",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
|
"sass": "^1.77.2",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"teamsnap.js": "github:anthonyscorrea/teamsnap-javascript-sdk#link-with-null-link",
|
"teamsnap.js": "github:anthonyscorrea/teamsnap-javascript-sdk#link-with-null-link",
|
||||||
"tinymce": "^6.8.3",
|
"tinymce": "^6.8.3",
|
||||||
|
|||||||
11
src/app.js
11
src/app.js
@@ -62,12 +62,14 @@ app.set("view engine", "hbs");
|
|||||||
app.locals.pluralize = require("pluralize");
|
app.locals.pluralize = require("pluralize");
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
|
console.log('adding connectLiveReload')
|
||||||
var connectLiveReload = require("connect-livereload");
|
var connectLiveReload = require("connect-livereload");
|
||||||
app.use(connectLiveReload());
|
app.use("/scss", express.static(path.join(__dirname, "scss")));
|
||||||
|
app.use(connectLiveReload({port: 35729, src:"http://localhost:35729/livereload.js?snipver=1"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded());
|
app.use(bodyParser.urlencoded({extended: true }));
|
||||||
app.use(logger("dev"));
|
app.use(logger("dev"));
|
||||||
app.use(cors(corsOptions))
|
app.use(cors(corsOptions))
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
@@ -172,7 +174,10 @@ 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));
|
||||||
|
res.status(404).send('not found')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.set('trust proxy')
|
||||||
|
|
||||||
module.exports = {app};
|
module.exports = {app};
|
||||||
@@ -21,6 +21,10 @@ exports.helpers = {
|
|||||||
|
|
||||||
exports.partials = path.join(__dirname, "../views/event/partials")
|
exports.partials = path.join(__dirname, "../views/event/partials")
|
||||||
|
|
||||||
|
exports.confirmModalAvailabilityReminders = async (req, res) => {
|
||||||
|
res.status(200).render("event/partials/modal_availability_reminders")
|
||||||
|
}
|
||||||
|
|
||||||
exports.getEvents = async (req, res, next) => {
|
exports.getEvents = async (req, res, next) => {
|
||||||
const {user, team, layout} = req
|
const {user, team, layout} = req
|
||||||
const bulkLoadTypes = ["event", "availabilitySummary"]
|
const bulkLoadTypes = ["event", "availabilitySummary"]
|
||||||
@@ -70,19 +74,50 @@ exports.getEvent = async (req, res, next) => {
|
|||||||
|
|
||||||
exports.sendAvailabilityReminders = async (req,res,next) => {
|
exports.sendAvailabilityReminders = async (req,res,next) => {
|
||||||
await Promise.all(req.promises)
|
await Promise.all(req.promises)
|
||||||
|
if (!req.body || ! (req.body.event_id && req.body.memberIds)) {
|
||||||
|
res.status(400).send('Malformed post')
|
||||||
|
}
|
||||||
if (req.params.event_id != req.body.eventId) {
|
if (req.params.event_id != req.body.eventId) {
|
||||||
// Load actual event. Do I want this to be an error? probably
|
// Load actual event. Do I want this to be an error? probably
|
||||||
res.status(500).send()
|
res.status(400).send('Event ID parameter does not match the POST body')
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {event} = req
|
const {event} = req
|
||||||
const {eventId, memberIds} = req.body
|
const {eventId, memberIds} = req.body
|
||||||
const sendingMember = req.members.find(m=>m.userId==req.user.id)
|
const sendingMember = req.members.find(m=>m.userId==req.user.id)
|
||||||
try {
|
try {
|
||||||
await teamsnap.sendAvailabilityReminders(event, sendingMember, memberIds)
|
const promise = teamsnap.sendAvailabilityReminders(event, sendingMember, memberIds)
|
||||||
res.status(200).send('OK')
|
await promise
|
||||||
|
.then (res.status(200).send('OK'))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).send()
|
res.status(500).send()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.submitResetAvailabilities = async (req,res,next) => {
|
||||||
|
await Promise.all(req.promises)
|
||||||
|
if (!req.body || ! (req.body.event_id && req.body.memberIds)) {
|
||||||
|
res.status(400).send('Malformed post')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.params.event_id != req.body.event_id) {
|
||||||
|
// Load actual event. Do I want this to be an error? probably
|
||||||
|
res.status(400).send('Event ID parameter does not match the POST body');
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const {event_id, memberIds} = req.body
|
||||||
|
const reset_promises = []
|
||||||
|
|
||||||
|
const availabilities = await teamsnap.loadAvailabilities({eventId: event_id}, teamsnapCallback);
|
||||||
|
|
||||||
|
availabilities.filter(availability =>memberIds.includes(availability.memberId.toString())).forEach( availability => {
|
||||||
|
availability.statusCode = teamsnap.AVAILABILITIES.NONE
|
||||||
|
const promise = teamsnap.saveAvailability(availability, teamsnapCallback)
|
||||||
|
reset_promises.push(promise)
|
||||||
|
})
|
||||||
|
await Promise.all(reset_promises)
|
||||||
|
.then(res.status(200).send('OK'))
|
||||||
|
}
|
||||||
@@ -1,104 +1,11 @@
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const {embeddedSvgFromPath, parsePositionLabel, compilePositionLabel} = require("../lib/utils")
|
const {groupTeamsnapItems, parsePositionLabel, compilePositionLabel, teamsnapCallback} = require("../lib/utils")
|
||||||
const tsUtils = require('../lib/utils')
|
const tsUtils = require('../lib/utils')
|
||||||
const { loadEventLineupEntries } = require('teamsnap.js')
|
const { loadEventLineupEntries } = require('teamsnap.js')
|
||||||
|
|
||||||
exports.partials = path.join(__dirname, "../views/eventlineup/partials")
|
exports.partials = path.join(__dirname, "../views/eventlineup/partials")
|
||||||
|
exports.helpers = require('../helpers/eventlineup.js')
|
||||||
const statusCodeIcons = {
|
|
||||||
1: embeddedSvgFromPath("/teamsnap-ui/assets/icons/check.svg"),
|
|
||||||
0: embeddedSvgFromPath("/teamsnap-ui/assets/icons/dismiss.svg"),
|
|
||||||
2: embeddedSvgFromPath("/bootstrap-icons/question-lg.svg"),
|
|
||||||
null: embeddedSvgFromPath("/bootstrap-icons/question.svg"),
|
|
||||||
undefined: embeddedSvgFromPath("/bootstrap-icons/question-lg.svg")
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusCodeClasses = {
|
|
||||||
1: "u-colorPositive",
|
|
||||||
0: "u-colorNegative",
|
|
||||||
2: "u-colorPrimary",
|
|
||||||
null: "u-colorGrey",
|
|
||||||
undefined: "u-colorGrey"
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusCodeButtonClasses = {
|
|
||||||
1: "Button--yes",
|
|
||||||
0: "Button--no",
|
|
||||||
2: "Button--maybe",
|
|
||||||
null: "",
|
|
||||||
undefined: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.helpers = {
|
|
||||||
flagsString: (flags) => {
|
|
||||||
return flags != null ? Array.from(flags).join(",") : ''
|
|
||||||
},
|
|
||||||
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) => {
|
|
||||||
const {positionLabelWithoutFlags} = parsePositionLabel(label);
|
|
||||||
return positionLabelWithoutFlags
|
|
||||||
},
|
|
||||||
positionLabelWithoutPOFlag: (label) => {
|
|
||||||
const {positionLabelWithoutFlags, positionFlags} = parsePositionLabel(label);
|
|
||||||
positionFlags.delete('PO')
|
|
||||||
return compilePositionLabel(positionLabelWithoutFlags, positionFlags)
|
|
||||||
},
|
|
||||||
positionFlags: (label)=> {
|
|
||||||
const {positionFlags} = parsePositionLabel(label);
|
|
||||||
return `[${Array.from(positionFlags).join(",")}]`
|
|
||||||
},
|
|
||||||
hasPositionFlags: (label) => {
|
|
||||||
const {positionLabelWithoutFlags, positionFlags} = parsePositionLabel(label);
|
|
||||||
return positionFlags.size > 0;
|
|
||||||
},
|
|
||||||
comparePositionWithFlags: (labelWithoutFlags, eventLineupEntry, options) => {
|
|
||||||
labelWithFlags = eventLineupEntry?.label
|
|
||||||
const {positionLabelWithoutFlags} = parsePositionLabel(labelWithFlags);
|
|
||||||
return positionLabelWithoutFlags == labelWithoutFlags;
|
|
||||||
},
|
|
||||||
isStarting: (member) => {
|
|
||||||
return (member.benchcoach?.eventLineupEntry != null);
|
|
||||||
},
|
|
||||||
isInStartingLineup: (member) => {
|
|
||||||
if (member.benchcoach.eventLineupEntry == null || member.benchcoach.eventLineupEntry.label == '') return false;
|
|
||||||
const {positionFlags} = parsePositionLabel(member.benchcoach.eventLineupEntry?.label);
|
|
||||||
return (!positionFlags.has("PO"))
|
|
||||||
},
|
|
||||||
isInPositionOnly: (member) => {
|
|
||||||
if (!member.benchcoach || member.benchcoach.eventLineupEntry == null) return false;
|
|
||||||
const {positionFlags} = parsePositionLabel(member.benchcoach.eventLineupEntry?.label);
|
|
||||||
return (member.benchcoach.eventLineupEntry != null && positionFlags.has("PO"))
|
|
||||||
},
|
|
||||||
isInBench: (member) => {
|
|
||||||
if ((member.benchcoach.eventLineupEntry != null && member.benchcoach.eventLineupEntry.label != '') || member.isNonPlayer) return false;
|
|
||||||
return (member.benchcoach.availability?.statusCode != 0 && member.benchcoach.availability?.statusCode != null)
|
|
||||||
},
|
|
||||||
isInOut: (member) => {
|
|
||||||
if ((member.benchcoach.eventLineupEntry != null && member.benchcoach.eventLineupEntry.label != '') || member.isNonPlayer) return false;
|
|
||||||
return (member.benchcoach.availability?.statusCode == 0 || member.benchcoach.availability?.statusCode == null)
|
|
||||||
},
|
|
||||||
availabilityStatusShort: (availability) => {
|
|
||||||
const {YES, MAYBE, NO, NONE} = teamsnap.AVAILABILITIES
|
|
||||||
const statusShortLookup = {}
|
|
||||||
statusShortLookup[YES] = "YES"
|
|
||||||
statusShortLookup[MAYBE] = "MAY"
|
|
||||||
statusShortLookup[NO] = "NO"
|
|
||||||
statusShortLookup[NONE] = "UNK"
|
|
||||||
statusShortLookup[undefined] = "UNK"
|
|
||||||
return (statusShortLookup[availability?.statusCode])
|
|
||||||
},
|
|
||||||
filterNonPlayers: (members) => {
|
|
||||||
return members.filter(m=>!m.isNonPlayer)
|
|
||||||
},
|
|
||||||
joinMemberEmailAddresses: (members) => {
|
|
||||||
return members.map(m=>m.emailAddresses.join(',')).join(',')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getEventLineup = async (req, res)=>{
|
exports.getEventLineup = async (req, res)=>{
|
||||||
await Promise.all(req.promises)
|
await Promise.all(req.promises)
|
||||||
@@ -110,7 +17,7 @@ exports.getEventLineup = async (req, res)=>{
|
|||||||
"/js/eventlineup.js",
|
"/js/eventlineup.js",
|
||||||
"/js/tinymce.min.js"
|
"/js/tinymce.min.js"
|
||||||
]
|
]
|
||||||
res.render("eventlineup/edit", {user, team, members, event, scripts, layout, event_lineup, event_lineup_entries, availabilitySummary, csrfToken})
|
res.render("eventlineup/edit", {user, team, members, event, availabilities, scripts, layout, event_lineup, event_lineup_entries, availabilitySummary, csrfToken})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getAdjacentEventLineup = async (req, res) => {
|
exports.getAdjacentEventLineup = async (req, res) => {
|
||||||
@@ -131,14 +38,14 @@ exports.getAdjacentEventLineup = async (req, res) => {
|
|||||||
return
|
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)
|
||||||
console.log()
|
console.log()
|
||||||
// res.status(200).send('Received')
|
|
||||||
res.render("eventlineup/edit", {user, team, members, event, layout: null, event_lineup, event_lineup_entries, availabilitySummary, csrfToken})
|
res.render("eventlineup/edit", {user, team, members, event, layout: null, event_lineup, event_lineup_entries, availabilitySummary, availabilities, csrfToken})
|
||||||
}
|
}
|
||||||
|
|
||||||
attachBenchcoachPropertiesToMember = (members, event_lineup_entries, availabilities) => {
|
attachBenchcoachPropertiesToMember = (members, event_lineup_entries, availabilities) => {
|
||||||
@@ -181,6 +88,10 @@ exports.getEventLineupEmail = async (req, res)=>{
|
|||||||
res.status(200).render("eventlineup/partials/email_modal.hbs", {layout:null, user, team, members, event, event_lineup, event_lineup_entries: newEventLineupEntries, availabilities, availabilitySummary})
|
res.status(200).render("eventlineup/partials/email_modal.hbs", {layout:null, user, team, members, event, event_lineup, event_lineup_entries: newEventLineupEntries, availabilities, availabilitySummary})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.getAvailabilityRemindersModal = (req, res) => {
|
||||||
|
res.status(200).render("eventlineup/partials/availability_reminder_modal.hbs")
|
||||||
|
}
|
||||||
|
|
||||||
exports.getEventLineupEntries = async (req, res)=>{
|
exports.getEventLineupEntries = async (req, res)=>{
|
||||||
const {event_lineup, event_lineup_entries} = req
|
const {event_lineup, event_lineup_entries} = req
|
||||||
res.setHeader('Content-Type', 'application/json').send(JSON.stringify(req.event_lineup_entries))
|
res.setHeader('Content-Type', 'application/json').send(JSON.stringify(req.event_lineup_entries))
|
||||||
@@ -198,14 +109,20 @@ exports.postEventLineup = async (req,res) => {
|
|||||||
const eventLineupEntries = req.event_lineup.eventLineupEntries
|
const eventLineupEntries = req.event_lineup.eventLineupEntries
|
||||||
const {newEventLineupEntries, deleteEventLineupEntries} = processPostedEventLineupEntries(body, eventLineupEntries, req.event_lineup)
|
const {newEventLineupEntries, deleteEventLineupEntries} = processPostedEventLineupEntries(body, eventLineupEntries, req.event_lineup)
|
||||||
newEventLineupEntries.forEach(e=>{
|
newEventLineupEntries.forEach(e=>{
|
||||||
teamsnap.saveEventLineupEntry(e)
|
teamsnap.saveEventLineupEntry(e, teamsnapCallback)
|
||||||
})
|
})
|
||||||
deleteEventLineupEntries.forEach(e=>{
|
deleteEventLineupEntries.forEach(e=>{
|
||||||
teamsnap.deleteEventLineupEntry(e)
|
teamsnap.deleteEventLineupEntry(e, teamsnapCallback)
|
||||||
})
|
})
|
||||||
|
|
||||||
eventLineup = await teamsnap.loadEventLineups(req.params.event_id)
|
const bulk_items = await teamsnap.bulkLoad(
|
||||||
res.status(201).end()
|
{teamId: req.params.team_id, types: ['eventLineup', 'eventLineupEntry'], scopeTo:'event', event__id:req.params.event_id,},
|
||||||
|
null,
|
||||||
|
(err, items) => {teamsnapCallback(err, items, {req, source:"postEventLineup", method:'bulkLoad'})}
|
||||||
|
)
|
||||||
|
groupedReturnedItems = groupTeamsnapItems(bulk_items)
|
||||||
|
returnedEventLineupEntries = groupedReturnedItems.eventLineupEntries
|
||||||
|
res.status(201).end(JSON.stringify(returnedEventLineupEntries))
|
||||||
}
|
}
|
||||||
|
|
||||||
const processPostedEventLineupEntries = (body, eventLineupEntries, eventLineup) => {
|
const processPostedEventLineupEntries = (body, eventLineupEntries, eventLineup) => {
|
||||||
@@ -248,3 +165,32 @@ const processPostedEventLineupEntries = (body, eventLineupEntries, eventLineup)
|
|||||||
})
|
})
|
||||||
return {newEventLineupEntries, eventLineupEntries, deleteEventLineupEntries}
|
return {newEventLineupEntries, eventLineupEntries, deleteEventLineupEntries}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.submitDeleteEventLineupEntries = async (req,res) => {
|
||||||
|
await Promise.all(req.promises);
|
||||||
|
const {event_lineup, event_lineup_entries} = req
|
||||||
|
let event_id
|
||||||
|
let memberIds
|
||||||
|
|
||||||
|
if (!req.body || ! (req.body.event_id && req.body.memberIds)) {
|
||||||
|
res.status(400).send('Malformed post')
|
||||||
|
} else if (req.params.event_id != req.body.event_id) {
|
||||||
|
// Load actual event. Do I want this to be an error? probably
|
||||||
|
res.status(400).send('Event ID parameter does not match the POST body');
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
event_id = req.body.event_id
|
||||||
|
memberIds = req.body.memberIds
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletion_promises = []
|
||||||
|
|
||||||
|
event_lineup_entries.filter(entry =>memberIds.includes(entry.memberId.toString())).forEach( entry => {
|
||||||
|
const promise = teamsnap.deleteEventLineupEntry(entry, teamsnapCallback)
|
||||||
|
deletion_promises.push(promise)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all(deletion_promises)
|
||||||
|
.then(res.status(202).send('OK'))
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,8 +23,14 @@ exports.getEventSheet = async (req,res) =>{
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
await Promise.all(req.promises)
|
await Promise.all(req.promises)
|
||||||
|
const {sheet_size, sheet_layout} = req.query
|
||||||
|
|
||||||
const {user, team, team_preferences, members, event, event_lineup, event_lineup_entries, availabilities, availabilitySummary, timeline, recent_events, opponent_logo, upcoming_events} = req
|
const {user, team, team_preferences, members, event, event_lineup, event_lineup_entries, availabilities, availabilitySummary, timeline, recent_events, opponent_logo, upcoming_events} = req
|
||||||
res.render('eventsheet/sheet', {user, team, team_preferences, members, event, event_lineup, event_lineup_entries, availabilities, availabilitySummary, timeline, recent_events, opponent_logo,upcoming_events})
|
res.render('eventsheet/sheet', {sheet_size, sheet_layout, user, team, team_preferences, members, event, event_lineup, event_lineup_entries, availabilities, availabilitySummary, timeline, recent_events, opponent_logo,upcoming_events})
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getEventSheetBlank = (req,res) => {
|
||||||
|
res.render('eventsheet/sheet_blank')
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getLineupCard = (req, res, next) => {
|
exports.getLineupCard = (req, res, next) => {
|
||||||
|
|||||||
119
src/helpers/eventlineup.js
Normal file
119
src/helpers/eventlineup.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
const {embeddedSvgFromPath, parsePositionLabel, compilePositionLabel} = require("../lib/utils")
|
||||||
|
var hb = require('hbs').create();
|
||||||
|
|
||||||
|
const statusCodeIcons = {
|
||||||
|
1: embeddedSvgFromPath("/teamsnap-ui/assets/icons/check.svg"),
|
||||||
|
0: embeddedSvgFromPath("/teamsnap-ui/assets/icons/dismiss.svg"),
|
||||||
|
2: embeddedSvgFromPath("/bootstrap-icons/question-lg.svg"),
|
||||||
|
null: embeddedSvgFromPath("/bootstrap-icons/question.svg"),
|
||||||
|
undefined: embeddedSvgFromPath("/bootstrap-icons/question-lg.svg")
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusCodeClasses = {
|
||||||
|
1: "u-colorPositive",
|
||||||
|
0: "u-colorNegative",
|
||||||
|
2: "u-colorPrimary",
|
||||||
|
null: "u-colorGrey",
|
||||||
|
undefined: "u-colorGrey"
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusCodeButtonClasses = {
|
||||||
|
1: "Button--yes",
|
||||||
|
0: "Button--no",
|
||||||
|
2: "Button--maybe",
|
||||||
|
null: "",
|
||||||
|
undefined: ""
|
||||||
|
}
|
||||||
|
exports.flagsString = (flags) => {
|
||||||
|
return flags != null ? Array.from(flags).join(",") : ''
|
||||||
|
};
|
||||||
|
exports.plus1 = (i) => Number(i)+1;
|
||||||
|
exports.positions = () => ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH", "DR"];
|
||||||
|
exports.defense_positions = () => ["C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "P"];
|
||||||
|
exports.avail_status_code_class = (status_code) => statusCodeButtonClasses[status_code];
|
||||||
|
exports.avail_status_code_icon = (status_code) => statusCodeIcons[status_code];
|
||||||
|
exports.positionLabelWithoutFlags = (label) => {
|
||||||
|
const {positionLabelWithoutFlags} = parsePositionLabel(label);
|
||||||
|
return positionLabelWithoutFlags
|
||||||
|
};
|
||||||
|
exports.positionLabelWithoutPOFlag = (label) => {
|
||||||
|
const {positionLabelWithoutFlags, positionFlags} = parsePositionLabel(label);
|
||||||
|
positionFlags.delete('PO')
|
||||||
|
return compilePositionLabel(positionLabelWithoutFlags, positionFlags)
|
||||||
|
};
|
||||||
|
exports.positionFlags = (label)=> {
|
||||||
|
const {positionFlags} = parsePositionLabel(label);
|
||||||
|
return `[${Array.from(positionFlags).join(",")}]`
|
||||||
|
};
|
||||||
|
exports.hasPositionFlags = (label) => {
|
||||||
|
const {positionLabelWithoutFlags, positionFlags} = parsePositionLabel(label);
|
||||||
|
return positionFlags.size > 0;
|
||||||
|
};
|
||||||
|
exports.comparePositionWithFlags = (labelWithoutFlags, eventLineupEntry, options) => {
|
||||||
|
labelWithFlags = eventLineupEntry?.label
|
||||||
|
const {positionLabelWithoutFlags} = parsePositionLabel(labelWithFlags);
|
||||||
|
return positionLabelWithoutFlags == labelWithoutFlags;
|
||||||
|
};
|
||||||
|
exports.isStarting = (member) => {
|
||||||
|
return (member.benchcoach?.eventLineupEntry != null);
|
||||||
|
};
|
||||||
|
exports.isInStartingLineup = (member) => {
|
||||||
|
if (member.benchcoach.eventLineupEntry == null || member.benchcoach.eventLineupEntry.label == '') return false;
|
||||||
|
const {positionFlags} = parsePositionLabel(member.benchcoach.eventLineupEntry?.label);
|
||||||
|
return (!positionFlags.has("PO"))
|
||||||
|
};
|
||||||
|
exports.isInPositionOnly = (member) => {
|
||||||
|
if (!member.benchcoach || member.benchcoach.eventLineupEntry == null) return false;
|
||||||
|
const {positionFlags} = parsePositionLabel(member.benchcoach.eventLineupEntry?.label);
|
||||||
|
return (member.benchcoach.eventLineupEntry != null && positionFlags.has("PO"))
|
||||||
|
};
|
||||||
|
exports.isInBench = (member) => {
|
||||||
|
if ((member.benchcoach.eventLineupEntry != null && member.benchcoach.eventLineupEntry.label != '') || member.isNonPlayer) return false;
|
||||||
|
return (member.benchcoach.availability?.statusCode != 0 && member.benchcoach.availability?.statusCode != null)
|
||||||
|
};
|
||||||
|
exports. isInOut = (member) => {
|
||||||
|
if ((member.benchcoach.eventLineupEntry != null && member.benchcoach.eventLineupEntry.label != '') || member.isNonPlayer) return false;
|
||||||
|
return (member.benchcoach.availability?.statusCode == 0 || member.benchcoach.availability?.statusCode == null)
|
||||||
|
};
|
||||||
|
exports.availabilityStatusShort = (availability) => {
|
||||||
|
const {YES, MAYBE, NO, NONE} = teamsnap.AVAILABILITIES
|
||||||
|
const statusShortLookup = {}
|
||||||
|
statusShortLookup[YES] = "YES"
|
||||||
|
statusShortLookup[MAYBE] = "MAY"
|
||||||
|
statusShortLookup[NO] = "NO"
|
||||||
|
statusShortLookup[NONE] = "UNK"
|
||||||
|
statusShortLookup[undefined] = "UNK"
|
||||||
|
return (statusShortLookup[availability?.statusCode])
|
||||||
|
};
|
||||||
|
exports.filterNonPlayers = (members) => {
|
||||||
|
return members.filter(m=>!m.isNonPlayer)
|
||||||
|
};
|
||||||
|
exports.joinMemberEmailAddresses = (members) => {
|
||||||
|
return members.map(m=>m.emailAddresses.join(',')).join(',')
|
||||||
|
}
|
||||||
|
exports.loadSlots = (options) =>{
|
||||||
|
var s = ""
|
||||||
|
const {members, event_lineup, event_lineup_entries, event, availabilities} = options.data.root
|
||||||
|
event_lineup_entries.forEach(eventLineupEntry =>{
|
||||||
|
const availability = availabilities?.find(a=>a.memberId==eventLineupEntry.memberId)
|
||||||
|
const member = members.find(m=>m.id==eventLineupEntry.memberId)
|
||||||
|
const {positionFlags} = parsePositionLabel(eventLineupEntry.label)
|
||||||
|
const initial_lineup_segment = `${positionFlags.has('PO') ? 'position-only' : 'starting'}`
|
||||||
|
|
||||||
|
s+=options.fn({eventLineupEntry, availability, member, event, initial_lineup_segment})
|
||||||
|
})
|
||||||
|
const players_without_lineup_entry = members.filter(
|
||||||
|
member=>!event_lineup_entries.map(lue=>lue.memberId).includes(member.id) && !member.isNonPlayer
|
||||||
|
)
|
||||||
|
players_without_lineup_entry.forEach(member =>{
|
||||||
|
const availability = availabilities?.find(a=>a.memberId==member.id)
|
||||||
|
let initial_lineup_segment
|
||||||
|
if (availability?.statusCode == 0 || availability?.statusCode == null) {
|
||||||
|
initial_lineup_segment =`out`
|
||||||
|
} else {
|
||||||
|
initial_lineup_segment =`bench`
|
||||||
|
}
|
||||||
|
s+=options.fn({availability, member, event, initial_lineup_segment})
|
||||||
|
})
|
||||||
|
return s
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
const { parsePositionLabel, teamsnapMembersSortLineupAvailabilityLastName, teamsnapMembersSortAvailabilityLastName } = require('../lib/utils')
|
const { parsePositionLabel, teamsnapMembersSortLineupAvailabilityLastName, teamsnapMembersSortAvailabilityLastName } = require('../lib/utils')
|
||||||
const {attachBenchcoachPropertiesToMember} = require('../controllers/eventlineup')
|
const {attachBenchcoachPropertiesToMember} = require('../controllers/eventlineup')
|
||||||
|
const Handlebars = require("handlebars");
|
||||||
|
|
||||||
exports.offenseLineup = (number_of_slots, event_lineup_entries, members, options) => {
|
exports.offenseLineup = (number_of_slots, event_lineup_entries, members, options) => {
|
||||||
var results = ""
|
var results = ""
|
||||||
@@ -60,7 +61,7 @@ exports.rosterHistory = (event, event_lineup_entries, members, availabilities, o
|
|||||||
// const {event, event_lineup_entries, members, availabilities} = options.data.root
|
// const {event, event_lineup_entries, members, availabilities} = options.data.root
|
||||||
const players = members.filter(m=>!m.isNonPlayer)
|
const players = members.filter(m=>!m.isNonPlayer)
|
||||||
attachBenchcoachPropertiesToMember(players, event_lineup_entries ? event_lineup_entries.filter(i=>i.eventId==event.id) : [], availabilities.filter(i=>i.eventId==event.id))
|
attachBenchcoachPropertiesToMember(players, event_lineup_entries ? event_lineup_entries.filter(i=>i.eventId==event.id) : [], availabilities.filter(i=>i.eventId==event.id))
|
||||||
players.sort(teamsnapMembersSortAvailabilityLastName)
|
players.sort(teamsnapMembersSortLineupAvailabilityLastName)
|
||||||
|
|
||||||
players.forEach(member=>{
|
players.forEach(member=>{
|
||||||
const {firstName, lastName, jerseyNumber, benchcoach, position, id} = member
|
const {firstName, lastName, jerseyNumber, benchcoach, position, id} = member
|
||||||
@@ -87,6 +88,9 @@ const positionGroups = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exports.positionCapabilityFor = (member, position, options) => {
|
exports.positionCapabilityFor = (member, position, options) => {
|
||||||
|
if (!member.position) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
const member_positions = member.position.split(",").map(s=>s.trim())
|
const member_positions = member.position.split(",").map(s=>s.trim())
|
||||||
const member_position_groups = new Set(member.position.split(",").map(s=>positionGroups[s.trim()]))
|
const member_position_groups = new Set(member.position.split(",").map(s=>positionGroups[s.trim()]))
|
||||||
|
|
||||||
@@ -112,8 +116,15 @@ exports.repeat = (n, options) => {
|
|||||||
|
|
||||||
exports.loopEvents = (events, options) => {
|
exports.loopEvents = (events, options) => {
|
||||||
var results = "";
|
var results = "";
|
||||||
events.forEach(event => {
|
if (options.data) {
|
||||||
results += options.fn(event)
|
data = Handlebars.createFrame(options.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
events.forEach((event,i) => {
|
||||||
|
if (data) {
|
||||||
|
data.index = i;
|
||||||
|
}
|
||||||
|
results += options.fn(event, {data: data })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return results;
|
return results;
|
||||||
@@ -121,6 +132,9 @@ exports.loopEvents = (events, options) => {
|
|||||||
|
|
||||||
exports.timepointForMember = (member, timeline, event, options) => {
|
exports.timepointForMember = (member, timeline, event, options) => {
|
||||||
var results = ""
|
var results = ""
|
||||||
|
if (options.data) {
|
||||||
|
data = Handlebars.createFrame(options.data);
|
||||||
|
}
|
||||||
const availability = timeline.availabilities.find(a=>a.memberId==member.id && a.eventId==event.id)
|
const availability = timeline.availabilities.find(a=>a.memberId==member.id && a.eventId==event.id)
|
||||||
const eventLineupEntry = timeline.event_lineup_entries.find(a=>(a.memberId==member.id || a.memberName == `${member.firstName} ${member.lastName}`) && a.eventId==event.id)
|
const eventLineupEntry = timeline.event_lineup_entries.find(a=>(a.memberId==member.id || a.memberName == `${member.firstName} ${member.lastName}`) && a.eventId==event.id)
|
||||||
var value = ""
|
var value = ""
|
||||||
@@ -128,7 +142,15 @@ exports.timepointForMember = (member, timeline, event, options) => {
|
|||||||
value = parsePositionLabel(eventLineupEntry.label).positionLabelWithoutFlags
|
value = parsePositionLabel(eventLineupEntry.label).positionLabelWithoutFlags
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value = availability.status[0]
|
value = availability?.status[0]
|
||||||
|
}
|
||||||
|
return options.fn({availability: availability, eventLineupEntry: eventLineupEntry, value}, {data: data })
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.ifEquals = (testValue, targetValue, options) => {
|
||||||
|
if (testValue === targetValue) {
|
||||||
|
return options.fn();
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
return options.fn({availability: availability, eventLineupEntry: eventLineupEntry, value})
|
|
||||||
}
|
}
|
||||||
@@ -84,6 +84,10 @@ const getPluralType = (type) =>{
|
|||||||
// is not generated in the lookup. this is a
|
// is not generated in the lookup. this is a
|
||||||
// kludge around that. (specifically availabilitySummary)
|
// kludge around that. (specifically availabilitySummary)
|
||||||
plural = teamsnap.getPluralType(type) || (function() {
|
plural = teamsnap.getPluralType(type) || (function() {
|
||||||
|
if (type === undefined){
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
|
||||||
switch (type.slice(-1)) {
|
switch (type.slice(-1)) {
|
||||||
case 'y':
|
case 'y':
|
||||||
return type.slice(0, -1) + 'ies';
|
return type.slice(0, -1) + 'ies';
|
||||||
@@ -109,7 +113,7 @@ exports.groupTeamsnapItems = (items, types = [], params = {}) => {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.embeddedSvgFromPath = (svg_path, additional_classes = "") => {
|
exports.embeddedSvgFromPath = (svg_path, additional_classes, options) => {
|
||||||
const iconStaticPaths = {
|
const iconStaticPaths = {
|
||||||
"/teamsnap-ui/assets":path.join(__dirname, "/../../node_modules/@teamsnap/teamsnap-ui/src/assets"),
|
"/teamsnap-ui/assets":path.join(__dirname, "/../../node_modules/@teamsnap/teamsnap-ui/src/assets"),
|
||||||
"/bootstrap-icons":path.join(__dirname, "/../../node_modules/bootstrap-icons/icons"),
|
"/bootstrap-icons":path.join(__dirname, "/../../node_modules/bootstrap-icons/icons"),
|
||||||
@@ -122,6 +126,8 @@ exports.embeddedSvgFromPath = (svg_path, additional_classes = "") => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options) {options=additional_classes; additional_classes=''}
|
||||||
|
|
||||||
const svg = fs.readFileSync(`${svg_path}`, 'utf8');
|
const svg = fs.readFileSync(`${svg_path}`, 'utf8');
|
||||||
|
|
||||||
svgRegExWithClass = new RegExp(/<svg(.*)class="(.*?)"(.*)>/)
|
svgRegExWithClass = new RegExp(/<svg(.*)class="(.*?)"(.*)>/)
|
||||||
|
|||||||
@@ -2312,13 +2312,13 @@ input:-webkit-autofill:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Popup-container::before {
|
.Popup-container::before {
|
||||||
top: calc( 100% - 6px );
|
top: calc(100% - 6px);
|
||||||
border: solid #d6d6d6 1px;
|
border: solid #d6d6d6 1px;
|
||||||
box-shadow: 0 0 2px rgba(56, 56, 56, 0.15);
|
box-shadow: 0 0 2px rgba(56, 56, 56, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Popup-container::after {
|
.Popup-container::after {
|
||||||
top: calc( 100% - 7px );
|
top: calc(100% - 7px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Popup-content {
|
.Popup-content {
|
||||||
@@ -2757,7 +2757,7 @@ input:-webkit-autofill:focus {
|
|||||||
|
|
||||||
.StepNav-stepTitle {
|
.StepNav-stepTitle {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
left: calc( 0px - 43px);
|
left: calc(0px - 43px);
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2875,7 +2875,7 @@ input:-webkit-autofill:focus {
|
|||||||
}
|
}
|
||||||
.StepNav--small .StepNav-stepTitle {
|
.StepNav--small .StepNav-stepTitle {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
left: calc( 0px - 53px);
|
left: calc(0px - 53px);
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
.StepNav--small .StepNav-stepIcon {
|
.StepNav--small .StepNav-stepIcon {
|
||||||
@@ -2910,7 +2910,7 @@ input:-webkit-autofill:focus {
|
|||||||
}
|
}
|
||||||
.StepNav--xsmall .StepNav-stepTitle {
|
.StepNav--xsmall .StepNav-stepTitle {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
left: calc( 0px - 62px);
|
left: calc(0px - 62px);
|
||||||
padding-top: 1px;
|
padding-top: 1px;
|
||||||
}
|
}
|
||||||
.StepNav--xsmall .StepNav-stepIcon {
|
.StepNav--xsmall .StepNav-stepIcon {
|
||||||
@@ -7014,7 +7014,7 @@ a.Panel-row {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[id^=event-lineup] {
|
div.event-lineup {
|
||||||
max-width: 576px;
|
max-width: 576px;
|
||||||
counter-reset: lineup-sequence-counter 0;
|
counter-reset: lineup-sequence-counter 0;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@@ -7093,9 +7093,23 @@ li .availability-status-code- {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[id^=event-lineup] .Panel.position-only .Panel-cell:has(.sequence), div[id^=event-lineup] .Panel.bench .Panel-cell:has(.sequence), div[id^=event-lineup] .Panel.out .Panel-cell:has(.sequence) {
|
div.event-lineup .lineup-segment:has(input.Toggle-input:not(:checked)).out .Panel-cell:has(.SelectBox),
|
||||||
|
div.event-lineup .lineup-segment:has(input.Toggle-input:not(:checked)).out .Panel-cell:has(.drag-handle),
|
||||||
|
div.event-lineup .lineup-segment:has(input.Toggle-input:not(:checked)).out button:has(+ .position-label-flags),
|
||||||
|
div.event-lineup .lineup-segment:has(input.Toggle-input:not(:checked)).out button.addToStarting,
|
||||||
|
div.event-lineup .lineup-segment:has(input.Toggle-input:not(:checked)).out button.addToBench {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
div.event-lineup .lineup-segment.bench .Panel-cell:has(.sequence), div.event-lineup .lineup-segment.position-only .Panel-cell:has(.sequence), div.event-lineup .lineup-segment.out .Panel-cell:has(.sequence) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
div.event-lineup .lineup-segment.bench.bench button.addToBench, div.event-lineup .lineup-segment.position-only.bench button.addToBench, div.event-lineup .lineup-segment.out.bench button.addToBench {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
div.event-lineup .lineup-segment.starting button.addToStarting, div.event-lineup .lineup-segment.position-only button.addToStarting {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.Tooltip:after {
|
.Tooltip:after {
|
||||||
padding: 2px !important;
|
padding: 2px !important;
|
||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -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;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;AACA;AAER;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIF;AACA;EACE;IACE;;EAEF;IACE;;EAEF;IACE;IACA;;;AAIJ;AACA;EACE;IACE;;EAEF;IACE;;EAEF;IACE;IACA;IACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;AACA;EAA+B;EAAc;;;AAC7C;EAA+B;EAAc;;;AAC7C;EAA+B;EAAc;;;AAE7C;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAEF;EACE;EACA;;AAEA;EACE;;AAMkB;EAChB;;AAGiB;EACjB;;;AAOR;EACE;;;AAGF;EACE;;;AAGF;EACE;;AACA;EACE;;AACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAMN;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;;AAIN;EACE;;;AAGF;EACE;EACE;EACA;EACA;EACA;;AACA;EACE;;;AAIN;EACE;EACE;EACA;EACA;EACA;;AACA;EACE;;;AAIN;EACE;EAEA;EAEA;;AAEA;EACE;EACA;EACA;EACA;;AACA;EACE;;AAIJ;EACE;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAMN;EACE;EACA;EACA;;AAGF;EAEE;;AAGF;AACE;;AACA;EACE;;AACA;EACE;;AAGJ;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAKF;EAEA;;AAIA;EACE;EACA;;AAEF;EACE;;AAKF;EACE;;AACA;EACE;;AAGJ;EACE;;AAGF;EACE;;;AAMJ;EACE;;AAEF;EACE;;AACA;EACE;;;AAOJ;EACE;EACA;EACA;EACA,qBACE;;AAIJ;EACE;;AAGF;EACE;;AAGF;AACE;EACA;EACA;EACA;AACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGE;EACA;EACA;EACA;;AAGA;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;;;AAcV;EACE;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;;AAIA;EACE;;AAGF;EACE;EACA;EACA;;AAEE;EACE;;AAEM;EACN;;AAEF;EACA;EACA;EACA;;AAQA;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AA4BR;EACE;;AACA;EACA,SA/BM;;AAoCZ;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;EACE;;AACA;EACE;;;AASV;EACE;AACA;EACA;EAEA;EACA;AACA;;AAEA;EACE;EACA;;AAGF;EACE;;AACA;EACE;;;AAMN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;;;AAGF;EACE;;;AAKF;EACE;;AAME;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EAEE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;AAEF;AACE;EACA;EACA;AACA;;AAIA;EACA;;AAKF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAOF;EACE;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACI;EACA;EACA;EACA;EACA;;AAEJ;EACE;;AACA;EACE;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;EAEE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAMN;EACE;EACA;EACA;;AAEF;EACE;;AAIJ;EACE;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAGF;EAEE;;AAGF;EACE;EACA;;AAEA;EACE;AACA;EACA;EACA;EACA;;AAQJ;EACE;;AAGF;EACE;;AAGa;EACb;;;AAMF;EACE;;AAEF;EACE;;AAEF;EACE;;AAIA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAQE;EACA;;AARA;EACE;;AACA;EACE;EACA;;AAWJ;EACE;EACA;;AAQJ;EACE;;;AAKN;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;AACA;AAAA;;;AAIF;EACE;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE","file":"eventsheet.css"}
|
||||||
@@ -1,4 +1,42 @@
|
|||||||
/* Project specific Javascript goes here. */
|
const lineupChangedEvent = new Event('bc:lineupChanged')
|
||||||
|
|
||||||
|
document.querySelectorAll('.event-lineup').forEach(lineup=>{
|
||||||
|
lineup.addEventListener('bc:lineupChanged', (evt)=>{
|
||||||
|
console.log(`lineup changed`, evt.target)
|
||||||
|
const lineup = evt.target
|
||||||
|
colorPositions(lineup)
|
||||||
|
lineup.querySelectorAll(".lineup-slot").forEach((slot, i) => {
|
||||||
|
const lineup_segment = determineLineupSegment(slot)
|
||||||
|
if (lineup_segment != 'bench' && lineup_segment != 'out'){
|
||||||
|
slot.querySelector("input[name=sequence]").value = i;
|
||||||
|
} else {
|
||||||
|
slot.querySelector("input[name=sequence]").value = null;
|
||||||
|
}
|
||||||
|
updateFlagInput(slot)
|
||||||
|
updatePositionInput(slot)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-control=popup]').forEach(popup_control=>{
|
||||||
|
console.log(popup_control)
|
||||||
|
popup_control.addEventListener('click', (evt)=>{
|
||||||
|
const popup = evt.target.closest(".Popup")
|
||||||
|
const to_open = popup.querySelector(".Popup-toggle").dataset.open
|
||||||
|
popup.querySelectorAll(`[data-popup=${to_open}]`).forEach(popup_container => {
|
||||||
|
console.log(evt, evt.target, popup, popup_container)
|
||||||
|
popup_container.classList.toggle('is-open')
|
||||||
|
evt.stopPropagation()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
document.querySelectorAll('.position-label-flags input[type="checkbox"]').forEach(flagCheckbox => {
|
||||||
|
const lineup = flagCheckbox.closest('.event-lineup')
|
||||||
|
flagCheckbox.addEventListener('click', ()=>{lineup.dispatchEvent(lineupChangedEvent)})
|
||||||
|
})
|
||||||
|
|
||||||
function onPositionSelectChange(elem) {
|
function onPositionSelectChange(elem) {
|
||||||
elem.querySelectorAll("option").forEach((option) => {
|
elem.querySelectorAll("option").forEach((option) => {
|
||||||
if (option.innerText.trim() == elem.value) {
|
if (option.innerText.trim() == elem.value) {
|
||||||
@@ -7,248 +45,242 @@ function onPositionSelectChange(elem) {
|
|||||||
option.removeAttribute("selected");
|
option.removeAttribute("selected");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
colorPositions();
|
const lineup = elem.closest('.event-lineup')
|
||||||
refreshLineup();
|
lineup.dispatchEvent(lineupChangedEvent)
|
||||||
|
elem
|
||||||
}
|
}
|
||||||
|
|
||||||
function togglePopup(el) {
|
function colorPositions(lineup) {
|
||||||
el.querySelector(".Popup-container").classList.toggle("is-open");
|
const class_none = "u-colorNegative"
|
||||||
}
|
const class_good = "u-colorPositive"
|
||||||
|
const class_over = "u-colorHighlight"
|
||||||
|
|
||||||
function colorPositions() {
|
lineup.querySelectorAll('.position-status').forEach(
|
||||||
for (bcLineup of document.querySelectorAll("[id^=event-lineup]")) {
|
position_status=>{
|
||||||
selected_lineup_positions = Array.from(
|
position_status.classList.remove(class_over, class_good, class_none);
|
||||||
bcLineup.querySelectorAll(".position-select-box option:checked")
|
const occurences = lineup.querySelectorAll(`.position-select-box option:checked[value="${position_status.dataset.value}"]`)
|
||||||
).map((el) => el.value);
|
switch (occurences.length){
|
||||||
|
case 0:
|
||||||
for (position_status of bcLineup.querySelectorAll(".position-status")) {
|
position_status.classList.add(class_none)
|
||||||
for (class_name of ["u-colorNegative", "u-colorHighlight", "u-colorPositive"]) {
|
break;
|
||||||
position_status.classList.remove(class_name);
|
case 1:
|
||||||
|
position_status.classList.add(class_good)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
position_status.classList.add(class_over)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
})
|
||||||
occurrences = selected_lineup_positions.filter((s) => s == position_status.innerText).length;
|
|
||||||
|
|
||||||
if (occurrences == 1) {
|
|
||||||
position_status.classList.add("u-colorPositive");
|
|
||||||
} else if (occurrences > 1) {
|
|
||||||
position_status.classList.add("u-colorHighlight");
|
|
||||||
} else {
|
|
||||||
position_status.classList.add("u-colorNegative");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initFlagsCheckboxes(){
|
function initFlagsCheckboxes(){
|
||||||
Array.from(document.querySelectorAll("[id^=event-lineup]")).forEach((bcLineup) => {
|
document.querySelectorAll(".lineup-slot").forEach(lineup_slot=>{
|
||||||
Array.from(
|
const possible_flags = ['DHd', 'DRd']
|
||||||
bcLineup.querySelectorAll(
|
const flags_string = lineup_slot.querySelector("input[name=flags]")?.value
|
||||||
".starting .lineup-slot, \
|
const flags = flagSetFromString(flags_string)
|
||||||
.position-only .lineup-slot, \
|
|
||||||
.bench .lineup-slot"
|
possible_flags.forEach(flag=>{
|
||||||
|
if (flags.has(flag)){
|
||||||
|
lineup_slot.querySelector(`input[type=checkbox][name=${flag}]`).checked = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const flagSetFromString = (s) => {
|
||||||
|
if (!s) {return new Set()}
|
||||||
|
const array = s.split(',').map(item=>item.trim())
|
||||||
|
return new Set(array)
|
||||||
|
}
|
||||||
|
|
||||||
|
const flagSetFromSlot = (slot) => {
|
||||||
|
const inputs = slot.querySelectorAll('.position-label-flags input[type=checkbox]:checked')
|
||||||
|
const set = new Set()
|
||||||
|
inputs.forEach(i=>set.add(i.name))
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
const flagSetToString = (set) => {
|
||||||
|
return Array.from(set).join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateFlagInput = (slot) => {
|
||||||
|
const flags = flagSetFromSlot(slot)
|
||||||
|
const lineup_segment = slot.closest('.lineup-segment')
|
||||||
|
lineup_segment.classList.contains('position-only') ? flags.add('PO') : flags.delete('PO')
|
||||||
|
slot.querySelector('input[name="flags"]').value = flagSetToString(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatePositionInput = (slot) => {
|
||||||
|
const selected_position = slot.querySelector(".position-select-box option:checked");
|
||||||
|
const lineup_segment = slot.closest('.lineup-segment')
|
||||||
|
|
||||||
|
if (selected_position && selected_position.text != "--" && !lineup_segment.classList.contains('bench')) {
|
||||||
|
slot.querySelector("input[name=label]").value = selected_position.text;
|
||||||
|
} else {
|
||||||
|
slot.querySelector("input[name=label]").value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const determineLineupSegment = (slot) => {
|
||||||
|
const lineup_segments = ['starting', 'position-only', 'bench', 'out']
|
||||||
|
const lineup_segment = slot.closest('.lineup-segment')
|
||||||
|
const classList = Array.from(lineup_segment.classList)
|
||||||
|
const segments = classList.filter(c=>lineup_segments.includes(c))
|
||||||
|
|
||||||
|
if (segments.length == 1) {
|
||||||
|
return segments[0]
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAvailabilityReminderModal (el, team_id, event_id) {
|
||||||
|
const url = `/${team_id}/event/${event_id}/modal-confirm-availability-reminders/`
|
||||||
|
const form = el.closest('form')
|
||||||
|
const form_data = new FormData (form)
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.text();
|
||||||
|
} else {
|
||||||
|
return Promise.reject(response.text());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((html) => {
|
||||||
|
const parser = new DOMParser()
|
||||||
|
const modal = parser.parseFromString(html, 'text/html')
|
||||||
|
const modal_node = modal.firstElementChild.querySelector('#modal')
|
||||||
|
modal_node.classList.add('is-open')
|
||||||
|
const modal_node_accept = modal.querySelector('Button[data-confirm=yes]')
|
||||||
|
const checked = Array.from(el.querySelectorAll('input:checked')).map
|
||||||
|
const body = document.querySelector('body')
|
||||||
|
body.appendChild(modal_node)
|
||||||
|
modal_node_accept.addEventListener(
|
||||||
|
"click", ()=>{
|
||||||
|
// const memberIds = form_data.getAll('memberId')
|
||||||
|
const csrf_token = form_data.get('csrfToken')
|
||||||
|
const selected_status_codes = Array.from(document.querySelectorAll('input:checked')).map(e=>e.value)
|
||||||
|
const slots = Array.from(document.querySelectorAll('.lineup-slot')).filter(
|
||||||
|
slot =>{
|
||||||
|
const slot_status_code = slot.querySelector('input[name=availabilityStatusCode]').value
|
||||||
|
return selected_status_codes.includes(slot_status_code)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const memberIds = slots.map(
|
||||||
|
slot => slot.querySelector('input[name=memberId]').value
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log("sending reminders", el, event_id, memberIds, csrf_token)
|
||||||
|
sendAvailabilityReminder(el, event_id, memberIds, csrf_token)
|
||||||
|
body.removeChild(modal_node)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
).forEach((slot, i) => {
|
})
|
||||||
const flags = new Set(slot.querySelector("input[name*=flags]")?.value?.split(',')?.map(s=>s.trim())) || new Set()
|
|
||||||
if (flags.has('DHd')) {
|
|
||||||
console.log('dhd')
|
|
||||||
slot.querySelector('[name=flag-dhd]').checked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.has('DRd') ) {
|
|
||||||
slot.querySelector('[name=flag-drd]').checked = true;
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshLineup() {
|
|
||||||
Array.from(document.querySelectorAll("[id^=event-lineup]")).forEach((bcLineup) => {
|
|
||||||
Array.from(
|
|
||||||
bcLineup.querySelectorAll(
|
|
||||||
".starting .lineup-slot, \
|
|
||||||
.position-only .lineup-slot, \
|
|
||||||
.bench .lineup-slot"
|
|
||||||
)
|
|
||||||
).forEach((slot, i) => {
|
|
||||||
slot.querySelector("input[name*=sequence]").value = i;
|
|
||||||
selected_position = slot.querySelector(".position-select-box option:checked");
|
|
||||||
const flags = new Set(slot.querySelector("input[name*=flags]")?.value?.split(',')?.map(s=>s.trim())) || new Set()
|
|
||||||
|
|
||||||
if (slot.querySelector('[name=flag-dhd]').checked) {
|
|
||||||
flags.add('DHd')
|
|
||||||
} else {
|
|
||||||
flags.delete('DHd')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slot.querySelector('[name=flag-drd]').checked) {
|
|
||||||
flags.add('DRd')
|
|
||||||
} else {
|
|
||||||
flags.delete('DRd')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selected_position && selected_position.text != "--") {
|
|
||||||
slot.querySelector("input[name*=label]").value = selected_position.text;
|
|
||||||
} else {
|
|
||||||
slot.querySelector("input[name*=label]").value = null;
|
|
||||||
}
|
|
||||||
if (slot.closest('.position-only')){
|
|
||||||
flags.add('PO');flags.delete('')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
flags.delete('PO');flags.delete('')
|
|
||||||
}
|
|
||||||
if (slot.closest('.bench')){
|
|
||||||
slot.querySelector("input[name*=sequence]").value = '';
|
|
||||||
slot.querySelector("input[name*=label]").value = '';
|
|
||||||
}
|
|
||||||
slot.querySelector("input[name*=flags]").value = Array.from(flags).join(",");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshFlags(){
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyEmailTable(itemEl, subject, recipients) {
|
function confirmModal(el, prompt, fn, options) {
|
||||||
// Create container for the HTML
|
const url = "/modal-confirm"
|
||||||
// [1]
|
const params = new URLSearchParams(prompt)
|
||||||
let bcLineup = itemEl.closest(".benchcoach-lineup");
|
url.search = params.toString()
|
||||||
var container = document.createElement("div");
|
fetch(url+"?"+params.toString(), {method:"GET"})
|
||||||
var tbl = document.createElement("table");
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
let thead = tbl.createTHead();
|
return response.text();
|
||||||
let thead_row = thead.insertRow();
|
} else {
|
||||||
let thead_row_cell = thead_row.insertCell();
|
return Promise.reject(response.text());
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.then((html) => {
|
||||||
|
const parser = new DOMParser()
|
||||||
|
const modal = parser.parseFromString(html, 'text/html')
|
||||||
|
const modal_node = modal.firstElementChild.querySelector('#modal')
|
||||||
|
modal_node.classList.add('is-open')
|
||||||
|
const modal_node_accept = modal.querySelector('Button[data-confirm=yes]')
|
||||||
|
const body = document.querySelector('body')
|
||||||
|
body.appendChild(modal_node)
|
||||||
|
modal_node_accept.addEventListener("click", ()=>{fn(modal_node, options)})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleShowAndHideLoading = (el) => {
|
||||||
|
console.log(el)
|
||||||
|
el.querySelectorAll('.hideOnLoading').forEach((element)=>{
|
||||||
|
element.classList.add('u-hidden')
|
||||||
|
})
|
||||||
|
el.querySelectorAll('.showOnLoading').forEach((element)=>{
|
||||||
|
element.classList.remove('u-hidden')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const completeLoad = (el, success) => {
|
||||||
|
el.querySelectorAll('.hideOnLoading, .showOnLoading, .showOnFailure, .showOnSuccess').forEach((element)=>{
|
||||||
|
element.classList.add('u-hidden')
|
||||||
|
})
|
||||||
|
if (success) {
|
||||||
|
el.querySelectorAll('.showOnSuccess').forEach((element) => {
|
||||||
|
element.classList.remove('u-hidden')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
el.querySelectorAll('.showOnFailure').forEach((element) => {
|
||||||
|
element.classList.remove('u-hidden')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bcLineup.querySelector(".table-benchcoach-bench").rows.length > 0) {
|
function submitClearLineup(modal, options){
|
||||||
var tr = tbody.insertRow();
|
console.log('clearing lineup...')
|
||||||
cell = tr.insertCell();
|
toggleShowAndHideLoading(modal)
|
||||||
cell.colSpan = 3;
|
const {team_id, event_id, event_lineup_id} = options
|
||||||
cell.appendChild(document.createTextNode("SUBS"));
|
const url = `/${team_id}/event/${event_id}/lineup/${event_lineup_id}/delete`
|
||||||
cell.classList.add("title-cell");
|
const form = document.querySelector(`#event-lineup-${event_id} form`);
|
||||||
|
const data = new FormData(form);
|
||||||
for (row of bcLineup.querySelector(".table-benchcoach-bench").rows) {
|
const memberIds = data.getAll('memberId')
|
||||||
var tr = tbody.insertRow();
|
console.log(url)
|
||||||
cell = tr.insertCell();
|
fetch(url, {method:"POST", body: JSON.stringify({memberIds, event_id}), headers: {"Content-Type": "application/json"}})
|
||||||
cell.classList.add("sequence-cell");
|
.then((response) => {
|
||||||
availability_status = {
|
if (response.ok) {
|
||||||
None: "UNK",
|
completeLoad(modal, true);
|
||||||
0: "NO",
|
return response.text();
|
||||||
2: "MAY",
|
} else {
|
||||||
1: "YES",
|
completeLoad(modal, false);
|
||||||
}[row.dataset.availabilityStatuscode];
|
return Promise.reject(response.text());
|
||||||
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(""));
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.finally(()=>{
|
||||||
|
setTimeout(function (){
|
||||||
|
location.reload()
|
||||||
|
}, 500)
|
||||||
|
});//refresh page
|
||||||
|
}
|
||||||
|
|
||||||
if (bcLineup.querySelector(".table-benchcoach-out").rows.length > 0) {
|
function submitResetAvailabilities(modal, options){
|
||||||
var tr = tbody.insertRow();
|
const {team_id, event_id} = options
|
||||||
cell = tr.insertCell();
|
toggleShowAndHideLoading(modal)
|
||||||
cell.colSpan = 3;
|
const url = `/${team_id}/event/${event_id}/reset_availabilities`
|
||||||
cell.appendChild(document.createTextNode("OUT"));
|
const form = document.querySelector(`#event-lineup-${event_id} form`);
|
||||||
cell.classList.add("title-cell");
|
const data = new FormData(form);
|
||||||
|
const memberIds = data.getAll('memberId')
|
||||||
|
|
||||||
for (row of bcLineup.querySelector(".table-benchcoach-out").rows) {
|
console.log('submitting...', url)
|
||||||
var tr = tbody.insertRow();
|
fetch(url, {method:"POST", body: JSON.stringify({memberIds, event_id}), headers: {"Content-Type": "application/json"}})
|
||||||
cell = tr.insertCell();
|
.then((response) => {
|
||||||
cell.classList.add("sequence-cell");
|
if (response.ok) {
|
||||||
availability_status = {
|
completeLoad(modal, true);
|
||||||
None: "UNK",
|
return response.text();
|
||||||
0: "NO",
|
} else {
|
||||||
1: "MAY",
|
completeLoad(modal, false);
|
||||||
2: "YES",
|
return Promise.reject(response.text());
|
||||||
}[row.dataset.availabilityStatuscode];
|
|
||||||
cell.appendChild(document.createTextNode(availability_status));
|
|
||||||
tr.insertCell().appendChild(document.createTextNode(row.dataset.playerName));
|
|
||||||
tr.insertCell().appendChild(document.createTextNode(""));
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.finally(()=>{
|
||||||
container.appendChild(tbl);
|
setTimeout(function (){
|
||||||
for (cell of container.getElementsByClassName("title-cell")) {
|
location.reload()
|
||||||
cell.setAttribute("style", "font-weight:bold;background-color:#323669;color:#fff;padding:2px 5px;");
|
}, 500)
|
||||||
}
|
});//refresh page
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function emailModal(el, url) {
|
function emailModal(el, url) {
|
||||||
@@ -279,21 +311,18 @@ function emailModal(el, url) {
|
|||||||
email_modal_node.classList.add('is-open')
|
email_modal_node.classList.add('is-open')
|
||||||
body.appendChild(email_modal_node)
|
body.appendChild(email_modal_node)
|
||||||
tinymce.init({
|
tinymce.init({
|
||||||
selector:`#lineup-email-data-${data.get('event_lineup_id')} #email-editor`,
|
selector:`textarea#email-editor`,
|
||||||
content_css:"/css/application.css",
|
content_css:"/css/application.css",
|
||||||
plugins: 'image',
|
plugins: 'image',
|
||||||
menubar: false,
|
menubar: false,
|
||||||
toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | image',
|
toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | image',
|
||||||
paste_data_images: true,
|
paste_data_images: true,
|
||||||
statusbar:false})
|
statusbar:false})
|
||||||
// tinymce.activeEditor.setContent("Team,")
|
tinymce.remove();
|
||||||
// lineup_table_div.innerHTML = lineup_table
|
|
||||||
// email_modal.classList.add("is-open");
|
|
||||||
// email_modal.querySelector(".Modal-body").innerHTML = html;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSubmit(form, event) {
|
async function submitEventLineup(form, event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
console.log(event)
|
console.log(event)
|
||||||
teamsnap_icon = form.querySelector("#teamsnap-icon");
|
teamsnap_icon = form.querySelector("#teamsnap-icon");
|
||||||
@@ -303,8 +332,7 @@ async function onSubmit(form, event) {
|
|||||||
data = new FormData(form);
|
data = new FormData(form);
|
||||||
console.log(form)
|
console.log(form)
|
||||||
url = form.attributes.action.textContent;
|
url = form.attributes.action.textContent;
|
||||||
teamsnap_icon.classList.add("u-hidden")
|
toggleShowAndHideLoading(form)
|
||||||
waiting_icon.classList.remove("u-hidden");
|
|
||||||
await fetch(url, {
|
await fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: data,
|
body: data,
|
||||||
@@ -313,8 +341,8 @@ async function onSubmit(form, event) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
waiting_icon.classList.add("u-hidden");
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
|
||||||
return response.text();
|
return response.text();
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(response.text());
|
return Promise.reject(response.text());
|
||||||
@@ -322,201 +350,21 @@ async function onSubmit(form, event) {
|
|||||||
})
|
})
|
||||||
.then((text) => {
|
.then((text) => {
|
||||||
event.submitter.blur()
|
event.submitter.blur()
|
||||||
waiting_icon.classList.add("u-hidden");
|
completeLoad(form, true)
|
||||||
success_icon.classList.remove("u-hidden");
|
console.log(text);
|
||||||
// success_icon.querySelector("span.message").innerHTML = text;
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
event.submitter.blur()
|
event.submitter.blur()
|
||||||
waiting_icon.classList.add("u-hidden");
|
completeLoad(form, false)
|
||||||
failure_icon.classList.remove("u-hidden");
|
|
||||||
console.log(error);
|
console.log(error);
|
||||||
// success_icon.querySelector("span.message").innerHTML = error;
|
})
|
||||||
});
|
.finally(()=>{location.reload()});//refresh page
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
[waiting_icon, success_icon, failure_icon].forEach(e=>e.classList.add('u-hidden'))
|
[waiting_icon, success_icon, failure_icon].forEach(e=>e.classList.add('u-hidden'))
|
||||||
teamsnap_icon.classList.remove('u-hidden')
|
teamsnap_icon.classList.remove('u-hidden')
|
||||||
}, 3000)
|
}, 3000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyEmailTable(itemEl, subject, recipients) {
|
|
||||||
// Create container for the HTML
|
|
||||||
// [1]
|
|
||||||
let bcLineup = itemEl.closest(".event-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();
|
|
||||||
|
|
||||||
lineup_slots_starting = bcLineup.querySelectorAll(".starting .slot-set .lineup-slot");
|
|
||||||
|
|
||||||
for (node of lineup_slots_starting) {
|
|
||||||
console.log("node", node);
|
|
||||||
let tr = tbody.insertRow();
|
|
||||||
cell = tr.insertCell();
|
|
||||||
cell.classList.add("sequence-cell");
|
|
||||||
sequence = node.querySelector("input[name*='sequence']").value;
|
|
||||||
console.log(sequence);
|
|
||||||
cell.appendChild(document.createTextNode(parseInt(sequence) + 1));
|
|
||||||
name = node.querySelector("div:has(.lastname)");
|
|
||||||
cell = tr.insertCell();
|
|
||||||
cell.appendChild(document.createTextNode(name.textContent));
|
|
||||||
cell.classList.add("name-cell");
|
|
||||||
position_label = node.querySelector("input[name*='label']").value;
|
|
||||||
tr.insertCell().appendChild(document.createTextNode(position_label));
|
|
||||||
}
|
|
||||||
|
|
||||||
lineup_slots_position_only = bcLineup.querySelector(".position-only .slot-set .lineup-slot");
|
|
||||||
console.log("lineup slots position", lineup_slots_position_only);
|
|
||||||
if (lineup_slots_position_only.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 (node of lineup_slots_position_only) {
|
|
||||||
var tr = tbody.insertRow();
|
|
||||||
cell = tr.insertCell();
|
|
||||||
cell.classList.add("sequence-cell");
|
|
||||||
cell.appendChild(document.createTextNode(""));
|
|
||||||
cell = tr.insertCell();
|
|
||||||
name = node.querySelector("div:has(.lastname)");
|
|
||||||
cell.appendChild(document.createTextNode(name.textCotent));
|
|
||||||
cell.classList.add("name-cell");
|
|
||||||
position_label = node.querySelector("input[name*='label']").value;
|
|
||||||
tr.insertCell().appendChild(document.createTextNode(position_label));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lineup_slots_bench = bcLineup.querySelector(".bench .slot-set .lineup-slot");
|
|
||||||
if (lineup_slots_bench > 0) {
|
|
||||||
var tr = tbody.insertRow();
|
|
||||||
cell = tr.insertCell();
|
|
||||||
cell.colSpan = 3;
|
|
||||||
cell.appendChild(document.createTextNode("SUBS"));
|
|
||||||
cell.classList.add("title-cell");
|
|
||||||
|
|
||||||
for (node of lineup_slots_bench) {
|
|
||||||
var tr = tbody.insertRow();
|
|
||||||
cell = tr.insertCell();
|
|
||||||
cell.classList.add("sequence-cell");
|
|
||||||
|
|
||||||
div_avail_code = node.querySelector("div[class*='availability-status-code']");
|
|
||||||
if (div_with_avail_code.classList.includes("availability-status-code-1")) {
|
|
||||||
cell.appendChild(document.createTextNode("YES"));
|
|
||||||
} else if (div_with_avail_code.classList.includes("availability-status-code-2")) {
|
|
||||||
cell.appendChild(document.createTextNode("MAY"));
|
|
||||||
} else if (div_with_avail_code.classList.includes("availability-status-code-0")) {
|
|
||||||
cell.appendChild(document.createTextNode("NO"));
|
|
||||||
} else {
|
|
||||||
cell.appendChild(document.createTextNode("UNK"));
|
|
||||||
}
|
|
||||||
cell = tr.insertCell();
|
|
||||||
name = node.querySelector("div:has(.lastname)");
|
|
||||||
cell.appendChild(document.createTextNode(name.textCotent));
|
|
||||||
cell.classList.add("name-cell");
|
|
||||||
tr.insertCell().appendChild(document.createTextNode(""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lineup_slots_out = bcLineup.querySelector(".out .slot-set .lineup-slot");
|
|
||||||
if (lineup_slots_out > 0) {
|
|
||||||
var tr = tbody.insertRow();
|
|
||||||
cell = tr.insertCell();
|
|
||||||
cell.colSpan = 3;
|
|
||||||
cell.appendChild(document.createTextNode("OUT"));
|
|
||||||
cell.classList.add("title-cell");
|
|
||||||
|
|
||||||
for (node of lineup_slots_out) {
|
|
||||||
var tr = tbody.insertRow();
|
|
||||||
cell = tr.insertCell();
|
|
||||||
cell.classList.add("sequence-cell");
|
|
||||||
div_avail_code = node.querySelector("div[class*='availability-status-code']");
|
|
||||||
if (div_with_avail_code.classList.includes("availability-status-code-1")) {
|
|
||||||
cell.appendChild(document.createTextNode("YES"));
|
|
||||||
} else if (div_with_avail_code.classList.includes("availability-status-code-2")) {
|
|
||||||
cell.appendChild(document.createTextNode("MAY"));
|
|
||||||
} else if (div_with_avail_code.classList.includes("availability-status-code-0")) {
|
|
||||||
cell.appendChild(document.createTextNode("NO"));
|
|
||||||
} else {
|
|
||||||
cell.appendChild(document.createTextNode("UNK"));
|
|
||||||
}
|
|
||||||
cell = tr.insertCell();
|
|
||||||
name = node.querySelector("div:has(.lastname)");
|
|
||||||
cell.appendChild(document.createTextNode(name.textCotent));
|
|
||||||
cell.classList.add("name-cell");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleChildSlots (element) {
|
|
||||||
console.log(element);
|
|
||||||
console.log(element.closest(".slot-set"))
|
|
||||||
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
|
|
||||||
console.log(lineup_slot)
|
|
||||||
const cells = lineup_slot.querySelectorAll('.Panel-cell:has(.sequence), .Panel-cell:has(.drag-handle), .Panel-cell:has(.position-select-box), button:has(+.position-label-flags)')
|
|
||||||
Array.from(cells).forEach(cell=>{
|
|
||||||
cell.classList.toggle('u-hidden')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function copyEmailTable (element) {
|
async function copyEmailTable (element) {
|
||||||
// range=document.createRange();
|
// range=document.createRange();
|
||||||
// window.getSelection().removeAllRanges();
|
// window.getSelection().removeAllRanges();
|
||||||
@@ -580,6 +428,44 @@ async function copyEmailTable (element) {
|
|||||||
window.getSelection().removeAllRanges();
|
window.getSelection().removeAllRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveToLineupSegment = (slot, segment_name) => {
|
||||||
|
if (!slot.classList.contains('lineup-slot')) {
|
||||||
|
slot = slot.closest('.lineup-slot')
|
||||||
|
if (!slot) {return}
|
||||||
|
}
|
||||||
|
|
||||||
|
const current_lineup_segment = slot.closest('.lineup-segment')
|
||||||
|
|
||||||
|
if (current_lineup_segment.classList.contains(segment_name)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const lineup = slot.closest('.event-lineup')
|
||||||
|
const newParent = lineup.querySelector(`.lineup-segment.${segment_name} .slot-set`)
|
||||||
|
newParent.append(slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSlots () {
|
||||||
|
document.querySelectorAll('.lineup-slot').forEach(slot=>{
|
||||||
|
if (slot.dataset.initialLineupSegment) {
|
||||||
|
moveToLineupSegment(slot, slot.dataset.initialLineupSegment)
|
||||||
|
slot.removeAttribute('data-initial-lineup-segment')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
addToStarting = (el) => {
|
||||||
|
const slot = el.closest('.lineup-slot')
|
||||||
|
|
||||||
|
this.blur()
|
||||||
|
}
|
||||||
|
|
||||||
|
removeToBench = (el) => {
|
||||||
|
const slot = el.closest('.lineup-slot')
|
||||||
|
|
||||||
|
this.blue()
|
||||||
|
}
|
||||||
|
|
||||||
function insertLineup(direction, teamId, eventId, element) {
|
function insertLineup(direction, teamId, eventId, element) {
|
||||||
const currentUrl = window.location.href;
|
const currentUrl = window.location.href;
|
||||||
let search_params
|
let search_params
|
||||||
@@ -608,7 +494,7 @@ function insertLineup(direction, teamId, eventId, element) {
|
|||||||
.then((html) =>{
|
.then((html) =>{
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const new_lineup_doc = parser.parseFromString(html, 'text/html')
|
const new_lineup_doc = parser.parseFromString(html, 'text/html')
|
||||||
const new_lineup_doc_node = new_lineup_doc.firstElementChild.querySelector('[id*=event-lineup]')
|
const new_lineup_doc_node = new_lineup_doc.firstElementChild.querySelector('.event-lineup')
|
||||||
const main = document.querySelector("main")
|
const main = document.querySelector("main")
|
||||||
const new_csrf_token = new_lineup_doc.querySelector('form input[name=csrfToken]').value
|
const new_csrf_token = new_lineup_doc.querySelector('form input[name=csrfToken]').value
|
||||||
|
|
||||||
@@ -617,13 +503,13 @@ function insertLineup(direction, teamId, eventId, element) {
|
|||||||
main.classList.remove(...main.classList)
|
main.classList.remove(...main.classList)
|
||||||
main.classList.add('scroll-horizontal', 'u-spaceSidesSm', 'u-flex')
|
main.classList.add('scroll-horizontal', 'u-spaceSidesSm', 'u-flex')
|
||||||
|
|
||||||
Array.from(document.querySelectorAll("[id^=event-lineup]")).forEach((bcLineup) => {
|
Array.from(document.querySelectorAll(".event-lineup")).forEach((bcLineup) => {
|
||||||
// main.classList.remove('.u-max1200', 'u-flexExpandSides')
|
// main.classList.remove('.u-max1200', 'u-flexExpandSides')
|
||||||
bcLineup.classList.remove('u-spaceSidesNone', 'u-sm-spaceSidesAuto')
|
bcLineup.classList.remove('u-spaceSidesNone', 'u-sm-spaceSidesAuto')
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Array.from(document.querySelectorAll("[id^=event-lineup] .Panel")).forEach((bcLineupPanel) => {
|
Array.from(document.querySelectorAll(".event-lineup .Panel")).forEach((bcLineupPanel) => {
|
||||||
bcLineupPanel.classList.remove('Panel--full')
|
bcLineupPanel.classList.remove('Panel--full')
|
||||||
})
|
})
|
||||||
for (input of document.querySelectorAll("form input[name=csrfToken]")){
|
for (input of document.querySelectorAll("form input[name=csrfToken]")){
|
||||||
@@ -636,10 +522,10 @@ function insertLineup(direction, teamId, eventId, element) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initPage (){
|
function initPage (){
|
||||||
colorPositions();
|
initSlots();
|
||||||
initFlagsCheckboxes();
|
initFlagsCheckboxes();
|
||||||
refreshLineup();
|
for (bcLineup of document.querySelectorAll(".event-lineup")) {
|
||||||
for (bcLineup of document.querySelectorAll("[id^=event-lineup]")) {
|
bcLineup.dispatchEvent(lineupChangedEvent)
|
||||||
options = {
|
options = {
|
||||||
animation: 150,
|
animation: 150,
|
||||||
handle: ".Panel-cell:has(.drag-handle), .Panel-cell:has(.sequence)",
|
handle: ".Panel-cell:has(.drag-handle), .Panel-cell:has(.sequence)",
|
||||||
@@ -650,52 +536,31 @@ function initPage (){
|
|||||||
pull: [bcLineup.id],
|
pull: [bcLineup.id],
|
||||||
},
|
},
|
||||||
onAdd: function (/**Event*/ evt) {
|
onAdd: function (/**Event*/ evt) {
|
||||||
console.log("added to lineup");
|
bcLineup.dispatchEvent(lineupChangedEvent)
|
||||||
// Add to Lineup
|
|
||||||
var itemEl = evt.item; // dragged HTMLElement
|
|
||||||
|
|
||||||
refreshLineup();
|
|
||||||
},
|
},
|
||||||
onUpdate: function (/**Event*/ evt) {
|
onUpdate: function (/**Event*/ evt) {
|
||||||
console.log("update to lineup");
|
bcLineup.dispatchEvent(lineupChangedEvent)
|
||||||
// var itemEl = evt.item; // dragged HTMLElement
|
|
||||||
// refresh_lineup_order(itemEl);
|
|
||||||
refreshLineup();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
new Sortable.create(bcLineup.querySelector("[id^=lineup-starting] .slot-set"), options);
|
new Sortable.create(bcLineup.querySelector(".lineup-segment.starting .slot-set"), options);
|
||||||
new Sortable.create(bcLineup.querySelector("[id^=lineup-positiononly] .slot-set"), options);
|
new Sortable.create(bcLineup.querySelector(".lineup-segment.position-only .slot-set"), options);
|
||||||
options["sort"] = false;
|
new Sortable.create(bcLineup.querySelector(".lineup-segment.bench .slot-set"), {...options, sort:false});
|
||||||
new Sortable.create(bcLineup.querySelector("[id^=lineup-bench] .slot-set"), options);
|
new Sortable.create(bcLineup.querySelector(".lineup-segment.out .slot-set"), {...options, sort:false, group:{...options.group, put:[]}});
|
||||||
new Sortable.create(bcLineup.querySelector("[id^=lineup-out] .slot-set"), {...options, group:{...options.group, put:[]}});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (lineup_slot of document.querySelectorAll("[id^=lineup-out] .lineup-slot")) {
|
// for (lineup_slot of document.querySelectorAll(".lineup-segment.out .lineup-slot")) {
|
||||||
const cells = lineup_slot.querySelectorAll('.Panel-cell:has(.sequence), .Panel-cell:has(.drag-handle), .Panel-cell:has(.position-select-box), button:has(+.position-label-flags)')
|
// 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') {
|
function mailToLink(el, protocol) {
|
||||||
console.log(el)
|
const {to, bcc} = el.dataset
|
||||||
console.log(el.dataset)
|
const subject = document.getElementById('email-subject').value
|
||||||
const {to, bcc, subject} = el.dataset
|
const email_body = document.getElementById('email-editor').value
|
||||||
const params = new URLSearchParams({
|
const url = `${protocol}://compose?recipient=${to}&bcc=${bcc}&subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(email_body)}`
|
||||||
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)
|
console.log(url)
|
||||||
// location.href=`mailto:${to}${params}`
|
// location.href=`mailto:${to}${params}`
|
||||||
const windowRef = window.open(url, '_blank');
|
const windowRef = window.open(url, '_blank');
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ router.use("/:team_id([0-9]+)/event/:event_id([0-9]+)", loadEvent)
|
|||||||
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.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/availability_reminders", upload.none(), eventsController.sendAvailabilityReminders)
|
||||||
// router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup", eventsController.getLineup);
|
|
||||||
// router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup_card", eventsController.getLineupCard);
|
router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/modal-confirm-availability-reminders/", eventsController.confirmModalAvailabilityReminders)
|
||||||
|
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/reset_availabilities",upload.none(), eventsController.submitResetAvailabilities)
|
||||||
|
|
||||||
module.exports = {router, loadEvent, loadEvents}
|
module.exports = {router, loadEvent, loadEvents}
|
||||||
@@ -57,6 +57,7 @@ router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/adjacent", doubleCs
|
|||||||
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)/email", upload.none(), doubleCsrfProtection, eventsLineupController.getEventLineupEmail )
|
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)/email", upload.none(), doubleCsrfProtection, eventsLineupController.getEventLineupEmail )
|
||||||
router.get ("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)", upload.none(), doubleCsrfProtection, eventsLineupController.getEventLineup);
|
router.get ("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)", upload.none(), doubleCsrfProtection, eventsLineupController.getEventLineup);
|
||||||
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)", upload.none(), doubleCsrfProtection, eventsLineupController.postEventLineup);
|
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)", upload.none(), doubleCsrfProtection, eventsLineupController.postEventLineup);
|
||||||
|
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)/delete", upload.none(), eventsLineupController.submitDeleteEventLineupEntries);
|
||||||
|
|
||||||
|
|
||||||
module.exports = {router, loadEventLineup}
|
module.exports = {router, loadEventLineup}
|
||||||
@@ -30,6 +30,8 @@ router.get("/:team_id([0-9]+)/event/:event_id([0-9]+)/sheet", async (req,res) =>
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
router.get("/lineup/sheet/blank", eventsSheetController.getEventSheetBlank )
|
||||||
|
|
||||||
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)/sheet", upload.none(), eventsSheetController.getEventSheet )
|
router.post("/:team_id([0-9]+)/event/:event_id([0-9]+)/lineup/:event_lineup_id([0-9]+)/sheet", upload.none(), eventsSheetController.getEventSheet )
|
||||||
|
|
||||||
module.exports = {router}
|
module.exports = {router}
|
||||||
@@ -27,4 +27,10 @@ router.get("/", (req,res,next) => {
|
|||||||
|
|
||||||
router.get("/:team_id([0-9]+)/members", membersController.getMembers);
|
router.get("/:team_id([0-9]+)/members", membersController.getMembers);
|
||||||
|
|
||||||
|
router.get("/modal-confirm/", (req,res) => {
|
||||||
|
const {title, body} = req.query
|
||||||
|
res.render('modal_confirm', {title, body} )
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
module.exports = {router, partials};
|
module.exports = {router, partials};
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ a.Panel-row {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[id^="event-lineup"] {
|
div.event-lineup {
|
||||||
max-width: 576px;
|
max-width: 576px;
|
||||||
counter-reset: lineup-sequence-counter 0;
|
counter-reset: lineup-sequence-counter 0;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@@ -289,17 +289,31 @@ li .availability-status-code- {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div[id^="event-lineup"] .Panel {
|
div.event-lineup {
|
||||||
&.position-only .Panel-cell:has(.sequence), &.bench .Panel-cell:has(.sequence), &.out .Panel-cell:has(.sequence){
|
.lineup-segment {
|
||||||
display: none;
|
&:has(input.Toggle-input:not(:checked)) {
|
||||||
}
|
&.out {
|
||||||
|
.Panel-cell:has(.SelectBox),
|
||||||
&.out {
|
.Panel-cell:has(.drag-handle),
|
||||||
.Panel-cell {
|
button:has(+.position-label-flags),
|
||||||
&:has(.sequence), .drag-handle, .SelectBox {
|
button.addToStarting,
|
||||||
// display: none;
|
button.addToBench
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.bench, &.position-only, &.out {
|
||||||
|
.Panel-cell:has(.sequence) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&.bench button.addToBench {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.starting button.addToStarting, &.position-only button.addToStarting {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
38
src/views/event/partials/modal_availability_reminders.hbs
Normal file
38
src/views/event/partials/modal_availability_reminders.hbs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<div id="modal" class="Modal Modal--clickableBg">
|
||||||
|
<div class="Modal-content">
|
||||||
|
<div onclick="javascript:this.closest('.Modal').remove();">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg" "Modal-iconDismiss"}}}</div>
|
||||||
|
<div class="Modal-header">
|
||||||
|
<div class="Modal-title">Send Reminders</div>
|
||||||
|
</div>
|
||||||
|
<div class="Modal-body">
|
||||||
|
<div class="u-padSidesMd">
|
||||||
|
<strong>Send to players who have selected:</strong>
|
||||||
|
<div class="u-spaceTopSm"><div class="Checkbox">
|
||||||
|
<input class="Checkbox-input" type="checkbox" name="undecidedCheckBox" id="undecidedCheckBox" checked="" value>
|
||||||
|
<label class="Checkbox-label" for="undecidedCheckBox">Undecided</label>
|
||||||
|
</div>
|
||||||
|
<div class="Checkbox">
|
||||||
|
<input class="Checkbox-input" type="checkbox" name="maybeCheckbox" id="maybeCheckbox" value="2">
|
||||||
|
<label class="Checkbox-label" for="maybeCheckbox">Maybe</label>
|
||||||
|
</div>
|
||||||
|
<div class="Checkbox">
|
||||||
|
<input class="Checkbox-input" type="checkbox" name="attendingCheckbox" id="attendingCheckbox" value="1">
|
||||||
|
<label class="Checkbox-label" for="attendingCheckbox">Attending</label>
|
||||||
|
</div>
|
||||||
|
<div class="Checkbox u-padBottomNone">
|
||||||
|
<input class="Checkbox-input" type="checkbox" name="notAttendingCheckbox" id="notAttendingCheckbox" value="0">
|
||||||
|
<label class="Checkbox-label" for="notAttendingCheckbox">Not Attending</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="Modal-footer">
|
||||||
|
<button class="Button Button--negative" role="button" type="button" onclick="javascript:this.closest('.Modal').remove();" data-confirm="cancel">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button class="Button Button--primary" role="button" type="button" data-confirm="yes">
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
0
src/views/event/stats-importer.hbs
Normal file
0
src/views/event/stats-importer.hbs
Normal file
@@ -1,66 +1,70 @@
|
|||||||
<div class="u-spaceSidesNone u-sm-spaceSidesAuto" id="event-lineup-{{event.id}}" data-event-lineup-id="{{event_lineup.id}}" data-event-id="{{event.id}}">
|
<div class="u-spaceSidesNone u-sm-spaceSidesAuto event-lineup" id="event-lineup-{{event.id}}" data-event-lineup-id="{{event_lineup.id}}" data-event-id="{{event.id}}">
|
||||||
<form onsubmit="onSubmit(this,event)" action="/{{team.id}}/event/{{event.id}}/lineup/{{event_lineup.id}}">
|
<form onsubmit="submitEventLineup(this,event)" action="/{{team.id}}/event/{{event.id}}/lineup/{{event_lineup.id}}">
|
||||||
<input type="hidden" name="event_lineup_id" value="{{event_lineup.id}}">
|
<input type="hidden" name="event_lineup_id" value="{{event_lineup.id}}">
|
||||||
{{!-- <input type="hidden" name="_csrf" value="{{csrfToken}}"> --}}
|
{{!-- <input type="hidden" name="_csrf" value="{{csrfToken}}"> --}}
|
||||||
<input type="hidden" name="csrfToken" value="{{csrfToken}}">
|
<input type="hidden" name="csrfToken" value="{{csrfToken}}">
|
||||||
<div class="Panel Panel--full">
|
<div class="Panel Panel--full">
|
||||||
<div class="Panel-header u-padEndsSm">
|
<div class="Panel-header u-padEndsSm">
|
||||||
<h3 style="flex: 1 1 0%;">{{event.formattedTitle}}</h3>
|
<h3 style="flex: 1 1 0%;">{{event.formattedTitle}}</h3>
|
||||||
<div class="ButtonGroup">
|
<div class="Popup">
|
||||||
<button class="Button Button--orange" type="submit" formmethod="post">
|
<div class="ButtonGroup">
|
||||||
<div>
|
<button class="Button Button--orange" type="submit" formmethod="post">
|
||||||
<span id="teamsnap-icon">{{{embeddedSvgFromPath "/media/teamsnap_star.svg"}}}</span>
|
<div>
|
||||||
<span id="waiting-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/loader.svg" "Icon--loader"}}}</span>
|
<span id="teamsnap-icon" class="hideOnLoading">{{{embeddedSvgFromPath "/media/teamsnap_star.svg"}}}</span>
|
||||||
<span id="success-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/check.svg"}}}</span>
|
<span id="waiting-icon" class="u-hidden showOnLoading">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/loader.svg" "Icon--loader"}}}</span>
|
||||||
<span id="failure-icon" class="u-hidden">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg"}}}</span>
|
<span id="success-icon" class="u-hidden showOnSuccess">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/check.svg"}}}</span>
|
||||||
Save
|
<span id="failure-icon" class="u-hidden showOnFailure">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg"}}}</span>
|
||||||
</div>
|
Save
|
||||||
</button>
|
</div>
|
||||||
<div class="Button Button--orange .u-padSidesXs Popup" onclick="togglePopup(this)">
|
</button>
|
||||||
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/caret-down.svg"}}}
|
<div class="Button Button--orange .u-padSidesXs Popup-toggle" data-control="popup" data-open="event-lineup-more-actions-{{event_lineup.id}}">
|
||||||
<div class="Popup-container Popup-container--down Popup-container--right" style="width: 200px">
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/caret-down.svg"}}}
|
||||||
<div class="Popup-content u-textDecorationNone">
|
<div class="Popup-container Popup-container--down Popup-container--right" style="width: 200px" data-popup="event-lineup-more-actions-{{event_lineup.id}}">
|
||||||
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="emailModal(this, '{{event_lineup.id}}/email')">
|
<div class="Popup-content u-textDecorationNone">
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/envelope.svg"}}}
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="emailModal(this, '{{event_lineup.id}}/email')">
|
||||||
<span>Generate Email</span>
|
{{{embeddedSvgFromPath "/bootstrap-icons/envelope.svg"}}}
|
||||||
</a>
|
<span>Generate Email</span>
|
||||||
<hr class="Divider u-spaceEndsNone">
|
</a>
|
||||||
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="/{{team.id}}/event/{{event.id}}/sheet">
|
|
||||||
<span>{{{embeddedSvgFromPath "/bootstrap-icons/file-earmark.svg"}}}</span>
|
|
||||||
<span class="u-hidden u-xs-inline">Game Sheet</span>
|
|
||||||
</a>
|
|
||||||
<hr class="Divider u-spaceEndsNone">
|
|
||||||
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="insertLineup(1, {{team.id}}, {{event.id}}, this)">
|
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/caret-right.svg"}}}
|
|
||||||
<span>Insert next lineup</span>
|
|
||||||
</a>
|
|
||||||
<hr class="Divider u-spaceEndsNone">
|
|
||||||
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="insertLineup(-1, {{team.id}}, {{event.id}}, this)">
|
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/caret-left.svg"}}}
|
|
||||||
<span>Insert previous lineup</span>
|
|
||||||
</a>
|
|
||||||
<div class="u-hidden">
|
|
||||||
<hr class="Divider u-spaceEndsNone">
|
<hr class="Divider u-spaceEndsNone">
|
||||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="/{{team.id}}/event/{{event.id}}/sheet">
|
||||||
|
<span>{{{embeddedSvgFromPath "/bootstrap-icons/file-earmark.svg"}}}</span>
|
||||||
|
<span class="u-hidden u-xs-inline">Game Sheet</span>
|
||||||
|
</a>
|
||||||
|
<hr class="Divider u-spaceEndsNone">
|
||||||
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="insertLineup(1, {{team.id}}, {{event.id}}, this)">
|
||||||
|
{{{embeddedSvgFromPath "/bootstrap-icons/caret-right.svg"}}}
|
||||||
|
<span>Insert next lineup</span>
|
||||||
|
</a>
|
||||||
|
<hr class="Divider u-spaceEndsNone">
|
||||||
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="insertLineup(-1, {{team.id}}, {{event.id}}, this)">
|
||||||
|
{{{embeddedSvgFromPath "/bootstrap-icons/caret-left.svg"}}}
|
||||||
|
<span>Insert previous lineup</span>
|
||||||
|
</a>
|
||||||
|
<hr class="Divider u-spaceEndsNone">
|
||||||
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="openAvailabilityReminderModal(this, {{team.id}}, {{event.id}})">
|
||||||
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/send.svg"}}}
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/send.svg"}}}
|
||||||
<span>Availability Reminders</span>
|
<span>Availability Reminders</span>
|
||||||
</span>
|
</a>
|
||||||
<hr class="Divider u-spaceEndsNone">
|
<hr class="Divider u-spaceEndsNone">
|
||||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="confirmModal(this, {title:'Reset Availabilities',body:'Are sure you want to reset availabilities?'}, submitResetAvailabilities, {team_id:{{team.id}}, event_id:{{event.id}} })";>
|
||||||
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/refresh.svg"}}}
|
||||||
<span>Reset All Availabilities</span>
|
<span>Reset All Availabilities</span>
|
||||||
</span>
|
</a>
|
||||||
<hr class="Divider u-spaceEndsNone">
|
<hr class="Divider u-spaceEndsNone">
|
||||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
<a class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="confirmModal(this, {title:'Clear Lineup',body:'Are sure you want to clear lineup?'}, submitClearLineup, {team_id:{{team.id}}, event_id:{{event.id}}, event_lineup_id:{{event_lineup.id}} })">
|
||||||
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/trash.svg"}}}
|
||||||
<span>Clear Lineup</span>
|
<span>Clear Lineup</span>
|
||||||
</span>
|
</a>
|
||||||
<hr class="Divider u-spaceEndsNone">
|
<div class="u-hidden">
|
||||||
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
<hr class="Divider u-spaceEndsNone">
|
||||||
<span>Publish</span>
|
<span class="u-padEndsSm u-padSidesMd u-textDecorationNone" href="javascript:void(0)" onclick="console.log('not implemented yet')">
|
||||||
</span>
|
<span>Publish</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class=" Panel-body u-padEndsSm">
|
<div class=" Panel-body u-padEndsSm">
|
||||||
@@ -68,12 +72,12 @@
|
|||||||
<div class="date">{{dateFormat event.startDate "ddd, MMM D h:mm A" }}</div>
|
<div class="date">{{dateFormat event.startDate "ddd, MMM D h:mm A" }}</div>
|
||||||
<div class="location">{{event.locationName}}</div>
|
<div class="location">{{event.locationName}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class=" availability-bar fullwidth">
|
<div class="availability-bar fullwidth">
|
||||||
|
{{> availability_bar availabilitySummary=availabilitySummary}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="lineup-starting-{{event.id}}" class="Panel u-maxWidthSm starting Panel--fullWidthMobile Panel--full">
|
<div class="Panel u-maxWidthSm lineup-segment starting Panel--fullWidthMobile Panel--full">
|
||||||
<div class="Panel-body">
|
<div class="Panel-body">
|
||||||
<div class="Panel-row Panel-title u-padXs">
|
<div class="Panel-row Panel-title u-padXs">
|
||||||
<i>{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}</i>
|
<i>{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}</i>
|
||||||
@@ -81,59 +85,45 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class=" Panel-row Grid Grid--fit u-textBold u-textCenter u-padXs">
|
<div class=" Panel-row Grid Grid--fit u-textBold u-textCenter u-padXs">
|
||||||
{{#each (positions)}}
|
{{#each (positions)}}
|
||||||
<div class="Grid-cell position-status">{{this}}</div>
|
<div class="Grid-cell position-status" data-value="{{this}}">{{this}}</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
<div class="slot-set">
|
<div class="slot-set">
|
||||||
{{#each members}}
|
|
||||||
{{#if (isInStartingLineup this)}}
|
|
||||||
{{> slot member=this}}
|
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="lineup-positiononly-{{event.id}}" class="Panel u-maxWidthSm position-only Panel--full">
|
<div class="Panel u-maxWidthSm lineup-segment position-only Panel--full">
|
||||||
<div class="Panel-row Panel-title u-padXs">
|
<div class="Panel-row Panel-title u-padXs">
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}
|
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-check.svg"}}}
|
||||||
<span>Position Only</span>
|
<span>Position Only</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="slot-set">
|
<div class="slot-set">
|
||||||
{{#each members}}
|
|
||||||
{{#if (isInPositionOnly this)}}
|
|
||||||
{{> slot member=this}}
|
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="lineup-bench-{{event.id}}" class="Panel u-maxWidthSm bench Panel--full">
|
<div class="Panel u-maxWidthSm lineup-segment bench Panel--full">
|
||||||
<div class="Panel-row Panel-title u-padXs">
|
<div class="Panel-row Panel-title u-padXs">
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-minus.svg"}}}
|
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-minus.svg"}}}
|
||||||
<span>Bench</span>
|
<span>Bench</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="slot-set">
|
<div class="slot-set">
|
||||||
{{#each members}}
|
{{#loadSlots}}
|
||||||
{{#if (isInBench this)}}
|
{{>slot member=member event_lineup=event_event_lineup availablity=availability}}
|
||||||
{{> slot member=this event=../event}}
|
{{/loadSlots}}
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="lineup-out-{{event.id}}" class="Panel u-maxWidthSm out Panel--full">
|
<div class="Panel u-maxWidthSm lineup-segment out Panel--full">
|
||||||
<div class="Panel-row Panel-title u-padXs u-flex">
|
<div class="Panel-row Panel-title u-padXs u-flex">
|
||||||
<div><span style="flex: 1 1 0%;">{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-x.svg"}}}Out</span></div>
|
<div><span style="flex: 1 1 0%;">{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-x.svg"}}}Out</span></div>
|
||||||
<div class="u-flexGrow1"></div>
|
<div class="u-flexGrow1"></div>
|
||||||
<div class="Toggle">
|
<div class="Toggle">
|
||||||
<input class="Toggle-input" type="checkbox" id="enable-slots" onclick="toggleChildSlots(this);">
|
<input class="Toggle-input" type="checkbox" id="enable-slots">
|
||||||
<label class="Toggle-label" for="enable-slots"></label>
|
<label class="Toggle-label" for="enable-slots"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="slot-set">
|
<div class="slot-set">
|
||||||
{{#each members}}
|
|
||||||
{{#if (isInOut this)}}
|
|
||||||
{{> slot member=this}}
|
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<div id="availability-reminder-modal-{{event.id}}" class="Modal Modal--clickableBg">
|
||||||
|
<div class="Modal-content">
|
||||||
|
<div onclick="javascript:this.closest('.Modal').remove();">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg" "Modal-iconDismiss"}}}</div>
|
||||||
|
<div class="Modal-header">
|
||||||
|
<div class="Modal-title">Send Reminders</div>
|
||||||
|
</div>
|
||||||
|
<div class="Modal-body">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -8,32 +8,37 @@
|
|||||||
<form>
|
<form>
|
||||||
<div class="FieldGroup">
|
<div class="FieldGroup">
|
||||||
<label class="FieldGroup-label">Subject</label>
|
<label class="FieldGroup-label">Subject</label>
|
||||||
<input class="Input" type="text" value="{{dateFormat event.startDate "ddd, MMM D, YYYY h:mm A" }}, {{ event.locationName }}, ({{#if (isAway event) }}@{{/if}}{{ event.opponentName }})">
|
<input class="Input" id="email-subject" type="text" value="{{dateFormat event.startDate "ddd, MMM D, YYYY h:mm A" }}, {{ event.locationName }}, ({{#if (isAway event) }}@{{/if}}{{ event.opponentName }})">
|
||||||
</div>
|
</div>
|
||||||
<div class="FieldGroup">
|
<div class="FieldGroup">
|
||||||
<label class="FieldGroup-label">Body</label>
|
<label class="FieldGroup-label">Body</label>
|
||||||
<textarea id="email-editor" class="Input"></textarea>
|
<textarea id="email-editor" class="Input"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="FieldGroup">
|
<div class="FieldGroup">
|
||||||
<label class="FieldGroup-label">Lineup</label>
|
<label class="FieldGroup-label">
|
||||||
|
Lineup
|
||||||
|
<button class="Button Button--smallSquare" role="button" type="button" onclick="copyEmailTable(this)">
|
||||||
|
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-fill.svg"}}}
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
<div class="lineup-email lineup-table">{{>email_table}}</div>
|
<div class="lineup-email lineup-table">{{>email_table}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="FieldGroup">
|
|
||||||
<button class="Button" role="button" type="button" onclick="copyEmailTable(this)">
|
</form>
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/clipboard-fill.svg"}}}
|
</div>
|
||||||
{{{embeddedSvgFromPath "/bootstrap-icons/table.svg"}}}
|
<div class="Modal-footer">
|
||||||
Copy Table
|
<button class="Button" role="button" type="button" onclick="mailToLink(this, 'readdle-spark');",
|
||||||
</button>
|
|
||||||
<button class="Button" role="button" type="button" onclick="sparkMailToLink(this);",
|
|
||||||
data-to="{{user.email}}"
|
data-to="{{user.email}}"
|
||||||
data-bcc="{{joinMemberEmailAddresses (filterNonPlayers members)}}"
|
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"}}}
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/mail.svg"}}}
|
||||||
Spark Mail
|
Spark Mail
|
||||||
</button>
|
</button>
|
||||||
</div>
|
<button class="Button" role="button" type="button" onclick="mailToLink(this, 'mailto');",
|
||||||
</form>
|
data-to="{{user.email}}"
|
||||||
|
data-bcc="{{joinMemberEmailAddresses (filterNonPlayers members)}}">
|
||||||
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/mail.svg"}}}
|
||||||
|
Mail
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</script>
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<table>
|
<table class="lineup-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="title-cell" colSpan=3>
|
<th class="title-cell" colSpan=3>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<div class="Panel-expandableRow lineup-slot">
|
<div class="Panel-expandableRow lineup-slot" data-initial-lineup-segment="{{initial_lineup_segment}}">
|
||||||
<input type="hidden" name="label" value="{{member.benchcoach.eventLineupEntry.label}}">
|
<input type="hidden" name="label" value="{{eventLineupEntry.label}}">
|
||||||
<input type="hidden" name="flags" value="{{flagsString member.benchcoach.eventLineupEntry.flags}}">
|
<input type="hidden" name="flags" value="{{flagsString eventLineupEntry.flags}}">
|
||||||
<input type="hidden" name="sequence" value="{{member.benchcoach.eventLineupEntry.sequence}}">
|
<input type="hidden" name="sequence" value="{{eventLineupEntry.sequence}}">
|
||||||
<input type="hidden" name="eventId" value="{{event.id}}">
|
<input type="hidden" name="eventId" value="{{event.id}}">
|
||||||
<input type="hidden" name="eventLineupEntryId" value="{{member.benchcoach.eventLineupEntry.id}}">
|
<input type="hidden" name="eventLineupEntryId" value="{{eventLineupEntry.id}}">
|
||||||
<input type="hidden" name="availabilityStatusCode", value="{{member.benchcoach.availability?.statusCode}}">
|
<input type="hidden" name="availabilityStatusCode", value="{{#if availability}}{{availability.statusCode}}{{/if}}">
|
||||||
<input type="hidden" name="memberId" value="{{member.id}}">
|
<input type="hidden" name="memberId" value="{{member.id}}">
|
||||||
<input type="hidden" name="lastName" value="{{member.lastName}}">
|
<input type="hidden" name="lastName" value="{{member.lastName}}">
|
||||||
<input type="hidden" name="firstName" value="{{member.firstName}}">
|
<input type="hidden" name="firstName" value="{{member.firstName}}">
|
||||||
@@ -18,31 +18,32 @@
|
|||||||
<div class="Panel-cell u-padXs u-sizeFill u-flex">
|
<div class="Panel-cell u-padXs u-sizeFill u-flex">
|
||||||
<div
|
<div
|
||||||
class="Popup availability-status-code-{{
|
class="Popup availability-status-code-{{
|
||||||
member.benchcoach.availability?.statusCode
|
availability?.statusCode
|
||||||
}}"
|
}}"
|
||||||
>
|
>
|
||||||
{{#if member.benchcoach.availability}}
|
{{#if availability}}
|
||||||
{{#with member.benchcoach.availability}}
|
{{#with availability}}
|
||||||
<button class="Popup-toggle Button Button--smallSquare {{avail_status_code_class statusCode}}"
|
<div class="Popup">
|
||||||
type="button"
|
<button class="Popup-toggle Button Button--smallSquare {{avail_status_code_class statusCode}}"
|
||||||
data-control="popup"
|
type="button"
|
||||||
data-open="availablility-popup-{{memberId}}-{{eventId}}"
|
data-control="popup"
|
||||||
onclick="this.closest('div').querySelector('.Popup-container').classList.toggle('is-open')"
|
data-open="availablility-popup-{{eventId}}-{{memberId}}"
|
||||||
>
|
>
|
||||||
{{#if notes}}{{{embeddedSvgFromPath "/bootstrap-icons/asterisk.svg"}}}{{else}}{{{avail_status_code_icon statusCode}}}{{/if}}
|
{{#if notes}}{{{embeddedSvgFromPath "/bootstrap-icons/asterisk.svg"}}}{{else}}{{{avail_status_code_icon statusCode}}}{{/if}}
|
||||||
</button>
|
</button>
|
||||||
<div class="Popup-container Popup-container--left" data-popup="availablility-popup-{{memberId}}-{{eventId}}">
|
<div class="Popup-container Popup-container--left" data-popup="availablility-popup-{{eventId}}-{{memberId}}">
|
||||||
<div class="Popup-content u-padSm u-textCenter">
|
<div class="Popup-content u-padSm u-textCenter">
|
||||||
<h3 class="u-spaceBottomSm">Availability</h3>
|
<h3 class="u-spaceBottomSm">Availability</h3>
|
||||||
{{#if notes}}
|
{{#if notes}}
|
||||||
<p class="u-textLeft">“ <i>{{notes}}</i> ”</p>
|
<p class="u-textLeft">“ <i>{{notes}}</i> ”</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p class="u-textLeft">No notes.</p>
|
<p class="u-textLeft">No notes.</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<button type="button" class="Button u-spaceTopSm" onclick="sendAvailabilityReminder(this, {{eventId}}, ['{{memberId}}'], {{csrfToken}})">
|
<button type="button" class="Button u-spaceTopSm" onclick="sendAvailabilityReminder(this, {{eventId}}, ['{{memberId}}'], {{csrfToken}})">
|
||||||
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/send.svg"}}}
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/send.svg"}}}
|
||||||
<span>Send Reminder</span>
|
<span>Send Reminder</span>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
@@ -61,19 +62,25 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="u-flexGrow1"></div>
|
<div class="u-flexGrow1"></div>
|
||||||
|
<button type="button" class="Button Button--smallSquare addToBench" onclick="moveToLineupSegment(this, 'bench');this.blur()">
|
||||||
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg"}}}
|
||||||
|
</button>
|
||||||
|
<button type="button" class="Button Button--smallSquare addToStarting" onclick="moveToLineupSegment(this, 'starting');this.blur()">
|
||||||
|
{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/plus.svg"}}}
|
||||||
|
</button>
|
||||||
<div class="Popup">
|
<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)">
|
<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"}}}
|
{{{embeddedSvgFromPath "/bootstrap-icons/three-dots.svg"}}}
|
||||||
</button>
|
</button>
|
||||||
<div class="Popup-container Popup-container--rightHang position-label-flags">
|
<div class="Popup-container Popup-container--rightHang position-label-flags">
|
||||||
<div class="Popup-content u-padSm u-textCenter">
|
<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="DRd" id="flag-drd-{{member.id}}-{{eventLineupEntry.id}}">
|
||||||
<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}}-{{eventLineupEntry.id}}">DR<small>d</small></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="Checkbox Checkbox--inline">
|
<div class="Checkbox Checkbox--inline">
|
||||||
<input class="Checkbox-input" type="checkbox" name="flag-dhd" id="flag-dhd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}" onclick="refreshLineup()">
|
<input class="Checkbox-input" type="checkbox" name="DHd" id="flag-dhd-{{member.id}}-{{eventLineupEntry.id}}">
|
||||||
<label class="Checkbox-label" for="flag-dhd-{{member.id}}-{{member.benchcoach.eventLineupEntry.id}}">DH<small>d</small></label>
|
<label class="Checkbox-label" for="flag-dhd-{{member.id}}-{{eventLineupEntry.id}}">DH<small>d</small></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -86,7 +93,7 @@
|
|||||||
--
|
--
|
||||||
</option>
|
</option>
|
||||||
{{#each (positions)}}
|
{{#each (positions)}}
|
||||||
<option value="{{this}}" {{#if (comparePositionWithFlags this ../member.benchcoach.eventLineupEntry)}}selected{{/if}}>
|
<option value="{{this}}" {{#if (comparePositionWithFlags this ../eventLineupEntry)}}selected{{/if}}>
|
||||||
{{this}}
|
{{this}}
|
||||||
</option>
|
</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<div class="field-container">
|
<div class="field-container">
|
||||||
<img src="/media/baseball-diamond.svg" />
|
{{{embeddedSvgFromPath "/media/baseball-diamond.svg" 'baseball-diamond'}}}
|
||||||
{{#defenseLineup event_lineup_entries members}}
|
{{#defenseLineup event_lineup_entries members}}
|
||||||
<div class="slot-set pos-{{this.position}}">
|
<div class="slot-set pos-{{this.position}}">
|
||||||
<table>
|
<table class="striped">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr class="slot">
|
<tr class="slot">
|
||||||
<th class="position"></th>
|
<th class="position"></th>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
<table>
|
<table>
|
||||||
<colgroup><col span="3" class="player"></colgroup>
|
{{!-- <colgroup><col span="4" class="player"></colgroup> --}}
|
||||||
{{!-- <colgroup><col span="0" class="player-stats"></colgroup> --}}
|
{{!-- <colgroup><col span="1" class="spacer"></colgroup> --}}
|
||||||
<colgroup><col span="4" class="position-capability"></colgroup>
|
{{!-- <colgroup><col span="1" class="player-stats"></colgroup> --}}
|
||||||
|
{{!-- <colgroup><col span="4" class="position-capability"></colgroup>
|
||||||
<colgroup><col span="4" class="availability-on-day future"></colgroup>
|
<colgroup><col span="4" class="availability-on-day future"></colgroup>
|
||||||
<colgroup><col span="4" class="availability-on-day past"></colgroup>
|
<colgroup><col span="4" class="availability-on-day past"></colgroup> --}}
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="3" id="today-availability">
|
<th colspan="4" id="today-availability">
|
||||||
Available ({{availabilitySummary.playerGoingCount}}|{{availabilitySummary.playerMaybeCount}})
|
Available ({{availabilitySummary.playerGoingCount}}|{{availabilitySummary.playerMaybeCount}})
|
||||||
</th>
|
</th>
|
||||||
|
<th class="spacer first-of-group last-of-group"></th>
|
||||||
<th class="player-stats">
|
<th class="player-stats">
|
||||||
<span class="decimal-point">.</span>AVG
|
<span class="decimal-point">.</span>AVG
|
||||||
<span class="delimiter">/</span>
|
<span class="delimiter">/</span>
|
||||||
@@ -17,34 +19,38 @@
|
|||||||
<span class="decimal-point">.</span>SLG
|
<span class="decimal-point">.</span>SLG
|
||||||
<span class="delimiter">:</span>PA
|
<span class="delimiter">:</span>PA
|
||||||
</th>
|
</th>
|
||||||
<th class="position-capability pitcher">P</th>
|
<th class="position-capability pitcher first-of-group">P</th>
|
||||||
<th class="position-capability catcher">C</th>
|
<th class="position-capability catcher">C</th>
|
||||||
<th class="position-capability infield">I</th>
|
<th class="position-capability infield">I</th>
|
||||||
<th class="position-capability outfield">O</th>
|
<th class="position-capability outfield last-of-group">O</th>
|
||||||
{{!-- <% for timepoint, i in timeline.select{|tp| tp[:comparison_to_selected]>0}.sort{|tp| -tp[:comparison_to_selected]}.each_with_index do%> --}}
|
{{!-- <% for timepoint, i in timeline.select{|tp| tp[:comparison_to_selected]>0}.sort{|tp| -tp[:comparison_to_selected]}.each_with_index do%> --}}
|
||||||
|
|
||||||
{{#loopEvents upcoming_events}}
|
{{#loopEvents upcoming_events}}
|
||||||
<th class="availability-on-day avail-today-plus-{{@index}}" date="{{this.startDate}}"><div>{{dateFormat this.startDate "ddd" }}</div></th>
|
<th class="availability-on-day avail-today-plus-{{@index}} {{#ifEquals @index 0}}first-of-group{{/ifEquals}}{{#ifEquals @index 3}}last-of-group{{/ifEquals}}" date="{{this.startDate}}"><div>{{dateFormat this.startDate "ddd" }}</div></th>
|
||||||
{{/loopEvents}}
|
{{/loopEvents}}
|
||||||
{{#loopEvents recent_events}}
|
{{#loopEvents recent_events}}
|
||||||
<th class="availability-on-day avail-today-minus-{{@index}}" date="{{this.startDate}}"><div>{{dateFormat this.startDate "ddd" }}</div></th>
|
<th class="availability-on-day avail-today-minus-{{@index}} {{#ifEquals @index 0}}first-of-group{{/ifEquals}}{{#ifEquals @index 3}}last-of-group{{/ifEquals}}" date="{{this.startDate}}"><div>{{dateFormat this.startDate "ddd" }}</div></th>
|
||||||
{{/loopEvents}}
|
{{/loopEvents}}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{!-- <% by_member.select{|m,d| !m.is_non_player}.each_with_index do |(member, d), i|%> --}}
|
{{!-- <% by_member.select{|m,d| !m.is_non_player}.each_with_index do |(member, d), i|%> --}}
|
||||||
{{#rosterHistory event event_lineup_entries members availabilities}}
|
{{#rosterHistory event event_lineup_entries members availabilities}}
|
||||||
<tr id="roster-history-slot-<%= ::Temple::Utils.escape_html((i)) %>">
|
<tr class="roster-history-slot{{#if (isStarting this)}} starting-today{{/if}}">
|
||||||
<td class="is-present-checkbox available-status-code-{{this.benchcoach.availability.statusCode}}">
|
<td class="is-present-checkbox available-status-code-{{this.benchcoach.availability.statusCode}} first-of-group">
|
||||||
<span>■</span>
|
<span>■</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="jersey-number available-status-code-{{this.benchcoach.availability.statusCode}}{{#if (isStarting this)}} starting{{/if}}">
|
<td class="jersey-number available-status-code-{{this.benchcoach.availability.statusCode}}">
|
||||||
{{this.jerseyNumber}}
|
{{this.jerseyNumber}}
|
||||||
</td>
|
</td>
|
||||||
<td class="player-name available-status-code-{{this.benchcoach.availability.statusCode}}{{#if (isStarting this)}} starting{{/if}}">
|
<td class="player-name available-status-code-{{this.benchcoach.availability.statusCode}}">
|
||||||
{{this.lastName}}
|
{{this.lastName}}
|
||||||
</td>
|
</td>
|
||||||
<td class="player-stats border-left border-right">
|
<td class="position available-status-code-{{this.benchcoach.availability.statusCode}} last-of-group">
|
||||||
|
<span>{{this.benchcoach.eventLineupEntry.label}}</span>
|
||||||
|
</td>
|
||||||
|
<td class="spacer"></td>
|
||||||
|
<td class="player-stats first-of-group last-of-group">
|
||||||
<span class="decimal-point">.</span>
|
<span class="decimal-point">.</span>
|
||||||
<span class="avg">000</span>
|
<span class="avg">000</span>
|
||||||
<span class="delimiter">/</span>
|
<span class="delimiter">/</span>
|
||||||
@@ -56,20 +62,20 @@
|
|||||||
<span class="delimiter">:</span>
|
<span class="delimiter">:</span>
|
||||||
<span class="pa">00</span>
|
<span class="pa">00</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="position-capability pitcher">{{positionCapabilityFor this "P"}}</td>
|
<td class="position-capability pitcher first-of-group">{{positionCapabilityFor this "P"}}</td>
|
||||||
<td class="position-capability catcher">{{positionCapabilityFor this "C"}}</td>
|
<td class="position-capability catcher">{{positionCapabilityFor this "C"}}</td>
|
||||||
<td class="position-capability infield">{{positionCapabilityFor this "IF"}}</td>
|
<td class="position-capability infield">{{positionCapabilityFor this "IF"}}</td>
|
||||||
<td class="position-capability outfield">{{positionCapabilityFor this "OF"}}</td>
|
<td class="position-capability outfield last-of-group">{{positionCapabilityFor this "OF"}}</td>
|
||||||
{{#loopEvents ../upcoming_events}}
|
{{#loopEvents ../upcoming_events}}
|
||||||
{{#timepointForMember ../this ../../timeline this}}
|
{{#timepointForMember ../this ../../timeline this}}
|
||||||
<td class="availability-on-day future available-status-code-{{this.availability.statusCode}}">
|
<td class="availability-on-day future available-status-code-{{this.availability.statusCode}} {{this.value}} {{#ifEquals @index 0}}first-of-group{{/ifEquals}}{{#ifEquals @index 3}}last-of-group{{/ifEquals}}">
|
||||||
{{this.value}}
|
{{this.value}}
|
||||||
</td>
|
</td>
|
||||||
{{/timepointForMember}}
|
{{/timepointForMember}}
|
||||||
{{/loopEvents}}
|
{{/loopEvents}}
|
||||||
{{#loopEvents ../recent_events}}
|
{{#loopEvents ../recent_events}}
|
||||||
{{#timepointForMember ../this ../../timeline this}}
|
{{#timepointForMember ../this ../../timeline this}}
|
||||||
<td class="availability-on-day past available-status-code-{{this.availability.statusCode}}">
|
<td class="availability-on-day past available-status-code-{{this.availability.statusCode}} {{this.value}} {{#ifEquals @index 0}}first-of-group{{/ifEquals}}{{#ifEquals @index 3}}last-of-group{{/ifEquals}}">
|
||||||
{{this.value}}
|
{{this.value}}
|
||||||
</td>
|
</td>
|
||||||
{{/timepointForMember}}
|
{{/timepointForMember}}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<link rel="stylesheet" href="/css/eventsheet.css">
|
<link rel="stylesheet" href="/css/eventsheet.css">
|
||||||
|
|
||||||
<body class="B5">
|
<body class="{{#if sheet_size}}{{sheet_size}}{{else}}B5{{/if}}">
|
||||||
<div class="sheet eventsheet" id="page-1">
|
<div class="sheet eventsheet {{#if sheet_layout}}{{sheet_layout}}{{else}}quarters{{/if}}" id="page-1">
|
||||||
<section id="defense-card">
|
<section class="NE" id="defense-card">
|
||||||
<header>
|
<header>
|
||||||
<div class="event-title float-left">
|
<div class="event-title float-left">
|
||||||
{{event.formattedTitle}} – {{dateFormat event.startDate "ddd, MMM D h:mm A" }}
|
{{event.formattedTitle}}
|
||||||
</div>
|
</div>
|
||||||
<div class="homeaway float-right">
|
<div class="homeaway float-right">
|
||||||
{{event.gameType}}
|
{{event.gameType}}
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="roster-and-history">
|
<section class="SW" id="roster-and-history">
|
||||||
<div class="roster-and-history">
|
<div class="container">
|
||||||
{{> roster_and_history
|
{{> roster_and_history
|
||||||
event=event
|
event=event
|
||||||
event_lineup_entries=event_lineup_entries
|
event_lineup_entries=event_lineup_entries
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="lineup-card" id="lineup-card-dugout">
|
<section class="NW lineup-card dugout" id="lineup-card-dugout">
|
||||||
<header>
|
<header>
|
||||||
<div class="float-left event-title">{{event.formattedTitle}}</div>
|
<div class="float-left event-title">{{event.formattedTitle}}</div>
|
||||||
<div class="float-right homeaway">{{event.gameType}}</div>
|
<div class="float-right homeaway">{{event.gameType}}</div>
|
||||||
@@ -80,9 +80,9 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="lineup-card" id="lineup-card-exchange">
|
<section class="SE lineup-card exchange" id="lineup-card-exchange">
|
||||||
<header>
|
<header>
|
||||||
<div class="float-left event-title">{{event.formattedTitle}}</div>
|
<div class="float-left event-title">{{event.formattedTitleForMultiTeam}}</div>
|
||||||
<div class="float-right homeaway">{{event.gameType}}</div>
|
<div class="float-right homeaway">{{event.gameType}}</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="starting-lineup-table">
|
<div class="starting-lineup-table">
|
||||||
@@ -119,24 +119,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div class="sheet eventsheet" id="page-2">
|
<div class="sheet eventsheet {{#if sheet_layout}}{{sheet_layout}}{{else}}quarters{{/if}}" id="page-2">
|
||||||
<section id="defense-card" style="border:solid black;">
|
<section class="SE" id="front-cover">
|
||||||
<div id="defense-pane">
|
|
||||||
{{> defense_pane}}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section id="front-cover">
|
|
||||||
<header>
|
<header>
|
||||||
<div class="homeaway">
|
<div class="game-number">
|
||||||
<span>{{firstLetter event.gameType}}</span>
|
{{event.label}}
|
||||||
</div>
|
</div>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<span class="date-time">{{dateFormat event.startDate "ddd, MMM D h:mm A" }}</span>
|
<span class="date-time">{{dateFormat event.startDate "ddd, MMM D h:mm A" }}</span>
|
||||||
<span class="location">{{event.locationName}}</span>
|
<span class="location">{{event.locationName}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="game-number">
|
<div class="homeaway">
|
||||||
<span class="label">Game #</span>
|
<span>{{firstLetter event.gameType}}</span>
|
||||||
<span class="value">XX</span>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div style="display:block;max-height: 1em;background-color: lightgray;border-bottom: solid 2px black;">
|
<div style="display:block;max-height: 1em;background-color: lightgray;border-bottom: solid 2px black;">
|
||||||
@@ -149,10 +143,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{# if event.opponentName}}
|
{{# if event.opponentName}}
|
||||||
<div>
|
<div class="conjuction">
|
||||||
<div style="text-align: center;font-family: 'Pacifico';">
|
|
||||||
<span>vs</span>
|
<span>vs</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="opponent">
|
<div class="opponent">
|
||||||
<div>
|
<div>
|
||||||
@@ -184,7 +176,70 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="lineup-card" id="lineup-card-dugout-blank">
|
<section class="NW blank" id="defense-card">
|
||||||
|
<header>
|
||||||
|
<div class="event-title float-left">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="homeaway float-right">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
<div id="defense-pane">
|
||||||
|
{{> defense_pane event_lineup_entries=null members=null}}
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<table class="notes">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Notes</th>
|
||||||
|
</tr>
|
||||||
|
{{#repeat 3}}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{{/repeat}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="SW lineup-card exchange blank" id="lineup-card-exchange-blank">
|
||||||
|
<header></header>
|
||||||
|
<div class="starting-lineup-table">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">
|
||||||
|
Starting
|
||||||
|
</th>
|
||||||
|
<th class="substitution">
|
||||||
|
Substitution
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#repeat 12}}
|
||||||
|
<tr class="slot">
|
||||||
|
<th class="sequence">
|
||||||
|
</th>
|
||||||
|
<td class="player-name">
|
||||||
|
</td>
|
||||||
|
<td class="jersey-number">
|
||||||
|
</td>
|
||||||
|
<td class="position">
|
||||||
|
</td>
|
||||||
|
<td class="substitution">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{/repeat}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="NE lineup-card dugout blank" id="lineup-card-dugout-blank">
|
||||||
|
<header></header>
|
||||||
<div class="starting-lineup-table">
|
<div class="starting-lineup-table">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
@@ -218,38 +273,5 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="lineup-card" id="lineup-card-exchange-blank">
|
|
||||||
<div class="starting-lineup-table">
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="4">
|
|
||||||
Starting
|
|
||||||
</th>
|
|
||||||
<th class="substitution">
|
|
||||||
Substitution
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{#repeat 12}}
|
|
||||||
<tr class="slot">
|
|
||||||
<th class="sequence">
|
|
||||||
</th>
|
|
||||||
<td class="player-name">
|
|
||||||
</td>
|
|
||||||
<td class="jersey-number">
|
|
||||||
</td>
|
|
||||||
<td class="position">
|
|
||||||
</td>
|
|
||||||
<td class="substitution">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{/repeat}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
248
src/views/eventsheet/sheet_blank.hbs
Normal file
248
src/views/eventsheet/sheet_blank.hbs
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
<link rel="stylesheet" href="/css/eventsheet.css">
|
||||||
|
|
||||||
|
<body class="{{page_size}} ">
|
||||||
|
<div class="sheet eventsheet {{layout}}" id="page-1">
|
||||||
|
<section class="NW" id="roster-and-history">
|
||||||
|
<div class="roster-and-history">
|
||||||
|
{{> roster_and_history
|
||||||
|
event=event
|
||||||
|
event_lineup_entries=event_lineup_entries
|
||||||
|
members=members availabilities=availabilities
|
||||||
|
recent_events=recent_events
|
||||||
|
upcoming_events=upcoming_events
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="NE blank" id="defense-card">
|
||||||
|
<header>
|
||||||
|
<div class="event-title float-left">
|
||||||
|
</div>
|
||||||
|
<div class="homeaway float-right">
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
<div id="defense-pane">
|
||||||
|
{{> defense_pane event_lineup_entries=event_lineup_entries members=members}}
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<table class="notes">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Notes</th>
|
||||||
|
</tr>
|
||||||
|
{{#repeat 3}}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{{/repeat}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="SW lineup-card dugout blank" id="lineup-card-dugout">
|
||||||
|
<header>
|
||||||
|
<div class="float-left event-title">{{event.formattedTitle}}</div>
|
||||||
|
<div class="float-right homeaway">{{event.gameType}}</div>
|
||||||
|
</header>
|
||||||
|
<div class="starting-lineup-table">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">Starting</th>
|
||||||
|
<th class="substitution">Substitution</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#offenseLineup 11 event_lineup_entries members}}
|
||||||
|
<tr class="slot">
|
||||||
|
<th class="sequence{{#if this.member.lastName}} counter{{/if}}"></th>
|
||||||
|
<td class="player-name">{{this.member.lastName}}</td>
|
||||||
|
<td class="jersey-number">{{this.member.jerseyNumber}}</td>
|
||||||
|
<td class="position">{{this.label}}</td>
|
||||||
|
<td class="substitution"></td>
|
||||||
|
</tr>
|
||||||
|
{{/offenseLineup }}
|
||||||
|
{{#defenseLineup event_lineup_entries members}}
|
||||||
|
<tr class="slot">
|
||||||
|
{{#if (isInPositionOnly this.member)}}{{#if (comparePositionWithFlags "P" this.eventLineupEntry)}}
|
||||||
|
<th class="sequence">PO</th>
|
||||||
|
<td class="player-name">{{this.member.lastName}}</td>
|
||||||
|
<td class="jersey-number">{{this.member.jerseyNumber}}</td>
|
||||||
|
<td class="position">{{positionLabelWithoutFlags this.eventLineupEntry.label}}</td>
|
||||||
|
<td class="substitution"></td>
|
||||||
|
{{/if}}{{/if}}
|
||||||
|
</tr>
|
||||||
|
{{/defenseLineup}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="SE lineup-card exchange blank" id="lineup-card-exchange">
|
||||||
|
<header>
|
||||||
|
<div class="float-left event-title">{{event.formattedTitle}}</div>
|
||||||
|
<div class="float-right homeaway">{{event.gameType}}</div>
|
||||||
|
</header>
|
||||||
|
<div class="starting-lineup-table">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">Starting</th>
|
||||||
|
<th class="substitution">Substitution</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#offenseLineup 11 event_lineup_entries members}}
|
||||||
|
<tr class="slot">
|
||||||
|
<th class="sequence {{#if this.member.lastName}}counter{{/if}}"></th>
|
||||||
|
<td class="player-name">{{this.member.lastName}}</td>
|
||||||
|
<td class="jersey-number">{{this.member.jerseyNumber}}</td>
|
||||||
|
<td class="position">{{this.label}}</td>
|
||||||
|
<td class="substitution"></td>
|
||||||
|
</tr>
|
||||||
|
{{/offenseLineup}}
|
||||||
|
{{#defenseLineup event_lineup_entries members}}
|
||||||
|
<tr class="slot">
|
||||||
|
{{#if (isInPositionOnly this.member)}}{{#if (comparePositionWithFlags "P" this.eventLineupEntry)}}
|
||||||
|
<th class="sequence">PO</th>
|
||||||
|
<td class="player-name">{{this.member.lastName}}</td>
|
||||||
|
<td class="jersey-number">{{this.member.jerseyNumber}}</td>
|
||||||
|
<td class="position">{{positionLabelWithoutFlags this.eventLineupEntry.label}}</td>
|
||||||
|
<td class="substitution"></td>
|
||||||
|
{{/if}}{{/if}}
|
||||||
|
</tr>
|
||||||
|
{{/defenseLineup}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="sheet eventsheet {{layout}}" id="page-2">
|
||||||
|
<section class="NW blank" id="defense-card">
|
||||||
|
<header>
|
||||||
|
<div class="event-title float-left">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="homeaway float-right">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
<div id="defense-pane">
|
||||||
|
{{> defense_pane event_lineup_entries=null members=null}}
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<table class="notes">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Notes</th>
|
||||||
|
</tr>
|
||||||
|
{{#repeat 3}}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{{/repeat}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="NE blank" id="defense-card">
|
||||||
|
<header>
|
||||||
|
<div class="event-title float-left">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="homeaway float-right">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
<div id="defense-pane">
|
||||||
|
{{> defense_pane event_lineup_entries=null members=null}}
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<table class="notes">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Notes</th>
|
||||||
|
</tr>
|
||||||
|
{{#repeat 3}}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{{/repeat}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="SW lineup-card exchange blank" id="lineup-card-exchange-blank">
|
||||||
|
<header></header>
|
||||||
|
<div class="starting-lineup-table">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">
|
||||||
|
Starting
|
||||||
|
</th>
|
||||||
|
<th class="substitution">
|
||||||
|
Substitution
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#repeat 12}}
|
||||||
|
<tr class="slot">
|
||||||
|
<th class="sequence">
|
||||||
|
</th>
|
||||||
|
<td class="player-name">
|
||||||
|
</td>
|
||||||
|
<td class="jersey-number">
|
||||||
|
</td>
|
||||||
|
<td class="position">
|
||||||
|
</td>
|
||||||
|
<td class="substitution">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{/repeat}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="SE lineup-card dugout blank" id="lineup-card-dugout-blank">
|
||||||
|
<header></header>
|
||||||
|
<div class="starting-lineup-table">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">
|
||||||
|
Starting
|
||||||
|
</th>
|
||||||
|
<th class="substitution">
|
||||||
|
Substitution
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{!-- <% for i in (0...12) do%> --}}
|
||||||
|
{{#repeat 12}}
|
||||||
|
<tr class="slot">
|
||||||
|
<th class="sequence">
|
||||||
|
</th>
|
||||||
|
<td class="player-name">
|
||||||
|
</td>
|
||||||
|
<td class="jersey-number">
|
||||||
|
</td>
|
||||||
|
<td class="position">
|
||||||
|
</td>
|
||||||
|
<td class="substitution">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{/repeat}}
|
||||||
|
{{!-- <% end %> --}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
26
src/views/modal_confirm.hbs
Normal file
26
src/views/modal_confirm.hbs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<div id="modal" class="Modal Modal--clickableBg">
|
||||||
|
<div class="Modal-content">
|
||||||
|
<div onclick="javascript:this.closest('.Modal').remove();">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg" "Modal-iconDismiss"}}}</div>
|
||||||
|
<div class="Modal-header">
|
||||||
|
<div class="Modal-title">{{title}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="Modal-body">
|
||||||
|
{{body}}
|
||||||
|
</div>
|
||||||
|
<div class="Modal-footer">
|
||||||
|
<button class="Button Button--negative" role="button" type="button" onclick="javascript:this.closest('.Modal').remove();" data-confirm="cancel">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button class="Button Button--primary" role="button" type="button" data-confirm="yes">
|
||||||
|
<span class="hideOnLoading">Yes</span>
|
||||||
|
<span id="success-icon" class="u-hidden showOnSuccess">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/check.svg"}}}</span>
|
||||||
|
<span id="failure-icon" class="u-hidden showOnFailure">{{{embeddedSvgFromPath "/teamsnap-ui/assets/icons/dismiss.svg"}}}</span>
|
||||||
|
<span class="PulseAnimation showOnLoading u-hidden">
|
||||||
|
<span class="PulseAnimation-dot"></span>
|
||||||
|
<span class="PulseAnimation-dot"></span>
|
||||||
|
<span class="PulseAnimation-dot"></span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user