Deno #6
No files matched your search
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"deploy": {
|
||||||
|
"project": "7a93d03e-eabe-4db1-b78e-5f1bbcb460b0",
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules"
|
||||||
|
],
|
||||||
|
"include": [],
|
||||||
|
"entrypoint": "server.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
{
|
||||||
|
"version": "3",
|
||||||
|
"packages": {
|
||||||
|
"specifiers": {
|
||||||
|
"jsr:@oak/commons@0.11": "jsr:@oak/commons@0.11.0",
|
||||||
|
"jsr:@oak/oak": "jsr:@oak/oak@16.1.0",
|
||||||
|
"jsr:@std/assert@0.223": "jsr:@std/assert@0.223.0",
|
||||||
|
"jsr:@std/assert@0.226": "jsr:@std/assert@0.226.0",
|
||||||
|
"jsr:@std/assert@^0.223.0": "jsr:@std/assert@0.223.0",
|
||||||
|
"jsr:@std/assert@^0.224.0": "jsr:@std/assert@0.224.0",
|
||||||
|
"jsr:@std/bytes@0.223": "jsr:@std/bytes@0.223.0",
|
||||||
|
"jsr:@std/bytes@0.224": "jsr:@std/bytes@0.224.0",
|
||||||
|
"jsr:@std/bytes@^0.223.0": "jsr:@std/bytes@0.223.0",
|
||||||
|
"jsr:@std/crypto@0.223": "jsr:@std/crypto@0.223.0",
|
||||||
|
"jsr:@std/crypto@0.224": "jsr:@std/crypto@0.224.0",
|
||||||
|
"jsr:@std/encoding@1.0.0-rc.2": "jsr:@std/encoding@1.0.0-rc.2",
|
||||||
|
"jsr:@std/encoding@^0.223.0": "jsr:@std/encoding@0.223.0",
|
||||||
|
"jsr:@std/http@0.223": "jsr:@std/http@0.223.0",
|
||||||
|
"jsr:@std/http@0.224": "jsr:@std/http@0.224.5",
|
||||||
|
"jsr:@std/io@0.223": "jsr:@std/io@0.223.0",
|
||||||
|
"jsr:@std/media-types@0.223": "jsr:@std/media-types@0.223.0",
|
||||||
|
"jsr:@std/media-types@0.224": "jsr:@std/media-types@0.224.1",
|
||||||
|
"jsr:@std/path@0.223": "jsr:@std/path@0.223.0",
|
||||||
|
"npm:path-to-regexp@6.2.1": "npm:path-to-regexp@6.2.1"
|
||||||
|
},
|
||||||
|
"jsr": {
|
||||||
|
"@oak/commons@0.11.0": {
|
||||||
|
"integrity": "07702bfe5c07cd8144c422022994da1f9fea466b185824f4be63a2b1b1a65125",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/assert@0.226",
|
||||||
|
"jsr:@std/bytes@0.224",
|
||||||
|
"jsr:@std/crypto@0.224",
|
||||||
|
"jsr:@std/http@0.224",
|
||||||
|
"jsr:@std/media-types@0.224"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@oak/oak@16.1.0": {
|
||||||
|
"integrity": "ab21506555fffeb08dc8f45ff5d28607e8087949ff58bd2964b27df65994480b",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@oak/commons@0.11",
|
||||||
|
"jsr:@std/assert@0.223",
|
||||||
|
"jsr:@std/bytes@0.223",
|
||||||
|
"jsr:@std/crypto@0.223",
|
||||||
|
"jsr:@std/http@0.223",
|
||||||
|
"jsr:@std/io@0.223",
|
||||||
|
"jsr:@std/media-types@0.223",
|
||||||
|
"jsr:@std/path@0.223",
|
||||||
|
"npm:path-to-regexp@6.2.1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@std/assert@0.223.0": {
|
||||||
|
"integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24"
|
||||||
|
},
|
||||||
|
"@std/assert@0.224.0": {
|
||||||
|
"integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f"
|
||||||
|
},
|
||||||
|
"@std/assert@0.226.0": {
|
||||||
|
"integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3"
|
||||||
|
},
|
||||||
|
"@std/bytes@0.223.0": {
|
||||||
|
"integrity": "84b75052cd8680942c397c2631318772b295019098f40aac5c36cead4cba51a8"
|
||||||
|
},
|
||||||
|
"@std/bytes@0.224.0": {
|
||||||
|
"integrity": "a2250e1d0eb7d1c5a426f21267ab9bdeac2447fa87a3d0d1a467d3f7a6058e49"
|
||||||
|
},
|
||||||
|
"@std/crypto@0.223.0": {
|
||||||
|
"integrity": "1aa9555ff56b09e197ad988ea200f84bc6781fd4fd83f3a156ee44449af93000",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/assert@^0.223.0",
|
||||||
|
"jsr:@std/encoding@^0.223.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@std/crypto@0.224.0": {
|
||||||
|
"integrity": "154ef3ff08ef535562ef1a718718c5b2c5fc3808f0f9100daad69e829bfcdf2d",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/assert@^0.224.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@std/encoding@0.223.0": {
|
||||||
|
"integrity": "2b5615a75e00337ce113f34cf2f9b8c18182c751a8dcc8b1a2c2fc0e117bef00"
|
||||||
|
},
|
||||||
|
"@std/encoding@1.0.0-rc.2": {
|
||||||
|
"integrity": "160d7674a20ebfbccdf610b3801fee91cf6e42d1c106dd46bbaf46e395cd35ef"
|
||||||
|
},
|
||||||
|
"@std/http@0.223.0": {
|
||||||
|
"integrity": "15ab8a0c5a7e9d5be017a15b01600f20f66602ceec48b378939fa24fcec522aa",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/assert@^0.223.0",
|
||||||
|
"jsr:@std/encoding@^0.223.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@std/http@0.224.5": {
|
||||||
|
"integrity": "b03b5d1529f6c423badfb82f6640f9f2557b4034cd7c30655ba5bb447ff750a4",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/encoding@1.0.0-rc.2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@std/io@0.223.0": {
|
||||||
|
"integrity": "2d8c3c2ab3a515619b90da2c6ff5ea7b75a94383259ef4d02116b228393f84f1",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/bytes@^0.223.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@std/media-types@0.223.0": {
|
||||||
|
"integrity": "84684680c2eb6bc6d9369c6d6f26a49decaf2c7603ff531862dda575d9d6776e"
|
||||||
|
},
|
||||||
|
"@std/media-types@0.224.1": {
|
||||||
|
"integrity": "9e69a5daed37c5b5c6d3ce4731dc191f80e67f79bed392b0957d1d03b87f11e1"
|
||||||
|
},
|
||||||
|
"@std/path@0.223.0": {
|
||||||
|
"integrity": "593963402d7e6597f5a6e620931661053572c982fc014000459edc1f93cc3989",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/assert@^0.223.0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"path-to-regexp@6.2.1": {
|
||||||
|
"integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==",
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"https://deno.land/std@0.205.0/assert/assert.ts": "9a97dad6d98c238938e7540736b826440ad8c1c1e54430ca4c4e623e585607ee",
|
||||||
|
"https://deno.land/std@0.205.0/assert/assertion_error.ts": "4d0bde9b374dfbcbe8ac23f54f567b77024fb67dbb1906a852d67fe050d42f56",
|
||||||
|
"https://deno.land/std@0.205.0/html/entities.ts": "43f208131bb847e6e222c9dd50322066491da93ed945a93d778923ef7e975398",
|
||||||
|
"https://deno.land/std@0.205.0/html/mod.ts": "3f8c71781e32037ab63bd417759d15d31fb9606c6615c85dcabcc515986494ba",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/assert_path.ts": "061e4d093d4ba5aebceb2c4da3318bfe3289e868570e9d3a8e327d91c2958946",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/basename.ts": "0d978ff818f339cd3b1d09dc914881f4d15617432ae519c1b8fdc09ff8d3789a",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/common.ts": "9e4233b2eeb50f8b2ae10ecc2108f58583aea6fd3e8907827020282dc2b76143",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/dirname.ts": "2ba7fb4cc9fafb0f38028f434179579ce61d4d9e51296fad22b701c3d3cd7397",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/format.ts": "11aa62e316dfbf22c126917f5e03ea5fe2ee707386555a8f513d27ad5756cf96",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/from_file_url.ts": "ef1bf3197d2efbf0297a2bdbf3a61d804b18f2bcce45548ae112313ec5be3c22",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/glob_to_reg_exp.ts": "5c3c2b79fc2294ec803d102bd9855c451c150021f452046312819fbb6d4dc156",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/is_glob.ts": "567dce5c6656bdedfc6b3ee6c0833e1e4db2b8dff6e62148e94a917f289c06ad",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/normalize.ts": "2ba7fb4cc9fafb0f38028f434179579ce61d4d9e51296fad22b701c3d3cd7397",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/normalize_string.ts": "88c472f28ae49525f9fe82de8c8816d93442d46a30d6bb5063b07ff8a89ff589",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/relative.ts": "1af19d787a2a84b8c534cc487424fe101f614982ae4851382c978ab2216186b4",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/strip_trailing_separators.ts": "7ffc7c287e97bdeeee31b155828686967f222cd73f9e5780bfe7dfb1b58c6c65",
|
||||||
|
"https://deno.land/std@0.205.0/path/_common/to_file_url.ts": "a8cdd1633bc9175b7eebd3613266d7c0b6ae0fb0cff24120b6092ac31662f9ae",
|
||||||
|
"https://deno.land/std@0.205.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b",
|
||||||
|
"https://deno.land/std@0.205.0/path/_os.ts": "30b0c2875f360c9296dbe6b7f2d528f0f9c741cecad2e97f803f5219e91b40a2",
|
||||||
|
"https://deno.land/std@0.205.0/path/basename.ts": "04bb5ef3e86bba8a35603b8f3b69537112cdd19ce64b77f2522006da2977a5f3",
|
||||||
|
"https://deno.land/std@0.205.0/path/common.ts": "f4d061c7d0b95a65c2a1a52439edec393e906b40f1caf4604c389fae7caa80f5",
|
||||||
|
"https://deno.land/std@0.205.0/path/dirname.ts": "88a0a71c21debafc4da7a4cd44fd32e899462df458fbca152390887d41c40361",
|
||||||
|
"https://deno.land/std@0.205.0/path/extname.ts": "2da4e2490f3b48b7121d19fb4c91681a5e11bd6bd99df4f6f47d7a71bb6ecdf2",
|
||||||
|
"https://deno.land/std@0.205.0/path/format.ts": "3457530cc85d1b4bab175f9ae73998b34fd456c830d01883169af0681b8894fb",
|
||||||
|
"https://deno.land/std@0.205.0/path/from_file_url.ts": "e7fa233ea1dff9641e8d566153a24d95010110185a6f418dd2e32320926043f8",
|
||||||
|
"https://deno.land/std@0.205.0/path/glob.ts": "9c77cf47db1d786e2ebf66670824d03fd84ecc7c807cac24441eb9d5cb6a2986",
|
||||||
|
"https://deno.land/std@0.205.0/path/is_absolute.ts": "67232b41b860571c5b7537f4954c88d86ae2ba45e883ee37d3dec27b74909d13",
|
||||||
|
"https://deno.land/std@0.205.0/path/join.ts": "98d3d76c819af4a11a81d5ba2dbb319f1ce9d63fc2b615597d4bcfddd4a89a09",
|
||||||
|
"https://deno.land/std@0.205.0/path/mod.ts": "2d62a0a8b78a60e8e6f485d881bac6b61d58573b11cf585fb7c8fc50d9b20d80",
|
||||||
|
"https://deno.land/std@0.205.0/path/normalize.ts": "aa95be9a92c7bd4f9dc0ba51e942a1973e2b93d266cd74f5ca751c136d520b66",
|
||||||
|
"https://deno.land/std@0.205.0/path/parse.ts": "d87ff0deef3fb495bc0d862278ff96da5a06acf0625ca27769fc52ac0d3d6ece",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/_util.ts": "ecf49560fedd7dd376c6156cc5565cad97c1abe9824f4417adebc7acc36c93e5",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/basename.ts": "a630aeb8fd8e27356b1823b9dedd505e30085015407caa3396332752f6b8406a",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/common.ts": "e781d395dc76f6282e3f7dd8de13194abb8b04a82d109593141abc6e95755c8b",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/dirname.ts": "f48c9c42cc670803b505478b7ef162c7cfa9d8e751b59d278b2ec59470531472",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/extname.ts": "ee7f6571a9c0a37f9218fbf510c440d1685a7c13082c348d701396cc795e0be0",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/format.ts": "b94876f77e61bfe1f147d5ccb46a920636cd3cef8be43df330f0052b03875968",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/from_file_url.ts": "b97287a83e6407ac27bdf3ab621db3fccbf1c27df0a1b1f20e1e1b5acf38a379",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/glob.ts": "86c3f06d1c98303613c74650961c3e24bdb871cde2a97c3ae7f0f6d4abbef445",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/is_absolute.ts": "159900a3422d11069d48395568217eb7fc105ceda2683d03d9b7c0f0769e01b8",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/join.ts": "0c0d84bdc344876930126640011ec1b888e6facf74153ffad9ef26813aa2a076",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/mod.ts": "6bfa8a42d85345b12dbe8571028ca2c62d460b6ef968125e498602b43b6cf6b6",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/normalize.ts": "11de90a94ab7148cc46e5a288f7d732aade1d616bc8c862f5560fa18ff987b4b",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/parse.ts": "199208f373dd93a792e9c585352bfc73a6293411bed6da6d3bc4f4ef90b04c8e",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/relative.ts": "e2f230608b0f083e6deaa06e063943e5accb3320c28aef8d87528fbb7fe6504c",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/resolve.ts": "51579d83159d5c719518c9ae50812a63959bbcb7561d79acbdb2c3682236e285",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/separator.ts": "0b6573b5f3269a3164d8edc9cefc33a02dd51003731c561008c8bb60220ebac1",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/to_file_url.ts": "08d43ea839ee75e9b8b1538376cfe95911070a655cd312bc9a00f88ef14967b6",
|
||||||
|
"https://deno.land/std@0.205.0/path/posix/to_namespaced_path.ts": "c9228a0e74fd37e76622cd7b142b8416663a9b87db643302fa0926b5a5c83bdc",
|
||||||
|
"https://deno.land/std@0.205.0/path/relative.ts": "23d45ede8b7ac464a8299663a43488aad6b561414e7cbbe4790775590db6349c",
|
||||||
|
"https://deno.land/std@0.205.0/path/resolve.ts": "5b184efc87155a0af9fa305ff68a109e28de9aee81fc3e77cd01380f19daf867",
|
||||||
|
"https://deno.land/std@0.205.0/path/separator.ts": "40a3e9a4ad10bef23bc2cd6c610291b6c502a06237c2c4cd034a15ca78dedc1f",
|
||||||
|
"https://deno.land/std@0.205.0/path/to_file_url.ts": "edaafa089e0bce386e1b2d47afe7c72e379ff93b28a5829a5885e4b6c626d864",
|
||||||
|
"https://deno.land/std@0.205.0/path/to_namespaced_path.ts": "cf8734848aac3c7527d1689d2adf82132b1618eff3cc523a775068847416b22a",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/_util.ts": "f32b9444554c8863b9b4814025c700492a2b57ff2369d015360970a1b1099d54",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/basename.ts": "8a9dbf7353d50afbc5b221af36c02a72c2d1b2b5b9f7c65bf6a5a2a0baf88ad3",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/common.ts": "e781d395dc76f6282e3f7dd8de13194abb8b04a82d109593141abc6e95755c8b",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/dirname.ts": "5c2aa541384bf0bd9aca821275d2a8690e8238fa846198ef5c7515ce31a01a94",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/extname.ts": "07f4fa1b40d06a827446b3e3bcc8d619c5546b079b8ed0c77040bbef716c7614",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/format.ts": "343019130d78f172a5c49fdc7e64686a7faf41553268961e7b6c92a6d6548edf",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/from_file_url.ts": "d53335c12b0725893d768be3ac6bf0112cc5b639d2deb0171b35988493b46199",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/glob.ts": "0286fb89ecd21db5cbf3b6c79e2b87c889b03f1311e66fb769e6b905d4142332",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/is_absolute.ts": "245b56b5f355ede8664bd7f080c910a97e2169972d23075554ae14d73722c53c",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/join.ts": "e6600bf88edeeef4e2276e155b8de1d5dec0435fd526ba2dc4d37986b2882f16",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/mod.ts": "c3d1a36fbf9f6db1320bcb4fbda8de011d25461be3497105e15cbea1e3726198",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/normalize.ts": "9deebbf40c81ef540b7b945d4ccd7a6a2c5a5992f791e6d3377043031e164e69",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/parse.ts": "120faf778fe1f22056f33ded069b68e12447668fcfa19540c0129561428d3ae5",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/relative.ts": "026855cd2c36c8f28f1df3c6fbd8f2449a2aa21f48797a74700c5d872b86d649",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/resolve.ts": "5ff441ab18a2346abadf778121128ee71bda4d0898513d4639a6ca04edca366b",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/separator.ts": "ae21f27015f10510ed1ac4a0ba9c4c9c967cbdd9d9e776a3e4967553c397bd5d",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/to_file_url.ts": "8e9ea9e1ff364aa06fa72999204229952d0a279dbb876b7b838b2b2fea55cce3",
|
||||||
|
"https://deno.land/std@0.205.0/path/windows/to_namespaced_path.ts": "e0f4d4a5e77f28a5708c1a33ff24360f35637ba6d8f103d19661255ef7bfd50d",
|
||||||
|
"https://deno.land/std@0.224.0/assert/_constants.ts": "a271e8ef5a573f1df8e822a6eb9d09df064ad66a4390f21b3e31f820a38e0975",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert.ts": "09d30564c09de846855b7b071e62b5974b001bb72a4b797958fe0660e7849834",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_almost_equals.ts": "9e416114322012c9a21fa68e187637ce2d7df25bcbdbfd957cd639e65d3cf293",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_array_includes.ts": "14c5094471bc8e4a7895fc6aa5a184300d8a1879606574cb1cd715ef36a4a3c7",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_equals.ts": "3bbca947d85b9d374a108687b1a8ba3785a7850436b5a8930d81f34a32cb8c74",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_exists.ts": "43420cf7f956748ae6ed1230646567b3593cb7a36c5a5327269279c870c5ddfd",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_false.ts": "3e9be8e33275db00d952e9acb0cd29481a44fa0a4af6d37239ff58d79e8edeff",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_greater.ts": "5e57b201fd51b64ced36c828e3dfd773412c1a6120c1a5a99066c9b261974e46",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_greater_or_equal.ts": "9870030f997a08361b6f63400273c2fb1856f5db86c0c3852aab2a002e425c5b",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_instance_of.ts": "e22343c1fdcacfaea8f37784ad782683ec1cf599ae9b1b618954e9c22f376f2c",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_is_error.ts": "f856b3bc978a7aa6a601f3fec6603491ab6255118afa6baa84b04426dd3cc491",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_less.ts": "60b61e13a1982865a72726a5fa86c24fad7eb27c3c08b13883fb68882b307f68",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_less_or_equal.ts": "d2c84e17faba4afe085e6c9123a63395accf4f9e00150db899c46e67420e0ec3",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_match.ts": "ace1710dd3b2811c391946954234b5da910c5665aed817943d086d4d4871a8b7",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_not_equals.ts": "78d45dd46133d76ce624b2c6c09392f6110f0df9b73f911d20208a68dee2ef29",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_not_instance_of.ts": "3434a669b4d20cdcc5359779301a0588f941ffdc2ad68803c31eabdb4890cf7a",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_not_match.ts": "df30417240aa2d35b1ea44df7e541991348a063d9ee823430e0b58079a72242a",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_not_strict_equals.ts": "37f73880bd672709373d6dc2c5f148691119bed161f3020fff3548a0496f71b8",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_object_match.ts": "411450fd194fdaabc0089ae68f916b545a49d7b7e6d0026e84a54c9e7eed2693",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_rejects.ts": "4bee1d6d565a5b623146a14668da8f9eb1f026a4f338bbf92b37e43e0aa53c31",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_strict_equals.ts": "b4f45f0fd2e54d9029171876bd0b42dd9ed0efd8f853ab92a3f50127acfa54f5",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_string_includes.ts": "496b9ecad84deab72c8718735373feb6cdaa071eb91a98206f6f3cb4285e71b8",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assert_throws.ts": "c6508b2879d465898dab2798009299867e67c570d7d34c90a2d235e4553906eb",
|
||||||
|
"https://deno.land/std@0.224.0/assert/assertion_error.ts": "ba8752bd27ebc51f723702fac2f54d3e94447598f54264a6653d6413738a8917",
|
||||||
|
"https://deno.land/std@0.224.0/assert/equal.ts": "bddf07bb5fc718e10bb72d5dc2c36c1ce5a8bdd3b647069b6319e07af181ac47",
|
||||||
|
"https://deno.land/std@0.224.0/assert/fail.ts": "0eba674ffb47dff083f02ced76d5130460bff1a9a68c6514ebe0cdea4abadb68",
|
||||||
|
"https://deno.land/std@0.224.0/assert/mod.ts": "48b8cb8a619ea0b7958ad7ee9376500fe902284bb36f0e32c598c3dc34cbd6f3",
|
||||||
|
"https://deno.land/std@0.224.0/assert/unimplemented.ts": "8c55a5793e9147b4f1ef68cd66496b7d5ba7a9e7ca30c6da070c1a58da723d73",
|
||||||
|
"https://deno.land/std@0.224.0/assert/unreachable.ts": "5ae3dbf63ef988615b93eb08d395dda771c96546565f9e521ed86f6510c29e19",
|
||||||
|
"https://deno.land/std@0.224.0/fmt/colors.ts": "508563c0659dd7198ba4bbf87e97f654af3c34eb56ba790260f252ad8012e1c5",
|
||||||
|
"https://deno.land/std@0.224.0/internal/diff.ts": "6234a4b493ebe65dc67a18a0eb97ef683626a1166a1906232ce186ae9f65f4e6",
|
||||||
|
"https://deno.land/std@0.224.0/internal/format.ts": "0a98ee226fd3d43450245b1844b47003419d34d210fa989900861c79820d21c2",
|
||||||
|
"https://deno.land/std@0.224.0/internal/mod.ts": "534125398c8e7426183e12dc255bb635d94e06d0f93c60a297723abe69d3b22e",
|
||||||
|
"https://deno.land/std@0.84.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58",
|
||||||
|
"https://deno.land/std@0.84.0/_util/os.ts": "e282950a0eaa96760c0cf11e7463e66babd15ec9157d4c9ed49cc0925686f6a7",
|
||||||
|
"https://deno.land/std@0.84.0/path/_constants.ts": "1247fee4a79b70c89f23499691ef169b41b6ccf01887a0abd131009c5581b853",
|
||||||
|
"https://deno.land/std@0.84.0/path/_interface.ts": "1fa73b02aaa24867e481a48492b44f2598cd9dfa513c7b34001437007d3642e4",
|
||||||
|
"https://deno.land/std@0.84.0/path/_util.ts": "f4fa69aa3cbbd8568763bfc43c7236875015ba343602d8bafd332b4b4243681b",
|
||||||
|
"https://deno.land/std@0.84.0/path/common.ts": "eaf03d08b569e8a87e674e4e265e099f237472b6fd135b3cbeae5827035ea14a",
|
||||||
|
"https://deno.land/std@0.84.0/path/glob.ts": "4a524c1c9da3e79a9fdabdc6e850cd9e41bdf31e442856ffa19c5b123268ca95",
|
||||||
|
"https://deno.land/std@0.84.0/path/mod.ts": "4465dc494f271b02569edbb4a18d727063b5dbd6ed84283ff906260970a15d12",
|
||||||
|
"https://deno.land/std@0.84.0/path/posix.ts": "1408f8ba482a4dc5fc0a7cd7be28bbbff9608d2b3b5ffdcf288ae1228d959add",
|
||||||
|
"https://deno.land/std@0.84.0/path/separator.ts": "8fdcf289b1b76fd726a508f57d3370ca029ae6976fcde5044007f062e643ff1c",
|
||||||
|
"https://deno.land/std@0.84.0/path/win32.ts": "6ca052f54500f00cd7a5172fde62900626ab620dcd5bdcf4e6f5695d001ddef6",
|
||||||
|
"https://deno.land/std@0.99.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58",
|
||||||
|
"https://deno.land/std@0.99.0/_util/os.ts": "e282950a0eaa96760c0cf11e7463e66babd15ec9157d4c9ed49cc0925686f6a7",
|
||||||
|
"https://deno.land/std@0.99.0/path/_constants.ts": "1247fee4a79b70c89f23499691ef169b41b6ccf01887a0abd131009c5581b853",
|
||||||
|
"https://deno.land/std@0.99.0/path/_interface.ts": "1fa73b02aaa24867e481a48492b44f2598cd9dfa513c7b34001437007d3642e4",
|
||||||
|
"https://deno.land/std@0.99.0/path/_util.ts": "2e06a3b9e79beaf62687196bd4b60a4c391d862cfa007a20fc3a39f778ba073b",
|
||||||
|
"https://deno.land/std@0.99.0/path/common.ts": "eaf03d08b569e8a87e674e4e265e099f237472b6fd135b3cbeae5827035ea14a",
|
||||||
|
"https://deno.land/std@0.99.0/path/glob.ts": "314ad9ff263b895795208cdd4d5e35a44618ca3c6dd155e226fb15d065008652",
|
||||||
|
"https://deno.land/std@0.99.0/path/mod.ts": "4465dc494f271b02569edbb4a18d727063b5dbd6ed84283ff906260970a15d12",
|
||||||
|
"https://deno.land/std@0.99.0/path/posix.ts": "f56c3c99feb47f30a40ce9d252ef6f00296fa7c0fcb6dd81211bdb3b8b99ca3b",
|
||||||
|
"https://deno.land/std@0.99.0/path/separator.ts": "8fdcf289b1b76fd726a508f57d3370ca029ae6976fcde5044007f062e643ff1c",
|
||||||
|
"https://deno.land/std@0.99.0/path/win32.ts": "77f7b3604e0de40f3a7c698e8a79e7f601dc187035a1c21cb1e596666ce112f8",
|
||||||
|
"https://deno.land/x/media_types@v2.7.1/db.ts": "1d95aa3fc1fe076638550640609394f0e157b18b430800e419aa7ece5c151d9c",
|
||||||
|
"https://deno.land/x/media_types@v2.7.1/deps.ts": "cd4c31e4b5ed8c4d8c61bd2fb38a82d68d3fd2dcf6d43f22511cbe6d9d310e51",
|
||||||
|
"https://deno.land/x/media_types@v2.7.1/mod.ts": "d63583b978d32eff8b76e1ae5d83cba2fb27baa90cc1bcb0ad15a06122ea8c19",
|
||||||
|
"https://deno.land/x/static_files@1.1.6/mod.ts": "8a9bb05599e53864c54eb22931fe98507818517e0d69f26e099a1d8f4ef2b638",
|
||||||
|
"https://deno.land/x/static_files@1.1.6/src/deps.ts": "fb62be7a780339157bf692a619d6d02ea9662490deca275f488f9f9db917fc4a",
|
||||||
|
"https://deno.land/x/static_files@1.1.6/src/types.ts": "ef201288626294e9e1b8ee85cdfe2cdfb282e4d78af445df1726050dfa0c0988",
|
||||||
|
"https://deno.land/x/static_files@1.1.6/src/utils.ts": "9e6172dc97fed01e70a6b063c5afff40e20fe726b3bae0c5f0a962bad74b7107",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/deps.ts": "1fb4acd6b3b6261c308280b09e8feadac7b0fac1e01bd0e0f1e75527a2181a52",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/mod.ts": "ab690911075158ee3762bd7aefe209cdcb6ead7b492f14b0693d7025244db8e6",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/echo.ts": "f7c064fb6d34b29852f46f6e01583ed87656dcbbc5cae51c8f29198d6951d0cf",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/escape.ts": "8115ec84c84c13811f4a43263b8954e912df94df6565d6ff9ce7faea7daa50be",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/export.ts": "ef54811ed0205aaeef6ad09557c94b8ae98e1457234898da5a1c5461a7dcf424",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/for.ts": "6313e139a23ed17ca8b0852031f8d9e11aeb7520b228e68b9233418d25745414",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/function.ts": "cdf610a98493e4a093c53473abdad7d47cbcff40aa8362d280e39910620cb8d6",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/if.ts": "9de295f8675cacaec7866ad21068b6b089bfcadf72d3c62e1df50ca378c04279",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/import.ts": "406204ab9d785db206da5d5cbcffa9a111cef2a39a19574e630cdea89b0691c5",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/include.ts": "a9c65ce90354766220c0c9f7b21ea2db97bed99d9ffbe28f8a5ac035d488b163",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/js.ts": "2c50d60061e9c5b6280a145266e617181534b8767e91127d59d5cf5febdcfb03",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/layout.ts": "b9970b762ba73cf5605e63e585792803a48e326621c6cb2ec216502ba21a90cd",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/set.ts": "016235a906f99cbfab78d29dfdfe8ca0925db7a46458fd873adacd0d7c6ed82d",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/plugins/unescape.ts": "946512835a409815d6ad98ac4529440e9a368f42ca499791d0f25ee0ecc4c4d6",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/src/environment.ts": "9c28fbf05176297adb93fc688711125b295c69089554d4211cd38a5b04028ec5",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/src/loader.ts": "eb01b0dca7ea8bcdcdfd30b1f90f2fad28fb7f2cfd943900322a85bfaa86130c",
|
||||||
|
"https://deno.land/x/vento@v0.9.1/src/tokenizer.ts": "e9918ac58f941e048fe08cea10e65fb6e19c00fe7ed31fb050663445f11c6e9d",
|
||||||
|
"https://esm.sh/lodash-es@4.17.21": "460848e64379750386465df2bfcbe530dc5be584cabb39816e0dec105e5f9af2",
|
||||||
|
"https://esm.sh/v135/lodash-es@4.17.21/denonext/lodash-es.mjs": "ca6d37e6a1271d1bd8920da5ff11f7d05465f5d7961d5d09b44db331838981d7"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
exec deno run -A https://deno.land/x/deploy/deployctl.ts deploy --prod --project=phenix server.ts
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
hello {{ title }}
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
import { Application } from "jsr:@oak/oak/application";
|
||||||
|
import { Router } from "jsr:@oak/oak/router";
|
||||||
|
import { GameService } from "./server/game-service.ts";
|
||||||
|
import { Game } from "./server/types.ts";
|
||||||
|
import staticFiles from "https://deno.land/x/static_files@1.1.6/mod.ts";
|
||||||
|
import vento from "https://deno.land/x/vento@v0.9.1/mod.ts";
|
||||||
|
import { LoginService } from "./server/login-service.ts";
|
||||||
|
|
||||||
|
const env = vento();
|
||||||
|
setInterval(() => env.cache.clear(), 1000);
|
||||||
|
const gameService = new GameService(await Deno.openKv());
|
||||||
|
const loginService = LoginService.officialLoginService();
|
||||||
|
|
||||||
|
const router = new Router();
|
||||||
|
|
||||||
|
router.get("/", async (ctx) => {
|
||||||
|
const template = await env.load("templates/home.vto");
|
||||||
|
const result = await template({ tab: "home" });
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/calendrier", async (ctx) => {
|
||||||
|
const template = await env.load("templates/calendrier.vto");
|
||||||
|
const result = await template({
|
||||||
|
tab: "calendrier",
|
||||||
|
});
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/nouvelles", async (ctx) => {
|
||||||
|
const template = await env.load("templates/nouvelles.vto");
|
||||||
|
const result = await template({ tab: "nouvelles" });
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/contact", async (ctx) => {
|
||||||
|
const template = await env.load("templates/contact.vto");
|
||||||
|
const result = await template({ tab: "contact" });
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/reglement", async (ctx) => {
|
||||||
|
const template = await env.load("templates/reglement.vto");
|
||||||
|
const result = await template({ tab: "reglement" });
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/login", async (ctx) => {
|
||||||
|
const username = ctx.request.url.searchParams.get("username") || "";
|
||||||
|
const password = ctx.request.url.searchParams.get("password") || "";
|
||||||
|
|
||||||
|
if (!(await loginService.validateCredentials(username, password))) {
|
||||||
|
ctx.response.status = 403;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await loginService.login(ctx);
|
||||||
|
ctx.response.redirect("/membre/games-editor/today");
|
||||||
|
});
|
||||||
|
|
||||||
|
const memberRouter = new Router();
|
||||||
|
|
||||||
|
memberRouter.use(async (ctx, next) => {
|
||||||
|
const isLoggedIn = await loginService.isLoggedIn(ctx);
|
||||||
|
if (ctx.request.url.pathname !== "/membre" && !isLoggedIn) {
|
||||||
|
ctx.response.redirect("/membre");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.params.isLoggedIn = isLoggedIn;
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
memberRouter.get("/", async (ctx) => {
|
||||||
|
const template = await env.load("templates/membre.vto");
|
||||||
|
const result = await template({
|
||||||
|
tab: "membre",
|
||||||
|
isLoggedIn: ctx.params.isLoggedIn,
|
||||||
|
});
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
function today(): Date {
|
||||||
|
const date = new Date().toLocaleDateString("fr-CA", {
|
||||||
|
timeZone: "America/New_York",
|
||||||
|
});
|
||||||
|
return new Date(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
memberRouter.get("/games-editor/today", async (ctx) => {
|
||||||
|
const template = await env.load("templates/partials/games-editor.vto");
|
||||||
|
const games = await gameService.getAllGames();
|
||||||
|
const lastGameDay = games
|
||||||
|
.map((g) => g.date)
|
||||||
|
.filter((d) => new Date(d) <= today())
|
||||||
|
.sort()
|
||||||
|
.reverse()[0];
|
||||||
|
|
||||||
|
const result = await template({
|
||||||
|
tab: "membre",
|
||||||
|
selectedYear: null,
|
||||||
|
isToday: true,
|
||||||
|
games: games.filter((g) => g.date === lastGameDay),
|
||||||
|
years: [...new Set(games.map((x) => x.year))].sort().reverse(),
|
||||||
|
});
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
memberRouter.get("/games-editor/:year", async (ctx) => {
|
||||||
|
const template = await env.load("templates/partials/games-editor.vto");
|
||||||
|
const games = await gameService.getAllGames();
|
||||||
|
const selectedYear = parseInt(ctx.params.year);
|
||||||
|
const result = await template({
|
||||||
|
tab: "membre",
|
||||||
|
selectedYear: selectedYear,
|
||||||
|
games: games.filter((g) => g.year === selectedYear),
|
||||||
|
years: [...new Set(games.map((x) => x.year))].sort().reverse(),
|
||||||
|
});
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
memberRouter.get("/new-game-editor", async (ctx) => {
|
||||||
|
const template = await env.load("templates/partials/new-games-editor.vto");
|
||||||
|
const result = await template({
|
||||||
|
tab: "membre",
|
||||||
|
});
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
memberRouter.post("/new-game", async (ctx) => {
|
||||||
|
const payload = await ctx.request.body.form();
|
||||||
|
const preGame = {
|
||||||
|
date: payload.get("game-date"),
|
||||||
|
time: payload.get("game-time"),
|
||||||
|
away: payload.get("away-team"),
|
||||||
|
home: payload.get("home-team"),
|
||||||
|
};
|
||||||
|
const [game, error] = await gameService.createNewGame(preGame);
|
||||||
|
|
||||||
|
if (error !== "") {
|
||||||
|
const template = await env.load("templates/partials/new-game-error.vto");
|
||||||
|
const result = await template({
|
||||||
|
tab: "membre",
|
||||||
|
error: error,
|
||||||
|
});
|
||||||
|
ctx.response.status = 500;
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const template = await env.load("templates/partials/single-game-editor.vto");
|
||||||
|
const result = await template({
|
||||||
|
tab: "membre",
|
||||||
|
game: game,
|
||||||
|
});
|
||||||
|
ctx.response.headers.set("game-id", game?.id ?? "");
|
||||||
|
ctx.response.body = result.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
memberRouter.delete("/games/:gameId", async (ctx) => {
|
||||||
|
if (!(await loginService.isLoggedIn(ctx))) {
|
||||||
|
ctx.response.redirect("/membre");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const success = await gameService.deleteGameById(ctx.params.gameId);
|
||||||
|
ctx.response.body = `${success}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
memberRouter.post("/games/:gameId", async (ctx) => {
|
||||||
|
if (!(await loginService.isLoggedIn(ctx))) {
|
||||||
|
ctx.response.redirect("/membre");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const payload = await ctx.request.body.form();
|
||||||
|
let preGame = {
|
||||||
|
awayScore: payload.get("away-score") ?? null,
|
||||||
|
homeScore: payload.get("home-score") ?? null,
|
||||||
|
rain: payload.get("game-type") === "rain",
|
||||||
|
practice: payload.get("game-type") === "practice",
|
||||||
|
};
|
||||||
|
|
||||||
|
preGame = Object.fromEntries(
|
||||||
|
Object.entries(preGame).filter(([_, v]) => v !== null),
|
||||||
|
) as Partial<Game>;
|
||||||
|
|
||||||
|
const success = await gameService.updateGame(ctx.params.gameId, preGame);
|
||||||
|
ctx.response.body = success
|
||||||
|
? `<i class="fa fa-floppy-o" aria-hidden="true"></i>`
|
||||||
|
: `<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const apiRouter = new Router();
|
||||||
|
|
||||||
|
apiRouter.get("/results/:year.json", async (ctx) => {
|
||||||
|
ctx.response.json = true;
|
||||||
|
const games = await gameService.getAllGames();
|
||||||
|
ctx.response.body = games
|
||||||
|
.filter((g) => g.year == ctx.params.year)
|
||||||
|
.map((g) => {
|
||||||
|
g[g.home] = parseInt(g.homeScore);
|
||||||
|
g[g.away] = parseInt(g.awayScore);
|
||||||
|
return g;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
apiRouter.get("/available-years.json", async (ctx) => {
|
||||||
|
ctx.response.json = true;
|
||||||
|
const games = await gameService.getAllGames();
|
||||||
|
ctx.response.body = [...new Set(games.map((g) => g.year))];
|
||||||
|
});
|
||||||
|
|
||||||
|
router.use("/membre", memberRouter.routes());
|
||||||
|
router.use("/api", apiRouter.routes());
|
||||||
|
|
||||||
|
const app = new Application();
|
||||||
|
app.use(router.routes());
|
||||||
|
|
||||||
|
app.use(staticFiles("static", { brotli: true, fetch: true }));
|
||||||
|
|
||||||
|
await app.listen({ port: 8000 });
|
||||||
@@ -0,0 +1,323 @@
|
|||||||
|
import { Game, PreGame } from "./types.ts";
|
||||||
|
import {
|
||||||
|
assertEquals,
|
||||||
|
assertNotEquals,
|
||||||
|
} from "https://deno.land/std@0.224.0/assert/mod.ts";
|
||||||
|
|
||||||
|
type GamePrimaryKey = ["phenix", "games", string];
|
||||||
|
|
||||||
|
type date = [number, number, number];
|
||||||
|
type time = [number, number];
|
||||||
|
type DateIndex = ["phenix", "indexes", "game-date", ...date, ...time];
|
||||||
|
|
||||||
|
export class GameService {
|
||||||
|
readonly kv: Deno.Kv;
|
||||||
|
private readonly DATE_VALIDATOR =
|
||||||
|
/^(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})$/;
|
||||||
|
private readonly TIME_VALIDATOR = /^(?<hour>\d{1,2})(:|h)(?<minute>\d{1,2})$/;
|
||||||
|
private readonly VALID_TEAMS: string[] = [
|
||||||
|
"jaune",
|
||||||
|
"rouge",
|
||||||
|
"bleu",
|
||||||
|
"gris",
|
||||||
|
"vert",
|
||||||
|
"noir",
|
||||||
|
"orange",
|
||||||
|
"mauve",
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(kv: Deno.Kv) {
|
||||||
|
this.kv = kv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private chronologicalGameOrder(game1: Game, game2: Game): number {
|
||||||
|
if (game1.date < game2.date) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (game1.date > game2.date) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (game1.time < game2.time) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (game1.time > game2.time) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllGames(): Promise<Game[]> {
|
||||||
|
const ite = this.kv.list<Game>({ prefix: ["phenix", "games"] });
|
||||||
|
return (await Array.fromAsync(ite))
|
||||||
|
.map((e) => e.value)
|
||||||
|
.sort(this.chronologicalGameOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private gamePrimaryKey(id: string): GamePrimaryKey {
|
||||||
|
return ["phenix", "games", id];
|
||||||
|
}
|
||||||
|
|
||||||
|
private dateIndex(date: string, time: string): DateIndex | null {
|
||||||
|
let destructedDate = this.DATE_VALIDATOR.exec(date)?.groups;
|
||||||
|
let destructedTime = this.TIME_VALIDATOR.exec(time)?.groups;
|
||||||
|
|
||||||
|
if (!destructedDate || !destructedTime) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
"phenix",
|
||||||
|
"indexes",
|
||||||
|
"game-date",
|
||||||
|
parseInt(destructedDate.year),
|
||||||
|
parseInt(destructedDate.month),
|
||||||
|
parseInt(destructedDate.day),
|
||||||
|
parseInt(destructedTime.hour),
|
||||||
|
parseInt(destructedTime.minute),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private cleanTime(raw: string): string {
|
||||||
|
const groups = this.TIME_VALIDATOR.exec(raw)!.groups!;
|
||||||
|
return `${groups.hour.padStart(2, "0")}:${groups.minute.padStart(2, "0")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private cleanDate(raw: string): string {
|
||||||
|
const groups = this.DATE_VALIDATOR.exec(raw)!.groups!;
|
||||||
|
return `${groups.year}-${groups.month.padStart(2, "0")}-${groups.day.padStart(2, "0")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractYearFromDate(date: string): number {
|
||||||
|
return parseInt(this.DATE_VALIDATOR.exec(date)!.groups!.year);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createGame(preGame: PreGame): Game {
|
||||||
|
const ret = {
|
||||||
|
...preGame,
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
practice: false,
|
||||||
|
rain: false,
|
||||||
|
year: this.extractYearFromDate(preGame.date),
|
||||||
|
homeScore: null,
|
||||||
|
awayScore: null,
|
||||||
|
};
|
||||||
|
ret.time = this.cleanTime(ret.time);
|
||||||
|
ret.date = this.cleanDate(ret.date);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private validatePregate(preGame: PreGame): string {
|
||||||
|
if (!this.DATE_VALIDATOR.test(preGame.date)) {
|
||||||
|
return `Invalide date format ${preGame.date}`;
|
||||||
|
}
|
||||||
|
if (!this.TIME_VALIDATOR.test(preGame.time)) {
|
||||||
|
return `Invalide time format ${preGame.time}`;
|
||||||
|
}
|
||||||
|
if (!this.VALID_TEAMS.includes(preGame.away)) {
|
||||||
|
return `Invalide away format ${preGame.away}`;
|
||||||
|
}
|
||||||
|
if (!this.VALID_TEAMS.includes(preGame.home)) {
|
||||||
|
return `Invalide home format ${preGame.home}`;
|
||||||
|
}
|
||||||
|
if (preGame.home === preGame.away) {
|
||||||
|
return `Home and away teams must be different (received ${preGame.home} for both)`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
async createNewGame(preGame: PreGame): Promise<[Game | null, string]> {
|
||||||
|
if (this.validatePregate(preGame) !== "") {
|
||||||
|
return [null, this.validatePregate(preGame)];
|
||||||
|
}
|
||||||
|
const game = this.createGame(preGame);
|
||||||
|
const dateIndex = this.dateIndex(game.date, game.time);
|
||||||
|
if (!dateIndex) {
|
||||||
|
return [null, "Cound not parse date or time"];
|
||||||
|
}
|
||||||
|
const precondition = await this.kv.get<string>(dateIndex);
|
||||||
|
if (precondition.value !== null) {
|
||||||
|
return [null, "game already exists " + precondition.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await this.kv
|
||||||
|
.atomic()
|
||||||
|
.check(precondition)
|
||||||
|
.set(this.gamePrimaryKey(game.id), game)
|
||||||
|
.set(dateIndex, game.id)
|
||||||
|
.commit();
|
||||||
|
if (!res.ok) {
|
||||||
|
return [null, "Transaction failed"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [game, ""];
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGameById(id: string): Promise<Game | null> {
|
||||||
|
const res = await this.kv.get<Game>(this.gamePrimaryKey(id));
|
||||||
|
return res.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteGameById(id: string): Promise<boolean> {
|
||||||
|
const precond = await this.kv.get<Game>(this.gamePrimaryKey(id));
|
||||||
|
if (precond.value === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await this.kv
|
||||||
|
.atomic()
|
||||||
|
.check(precond)
|
||||||
|
.delete(this.gamePrimaryKey(precond.value.id))
|
||||||
|
.delete(this.dateIndex(precond.value.date, precond.value.time)!)
|
||||||
|
.commit();
|
||||||
|
return res.ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateGame(id: string, partial: Partial<Game>): Promise<boolean> {
|
||||||
|
delete partial.id;
|
||||||
|
const precond = await this.kv.get<Game>(this.gamePrimaryKey(id));
|
||||||
|
if (precond.value === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const res = await this.kv
|
||||||
|
.atomic()
|
||||||
|
.check(precond)
|
||||||
|
.delete(this.gamePrimaryKey(precond.value.id))
|
||||||
|
.delete(this.dateIndex(precond.value.date, precond.value.time)!)
|
||||||
|
.set(
|
||||||
|
this.dateIndex(precond.value.date, precond.value.time)!,
|
||||||
|
precond.value.id,
|
||||||
|
)
|
||||||
|
.set(this.gamePrimaryKey(precond.value.id), {
|
||||||
|
...precond.value,
|
||||||
|
...partial,
|
||||||
|
})
|
||||||
|
.commit();
|
||||||
|
return res.ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Deno.test("saving simple games", async (t) => {
|
||||||
|
const kv = await Deno.openKv();
|
||||||
|
const service = new GameService(kv);
|
||||||
|
|
||||||
|
async function deleteAllKeys() {
|
||||||
|
const keys = kv.list({ prefix: [] });
|
||||||
|
for await (const entry of keys) {
|
||||||
|
await kv.delete(entry.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validePreGame(seed: number): PreGame {
|
||||||
|
let year = ((645 * seed + 162) % 10000) + 1;
|
||||||
|
let month = ((335 * seed + 71) % 12) + 1;
|
||||||
|
let day = ((72625 * seed + 176) % 28) + 1;
|
||||||
|
return {
|
||||||
|
date: `${(year + "").padStart(4, "0")}-${(month + "").padStart(2, "0")}-${(day + "").padStart(2, "0")}`,
|
||||||
|
time: "18:45",
|
||||||
|
away: "jaune",
|
||||||
|
home: "rouge",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step("creating games", async () => {
|
||||||
|
const preGame = validePreGame(7276);
|
||||||
|
const [game, error] = await service.createNewGame(preGame);
|
||||||
|
assertEquals(error, "");
|
||||||
|
const ret = await service.getGameById(game!.id);
|
||||||
|
assertEquals(game, ret);
|
||||||
|
});
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step("creating games with old date format", async () => {
|
||||||
|
const preGame = validePreGame(7276);
|
||||||
|
preGame.date = "2017-8-5";
|
||||||
|
const [game, error] = await service.createNewGame(preGame);
|
||||||
|
assertEquals(error, "");
|
||||||
|
assertEquals(game?.date, "2017-08-05");
|
||||||
|
});
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step("creating games with old time format", async () => {
|
||||||
|
const preGame = validePreGame(7276);
|
||||||
|
preGame.time = "9:00";
|
||||||
|
const [game, error] = await service.createNewGame(preGame);
|
||||||
|
assertEquals(error, "");
|
||||||
|
assertEquals(game?.time, "09:00");
|
||||||
|
});
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step(
|
||||||
|
"saving two games in the same timeslot should fail",
|
||||||
|
async () => {
|
||||||
|
const preGame = validePreGame(7276);
|
||||||
|
let [_, error] = await service.createNewGame(preGame);
|
||||||
|
assertEquals(error, "");
|
||||||
|
[_, error] = await service.createNewGame(preGame);
|
||||||
|
assertNotEquals(error, "");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step("saving games with bad fields", async () => {
|
||||||
|
let i = 0;
|
||||||
|
for (const key of Object.keys(validePreGame(7276))) {
|
||||||
|
let [_, error] = await service.createNewGame({
|
||||||
|
...validePreGame(7262 + i),
|
||||||
|
[key]: `Broken ${key}`,
|
||||||
|
});
|
||||||
|
assertNotEquals(error, "");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await t.step("saving games with the same home and away teams", async () => {
|
||||||
|
const preGame = validePreGame(7276);
|
||||||
|
preGame.home = preGame.away;
|
||||||
|
let [_, error] = await service.createNewGame(preGame);
|
||||||
|
assertNotEquals(error, "");
|
||||||
|
});
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step("listing games", async () => {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
await service.createNewGame(validePreGame(666 + i));
|
||||||
|
}
|
||||||
|
assertEquals((await service.getAllGames()).length, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step("deleting games", async () => {
|
||||||
|
let [game, error] = await service.createNewGame(validePreGame(8992));
|
||||||
|
await service.deleteGameById(game!.id);
|
||||||
|
assertEquals((await service.getAllGames()).length, 0);
|
||||||
|
|
||||||
|
[game, error] = await service.createNewGame(validePreGame(8992));
|
||||||
|
assertEquals(error, "");
|
||||||
|
});
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
|
||||||
|
await t.step("updating game scores", async () => {
|
||||||
|
let [game, _] = await service.createNewGame(validePreGame(8992));
|
||||||
|
const ret = await service.updateGame(game!.id, {
|
||||||
|
homeScore: 10,
|
||||||
|
awayScore: 32,
|
||||||
|
});
|
||||||
|
assertEquals(ret, true);
|
||||||
|
game = await service.getGameById(game!.id);
|
||||||
|
assertEquals(game!.homeScore, 10);
|
||||||
|
assertEquals(game!.awayScore, 32);
|
||||||
|
});
|
||||||
|
|
||||||
|
await deleteAllKeys();
|
||||||
|
await kv.close();
|
||||||
|
});
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import {
|
||||||
|
assert,
|
||||||
|
assertFalse,
|
||||||
|
} from "https://deno.land/std@0.224.0/assert/mod.ts";
|
||||||
|
|
||||||
|
type User = { username: string; passwordHashWithSalt: string };
|
||||||
|
|
||||||
|
const officialUsers: User[] = [
|
||||||
|
{
|
||||||
|
username: "marqueur",
|
||||||
|
passwordHashWithSalt:
|
||||||
|
"5603007580f73044864e7a0b66744f405406eaaf28fa514d724ccf11d010bd89:070b1a477e6a877d44f31961dc0402a9f3258465eed73ab6a9110c461ac68714",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export class LoginService {
|
||||||
|
private readonly users: User[];
|
||||||
|
|
||||||
|
constructor(users: User[]) {
|
||||||
|
this.users = users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static officialLoginService(): LoginService {
|
||||||
|
return new LoginService(officialUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async hashMessage(message: string): Promise<string> {
|
||||||
|
const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array
|
||||||
|
const hashBuffer = await crypto.subtle.digest("SHA-256", msgUint8); // hash the message
|
||||||
|
const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array
|
||||||
|
const hashHex = hashArray
|
||||||
|
.map((b) => b.toString(16).padStart(2, "0"))
|
||||||
|
.join(""); // convert bytes to hex string
|
||||||
|
return hashHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async shittyHmac(message: string, salt: string): Promise<string> {
|
||||||
|
const h1 = await this.hashMessage(message + salt);
|
||||||
|
const h2 = await this.hashMessage(salt + message);
|
||||||
|
return await this.hashMessage(h1 + h2);
|
||||||
|
}
|
||||||
|
|
||||||
|
async hashPassword(password: string): Promise<string> {
|
||||||
|
const salt = await this.hashMessage(`${Math.random()}`);
|
||||||
|
const hash = await this.shittyHmac(password, salt);
|
||||||
|
return `${salt}:${hash}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async verifyPassword(
|
||||||
|
password: string,
|
||||||
|
passwordHashWithSalt: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const [passwordSalt, passwordHash] = passwordHashWithSalt.split(":");
|
||||||
|
return passwordHash === (await this.shittyHmac(password, passwordSalt));
|
||||||
|
}
|
||||||
|
|
||||||
|
async validateCredentials(
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
for (const user of this.users) {
|
||||||
|
if (user.username === username) {
|
||||||
|
return this.verifyPassword(password, user.passwordHashWithSalt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(ctx: any): Promise<void> {
|
||||||
|
const nDays = 90;
|
||||||
|
const maxAgesInSecond = nDays * 24 * 3600;
|
||||||
|
const maxUnixEpoch = Math.floor(Date.now() / 1000) + maxAgesInSecond;
|
||||||
|
|
||||||
|
await ctx.cookies.set("phenix-session", `${maxUnixEpoch}`, {
|
||||||
|
maxAge: maxAgesInSecond,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async isLoggedIn(ctx: any): Promise<boolean> {
|
||||||
|
const expiration = await ctx.cookies.get("phenix-session");
|
||||||
|
if (!expiration || !/^\d+$/.test(expiration)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Date.now() < parseInt(expiration) * 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Deno.test("login service", async (t) => {
|
||||||
|
await t.step("hashing password", async () => {
|
||||||
|
const service = new LoginService([]);
|
||||||
|
const passwordHashWithSalt = await service.hashPassword("qwerty");
|
||||||
|
assert(await service.verifyPassword("qwerty", passwordHashWithSalt));
|
||||||
|
assertFalse(await service.verifyPassword("ytrewq", passwordHashWithSalt));
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
export type Game = {
|
||||||
|
id: string;
|
||||||
|
date: string;
|
||||||
|
time: string;
|
||||||
|
home: string;
|
||||||
|
away: string;
|
||||||
|
year: number;
|
||||||
|
homeScore: number | null;
|
||||||
|
awayScore: number | null;
|
||||||
|
practice: boolean;
|
||||||
|
rain: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PreGame = {
|
||||||
|
date: string;
|
||||||
|
time: string;
|
||||||
|
home: string;
|
||||||
|
away: string;
|
||||||
|
};
|
||||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,26 @@
|
|||||||
|
import * as util from "./util.js";
|
||||||
|
import m from "https://esm.sh/mithril@2.2.2"
|
||||||
|
import _ from "https://esm.sh/lodash-es@4.17.21"
|
||||||
|
import {statsView, tabView, schedulView } from './schedule.js'
|
||||||
|
|
||||||
|
const calendarPage = {
|
||||||
|
view: function(){
|
||||||
|
const availableYears = util.getAvailableYears();
|
||||||
|
const year = _.get(m.route.param(), 'year', util.getDefaultYear());
|
||||||
|
|
||||||
|
return m('div.uk-grid.uk-margin-top.uk-margin-bottom',
|
||||||
|
m('div.uk-width-large-3-5.uk-width-medium-4-5.uk-width-small-1-1.uk-container-center',
|
||||||
|
[
|
||||||
|
m(statsView, {year}),
|
||||||
|
m(tabView, {year, availableYears}),
|
||||||
|
m(schedulView, {year}),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.route.mode = "hash";
|
||||||
|
m.route(document.getElementById('mithril-content'), "/", {
|
||||||
|
"/": calendarPage,
|
||||||
|
"/:year": calendarPage,
|
||||||
|
});
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import m from "https://esm.sh/mithril@2.2.2"
|
||||||
|
|
||||||
|
export function rainSvg (size){
|
||||||
|
return m("svg[viewBox='0 0 107.95 87.723']",{width: size, height: size}, [
|
||||||
|
m("defs[id='defs16']"),
|
||||||
|
m("g[id='layer1'][transform='translate(-310.1 -167.39)']", [
|
||||||
|
m("g[id='g13542'][transform='translate(-2.4761 19.309)']", [
|
||||||
|
m("path[d='m378.31 207.24c15.43-1.4 26.66-5.66 26.66-10.69 0-0.41-0.27-0.8-0.42-1.2 0.91 0.23 1.83 0.46 2.83 0.46 5.57 0 10.07-3.78 10.07-8.44 0-4.65-4.5-8.41-10.07-8.41-0.68 0-1.29 0.22-1.93 0.33 0.56-1.86 0.95-3.77 0.95-5.79 0-12.33-11.17-22.34-24.95-22.34-9.77 0-18.13 5.09-22.23 12.4-1.64-0.92-3.47-1.48-5.4-1.48-5.83 0-10.68 4.69-12.18 11.06-2.56-1.01-5.52-1.64-8.7-1.64-9.54 0-17.29 5.23-17.29 11.67 0 5.81 6.35 10.59 14.6 11.47-0.37 0.63-0.66 1.25-0.66 1.91 0 4.25 8.01 7.94 19.79 9.83'][id='path8749']", {style: {"stroke-linejoin": "round", "stroke": "#6798e9", "stroke-linecap": "round", "stroke-miterlimit": ".5", "stroke-width": "12.154", "fill": "none"}}),
|
||||||
|
m("path[d='m338.14 223.91c-8.25 7.27 1.43 13.47 5.12 3.49l2.83-9.26-7.95 5.77z'][id='path8734']", {style: {"stroke": "#6798e9", "stroke-miterlimit": "3.2", "stroke-width": "8", "fill": "#6798e9"}}),
|
||||||
|
m("path[d='m367.18 225.11c-8.25 7.27 1.44 13.47 5.13 3.49l2.83-9.26-7.96 5.77z'][id='path8736']", {style: {"stroke": "#6798e9", "stroke-miterlimit": "3.2", "stroke-width": "8", "fill": "#6798e9"}}),
|
||||||
|
m("path[d='m360.42 209.77c-8.25 7.27 1.44 13.47 5.12 3.49l2.83-9.26-7.95 5.77z'][id='path8738']", {style: {"stroke": "#6798e9", "stroke-miterlimit": "3.2", "stroke-width": "8", "fill": "#6798e9"}}),
|
||||||
|
m("path[d='m378.31 207.24c15.43-1.4 26.66-5.66 26.66-10.69 0-0.41-0.27-0.8-0.42-1.2 0.91 0.23 1.83 0.46 2.83 0.46 5.57 0 10.07-3.78 10.07-8.44 0-4.65-4.5-8.41-10.07-8.41-0.68 0-1.29 0.22-1.93 0.33 0.56-1.86 0.95-3.77 0.95-5.79 0-12.33-11.17-22.34-24.95-22.34-9.77 0-18.13 5.09-22.23 12.4-1.64-0.92-3.47-1.48-5.4-1.48-5.83 0-10.68 4.69-12.18 11.06-2.56-1.01-5.52-1.64-8.7-1.64-9.54 0-17.29 5.23-17.29 11.67 0 5.81 6.35 10.59 14.6 11.47-0.37 0.63-0.66 1.25-0.66 1.91 0 4.25 8.01 7.94 19.79 9.83'][id='path10281']", {style: {"stroke-linejoin": "round", "stroke": "#6798e9", "stroke-linecap": "round", "stroke-miterlimit": ".5", "stroke-width": "12.154", "fill": "none"}}),
|
||||||
|
m("path[d='m338.14 223.91c-8.25 7.27 1.43 13.47 5.12 3.49l2.83-9.26-7.95 5.77z'][id='path10283']", {style: {"stroke": "#6798e9", "stroke-miterlimit": "3.2", "stroke-width": "8", "fill": "#6798e9"}}),
|
||||||
|
m("path[d='m367.18 225.11c-8.25 7.27 1.44 13.47 5.13 3.49l2.83-9.26-7.96 5.77z'][id='path10285']", {style: {"stroke": "#6798e9", "stroke-miterlimit": "3.2", "stroke-width": "8", "fill": "#6798e9"}}),
|
||||||
|
m("path[d='m360.42 209.77c-8.25 7.27 1.44 13.47 5.12 3.49l2.83-9.26-7.95 5.77z'][id='path10287']", {style: {"stroke": "#6798e9", "stroke-miterlimit": "3.2", "stroke-width": "8", "fill": "#6798e9"}})
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
}
|
||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
||||||
|
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}function fe(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}ce.fn=ce.prototype={jquery:t,constructor:ce,length:0,toArray:function(){return ae.call(this)},get:function(e){return null==e?ae.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=ce.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return ce.each(this,e)},map:function(n){return this.pushStack(ce.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(ae.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(ce.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(ce.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:oe.sort,splice:oe.splice},ce.extend=ce.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||v(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(ce.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||ce.isPlainObject(n)?n:{},i=!1,a[t]=ce.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},ce.extend({expando:"jQuery"+(t+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==i.call(e))&&(!(t=r(e))||"function"==typeof(n=ue.call(t,"constructor")&&t.constructor)&&o.call(n)===a)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){m(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(c(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},text:function(e){var t,n="",r=0,i=e.nodeType;if(!i)while(t=e[r++])n+=ce.text(t);return 1===i||11===i?e.textContent:9===i?e.documentElement.textContent:3===i||4===i?e.nodeValue:n},makeArray:function(e,t){var n=t||[];return null!=e&&(c(Object(e))?ce.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:se.call(t,e,n)},isXMLDoc:function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!l.test(t||n&&n.nodeName||"HTML")},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(c(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:le}),"function"==typeof Symbol&&(ce.fn[Symbol.iterator]=oe[Symbol.iterator]),ce.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var pe=oe.pop,de=oe.sort,he=oe.splice,ge="[\\x20\\t\\r\\n\\f]",ve=new RegExp("^"+ge+"+|((?:^|[^\\\\])(?:\\\\.)*)"+ge+"+$","g");ce.contains=function(e,t){var n=t&&t.parentNode;return e===n||!(!n||1!==n.nodeType||!(e.contains?e.contains(n):e.compareDocumentPosition&&16&e.compareDocumentPosition(n)))};var f=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;function p(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e}ce.escapeSelector=function(e){return(e+"").replace(f,p)};var ye=C,me=s;!function(){var e,b,w,o,a,T,r,C,d,i,k=me,S=ce.expando,E=0,n=0,s=W(),c=W(),u=W(),h=W(),l=function(e,t){return e===t&&(a=!0),0},f="checked|selected|async|autofocus|autoplay|conLine truncated
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
// alert("ok")
|
||||||
|
import * as util from "./util.js";
|
||||||
|
import * as resultParser from './resultParser.js'
|
||||||
|
import * as teams from './teams.js'
|
||||||
|
import m from "https://esm.sh/mithril@2.2.2"
|
||||||
|
import {rainSvg} from "./images.js";
|
||||||
|
import _ from "https://esm.sh/lodash-es@4.17.21"
|
||||||
|
|
||||||
|
import {statsView, tabView, scheduleTeamTags } from './schedule.js'
|
||||||
|
|
||||||
|
|
||||||
|
const nextGameDaySchedule = {};
|
||||||
|
|
||||||
|
nextGameDaySchedule._toDay = function(){
|
||||||
|
var now = new Date();
|
||||||
|
return new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||||
|
};
|
||||||
|
|
||||||
|
nextGameDaySchedule.oninit = async function(){
|
||||||
|
|
||||||
|
const result = await m.request({
|
||||||
|
method: "GET",
|
||||||
|
url: `/api/results/2024.json`
|
||||||
|
});
|
||||||
|
const nightGames = resultParser.getNightGames(result);
|
||||||
|
nextGameDaySchedule.games = nextGameDaySchedule._getNextNightGame(nightGames, nextGameDaySchedule._toDay());
|
||||||
|
};
|
||||||
|
|
||||||
|
nextGameDaySchedule._getNextNightGame = function(games, date){
|
||||||
|
return _(games)
|
||||||
|
.filter(g => g.jsDate.getTime() >= date.getTime())
|
||||||
|
.last()
|
||||||
|
.games
|
||||||
|
.sort((g1, g2) => g1.jsDate - g2.jsDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
nextGameDaySchedule._getTableHead = function(){
|
||||||
|
return m('thead', m('tr', [
|
||||||
|
m('td', 'Date'),
|
||||||
|
m('td', 'Heure'),
|
||||||
|
m('td', 'Receveur'),
|
||||||
|
m('td', 'Visiteur')
|
||||||
|
]));
|
||||||
|
};
|
||||||
|
|
||||||
|
nextGameDaySchedule._responsoveText = function(largeText, smallText, game){
|
||||||
|
var ret = [];
|
||||||
|
if(game.rain){
|
||||||
|
ret.push(rainSvg('1.5em'));
|
||||||
|
ret.push(' ');
|
||||||
|
} else if(game.practice){
|
||||||
|
ret.push(m('span.uk-badge.uk-badge-success', 'pratique!'));
|
||||||
|
ret.push(' ');
|
||||||
|
}
|
||||||
|
ret.push(m('span.uk-visible-large', largeText));
|
||||||
|
ret.push(m('span.uk-hidden-large', smallText));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
nextGameDaySchedule._getGamesRow = function(game){
|
||||||
|
return m('tr', [
|
||||||
|
m('td', nextGameDaySchedule._responsoveText(util.formatDate(game.jsDate),
|
||||||
|
util.formatDateSmall(game.jsDate),
|
||||||
|
game)),
|
||||||
|
m('td', game.time),
|
||||||
|
m('td', scheduleTeamTags.getHomeTeamTag(game)),
|
||||||
|
m('td',scheduleTeamTags.getAwayTeamTag(game))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
nextGameDaySchedule._getGamesRows = function(games){
|
||||||
|
return _.map(games, nextGameDaySchedule._getGamesRow);
|
||||||
|
};
|
||||||
|
|
||||||
|
nextGameDaySchedule.view = function(){
|
||||||
|
return m('table.uk-table.uk-table-hover.uk-table-striped.uk-table-condensed',[
|
||||||
|
nextGameDaySchedule._getTableHead(),
|
||||||
|
m('tbody',
|
||||||
|
nextGameDaySchedule._getGamesRows(nextGameDaySchedule.games)
|
||||||
|
)]);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const LittleCalendar = {}
|
||||||
|
|
||||||
|
LittleCalendar.view = function(){
|
||||||
|
return m(nextGameDaySchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
const containerIds = ['large-mithril-container',
|
||||||
|
'medium-mithril-container',
|
||||||
|
'small-mithril-container']
|
||||||
|
|
||||||
|
for(const id of containerIds){
|
||||||
|
m.mount(document.getElementById(id), LittleCalendar);
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
import * as _ from "https://esm.sh/lodash-es@4.17.21"
|
||||||
|
|
||||||
|
|
||||||
|
let resultParser = {};
|
||||||
|
|
||||||
|
resultParser._addJSDateToResult = function(res){
|
||||||
|
let date = res.date.split('-');
|
||||||
|
let time = _.isString(res.time) ? res.time.split(':'): [0, 0];
|
||||||
|
res.jsDate = new Date(
|
||||||
|
Number(date[0]),
|
||||||
|
Number(date[1]) - 1,
|
||||||
|
Number(date[2]),
|
||||||
|
Number(time[0]),
|
||||||
|
Number(time[1])
|
||||||
|
);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._setCanonicalPoints = function(res){
|
||||||
|
if(!_.isNumber(res.home_points) && _.isNumber(_.get(res, res.home))){
|
||||||
|
res.home_points = res[res.home];
|
||||||
|
}
|
||||||
|
if(!_.isNumber(res.away_points) && _.isNumber(_.get(res, res.away))){
|
||||||
|
res.away_points = res[res.away];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultParser.parseResults = function(rawResults){
|
||||||
|
rawResults = _.map(rawResults, resultParser._setCanonicalPoints);
|
||||||
|
rawResults = _.map(rawResults, resultParser._addJSDateToResult);
|
||||||
|
rawResults = _.map(rawResults, resultParser._addCustomStyle);
|
||||||
|
return rawResults;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser.getNightGames = function(rawResults){
|
||||||
|
let ret = {};
|
||||||
|
_.each(resultParser.parseResults(rawResults), function(res){
|
||||||
|
if(_.has(ret, res.date)){
|
||||||
|
ret[res.date].push(res);
|
||||||
|
}else{
|
||||||
|
ret[res.date] = [res];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return _.map(ret, function(games, date){
|
||||||
|
return resultParser._addJSDateToResult({date: date, games: games});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._getAllTeams = function(rawResults){
|
||||||
|
let homeTeams = _.map(rawResults, 'home');
|
||||||
|
let awayTeams = _.map(rawResults, 'away');
|
||||||
|
return _.uniq(_.concat(homeTeams, awayTeams));
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._getWinner = function(res){
|
||||||
|
if(res.home_points > res.away_points){
|
||||||
|
return res.home;
|
||||||
|
}
|
||||||
|
if(res.home_points < res.away_points){
|
||||||
|
return res.away;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._hasWon = function(res, team){
|
||||||
|
return resultParser._getWinner(res) == team;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._hasLost = function(res, team){
|
||||||
|
return !resultParser._isDraw(res) && resultParser._getWinner(res) != team;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._isDraw = function(res){
|
||||||
|
return res.home_points == res.away_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._getPointsFor = function(res, team){
|
||||||
|
if(res.home == team){
|
||||||
|
return res.home_points;
|
||||||
|
}
|
||||||
|
return res.away_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._getPointsForOpponent = function(res, team){
|
||||||
|
if(res.home == team){
|
||||||
|
return res.away_points;
|
||||||
|
}
|
||||||
|
return res.home_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._getPointsForGame = function(res, team){
|
||||||
|
if(resultParser._hasWon(res, team)){
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return resultParser._isDraw(res) ? 1: 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._getTeamStats = function(rawResults, team){
|
||||||
|
let ret = {
|
||||||
|
team: team, gamePlayed: 0, victories: 0, points: 0,
|
||||||
|
defeats: 0, draws: 0, pointsFor: 0, pointsAgaint: 0};
|
||||||
|
_.each(rawResults, function(res){
|
||||||
|
if((team != res.home && team != res.away) || !_.isNumber(res.home_points)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret.gamePlayed += 1;
|
||||||
|
ret.victories += resultParser._hasWon(res, team) ? 1: 0;
|
||||||
|
ret.defeats += resultParser._hasLost(res, team) ? 1: 0;
|
||||||
|
ret.draws += resultParser._isDraw(res) ? 1: 0;
|
||||||
|
ret.pointsFor += resultParser._getPointsFor(res, team);
|
||||||
|
ret.pointsAgaint += resultParser._getPointsForOpponent(res, team);
|
||||||
|
ret.points += resultParser._getPointsForGame(res, team);
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._removeTemporaryResults = function(rawResults){
|
||||||
|
return _.filter(rawResults, function(rawResult){
|
||||||
|
return !rawResult.temporary;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser._isValidGame = function(game){
|
||||||
|
return !game.rain && ! game.practice;
|
||||||
|
};
|
||||||
|
|
||||||
|
resultParser.getStats = function(rawResults){
|
||||||
|
rawResults = _.filter(rawResults, resultParser._isValidGame);
|
||||||
|
rawResults = _.map(rawResults, resultParser._setCanonicalPoints);
|
||||||
|
let allTeams = resultParser._getAllTeams(resultParser._removeTemporaryResults(rawResults));
|
||||||
|
let getTeamStats = _.partial(resultParser._getTeamStats, rawResults);
|
||||||
|
return _.map(allTeams, getTeamStats);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStats = resultParser.getStats;
|
||||||
|
export const getNightGames = resultParser.getNightGames;
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
import * as util from "./util.js";
|
||||||
|
import * as resultParser from './resultParser.js'
|
||||||
|
import * as teams from './teams.js'
|
||||||
|
import m from "https://esm.sh/mithril@2.2.2"
|
||||||
|
import {rainSvg} from "./images.js";
|
||||||
|
import _ from "https://esm.sh/lodash-es@4.17.21"
|
||||||
|
|
||||||
|
function ppYear(year, availableYears) {
|
||||||
|
return _.last(availableYears) === year ? "" : year;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const scheduleTeamTags = {};
|
||||||
|
|
||||||
|
scheduleTeamTags._getTeamTag = function(teamName){
|
||||||
|
var teamColor = teams.getTeamColor(teamName);
|
||||||
|
return [
|
||||||
|
m('i.fa.fa-flag', {style: {color: teamColor}}),
|
||||||
|
m('span', ' ' + teamName)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduleTeamTags._getAwayPracticeTeamTag = function(){
|
||||||
|
return [
|
||||||
|
m('i.fa.fa-hand-spock-o', {style: {color: ' #ff1493'}, title: 'pratique'}),
|
||||||
|
m('span', ' Amis #1')
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduleTeamTags._getHomePracticeTeamTag = function(){
|
||||||
|
return [
|
||||||
|
m('i.fa.fa-hand-spock-o', {style: {color: '#acbf60'}, title: 'pratique'}),
|
||||||
|
m('span', ' Amis #2')
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduleTeamTags.getAwayTeamTag = function(game){
|
||||||
|
if(game.practice){
|
||||||
|
return scheduleTeamTags._getAwayPracticeTeamTag();
|
||||||
|
}
|
||||||
|
return scheduleTeamTags._getTeamTag(game.away);
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduleTeamTags.getHomeTeamTag = function(game){
|
||||||
|
if(game.practice){
|
||||||
|
return scheduleTeamTags._getHomePracticeTeamTag();
|
||||||
|
}
|
||||||
|
return scheduleTeamTags._getTeamTag(game.home);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const statsView = {};
|
||||||
|
statsView.stats = [];
|
||||||
|
|
||||||
|
statsView.oninit = async function(vnode){
|
||||||
|
if(statsView.currentYear === vnode.attrs.year){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
statsView.currentYear = vnode.attrs.year;
|
||||||
|
const result = await m.request({
|
||||||
|
method: "GET",
|
||||||
|
url: `/api/results/${vnode.attrs.year}.json`
|
||||||
|
});
|
||||||
|
statsView.stats = resultParser.getStats(result)
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
statsView.onupdate = statsView.oninit;
|
||||||
|
|
||||||
|
|
||||||
|
statsView.getStatRow = function(teamStats){
|
||||||
|
var formatStat = function(n){
|
||||||
|
return teamStats.gamePlayed === 0 ? '-' : n;
|
||||||
|
};
|
||||||
|
return m('tr', [
|
||||||
|
m('td', teamStats.team),
|
||||||
|
m('td', teamStats.gamePlayed),
|
||||||
|
m('td', formatStat(teamStats.victories)),
|
||||||
|
m('td', formatStat(teamStats.defeats)),
|
||||||
|
m('td', formatStat(teamStats.draws)),
|
||||||
|
m('td', formatStat(teamStats.pointsFor)),
|
||||||
|
m('td', formatStat(teamStats.pointsAgaint)),
|
||||||
|
m('td', formatStat(teamStats.pointsFor - teamStats.pointsAgaint)),
|
||||||
|
m('td', formatStat(teamStats.points))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
statsView.isStatForValidTeam = function(stat){
|
||||||
|
var teamNames = _.map(teams.teams(), 'name');
|
||||||
|
return _.includes(teamNames, stat.team);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
statsView.mainTable = function(stats){
|
||||||
|
var orderedStats = _.reverse(_.sortBy(stats, ['points', 'pointsFor']));
|
||||||
|
return m('table.uk-table.uk-table-hover.uk-table-striped',[
|
||||||
|
m('thead', m('tr', [
|
||||||
|
m('th', 'Équipes'),
|
||||||
|
m('th', 'PJ'),
|
||||||
|
m('th', 'V'),
|
||||||
|
m('th', 'D'),
|
||||||
|
m('th', 'N'),
|
||||||
|
m('th', 'PP'),
|
||||||
|
m('th', 'PC'),
|
||||||
|
m('th', 'DIF'),
|
||||||
|
m('th', 'PTS')
|
||||||
|
])),
|
||||||
|
m('tbody', _(orderedStats)
|
||||||
|
.filter(statsView.isStatForValidTeam)
|
||||||
|
.map(statsView.getStatRow)
|
||||||
|
.value())
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
statsView.legend = function(){
|
||||||
|
var items = ["PJ : Parties joués", "V : Victoire", "D : Défaite",
|
||||||
|
"N : Nul", "PP : Points pour", "PC : Points contre",
|
||||||
|
"DIF : Diférenciel","PTS : Points"];
|
||||||
|
return m('ul.uk-subnav.uk-subnav-line.uk-flex-center',[
|
||||||
|
_.map(items, function(itm){
|
||||||
|
return m('li', itm);
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
statsView.view = function(vnode){
|
||||||
|
return m('div.uk-grid',
|
||||||
|
m('div.uk-width-medium-1-1.uk-width-large-1-1.uk-container-center',[
|
||||||
|
m('h2', 'Classement ' + vnode.attrs.year),
|
||||||
|
statsView.mainTable(statsView.stats),
|
||||||
|
statsView.legend()
|
||||||
|
]));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const schedulView = {};
|
||||||
|
|
||||||
|
schedulView.oninit = async function(vnode){
|
||||||
|
if(vnode.attrs.year === schedulView.currentYear){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
schedulView.currentYear = vnode.attrs.year;
|
||||||
|
const result = await m.request({
|
||||||
|
method: "GET",
|
||||||
|
url: `/api/results/${vnode.attrs.year}.json`
|
||||||
|
});
|
||||||
|
schedulView.games = resultParser.getNightGames(result)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
schedulView.onupdate = schedulView.oninit;
|
||||||
|
|
||||||
|
|
||||||
|
schedulView._asGamePoints = function(points){
|
||||||
|
return !_.isNumber(points) ? '-' : points + '';
|
||||||
|
};
|
||||||
|
|
||||||
|
schedulView._rainIcon = function(game){
|
||||||
|
if(game.rain){
|
||||||
|
return m('span', {title: 'pluie, partie annulée.'}, rainSvg('1.5em'));
|
||||||
|
}
|
||||||
|
return m('span', {style: {visibility: 'hidden'}}, rainSvg('1.5em'));
|
||||||
|
};
|
||||||
|
|
||||||
|
schedulView._gameName = function(game){
|
||||||
|
return [schedulView._rainIcon(game),
|
||||||
|
" ",
|
||||||
|
game.time];
|
||||||
|
};
|
||||||
|
|
||||||
|
schedulView._gameRow = function(game){
|
||||||
|
|
||||||
|
return m('tr',[
|
||||||
|
m('td', schedulView._gameName(game)),
|
||||||
|
m('td', scheduleTeamTags.getAwayTeamTag(game)),
|
||||||
|
m('td', schedulView._asGamePoints(game.away_points)),
|
||||||
|
m('td', 'vs'),
|
||||||
|
m('td', scheduleTeamTags.getHomeTeamTag(game)),
|
||||||
|
m('td', schedulView._asGamePoints(game.home_points))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
schedulView._gameView = function(gameNight){
|
||||||
|
return m('div', [m('h3', util.formatDate(gameNight.jsDate)),
|
||||||
|
m('table.uk-table.uk-table-hover.uk-table-condensed.uk-table-striped',
|
||||||
|
m('tbody',[
|
||||||
|
_.map(gameNight.games, schedulView._gameRow),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
schedulView.view = function(){
|
||||||
|
return m('div.uk-grid',
|
||||||
|
m('div.uk-width-large-3-5.uk-width-medium-1-1',
|
||||||
|
_.map(schedulView.games, schedulView._gameView)));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const tabView = {};
|
||||||
|
|
||||||
|
tabView._createTab = function(activeYear, availableYears, year){
|
||||||
|
const isActive = (activeYear == year) || (activeYear == ppYear(year, availableYears));
|
||||||
|
return m('li', {'class': isActive ? 'uk-active': ''}, // 'uk-active'
|
||||||
|
m('a', {href: '#/' + ppYear(year, availableYears)}, 'Saison ' + year));
|
||||||
|
}
|
||||||
|
|
||||||
|
tabView.view = function(vnode){
|
||||||
|
const activeYear = vnode.attrs.year;
|
||||||
|
const availableYears = vnode.attrs.availableYears;
|
||||||
|
const createTab = _.partial(tabView._createTab, activeYear, availableYears);
|
||||||
|
return m('div.uk-margin', m('h2', 'Calendrier ' + ppYear(activeYear, availableYears)),
|
||||||
|
m('ul.uk-tab', _.reverse(_.map(availableYears, createTab))));
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import * as _ from "https://esm.sh/lodash-es@4.17.21"
|
||||||
|
|
||||||
|
|
||||||
|
export function teams(){
|
||||||
|
return [
|
||||||
|
{name: 'remplaçants', color: '#FFA500'},
|
||||||
|
{name: 'jaune', color: '#FF0'},
|
||||||
|
{name:'rouge', color: '#F00'},
|
||||||
|
{name:'bleu', color: '#00F'},
|
||||||
|
{name:'gris', color: '#808080'},
|
||||||
|
{name:'vert', color: '#008000'},
|
||||||
|
{name: 'noir', color: '#000000'},
|
||||||
|
{name: 'orange', color: '#FFA500'},
|
||||||
|
{name: 'mauve', color: '#E0B0FF'}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getTeamColor(teamName){
|
||||||
|
return teams().filter(t => t.name == teamName)[0]?.color;
|
||||||
|
};
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
/*! UIkit 2.27.2 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */
|
||||||
|
!function(t){if("function"==typeof define&&define.amd&&define("uikit",function(){var i=window.UIkit||t(window,window.jQuery,window.document);return i.load=function(t,e,n,o){var s,a=t.split(","),r=[],l=(o.config&&o.config.uikit&&o.config.uikit.base?o.config.uikit.base:"").replace(/\/+$/g,"");if(!l)throw new Error("Please define base path to UIkit in the requirejs config.");for(s=0;s<a.length;s+=1){var c=a[s].replace(/\./g,"/");r.push(l+"/components/"+c)}e(r,function(){n(i)})},i}),!window.jQuery)throw new Error("UIkit requires jQuery");window&&window.jQuery&&t(window,window.jQuery,window.document)}(function(t,i,e){"use strict";var n={},o=t.UIkit?Object.create(t.UIkit):void 0;if(n.version="2.27.2",n.noConflict=function(){return o&&(t.UIkit=o,i.UIkit=o,i.fn.uk=o.fn),n},n.prefix=function(t){return t},n.$=i,n.$doc=n.$(document),n.$win=n.$(window),n.$html=n.$("html"),n.support={},n.support.transition=function(){var t=function(){var t,i=e.body||e.documentElement,n={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(t in n)if(void 0!==i.style[t])return n[t]}();return t&&{end:t}}(),n.support.animation=function(){var t=function(){var t,i=e.body||e.documentElement,n={WebkitAnimation:"webkitAnimationEnd",MozAnimation:"animationend",OAnimation:"oAnimationEnd oanimationend",animation:"animationend"};for(t in n)if(void 0!==i.style[t])return n[t]}();return t&&{end:t}}(),function(){Date.now=Date.now||function(){return(new Date).getTime()};for(var t=["webkit","moz"],i=0;i<t.length&&!window.requestAnimationFrame;++i){var e=t[i];window.requestAnimationFrame=window[e+"RequestAnimationFrame"],window.cancelAnimationFrame=window[e+"CancelAnimationFrame"]||window[e+"CancelRequestAnimationFrame"]}if(/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent)||!window.requestAnimationFrame||!window.cancelAnimationFrame){var n=0;window.requestAnimationFrame=function(t){var i=Date.now(),e=Math.max(n+16,i);return setTimeout(function(){t(n=e)},e-i)},window.cancelAnimationFrame=clearTimeout}}(),n.support.touch="ontouchstart"in document||t.DocumentTouch&&document instanceof t.DocumentTouch||t.navigator.msPointerEnabled&&t.navigator.msMaxTouchPoints>0||t.navigator.pointerEnabled&&t.navigator.maxTouchPoints>0||!1,n.support.mutationobserver=t.MutationObserver||t.WebKitMutationObserver||null,n.Utils={},n.Utils.isFullscreen=function(){return document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.fullscreenElement||!1},n.Utils.str2json=function(t,i){try{return i?JSON.parse(t.replace(/([\$\w]+)\s*:/g,function(t,i){return'"'+i+'":'}).replace(/'([^']+)'/g,function(t,i){return'"'+i+'"'})):new Function("","var json = "+t+"; return JSON.parse(JSON.stringify(json));")()}catch(e){return!1}},n.Utils.debounce=function(t,i,e){var n;return function(){var o=this,s=arguments,a=function(){n=null,e||t.apply(o,s)},r=e&&!n;clearTimeout(n),n=setTimeout(a,i),r&&t.apply(o,s)}},n.Utils.throttle=function(t,i){var e=!1;return function(){e||(t.call(),e=!0,setTimeout(function(){e=!1},i))}},n.Utils.removeCssRules=function(t){var i,e,n,o,s,a,r,l,c,u;t&&setTimeout(function(){try{for(u=document.styleSheets,o=0,r=u.length;r>o;o++){for(n=u[o],e=[],n.cssRules=n.cssRules,i=s=0,l=n.cssRules.length;l>s;i=++s)n.cssRules[i].type===CSSRule.STYLE_RULE&&t.test(n.cssRules[i].selectorText)&&e.unshift(i);for(a=0,c=e.length;c>a;a++)n.deleteRule(e[a])}}catch(d){}},0)},n.Utils.isInView=function(t,e){var o=i(t);if(!o.is(":visible"))return!1;var s=n.$win.scrollLeft(),a=n.$win.scrollTop(),r=o.offset(),l=r.left,c=r.top;return e=i.extend({topoffset:0,leftoffset:0},e),c+o.height()>=a&&c-e.topoffset<=a+n.$win.height()&&l+o.width()>=s&&l-e.leftoffset<=s+n.$win.width()?!0:!1},n.Utils.checkDisplay=function(t,e){var o=n.$("[data-uk-margin], [data-uk-grid-match], [data-uk-grid-margin], [data-uk-check-display]",t||document);return t&&!o.length&&(o=i(t)),o.trigger("display.uk.check"),e&&("string"!=typeof e&&(e='[class*="uk-animation-"]'),o.find(e).each(function(){var t=n.$(this),i=t.attr("class"),e=i.match(/uk-animation-(.+)/);t.removeClass(e[0]).width(),t.addClass(e[0])})),o},n.Utils.options=function(t){if("string"!=i.type(t))return t;-1!=t.indexOf(":")&&"}"!=t.trim().substr(-1)&&(t="{"+t+"}");var e=t?t.indexOf("{"):-1,o={};if(-1!=e)try{o=n.Utils.str2json(t.substr(e))}catch(s){}return o},n.Utils.animate=function(t,e){var o=i.Deferred();return t=n.$(t),t.css("display","none").addClass(e).one(n.support.animation.end,function(){t.removeClass(e),o.resolve()}),t.css("display",""),o.promise()},n.Utils.uid=function(t){return(t||"id")+(new Date).getTime()+"RAND"+Math.ceil(1e5*Math.random())},n.Utils.template=function(t,i){for(var e,n,o,s,a=t.replace(/\n/g,"\\n").replace(/\{\{\{\s*(.+?)\s*\}\}\}/g,"{{!$1}}").split(/(\{\{\s*(.+?)\s*\}\})/g),r=0,l=[],c=0;r<a.length;){if(e=a[r],e.match(/\{\{\s*(.+?)\s*\}\}/))switch(r+=1,e=a[r],n=e[0],o=e.substring(e.match(/^(\^|\#|\!|\~|\:)/)?1:0Line truncated
|
||||||
|
if(e=u.split("-"),h=d[u]?d[u]:d["bottom-left"],this.justified&&this.justified.length)i(a.css({left:0}),this.justified,c);else if(this.options.preventflip!==!0){var p;switch(this.checkBoundary(n.left+h.left,n.top+h.top,r,l,c)){case"x":"x"!==this.options.preventflip&&(p=o.x[u]||"right-top");break;case"y":"y"!==this.options.preventflip&&(p=o.y[u]||"top-left");break;case"xy":this.options.preventflip||(p=o.xy[u]||"right-bottom")}p&&(e=p.split("-"),h=d[p]?d[p]:d["bottom-left"],a.addClass("uk-dropdown-autoflip"),this.checkBoundary(n.left+h.left,n.top+h.top,r,l,c)&&(e=u.split("-"),h=d[u]?d[u]:d["bottom-left"]))}r>c&&(a.addClass("uk-dropdown-stack"),this.trigger("stack.uk.dropdown",[this])),a.css(h).css("display","").addClass("uk-dropdown-"+e[0])}},checkBoundary:function(i,e,n,o,s){var a="";return(0>i||i-t.$win.scrollLeft()+n>s)&&(a+="x"),(e-t.$win.scrollTop()<0||e-t.$win.scrollTop()+o>window.innerHeight)&&(a+="y"),a}}),t.component("dropdownOverlay",{defaults:{justify:!1,cls:"",duration:200},boot:function(){t.ready(function(i){t.$("[data-uk-dropdown-overlay]",i).each(function(){var i=t.$(this);i.data("dropdownOverlay")||t.dropdownOverlay(i,t.Utils.options(i.attr("data-uk-dropdown-overlay")))})})},init:function(){var e=this;this.justified=this.options.justify?t.$(this.options.justify):!1,this.overlay=this.element.find("uk-dropdown-overlay"),this.overlay.length||(this.overlay=t.$('<div class="uk-dropdown-overlay"></div>').appendTo(this.element)),this.overlay.addClass(this.options.cls),this.on({"beforeshow.uk.dropdown":function(t,n){e.dropdown=n,e.justified&&e.justified.length&&i(e.overlay.css({display:"block",marginLeft:"",marginRight:""}),e.justified,e.justified.outerWidth())},"show.uk.dropdown":function(){var i=e.dropdown.dropdown.outerHeight(!0);e.dropdown.element.removeClass("uk-open"),e.overlay.stop().css("display","block").animate({height:i},e.options.duration,function(){e.dropdown.dropdown.css("visibility",""),e.dropdown.element.addClass("uk-open"),t.Utils.checkDisplay(e.dropdown.dropdown,!0)}),e.pointerleave=!1},"hide.uk.dropdown":function(){e.overlay.stop().animate({height:0},e.options.duration)},"pointerenter.uk.dropdown":function(){clearTimeout(e.remainIdle)},"pointerleave.uk.dropdown":function(){e.pointerleave=!0}}),this.overlay.on({mouseenter:function(){e.remainIdle&&(clearTimeout(e.dropdown.remainIdle),clearTimeout(e.remainIdle))},mouseleave:function(){e.pointerleave&&n&&(e.remainIdle=setTimeout(function(){n&&n.hide()},n.options.remaintime))}})}})}(UIkit),function(t){"use strict";var i=[];t.component("gridMatchHeight",{defaults:{target:!1,row:!0,ignorestacked:!1,observe:!1},boot:function(){t.ready(function(i){t.$("[data-uk-grid-match]",i).each(function(){var i,e=t.$(this);e.data("gridMatchHeight")||(i=t.gridMatchHeight(e,t.Utils.options(e.attr("data-uk-grid-match"))))})})},init:function(){var e=this;this.columns=this.element.children(),this.elements=this.options.target?this.find(this.options.target):this.columns,this.columns.length&&(t.$win.on("load resize orientationchange",function(){var i=function(){e.element.is(":visible")&&e.match()};return t.$(function(){i()}),t.Utils.debounce(i,50)}()),this.options.observe&&t.domObserve(this.element,function(){e.element.is(":visible")&&e.match()}),this.on("display.uk.check",function(){this.element.is(":visible")&&this.match()}.bind(this)),i.push(this))},match:function(){var i=this.columns.filter(":visible:first");if(i.length){var e=Math.ceil(100*parseFloat(i.css("width"))/parseFloat(i.parent().css("width")))>=100;return e&&!this.options.ignorestacked?this.revert():t.Utils.matchHeights(this.elements,this.options),this}},revert:function(){return this.elements.css("min-height",""),this}}),t.component("gridMargin",{defaults:{cls:"uk-grid-margin",rowfirst:"uk-row-first"},boot:function(){t.ready(function(i){t.$("[data-uk-grid-margin]",i).each(function(){var i,e=t.$(this);e.data("gridMargin")||(i=t.gridMargin(e,t.Utils.options(e.attr("data-uk-grid-margin"))))})})},init:function(){t.stackMargin(this.element,this.options)}})}(UIkit),function(t){"use strict";function i(i,e){return e?("object"==typeof i?(i=i instanceof jQuery?i:t.$(i),i.parent().length&&(e.persist=i,e.persist.data("modalPersistParent",i.parent()))):i="string"==typeof i||"number"==typeof i?t.$("<div></div>").html(i):t.$("<div></div>").html("UIkit.modal Error: Unsupported data type: "+typeof i),i.appendTo(e.element.find(".uk-modal-dialog")),e):void 0}var e,n=!1,o=0,s=t.$html;t.$win.on("resize orientationchange",t.Utils.debounce(function(){t.$(".uk-modal.uk-open").each(function(){return t.$(this).data("modal")&&t.$(this).data("modal").resize()})},150)),t.component("modal",{defaults:{keyboard:!0,bgclose:!0,minScrollHeight:150,center:!1,modal:!0},scrollable:!1,transition:!1,hasTransitioned:!0,init:function(){if(e||(e=t.$("body")),this.element.length){var i=this;this.paddingdir="padding-"+("left"==t.langdirection?"right":"left"),this.dialog=this.find(".uk-modal-dialog"),this.active=!1,this.element.attr("aria-hiddLine truncated
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import m from "https://esm.sh/mithril@2.2.2"
|
||||||
|
import * as _ from "https://esm.sh/lodash-es@4.17.21"
|
||||||
|
|
||||||
|
|
||||||
|
let availableYears = []
|
||||||
|
m.request({
|
||||||
|
method: "GET",
|
||||||
|
url: `api/available-years.json`
|
||||||
|
}).then(d => {
|
||||||
|
availableYears = d.sort();
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
function resultatsURL (year){
|
||||||
|
var cacheBuster = window.Date.now();
|
||||||
|
year = !!year ? year: util.getDefaultYear();
|
||||||
|
return "api/resultats" + year + ".json?_=" + cacheBuster;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getAvailableYears(){
|
||||||
|
if(window.availableYears){
|
||||||
|
return _.clone(window.availableYears)
|
||||||
|
}
|
||||||
|
return availableYears.map(x => x)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getDefaultYear(){
|
||||||
|
return _.max(getAvailableYears());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatDate(date){
|
||||||
|
const monthNames = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',
|
||||||
|
'juillet', 'août', 'septembre', 'octobre', 'novembre',
|
||||||
|
'decembre'];
|
||||||
|
return [date.getDate(),
|
||||||
|
monthNames[date.getMonth()],
|
||||||
|
date.getFullYear()].join(' ');
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function getResults(year){
|
||||||
|
var url = resultatsURL(year);
|
||||||
|
return m.request({method: "GET", url: url})
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getDefaultResults() {
|
||||||
|
return getResults(getDefaultYear());
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export function formatDateSmall(date){
|
||||||
|
var smallMonthNames = ['janv', 'févr', 'mars', 'avr', 'mai', 'juin',
|
||||||
|
'juill', 'août', 'sept', 'oct', 'nov',
|
||||||
|
'dec'];
|
||||||
|
return [date.getDate(),
|
||||||
|
smallMonthNames[date.getMonth()],
|
||||||
|
date.getFullYear() % 1000].join(' ');
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{{ layout "templates/container.vto" }}
|
||||||
|
|
||||||
|
|
||||||
|
<div id="mithril-content"></div>
|
||||||
|
|
||||||
|
<script type=module src="scripts/calendar.js"></script>
|
||||||
|
|
||||||
|
{{ /layout }}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{{ layout "templates/container.vto" }}
|
||||||
|
|
||||||
|
<div class="uk-width-large-2-5 uk-width-medium-4-5 uk-width-small-1-1 uk-container-center">
|
||||||
|
<div class="uk-grid uk-margin">
|
||||||
|
<div class="uk-width-1-1">
|
||||||
|
<div style="height: 300px; width: 300px; background-size: 300px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="div uk-panel uk-panel-box uk-panel-box-secondary uk-container-center uk-margin">
|
||||||
|
<table class="uk-table">
|
||||||
|
<tr>
|
||||||
|
<td class="uk-text-right"><i class="fa fa-desktop"></i></td>
|
||||||
|
<td><a href="mailto:sportsphenixmtl@gmail.com">sportsphenixmtl@gmail.com</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="uk-text-right"><i class="fa fa-phone"></i></td>
|
||||||
|
<td> (514) 838-8950</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="uk-text-right"><i class="fa fa-envelope"></i></td>
|
||||||
|
<td>
|
||||||
|
<p> 10454 Sylvain-Garneau<br>Montréal, Québec H1C 0A2</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="uk-text-right"><i class="fa fa-gitlab"></i></td>
|
||||||
|
<td>
|
||||||
|
<p> Le site web est ouvert et accessible sur <a href="https://gitlab.com/ballephenix/website">gitlab.</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ /layout }}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Balle Phenix</title>
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="https://www.ballephenix.com/favicon.ico">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<script src="scripts/jquery-3.7.1.min.js"></script>
|
||||||
|
<script src="scripts/uikit.min.js"></script>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="uk-navbar uk-navbar-attached">
|
||||||
|
<ul class="uk-navbar-nav uk-visible-large uk-navbar-content uk-navbar-center">
|
||||||
|
<li class="uk-parent">
|
||||||
|
<div class="uk-navbar-brand"><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></div>
|
||||||
|
</li>
|
||||||
|
<li class="{{ if it.tab === 'home'}}uk-active{{ /if }}">
|
||||||
|
<a href="/">
|
||||||
|
<div><i class="fa fa-home"></i> Accueil</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ if it.tab === 'nouvelles'}}uk-active{{ /if }}">
|
||||||
|
<a href="/nouvelles">
|
||||||
|
<div><i class="fa fa-newspaper-o"></i> Nouvelles</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ if it.tab === 'calendrier'}}uk-active{{ /if }}">
|
||||||
|
<a href="/calendrier">
|
||||||
|
<div><i class="fa fa-calendar"></i> Calendrier</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ if it.tab === 'reglement'}}uk-active{{ /if }}">
|
||||||
|
<a href="/reglement">
|
||||||
|
<div><i class="fa fa-legal"></i> Règlement</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ if it.tab === 'membre'}}uk-active{{ /if }}">
|
||||||
|
<a href="/membre">
|
||||||
|
<div><i class="fa fa-lock"></i> Membre</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ if it.tab === 'contact'}}uk-active{{ /if }}">
|
||||||
|
<a href="/contact">
|
||||||
|
<div><i class="fa fa-phone"></i> Nous Joindre</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="uk-navbar-nav uk-visible-medium">
|
||||||
|
<li class="uk-parent">
|
||||||
|
<div class="uk-navbar-brand"><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></div>
|
||||||
|
</li>
|
||||||
|
<li class="{{ if tab === 'home'}}uk-active{{ /if }}"><a href="/"><i class="fa fa-home"></i> Accueil </a></li>
|
||||||
|
<li class="{{ if tab === 'nouvelles'}}uk-active{{ /if }}"><a href="/nouvelles"><i class="fa fa-newspaper-o"></i> Nouvelles</a></li>
|
||||||
|
<li class="{{ if it.tab === 'calendrier'}}uk-active{{ /if }}"><a href="/calendrier"><i class="fa fa-calendar"></i> Calendrier</a></li>
|
||||||
|
<li class="{{ if it.tab === 'reglement'}}uk-active{{ /if }}"><a href="/reglement"><i class="fa fa-legal"></i> Règlement</a></li>
|
||||||
|
<li class="{{ if it.tab === 'membre'}}uk-active{{ /if }}"><a href="/membre"><i class="fa fa-lock"></i> Membre</a></li>
|
||||||
|
<li class="{{ if it.tab === 'contact'}}uk-active{{ /if }}"><a href="/contact"><i class="fa fa-phone"></i> Nous Joindre</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul class="uk-navbar-nav uk-visible-small">
|
||||||
|
<li class="uk-parent">
|
||||||
|
<div class="uk-navbar-brand"><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></div>
|
||||||
|
</li>
|
||||||
|
<li data-uk-dropdown="" aria-expanded="" class="uk-parent"><a><i class="fa fa-bars"></i> Menu</a>
|
||||||
|
<div class="uk-dropdown">
|
||||||
|
<ul class="uk-nav uk-nav-navbar uk-dropdown-navbar">
|
||||||
|
<li class="uk-active"><a href="/"><i class="fa fa-home"></i> Accueil</a></li>
|
||||||
|
<li class=""><a href="/nouvelles"><i class="fa fa-newspaper-o"></i> Nouvelles</a></li>
|
||||||
|
<li class=""><a href="/calendrier"><i class="fa fa-calendar"></i> Calendrier</a></li>
|
||||||
|
<li class=""><a href="/reglement"><i class="fa fa-legal"></i> Règlement</a></li>
|
||||||
|
<li class=""><a href="/membre"><i class="fa fa-lock"></i> Membre</a></li>
|
||||||
|
<li class=""><a href="/contact"><i class="fa fa-phone"></i> Nous Joindre</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{{ content }}
|
||||||
|
|
||||||
|
<footer class="uk-grid ph-footer" style="padding: 40px;">
|
||||||
|
<div class="uk-container uk-container-center uk-text-center">
|
||||||
|
<div class="uk-panel"><span class="uk-hidden-small">Ligue de balle les Phénix... pour le plaisir de jouer!</span>
|
||||||
|
<h4 class="uk-visible-small">Ligue de balle les Phénix</h4>
|
||||||
|
</div>
|
||||||
|
<ul class="uk-subnav uk-subnav-line uk-flex-center">
|
||||||
|
<li><a href="mailto:sportsphenixmtl@gmail.com">sportsphenixmtl@gmail.com</a></li>
|
||||||
|
</ul>
|
||||||
|
<h1><a href="https://www.facebook.com/SportsPhenixMtl"><i class="fa fa-facebook-square"></i></a></h1>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
{{ layout "templates/container.vto" }}
|
||||||
|
<script type="module" src="scripts/little-calendar.js"></script>
|
||||||
|
|
||||||
|
<div class="uk-grid">
|
||||||
|
<div class="uk-large-1-3 uk-medium-2-3 uk-container-center">
|
||||||
|
<div style="height:300px; width: 300px; background-size: 300px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center uk-margin-left uk-margin-top"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-margin-top uk-margin-bottom uk-grid">
|
||||||
|
<div class="uk-width-large-3-5 uk-width-medium-4-5 uk-width-small-1-1 uk-container-center">
|
||||||
|
<div class="uk-grid uk-visible-large uk-grid-match">
|
||||||
|
<div class="uk-width-large-1-3 uk-width-medium-1-3">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge">
|
||||||
|
<i class="fa fa-newspaper-o" style="font-size: 1.7em;"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ include "templates/includes/home-news.vto" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-width-large-1-3 uk-width-medium-1-3">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-calendar" style="font-size: 1.7em;"></i></div>
|
||||||
|
<h3 class="uk-panel-title"><a href="#/calendrier" class="uk-link-muted">Calendrier</a></h3>
|
||||||
|
<div id="large-mithril-container"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-width-large-1-3 uk-width-medium-1-3">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-map-o" style="font-size: 1.7em;"></i></div>
|
||||||
|
<h3 class="uk-panel-title">Parc Walter-Stewart</h3>
|
||||||
|
{{ include "templates/includes/walter-stewart-map.vto" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- start -->
|
||||||
|
<div class="uk-visible-medium">
|
||||||
|
<div class="uk-grid uk-grid-match">
|
||||||
|
<div class="uk-width-medium-1-2">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-newspaper-o" style="font-size: 1.7em;"></i></div>
|
||||||
|
<div>
|
||||||
|
{{ include "templates/includes/home-news.vto" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-width-medium-1-2">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-calendar" style="font-size: 1.7em;"></i></div>
|
||||||
|
<h3 class="uk-panel-title"><a href="#/calendrier" class="uk-link-muted">Calendrier</a></h3>
|
||||||
|
<div id="medium-mithril-container"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-grid">
|
||||||
|
<div class="uk-width-medium-1-1">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-map-o" style="font-size: 1.7em;"></i></div>
|
||||||
|
<h3 class="uk-panel-title">Parc Walter-Stewart</h3>
|
||||||
|
{{ include "templates/includes/walter-stewart-map.vto" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- end -->
|
||||||
|
<div class="uk-visible-small">
|
||||||
|
<div class="uk-grid">
|
||||||
|
<div class="uk-width-small-1-1">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-newspaper-o" style="font-size: 1.7em;"></i></div>
|
||||||
|
<div>
|
||||||
|
{{ include "templates/includes/home-news.vto" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-grid">
|
||||||
|
<div class="uk-width-small-1-1">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-calendar" style="font-size: 1.7em;"></i></div>
|
||||||
|
<h3 class="uk-panel-title"><a href="#/calendrier" class="uk-link-muted">Calendrier</a></h3>
|
||||||
|
<div id="small-mithril-container"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-grid">
|
||||||
|
<div class="uk-width-small-1-1">
|
||||||
|
<div class="uk-panel uk-panel-box">
|
||||||
|
<div class="uk-panel-badge uk-badge"><i class="fa fa-map-o" style="font-size: 1.7em;"></i></div>
|
||||||
|
<h3 class="uk-panel-title">Parc Walter-Stewart</h3>
|
||||||
|
{{ include "templates/includes/walter-stewart-map.vto" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ /layout }}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<div id="game-{{ game.id }}">
|
||||||
|
|
||||||
|
{{set prettyGameDate = new Date(game.date).toLocaleString("fr-CA", { month: 'long', year: 'numeric', day: 'numeric', timeZone: 'UTC'}) }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3> {{ game.away }} vs {{ game.home }} | {{ prettyGameDate }} | {{ game.time }}</h3>
|
||||||
|
<form style="font-size: 1.1em;"
|
||||||
|
hx-trigger="input delay:250ms"
|
||||||
|
hx-post="/member/games/{{game.id}}"
|
||||||
|
hx-target="#saving-result">
|
||||||
|
|
||||||
|
<div class="uk-form-row">
|
||||||
|
<label>
|
||||||
|
Points {{ game.away }} : <input type=number
|
||||||
|
min=0
|
||||||
|
name="away-score"
|
||||||
|
value="{{ game.awayScore || 0 }}"
|
||||||
|
{{if game.rain || game.practice }}disabled{{ /if}}>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-form-row">
|
||||||
|
<label>
|
||||||
|
Points {{ game.home }} : <input type=number
|
||||||
|
min=0
|
||||||
|
name="home-score"
|
||||||
|
value="{{ game.homeScore || 0 }}"
|
||||||
|
{{if game.rain || game.practice }}disabled{{ /if}}>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-form-row">
|
||||||
|
<label>
|
||||||
|
Partie reguliere <input type=radio
|
||||||
|
name="game-type"
|
||||||
|
value="regular-game"
|
||||||
|
{{if ! game.practice && ! game.rain }} checked {{/if}}>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Pluie <input type=radio
|
||||||
|
name="game-type"
|
||||||
|
value="rain"
|
||||||
|
{{if game.rain }}checked{{/if}}>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Pratique <input
|
||||||
|
type=radio
|
||||||
|
name="game-type"
|
||||||
|
value="practice"
|
||||||
|
{{if game.practice && ! game.rain }}checked{{/if}}>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="saving-result">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div style="text-align: right">
|
||||||
|
<button class="uk-button-danger"
|
||||||
|
hx-delete="/membre/games/{{game.id}}"
|
||||||
|
hx-confirm="Certain de vouloir supprimer la partie?"
|
||||||
|
hx-target="#game-{{ game.id }}"
|
||||||
|
hx-swap="delete"
|
||||||
|
>Supprimer</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<h3 class="uk-panel-title">
|
||||||
|
<a href="#/nouvelles" class="uk-link-muted">
|
||||||
|
<h2 id="saison-2023">Saison 2023</h2>
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<p>Bonne saison à tous et toutes!</p>
|
||||||
|
<p>N'oubliez pas de consulter la page facebook: <a href="https://www.facebook.com/SportsPhenixMtl/">https://www.facebook.com/SportsPhenixMtl/</a> pour toutes mises à jour, y compris les annulations due à la météo.</p>
|
||||||
|
<p><strong><a href="#/nouvelles">lire la suite ...</a></strong></p>
|
||||||
|
</p>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{{ set selectedTeam = selectedTeam || "" }}
|
||||||
|
{{set isDisabled = isDisabled || false }}
|
||||||
|
{{set teams = ['jaune', 'rouge', 'bleu', 'gris', 'vert', 'noir', 'orange', 'mauve'] }}
|
||||||
|
|
||||||
|
|
||||||
|
<select name="{{- name -}}" class="uk-select" {{if isDisabled}} disabled {{ /if }}>
|
||||||
|
{{ for team of teams }}
|
||||||
|
<option name="{{team}}" {{if selectedTeam == team}} selected {{ /if }}>{{ team }}</option>
|
||||||
|
{{ /for }}
|
||||||
|
</select>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<div>
|
||||||
|
<iframe
|
||||||
|
style="border: 1px solid black; min-height: 300px;"
|
||||||
|
width="100%"
|
||||||
|
frameborder="0"
|
||||||
|
scrolling="no"
|
||||||
|
marginheight="0"
|
||||||
|
src="//www.openstreetmap.org/export/embed.html?bbox=-73.55936229228975%2C45.53102667048665%2C-73.55230271816255%2C45.53444249585723&layer=mapnik"; // "//www.openstreetmap.org/export/embed.html?bbox=-73.56355190277101%2C45.5294483312637%2C-73.54943275451662%2C45.53627996625677&layer=mapnik"; // "//www.openstreetmap.org/export/embed.html?bbox=-73.56355190277101%2C45.5294483312637%2C-73.54943275451662%2C45.53627996625677&layer=mapnik"
|
||||||
|
></iframe>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<small>
|
||||||
|
<a href="http://www.openstreetmap.org/#map=17/45.53216/-73.55692">Voir la carte</a>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{{ layout "templates/container.vto" }}
|
||||||
|
|
||||||
|
<div id="content"
|
||||||
|
{{ if isLoggedIn }}
|
||||||
|
hx-get="/membre/games-editor/today"
|
||||||
|
hx-trigger="load"
|
||||||
|
hx-target="#content"
|
||||||
|
{{ /if }}
|
||||||
|
>
|
||||||
|
<div class="uk-grid uk-margin">
|
||||||
|
<div class="uk-width-1-1">
|
||||||
|
<div style="height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-width-large-1-3 uk-container-center uk-margin">
|
||||||
|
<form action=""
|
||||||
|
class="uk-text-center"
|
||||||
|
|
||||||
|
hx-get="/login"
|
||||||
|
hx-target="#content">
|
||||||
|
<div class="uk-form-row"><label>Nom d'utilisateur <input type="text" name="username" class="uk-form-width-small"></label></div>
|
||||||
|
<div class="uk-form-row"><label>Mot de passe <input type="password" name="password" class="uk-form-width-small"></label></div>
|
||||||
|
<div class="uk-form-row"><button class="uk-button"><i class="fa fa-mars-double"></i> Pénétrez</button></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{{ /layout }}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{{ layout "templates/container.vto" }}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="uk-width-large-2-5 uk-width-medium-3-5 uk-width-small-1-1 uk-container-center">
|
||||||
|
<div>
|
||||||
|
<article class="uk-article uk-margin-">
|
||||||
|
<h1 class="uk-article-title">
|
||||||
|
<h2 id="saison-2023">Saison 2023</h2>
|
||||||
|
</h1>
|
||||||
|
<p class="uk-article-meta">
|
||||||
|
<p>Dimanche 10 Juillet 2023</p>
|
||||||
|
</p>
|
||||||
|
<p>Bonne saison à tous et toutes!</p>
|
||||||
|
<p>N'oubliez pas de consulter la page facebook: <a href="https://www.facebook.com/SportsPhenixMtl/">https://www.facebook.com/SportsPhenixMtl/</a> pour toutes mises à jour, y compris les annulations due à la météo.</p>
|
||||||
|
<p>Votre Comité 2023</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ /layout }}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{{set isToday = !!isToday }}
|
||||||
|
|
||||||
|
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||||
|
|
||||||
|
<div class="uk-margin" style="margin-top: 1em">
|
||||||
|
<ul class="uk-tab">
|
||||||
|
<li {{if isToday}} class="uk-active" {{ /if}}>
|
||||||
|
<a hx-get="/membre/games-editor/today"
|
||||||
|
hx-target="#content">
|
||||||
|
Aujourd'hui
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{ for year of years }}
|
||||||
|
<li {{if year === selectedYear}} class="uk-active" {{ /if}}>
|
||||||
|
<a hx-get="/membre/games-editor/{{year}}"
|
||||||
|
hx-target="#content">
|
||||||
|
Saison {{year}}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{ /for }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{ for game of games }}
|
||||||
|
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||||
|
{{ include "templates/includes/game-editor.vto" {game} }}
|
||||||
|
</div>
|
||||||
|
{{ /for }}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<button class="uk-button"
|
||||||
|
hx-get="/member/new-game-editor"
|
||||||
|
hx-target="#content">
|
||||||
|
Nouvelle Partie
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||||
|
|
||||||
|
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||||
|
<pre>{{ error }}</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||||
|
|
||||||
|
<div class="uk-margin"></div>
|
||||||
|
|
||||||
|
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||||
|
<form hx-post="/membre/new-game"
|
||||||
|
hx-target="#created-game"
|
||||||
|
hx-swap="afterbegin">
|
||||||
|
<div class="uk-form-row" style="text-align: center; font-size: 2em;">
|
||||||
|
|
||||||
|
{{ include "templates/includes/team-selector.vto" {name: "away-team"} }}
|
||||||
|
<label>
|
||||||
|
Vs.
|
||||||
|
</label>
|
||||||
|
{{ include "templates/includes/team-selector.vto" {name: "home-team"}}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-form-row">
|
||||||
|
<label>
|
||||||
|
Date: <input type=date name="game-date" required>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-form-row">
|
||||||
|
<label>
|
||||||
|
Heure: <input type="time" name="game-time">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<button class="uk-button">Creer</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="created-game"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<div class="uk-width-large-2-3 uk-container-center uk-margin">
|
||||||
|
|
||||||
|
<div class="uk-panel uk-panel-box uk-panel-box-secondary uk-margin">
|
||||||
|
{{ include "templates/includes/game-editor.vto" {game} }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{{ layout "templates/container.vto" }}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="uk-margin-top uk-margin-bottom uk-grid">
|
||||||
|
<div class="uk-width-large-3-5 uk-width-medium-4-5 uk-width-large-1-1 uk-container-center">
|
||||||
|
<div class="uk-grid">
|
||||||
|
<div class="uk-width-large-1-3 uk-width-small-1-1">
|
||||||
|
<div style="height: 250px; width: 250px; background-size: 250px; background-image: url(images/logosansfond.JPG);" class="uk-cover-background uk-container-center"></div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-width-large-2-3 uk-width-small-1-1">
|
||||||
|
<div class="uk-panel uk-panel-box uk-panel-box-secondary">
|
||||||
|
<h2>Règlements 2021</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<h3><a href="files/regle_de_jeux_2021.pdf">Règles de jeu</a></h3>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3><a href="files/regles_et_procedures_2021.pdf">Règles et procédures</a></h3>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3><a href="files/charte_organisationnelle_2021.pdf">Charte Organisationnelle</a></h3>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3><a href="files/formulaire_inscription_2021.pdf">Formulaire d'inscription</a></h3>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3><a href="files/code_ethique_2021.pdf">Code d'éthique</a></h3>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3><a href="http://www.asbm.ca/">Association des Sports de Balle à Montréal (ASBN)</a></h3>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-panel uk-panel-box uk-panel-box-secondary">
|
||||||
|
<h2>Mission</h2>
|
||||||
|
<p>La ligue de balle Les Phénix a été fondée en 2004 afin d'offrir aux membres de la communauté gaie et lesbienne et à leurs amis hétéros l'opportunité de s'amuser et de pratiquer un sport dans une ambiance amicale et décontractée. L'ouverture d'esprit, la camaraderie et le plaisir de pratiquer un sport à l'extérieur caractérisent cette ligue.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ /layout }}
|
||||||
Reference in new issue
Block a user