From 1d584b6e947011696de4c752b2534966ed9924ab Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 6 Aug 2022 13:46:44 -0400 Subject: [PATCH 01/86] setup npm and express --- .gitignore | 3 + package-lock.json | 1018 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 28 ++ server.js | 0 4 files changed, 1049 insertions(+) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 server.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28cde21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +.env +.DS_Store \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ea0ab47 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1018 @@ +{ + "name": "polltogether", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "polltogether", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^4.18.1" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + } + }, + "dependencies": { + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c39acab --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "polltogether", + "version": "1.0.0", + "description": "Together or together? For that is the question\r ### https://ms13380.github.io/PollTogether/", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ms13380/PollTogether.git" + }, + "keywords": [ + "poll", + "vote", + "data" + ], + "author": "Michael Sullivan, Ellis J, Adam Martin, Jared Daniel, Bocar Ly", + "license": "ISC", + "bugs": { + "url": "https://github.com/ms13380/PollTogether/issues" + }, + "homepage": "https://github.com/ms13380/PollTogether#readme", + "dependencies": { + "express": "^4.18.1" + } +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..e69de29 From 58797b03fae446e2ae61b0ba290408afae20ac54 Mon Sep 17 00:00:00 2001 From: Michael Sullivan <104106828+ms13380@users.noreply.github.com> Date: Sat, 6 Aug 2022 13:47:07 -0400 Subject: [PATCH 02/86] Update README.md Added group name --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9164015..4344ee9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ # Project Together or together? For that is the question ### https://ms13380.github.io/PollTogether/ +Made by the Polars From 2c299cb799a2ce123366b0411c4be0feca9324af Mon Sep 17 00:00:00 2001 From: VT_AOE_91 Date: Sat, 6 Aug 2022 13:51:19 -0400 Subject: [PATCH 03/86] Added poll_results.sql --- db/poll_results.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 db/poll_results.sql diff --git a/db/poll_results.sql b/db/poll_results.sql new file mode 100644 index 0000000..e69de29 From 0317aa37823873873ac8e117a938e244b990cc2b Mon Sep 17 00:00:00 2001 From: Michael Sullivan <104106828+ms13380@users.noreply.github.com> Date: Sat, 6 Aug 2022 13:55:23 -0400 Subject: [PATCH 04/86] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4344ee9..5e33412 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Project Together or together? For that is the question ### https://ms13380.github.io/PollTogether/ -Made by the Polars +Heroku: https://poll-together.herokuapp.com/ +## Made by the Polars From 59673076d93ac6720f21b0caf5be96428efb6197 Mon Sep 17 00:00:00 2001 From: VT_AOE_91 Date: Sat, 6 Aug 2022 13:57:43 -0400 Subject: [PATCH 05/86] Test commit --- db/poll_results.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/poll_results.sql b/db/poll_results.sql index e69de29..856af66 100644 --- a/db/poll_results.sql +++ b/db/poll_results.sql @@ -0,0 +1 @@ +--Testing commits-- \ No newline at end of file From 4ad43d39f73613485bd08a02ea8720591714d4ee Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Wed, 10 Aug 2022 20:06:34 -0400 Subject: [PATCH 06/86] Flesh out readme, add server.js --- README.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++ db/schema.sql | 3 ++ server.js | 44 ++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 db/schema.sql diff --git a/README.md b/README.md index 9164015..96111d3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,129 @@ # Project Together or together? For that is the question ### https://ms13380.github.io/PollTogether/ + +# 13 Object-Relational Mapping (ORM): E-Commerce Back End + +## User Story + +```md +AS A bootcam teacher +I WANT to be able to get input from my students +SO THAT make sure that everyone understands and is participating +``` + +## Acceptance Criteria + +```md +GIVEN a polling site +WHEN I visit the site for the first time +THEN I am presented with the homepage, which allows me to search for a poll and allows me to log in +WHEN I click on the homepage option +THEN I am taken to the homepage +WHEN I choose to sign up +THEN I am prompted to create a username and password +WHEN I click on the sign-up button +THEN my user credentials are saved and I am logged into the site +WHEN I revisit the site at a later time and choose to sign in +THEN I am prompted to enter my username and password +WHEN I am signed in to the site +THEN I see the polls I have created, and the option to log out +WHEN I click on the homepage option in the navigation +THEN I am taken to the homepage and presented with existing polls I have created +WHEN I click on an existing poll I have created +THEN I am presented with the results of the poll +WHEN I type a poll's id into the search bar, it brings up the poll's page. +WHEN I click on an answer choice +THEN an answer is recorded in the database +``` + +### Database Models + +Your database should contain the following four models, including the requirements listed for each model: + +* `User` + + * `id` + + * Integer. + + * Doesn't allow null values. + + * Set as primary key. + + * Uses auto increment. + + * `username` + + * String. + + * Doesn't allow null values. + + * `email` + + * String. + + * Doesn't allow null values. + + * `password` + + * String. + + * Doesn't allow null values. + +* `Poll` + + * `id` + + * Integer. + + * Doesn't allow null values. + + * Set as primary key. + + * Generated 6 diget code + + * `poll_name` + + * String. + + * Allow null values. + + * `description` + + * String. + + * Allow null values. + + * `created_by` + + * Integer. + + * Doesn't allow null values. + + * References the `User` model's `id`. + +* `Answer` + + * `poll_id` + + * Integer. + + * Doesn't allow null values. + + * References the `Poll` model's `id`. + + * `answer` + + * String. + + * Doesn't allow null values. + + +### Associations + +You'll need to execute association methods on your Sequelize models to create the following relationships between them: + +* `Poll` belongs to `User`, and `User` has many `Poll` models. + +* `Answer` belongs to `Poll` model, and `Poll` has many `Answer` models. \ No newline at end of file diff --git a/db/schema.sql b/db/schema.sql new file mode 100644 index 0000000..a64bc2f --- /dev/null +++ b/db/schema.sql @@ -0,0 +1,3 @@ +DROP DATABASE IF EXISTS pollTogether_db; + +CREATE DATABASE pollTogether_db; \ No newline at end of file diff --git a/server.js b/server.js index e69de29..4b1e641 100644 --- a/server.js +++ b/server.js @@ -0,0 +1,44 @@ +const path = require('path'); +const express = require('express'); +const session = require('express-session'); +const exphbs = require('express-handlebars'); +const SequelizeStore = require('connect-session-sequelize')(session.Store); + +const routes = require('./controllers'); +const sequelize = require('./config/connection'); +const helpers = require('./utils/helpers'); + +const app = express(); +const PORT = process.env.PORT || 3001; + +const sess = { + secret: 'togethertogether', + cookie: { + maxAge: 1000 * 60 * 60 * 4, + }, + resave: false, + rolling: true, + saveUninitialized: false, + store: new SequelizeStore({ + db: sequelize, + }), +}; + +app.use(session(sess)); + +const hbs = exphbs.create({ helpers }); + +app.engine('handlebars', hbs.engine); +app.set('view engine', 'handlebars'); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use(routes); + +sequelize.sync({ force: false }).then(() => { + app.listen(PORT, () => + console.log(`\nServer running: http://localhost:${PORT}`) + ); +}); \ No newline at end of file From 260fa7d26d2c10bfd0b4199235bfd881780fadf7 Mon Sep 17 00:00:00 2001 From: VT_AOE_91 Date: Wed, 10 Aug 2022 20:39:50 -0400 Subject: [PATCH 07/86] Created helper function for random 6-digit ID --- utils/helpers/randID.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 utils/helpers/randID.js diff --git a/utils/helpers/randID.js b/utils/helpers/randID.js new file mode 100644 index 0000000..8a47f3a --- /dev/null +++ b/utils/helpers/randID.js @@ -0,0 +1,12 @@ +// Sets upper and lower bounds for random ID generation +const idMin = 100000; +const idMax = 999999; + +// Function for generating random ID > takes min and max range as inputs +function randID(idMin,idMax){ + return Math.floor(Math.random()*(idMax - idMin + 1))+idMin; +} + +let ID = randID(idMin,idMax); // Random number between min and max + +console.log("Random ID: "+ID); // Console logging the function result From a88f89e7ca41666eb94aa900841f01b97958524d Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 10:29:30 -0400 Subject: [PATCH 08/86] Add Answer and User tables --- models/Answer.js | 29 ++++++++++++++++++++++++++ models/User.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 models/Answer.js create mode 100644 models/User.js diff --git a/models/Answer.js b/models/Answer.js new file mode 100644 index 0000000..0b4604b --- /dev/null +++ b/models/Answer.js @@ -0,0 +1,29 @@ +const { Model, DataTypes } = require('sequelize'); +const sequelize = require('../config/connection'); + +class Answer extends Model {} + +Answer.init( + { + poll_id: { + type: DataTypes.STRING, + allowNull: false + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false + }, + option: { + type: DataTypes.STRING, + allowNull: false + } + }, + { + sequelize, + freezeTableName: true, + underscored: true, + modelName: 'answer' + } +); + +module.exports = Answer; \ No newline at end of file diff --git a/models/User.js b/models/User.js new file mode 100644 index 0000000..64b9f92 --- /dev/null +++ b/models/User.js @@ -0,0 +1,54 @@ +const { Model, DataTypes } = require('sequelize'); +const sequelize = require('../config/connection'); +const bcrypt = require('bcrypt'); + +class User extends Model { + checkPassword(loginPw) { + return bcrypt.compareSync(loginPw, this.password); + } +} + +User.init( + { + id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true, + }, + username: { + type: DataTypes.STRING, + allowNull: false, + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + validate: { + isEmail: true, + }, + }, + password: { + type: DataTypes.STRING, + allowNull: false, + validate: { + len: [8], + }, + }, + }, + { + hooks: { + beforeCreate: async (newUserData) => { + newUserData.password = await bcrypt.hash(newUserData.password, 10); + return newUserData; + }, + }, + sequelize, + timestamps: false, + freezeTableName: true, + underscored: true, + modelName: 'user', + } +); + +module.exports = User; \ No newline at end of file From a5ea9d0d22e563ebba94699ed5807a0467483ad5 Mon Sep 17 00:00:00 2001 From: VT_AOE_91 Date: Sat, 13 Aug 2022 10:29:51 -0400 Subject: [PATCH 09/86] Created /models/polls.js --- models/polls.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 models/polls.js diff --git a/models/polls.js b/models/polls.js new file mode 100644 index 0000000..e69de29 From 4c2f9ca60e4a41e0963b83cad019e532c77c602e Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 10:35:43 -0400 Subject: [PATCH 10/86] change file structure --- index.html => views/main.handlebars | 0 search.html => views/search.html | 0 user-examples.html => views/user-examples.html | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename index.html => views/main.handlebars (100%) rename search.html => views/search.html (100%) rename user-examples.html => views/user-examples.html (100%) diff --git a/index.html b/views/main.handlebars similarity index 100% rename from index.html rename to views/main.handlebars diff --git a/search.html b/views/search.html similarity index 100% rename from search.html rename to views/search.html diff --git a/user-examples.html b/views/user-examples.html similarity index 100% rename from user-examples.html rename to views/user-examples.html From 13e07062ed9c727339b0ae9f980e05dfa2a56787 Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 10:37:19 -0400 Subject: [PATCH 11/86] adjust file structure again --- {css => public/css}/style.css | 0 {css => public/css}/wstyle.css | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {css => public/css}/style.css (100%) rename {css => public/css}/wstyle.css (100%) diff --git a/css/style.css b/public/css/style.css similarity index 100% rename from css/style.css rename to public/css/style.css diff --git a/css/wstyle.css b/public/css/wstyle.css similarity index 100% rename from css/wstyle.css rename to public/css/wstyle.css From 2898e148d1c7f41536c193a984942da0e6238a4a Mon Sep 17 00:00:00 2001 From: VT_AOE_91 Date: Sat, 13 Aug 2022 10:47:58 -0400 Subject: [PATCH 12/86] Created polls.js model --- models/polls.js | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/models/polls.js b/models/polls.js index e69de29..5c34fc4 100644 --- a/models/polls.js +++ b/models/polls.js @@ -0,0 +1,50 @@ +// import important parts of sequelize library +const { Model, DataTypes } = require('sequelize'); +// import our database connection from config.js +const sequelize = require('../config/connection'); + +// Initialize Polls model (table) by extending off Sequelize's Model class +class Polls extends Model {} + +// set up fields and rules for Polls model +Polls.init( + { + // Generated using utils/helpers/randID.js + id: { + type: DataTypes.STRING, + allowNull: false, + primaryKey: true, + autoIncrement: false + }, + + poll_title: { + type: DataTypes.STRING, + allowNull: false + }, + + poll_desc: { + type: DataTypes.STRING, + allowNull: true + }, + + poll_options: { + type: DataTypes.STRING, + allowNull: false + }, + + poll_userID: { + type: DataTypes.INTEGER, + allowNull: false + } + + }, + { + sequelize, + timestamps: false, + freezeTableName: true, + underscored: true, + modelName: 'polls', + } +); + +module.exports = Polls; \ No newline at end of file From 94d48d699aab4fd0216db37e59cc97e36b5d432c Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 10:48:01 -0400 Subject: [PATCH 13/86] Add home controller --- controllers/api/index.js | 0 controllers/home-routes.js | 35 +++++++++++++++++++++++++++++++++++ controllers/index.js | 12 ++++++++++++ models/index.js | 17 +++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 controllers/api/index.js create mode 100644 controllers/home-routes.js create mode 100644 controllers/index.js create mode 100644 models/index.js diff --git a/controllers/api/index.js b/controllers/api/index.js new file mode 100644 index 0000000..e69de29 diff --git a/controllers/home-routes.js b/controllers/home-routes.js new file mode 100644 index 0000000..b9fe047 --- /dev/null +++ b/controllers/home-routes.js @@ -0,0 +1,35 @@ +const router = require('express').Router(); +const { Poll, User, Answer } = require('../models'); + +router.get('/', async (req, res) => { + try { + const pollData = await Poll.findAll({ + attributes: ['id', 'title', 'description', 'options', 'user_id', 'created_at'], + include: [ + { + model: Answer, + attributes: ['poll_id', 'user_id', 'option'], + include: [{ + model: User, + attributes: ['username'] + }] + }, + { + model: User, + attributes: ['username'] + } + ], + order: [['created_at', 'DESC']] + }); + + const polls = pollData.map((post) => + post.get({ plain: true }) + ); + const session_user_id = req.session.user_id; + const data = {session_user_id, polls}; + res.render('homepage', {data, loggedIn: req.session.loggedIn}); + } catch (err) { + console.log(err); + res.status(500).json(err); + } + }); \ No newline at end of file diff --git a/controllers/index.js b/controllers/index.js new file mode 100644 index 0000000..7d50b53 --- /dev/null +++ b/controllers/index.js @@ -0,0 +1,12 @@ +const router = require('express').Router(); + +const apiRoutes = require('./api'); +const homeRoutes = require('./home-routes.js'); +// const userPageRoutes = require('./user-page-routes.js'); + +// router.use('/user-page', userPageRoutes); +router.use('/api', apiRoutes); +router.use('/', homeRoutes); + + +module.exports = router; \ No newline at end of file diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..8a3dc96 --- /dev/null +++ b/models/index.js @@ -0,0 +1,17 @@ +const User = require('./User'); +const Poll = require('./Poll'); +const Answer = require('./Answer'); + +User.hasMany(Poll, {foreignKey: 'user_id'}); + +User.hasMany(Answer, {foreignKey: 'user_id'}); + +Poll.hasMany(Answer, {foreignKey: 'post_id'}); + +Poll.belongsTo(User, {foreignKey: 'user_id'}); + +Answer.belongsTo(User, {foreignKey: 'user_id'}); + +Answer.belongsTo(Poll, {foreignKey: 'post_id'}); + +module.exports = {User, Poll, Comment}; \ No newline at end of file From 25d3c465ca023f94608c1f21792e6a529aa3ef41 Mon Sep 17 00:00:00 2001 From: Michael Sullivan <104106828+ms13380@users.noreply.github.com> Date: Sat, 13 Aug 2022 10:50:09 -0400 Subject: [PATCH 14/86] Delete user-examples.html --- views/user-examples.html | 52 ---------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 views/user-examples.html diff --git a/views/user-examples.html b/views/user-examples.html deleted file mode 100644 index d72616b..0000000 --- a/views/user-examples.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - User Examples - - - - - - - - - - - -
-
-

About Us

-
-
-
Michael S.
-
Gitlink
LinkedIn
-

SAMPLE TEXT.

-
-
-
Ellis J.
-
Gitlink
LinkedIn
-

SAMPLE TEXT

-
-
-
Jared D.
-
Gitlink
LinkedIn
-

SAMPLE TEXT

-
-
-
Bocar L.
-
Gitlink
LinkedIn
-

SAMPLE TEXT

-
-
-
Adam M.
-
Gitlink
LinkedIn
-

SAMPLE TEXT

-
-
-
-
- - - - \ No newline at end of file From fc0a16cda4a214b33e85583c107358c29d4c4bf0 Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 10:54:43 -0400 Subject: [PATCH 15/86] Update home route to match poll schema --- controllers/home-routes.js | 2 +- models/{polls.js => Poll.js} | 0 views/{ => layouts}/main.handlebars | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename models/{polls.js => Poll.js} (100%) rename views/{ => layouts}/main.handlebars (100%) diff --git a/controllers/home-routes.js b/controllers/home-routes.js index b9fe047..23ddd0e 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -4,7 +4,7 @@ const { Poll, User, Answer } = require('../models'); router.get('/', async (req, res) => { try { const pollData = await Poll.findAll({ - attributes: ['id', 'title', 'description', 'options', 'user_id', 'created_at'], + attributes: ['id', 'poll_title', 'poll_desc', 'poll_options', 'poll_userID', 'created_at'], include: [ { model: Answer, diff --git a/models/polls.js b/models/Poll.js similarity index 100% rename from models/polls.js rename to models/Poll.js diff --git a/views/main.handlebars b/views/layouts/main.handlebars similarity index 100% rename from views/main.handlebars rename to views/layouts/main.handlebars From 720b2a19c0ba5fe42e33d9dd45ac2c51f718ac53 Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 11:17:21 -0400 Subject: [PATCH 16/86] Get basic homepage working --- config/connection.js | 21 + controllers/home-routes.js | 4 +- controllers/index.js | 4 +- models/Poll.js | 1 - models/index.js | 2 +- package-lock.json | 1849 ++++++++++++++++++++++++++- package.json | 9 +- utils/helpers.js | 0 views/homepage.handlebars | 5 + views/partials/poll-card.handlebars | 5 + 10 files changed, 1890 insertions(+), 10 deletions(-) create mode 100644 config/connection.js create mode 100644 utils/helpers.js create mode 100644 views/homepage.handlebars create mode 100644 views/partials/poll-card.handlebars diff --git a/config/connection.js b/config/connection.js new file mode 100644 index 0000000..7e67099 --- /dev/null +++ b/config/connection.js @@ -0,0 +1,21 @@ +const Sequelize = require('sequelize'); +require('dotenv').config(); + +let sequelize; + +if (process.env.JAWSDB_URL) { + sequelize = new Sequelize(process.env.JAWSDB_URL); +} else { + sequelize = new Sequelize( + process.env.DB_NAME, + process.env.DB_USER, + process.env.DB_PASSWORD, + { + host: 'localhost', + dialect: 'mysql', + port: 3306, + } + ); +} + +module.exports = sequelize; \ No newline at end of file diff --git a/controllers/home-routes.js b/controllers/home-routes.js index 23ddd0e..d30b895 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -32,4 +32,6 @@ router.get('/', async (req, res) => { console.log(err); res.status(500).json(err); } - }); \ No newline at end of file + }); + + module.exports = router; \ No newline at end of file diff --git a/controllers/index.js b/controllers/index.js index 7d50b53..e89117c 100644 --- a/controllers/index.js +++ b/controllers/index.js @@ -1,11 +1,11 @@ const router = require('express').Router(); -const apiRoutes = require('./api'); +// const apiRoutes = require('./api'); const homeRoutes = require('./home-routes.js'); // const userPageRoutes = require('./user-page-routes.js'); // router.use('/user-page', userPageRoutes); -router.use('/api', apiRoutes); +// router.use('/api', apiRoutes); router.use('/', homeRoutes); diff --git a/models/Poll.js b/models/Poll.js index 5c34fc4..bae900a 100644 --- a/models/Poll.js +++ b/models/Poll.js @@ -40,7 +40,6 @@ Polls.init( }, { sequelize, - timestamps: false, freezeTableName: true, underscored: true, modelName: 'polls', diff --git a/models/index.js b/models/index.js index 8a3dc96..8e48a69 100644 --- a/models/index.js +++ b/models/index.js @@ -14,4 +14,4 @@ Answer.belongsTo(User, {foreignKey: 'user_id'}); Answer.belongsTo(Poll, {foreignKey: 'post_id'}); -module.exports = {User, Poll, Comment}; \ No newline at end of file +module.exports = {User, Poll, Answer}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ea0ab47..d0086c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,63 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "express": "^4.18.1" + "bcrypt": "^5.0.1", + "connect-session-sequelize": "^7.1.4", + "dotenv": "^16.0.1", + "express": "^4.18.1", + "express-handlebars": "^6.0.6", + "express-session": "^1.17.3", + "mysql2": "^2.3.3", + "sequelize": "^6.21.3" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dependencies": { + "@types/ms": "*" } }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, + "node_modules/@types/node": { + "version": "18.7.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.3.tgz", + "integrity": "sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w==" + }, + "node_modules/@types/validator": { + "version": "13.7.5", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.5.tgz", + "integrity": "sha512-9rQHeAqz6Jw3gDhttkmWetoriW5FPbxylv/6h6mXtaj2NKRcOvOmvfcswVdLVpbuy10NrO486K3lCoLgoIhiIA==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -24,11 +78,86 @@ "node": ">= 0.6" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -52,6 +181,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -72,6 +209,67 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/connect-session-sequelize": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-7.1.4.tgz", + "integrity": "sha512-adKkuliSL6eRCvMpc4gvM2rkw1emeOp9aobwmapbZ/vLsT60rsyYZ9XjPjoUQP0+es2fRNyBNoZSVv9SUd1IsQ==", + "dependencies": { + "debug": "^4.1.1" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "sequelize": ">= 6.1.0" + } + }, + "node_modules/connect-session-sequelize/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/connect-session-sequelize/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -112,6 +310,19 @@ "ms": "2.0.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -129,11 +340,37 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -196,6 +433,45 @@ "node": ">= 0.10.0" } }, + "node_modules/express-handlebars": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.6.tgz", + "integrity": "sha512-E4QHYCh+9fyfdBEb8uKJ8p6HD4qq/sUSHBq83lRNlLJp2TQKEg2nFJYbVdC+M3QzaV19dODe43lgjQWVaIpbyQ==", + "dependencies": { + "glob": "^8.0.2", + "graceful-fs": "^4.2.10", + "handlebars": "^4.7.7" + }, + "engines": { + "node": ">=v12.22.9" + } + }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -229,11 +505,54 @@ "node": ">= 0.6" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/get-intrinsic": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", @@ -247,6 +566,49 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -269,6 +631,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -284,6 +651,39 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -295,6 +695,23 @@ "node": ">=0.10.0" } }, + "node_modules/inflection": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", + "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -308,6 +725,62 @@ "node": ">= 0.10" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -359,11 +832,134 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/mysql2": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", + "integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", + "dependencies": { + "denque": "^2.0.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^4.0.0", + "lru-cache": "^6.0.0", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "dependencies": { + "lru-cache": "^4.1.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/named-placeholders/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -372,6 +968,68 @@ "node": ">= 0.6" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -391,6 +1049,22 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -399,11 +1073,24 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -416,6 +1103,11 @@ "node": ">= 0.10" } }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, "node_modules/qs": { "version": "6.10.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", @@ -430,6 +1122,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -452,6 +1152,77 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/retry-as-promised": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", + "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -476,6 +1247,20 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -504,6 +1289,98 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "node_modules/sequelize": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.21.3.tgz", + "integrity": "sha512-cJPrTTVCofUxaaNKoIETiXCYh2xJ+OFq5jMHJQqftp34M4kNoLpTfUMPSwYtRUeTcSh1/5HodfJXIBi7troIFA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], + "dependencies": { + "@types/debug": "^4.1.7", + "@types/validator": "^13.7.1", + "debug": "^4.3.3", + "dottie": "^2.0.2", + "inflection": "^1.13.2", + "lodash": "^4.17.21", + "moment": "^2.29.1", + "moment-timezone": "^0.5.34", + "pg-connection-string": "^2.5.0", + "retry-as-promised": "^5.0.0", + "semver": "^7.3.5", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.7.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "snowflake-sdk": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/sequelize/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/sequelize/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -518,6 +1395,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -536,6 +1418,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -544,6 +1447,54 @@ "node": ">= 0.8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -552,16 +1503,49 @@ "node": ">=0.6" } }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uglify-js": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.3.tgz", + "integrity": "sha512-uVbFqx9vvLhQg0iBaau9Z75AxWJ8tqM9AV890dIZCLApF4rTcyHwmAvLeEdYRs+BzYWu8Iw81F79ah0EfTXbaw==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/unpipe": { @@ -572,6 +1556,11 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -580,6 +1569,22 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -587,9 +1592,98 @@ "engines": { "node": ">= 0.8" } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } }, "dependencies": { + "@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + } + }, + "@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "requires": { + "@types/ms": "*" + } + }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, + "@types/node": { + "version": "18.7.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.3.tgz", + "integrity": "sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w==" + }, + "@types/validator": { + "version": "13.7.5", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.5.tgz", + "integrity": "sha512-9rQHeAqz6Jw3gDhttkmWetoriW5FPbxylv/6h6mXtaj2NKRcOvOmvfcswVdLVpbuy10NrO486K3lCoLgoIhiIA==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -599,11 +1693,67 @@ "negotiator": "0.6.3" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + } + }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -623,6 +1773,14 @@ "unpipe": "1.0.0" } }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -637,6 +1795,49 @@ "get-intrinsic": "^1.0.2" } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "connect-session-sequelize": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-7.1.4.tgz", + "integrity": "sha512-adKkuliSL6eRCvMpc4gvM2rkw1emeOp9aobwmapbZ/vLsT60rsyYZ9XjPjoUQP0+es2fRNyBNoZSVv9SUd1IsQ==", + "requires": { + "debug": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -668,6 +1869,16 @@ "ms": "2.0.0" } }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -678,11 +1889,31 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==" + }, + "dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -736,6 +1967,38 @@ "vary": "~1.1.2" } }, + "express-handlebars": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.6.tgz", + "integrity": "sha512-E4QHYCh+9fyfdBEb8uKJ8p6HD4qq/sUSHBq83lRNlLJp2TQKEg2nFJYbVdC+M3QzaV19dODe43lgjQWVaIpbyQ==", + "requires": { + "glob": "^8.0.2", + "graceful-fs": "^4.2.10", + "handlebars": "^4.7.7" + } + }, + "express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "requires": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + } + } + }, "finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -760,11 +2023,48 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, "get-intrinsic": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", @@ -775,6 +2075,35 @@ "has-symbols": "^1.0.3" } }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -788,6 +2117,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -800,6 +2134,30 @@ "toidentifier": "1.0.1" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -808,6 +2166,20 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "inflection": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", + "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -818,6 +2190,49 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -851,16 +2266,155 @@ "mime-db": "1.52.0" } }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, + "moment-timezone": { + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "requires": { + "moment": ">= 2.9.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "mysql2": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", + "integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", + "requires": { + "denque": "^2.0.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^4.0.0", + "lru-cache": "^6.0.0", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "requires": { + "lru-cache": "^4.1.3" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + } + } + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -874,16 +2428,39 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -893,6 +2470,11 @@ "ipaddr.js": "1.9.1" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, "qs": { "version": "6.10.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", @@ -901,6 +2483,11 @@ "side-channel": "^1.0.4" } }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -917,6 +2504,61 @@ "unpipe": "1.0.0" } }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "retry-as-promised": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", + "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -927,6 +2569,14 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -954,6 +2604,54 @@ } } }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "sequelize": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.21.3.tgz", + "integrity": "sha512-cJPrTTVCofUxaaNKoIETiXCYh2xJ+OFq5jMHJQqftp34M4kNoLpTfUMPSwYtRUeTcSh1/5HodfJXIBi7troIFA==", + "requires": { + "@types/debug": "^4.1.7", + "@types/validator": "^13.7.1", + "debug": "^4.3.3", + "dottie": "^2.0.2", + "inflection": "^1.13.2", + "lodash": "^4.17.21", + "moment": "^2.29.1", + "moment-timezone": "^0.5.34", + "pg-connection-string": "^2.5.0", + "retry-as-promised": "^5.0.0", + "semver": "^7.3.5", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.7.0", + "wkx": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==" + }, "serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -965,6 +2663,11 @@ "send": "0.18.0" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -980,16 +2683,80 @@ "object-inspect": "^1.9.0" } }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -999,20 +2766,94 @@ "mime-types": "~2.1.24" } }, + "uglify-js": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.3.tgz", + "integrity": "sha512-uVbFqx9vvLhQg0iBaau9Z75AxWJ8tqM9AV890dIZCLApF4rTcyHwmAvLeEdYRs+BzYWu8Iw81F79ah0EfTXbaw==", + "optional": true + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "requires": { + "@types/node": "*" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index c39acab..1e39ee3 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,13 @@ }, "homepage": "https://github.com/ms13380/PollTogether#readme", "dependencies": { - "express": "^4.18.1" + "bcrypt": "^5.0.1", + "connect-session-sequelize": "^7.1.4", + "dotenv": "^16.0.1", + "express": "^4.18.1", + "express-handlebars": "^6.0.6", + "express-session": "^1.17.3", + "mysql2": "^2.3.3", + "sequelize": "^6.21.3" } } diff --git a/utils/helpers.js b/utils/helpers.js new file mode 100644 index 0000000..e69de29 diff --git a/views/homepage.handlebars b/views/homepage.handlebars new file mode 100644 index 0000000..8248ce5 --- /dev/null +++ b/views/homepage.handlebars @@ -0,0 +1,5 @@ +
+ {{#each data.polls as |poll|}} + {{> poll-card poll}} + {{/each}} +
\ No newline at end of file diff --git a/views/partials/poll-card.handlebars b/views/partials/poll-card.handlebars new file mode 100644 index 0000000..31c2784 --- /dev/null +++ b/views/partials/poll-card.handlebars @@ -0,0 +1,5 @@ +
+ + {{poll_title}} - {{user.username}} + +
\ No newline at end of file From 2ba28571d9a6fc912f7d5147972f4e11e83a187b Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 13:01:44 -0400 Subject: [PATCH 17/86] Add seed data --- models/Answer.js | 6 +- package.json | 3 +- seeds/answer-seeds.js | 150 ++++++++++++++++++++++++++++++++++++++++++ seeds/index.js | 23 +++++++ seeds/poll-seeds.js | 29 ++++++++ seeds/user-seeds.js | 63 ++++++++++++++++++ 6 files changed, 271 insertions(+), 3 deletions(-) create mode 100644 seeds/answer-seeds.js create mode 100644 seeds/index.js create mode 100644 seeds/poll-seeds.js create mode 100644 seeds/user-seeds.js diff --git a/models/Answer.js b/models/Answer.js index 0b4604b..d9f2538 100644 --- a/models/Answer.js +++ b/models/Answer.js @@ -7,11 +7,13 @@ Answer.init( { poll_id: { type: DataTypes.STRING, - allowNull: false + allowNull: false, + primaryKey: true }, user_id: { type: DataTypes.INTEGER, - allowNull: false + allowNull: false, + primaryKey: true }, option: { type: DataTypes.STRING, diff --git a/package.json b/package.json index 1e39ee3..b8b2bd6 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "node server.js" + "start": "node server.js", + "seed": "node seeds/index.js" }, "repository": { "type": "git", diff --git a/seeds/answer-seeds.js b/seeds/answer-seeds.js new file mode 100644 index 0000000..0696e81 --- /dev/null +++ b/seeds/answer-seeds.js @@ -0,0 +1,150 @@ +const { Answer } = require('../models'); + +const pollData = [ + { + poll_id: 1, + user_id: 2, + option: "Option 1" + }, + { + poll_id: 1, + user_id: 3, + option: "Option 1" + }, + { + poll_id: 1, + user_id: 4, + option: "Option 2" + }, + { + poll_id: 1, + user_id: 5, + option: "Option 4" + }, + { + poll_id: 1, + user_id: 6, + option: "Option 4" + }, + { + poll_id: 1, + user_id: 7, + option: "Option 3" + }, + { + poll_id: 1, + user_id: 8, + option: "Option 1" + }, + { + poll_id: 1, + user_id: 9, + option: "Option 2" + }, + { + poll_id: 1, + user_id: 10, + option: "Option 2" + }, + { + poll_id: 1, + user_id: 11, + option: "Option 1" + }, + + //////////////////////// + + { + poll_id: 2, + user_id: 1, + option: "Blue" + }, + { + poll_id: 2, + user_id: 3, + option: "Purple" + }, + { + poll_id: 2, + user_id: 5, + option: "Red" + }, + { + poll_id: 2, + user_id: 6, + option: "Blue" + }, + { + poll_id: 2, + user_id: 7, + option: "Red" + }, + { + poll_id: 2, + user_id: 10, + option: "Green" + }, + { + poll_id: 2, + user_id: 11, + option: "Red" + }, + + //////////////////////// + + { + poll_id: 3, + user_id: 1, + option: "20-29" + }, + { + poll_id: 3, + user_id: 2, + option: "50-59" + }, + { + poll_id: 3, + user_id: 4, + option: "40-49" + }, + { + poll_id: 3, + user_id: 5, + option: "40-49" + }, + { + poll_id: 3, + user_id: 6, + option: "13-19" + }, + { + poll_id: 3, + user_id: 7, + option: "20-29" + }, + { + poll_id: 3, + user_id: 8, + option: "<13" + }, + { + poll_id: 3, + user_id: 9, + option: "20-29" + }, + { + poll_id: 3, + user_id: 10, + option: "13-19" + }, + { + poll_id: 3, + user_id: 11, + option: "30-39" + }, + +]; + +const seedAnswer = () => Answer.bulkCreate(pollData); + +module.exports = seedAnswer; diff --git a/seeds/index.js b/seeds/index.js new file mode 100644 index 0000000..11a7c59 --- /dev/null +++ b/seeds/index.js @@ -0,0 +1,23 @@ +const seedUsers = require('./user-seeds'); +const seedPolls = require('./poll-seeds'); +const seedAnswers = require('./answer-seeds'); + +const sequelize = require('../config/connection'); + +const seedAll = async () => { + await sequelize.sync({ force: true }); + console.log('\n----- DATABASE SYNCED -----\n'); + await seedUsers(); + console.log('\n----- USERS SEEDED -----\n'); + + await seedPolls(); + console.log('\n----- POLLS SEEDED -----\n'); + + await seedAnswers(); + console.log('\n----- ANSWERS SEEDED -----\n'); + + + process.exit(0); +}; + +seedAll(); diff --git a/seeds/poll-seeds.js b/seeds/poll-seeds.js new file mode 100644 index 0000000..5781ae2 --- /dev/null +++ b/seeds/poll-seeds.js @@ -0,0 +1,29 @@ +const { Poll } = require('../models'); + +const pollData = [ + { + id: 1, + poll_title: 'Sample', + poll_desc: "This is a sample poll.", + poll_options: `"Option 1","Option 2","Option 3","Option 4"`, + poll_userID: 1 + }, + { + id: 2, + poll_title: 'Favorite color', + poll_desc: "What is you favorite color?", + poll_options: `"Red","Green","Blue","Yellow","Orange","Purple"`, + poll_userID: 2 + }, + { + id: 3, + poll_title: 'How old are you?', + poll_desc: "", + poll_options: `"<13","13-19","20-29","30-39","40-49","50-59","60-69","70+"`, + poll_userID: 3 + } +]; + +const seedPolls = () => Poll.bulkCreate(pollData); + +module.exports = seedPolls; diff --git a/seeds/user-seeds.js b/seeds/user-seeds.js new file mode 100644 index 0000000..68dbc65 --- /dev/null +++ b/seeds/user-seeds.js @@ -0,0 +1,63 @@ +const { User } = require('../models'); + +const userData = [ + { + username: 'Lilly_Brooks', + email: 'lilly.b@example.com', + password: 'test.pass1' + }, + { + username: 'Nico_Cannon', + email: 'nico.c@example.com', + password: 'test.pass2' + }, + { + username: 'Dane_Larsen', + email: 'dane.l@example.com', + password: 'test.pass3' + }, + { + username: 'Madelyn_Tucker', + email: 'madelyn.t@example.com', + password: 'test.pass4' + }, + { + username: 'David_Graves', + email: 'david.g@example.com', + password: 'test.pass5' + }, + { + username: 'Noel_Park', + email: 'noel.p@example.com', + password: 'test.pass6' + }, + { + username: 'Samathna_McMillan', + email: 'samantha.m@example.com', + password: 'test.pass7' + }, + { + username: 'Devon_Burnett', + email: 'devon.b@example.com', + password: 'test.pass8' + }, + { + username: 'Jaeden_Rubio', + email: 'jaeden.r@example.com', + password: 'test.pass9' + }, + { + username: 'Joey_Mueller', + email: 'joey.m@example.com', + password: 'test.pass10' + }, + { + username: 'Ruth_Conley', + email: 'ruth.c@example.com', + password: 'test.pass11' + } +]; + +const seedUsers = () => User.bulkCreate(userData, {individualHooks: true}); + +module.exports = seedUsers; From 628c6dba2c47dfa18c591b041929fac362241a26 Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Sat, 13 Aug 2022 17:03:05 -0400 Subject: [PATCH 18/86] Add get poll route --- controllers/home-routes.js | 48 ++++++++++++++-- models/Poll.js | 2 +- models/index.js | 4 +- .../images/logo.png | Bin .../images/logo_w500.png | Bin .../images/logo_w800.png | Bin seeds/answer-seeds.js | 54 +++++++++--------- seeds/poll-seeds.js | 18 +++--- views/homepage.handlebars | 8 +-- views/layouts/main.handlebars | 11 ++-- views/main.html | 40 ------------- views/partials/poll-card.handlebars | 4 +- views/poll.handlebars | 4 ++ 13 files changed, 96 insertions(+), 97 deletions(-) rename "images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer.png" => public/images/logo.png (100%) rename "images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer-p-500.png" => public/images/logo_w500.png (100%) rename "images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer-p-800.png" => public/images/logo_w800.png (100%) delete mode 100644 views/main.html create mode 100644 views/poll.handlebars diff --git a/controllers/home-routes.js b/controllers/home-routes.js index d30b895..14602c2 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -4,7 +4,7 @@ const { Poll, User, Answer } = require('../models'); router.get('/', async (req, res) => { try { const pollData = await Poll.findAll({ - attributes: ['id', 'poll_title', 'poll_desc', 'poll_options', 'poll_userID', 'created_at'], + attributes: ['id', 'poll_title', 'poll_desc', 'poll_options', 'user_id', 'created_at'], include: [ { model: Answer, @@ -22,16 +22,52 @@ router.get('/', async (req, res) => { order: [['created_at', 'DESC']] }); - const polls = pollData.map((post) => + let polls = pollData.map((post) => post.get({ plain: true }) ); - const session_user_id = req.session.user_id; - const data = {session_user_id, polls}; - res.render('homepage', {data, loggedIn: req.session.loggedIn}); + + // const session_user_id = req.session.user_id; + // const data = {session_user_id, polls}; + res.render('homepage', {polls, logged_in: req.session.loggedIn, session_user_id: req.session_user_id}); } catch (err) { console.log(err); res.status(500).json(err); } }); - module.exports = router; \ No newline at end of file +router.get('/poll/:id', async (req, res) => { + try { + const pollData = await Poll.findByPk(req.params.id, { + attributes: ['id', 'poll_title', 'poll_desc', 'poll_options', 'user_id', 'created_at'], + include: [ + { + model: Answer, + where: { poll_id: req.params.id}, + attributes: ['poll_id', 'user_id', 'option'], + include: [ + { + model: User, + attributes: ['username'] + } + ] + }, + { + model: User, + attributes: ['username'] + } + ] + }); + let poll = pollData.get({ plain: true }); + poll.poll_options = JSON.parse(poll.poll_options); + poll.poll_options = poll.poll_options.options.map((o) => JSON.parse(`{"name": "${o}","count": 0}`)); + for (let i = 0; i < poll.answers.length; i++) { + poll.poll_options.find(e => e.name === poll.answers[i].option).count++; + } + res.render('poll', {poll, logged_in: req.session.loggedIn, session_user_id: req.session_user_id}) + } catch (err) { + console.log(err); + res.status(500).json(err); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/models/Poll.js b/models/Poll.js index bae900a..7dd2b7c 100644 --- a/models/Poll.js +++ b/models/Poll.js @@ -32,7 +32,7 @@ Polls.init( allowNull: false }, - poll_userID: { + user_id: { type: DataTypes.INTEGER, allowNull: false } diff --git a/models/index.js b/models/index.js index 8e48a69..7187ace 100644 --- a/models/index.js +++ b/models/index.js @@ -6,12 +6,12 @@ User.hasMany(Poll, {foreignKey: 'user_id'}); User.hasMany(Answer, {foreignKey: 'user_id'}); -Poll.hasMany(Answer, {foreignKey: 'post_id'}); +Poll.hasMany(Answer, {foreignKey: 'poll_id'}); Poll.belongsTo(User, {foreignKey: 'user_id'}); Answer.belongsTo(User, {foreignKey: 'user_id'}); -Answer.belongsTo(Poll, {foreignKey: 'post_id'}); +Answer.belongsTo(Poll, {foreignKey: 'poll_id'}); module.exports = {User, Poll, Answer}; \ No newline at end of file diff --git "a/images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer.png" b/public/images/logo.png similarity index 100% rename from "images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer.png" rename to public/images/logo.png diff --git "a/images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer-p-500.png" b/public/images/logo_w500.png similarity index 100% rename from "images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer-p-500.png" rename to public/images/logo_w500.png diff --git "a/images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer-p-800.png" b/public/images/logo_w800.png similarity index 100% rename from "images/DALL\302\267E-2022-08-08-18.43.47---penguin-using-a-computer-p-800.png" rename to public/images/logo_w800.png diff --git a/seeds/answer-seeds.js b/seeds/answer-seeds.js index 0696e81..406bc4e 100644 --- a/seeds/answer-seeds.js +++ b/seeds/answer-seeds.js @@ -2,52 +2,52 @@ const { Answer } = require('../models'); const pollData = [ { - poll_id: 1, + poll_id: "ABC123", user_id: 2, option: "Option 1" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 3, option: "Option 1" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 4, option: "Option 2" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 5, option: "Option 4" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 6, option: "Option 4" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 7, option: "Option 3" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 8, option: "Option 1" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 9, option: "Option 2" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 10, option: "Option 2" }, { - poll_id: 1, + poll_id: "ABC123", user_id: 11, option: "Option 1" }, @@ -55,37 +55,37 @@ const pollData = [ //////////////////////// { - poll_id: 2, + poll_id: "987CBA", user_id: 1, option: "Blue" }, { - poll_id: 2, + poll_id: "987CBA", user_id: 3, option: "Purple" }, { - poll_id: 2, + poll_id: "987CBA", user_id: 5, option: "Red" }, { - poll_id: 2, + poll_id: "987CBA", user_id: 6, option: "Blue" }, { - poll_id: 2, + poll_id: "987CBA", user_id: 7, option: "Red" }, { - poll_id: 2, + poll_id: "987CBA", user_id: 10, option: "Green" }, { - poll_id: 2, + poll_id: "987CBA", user_id: 11, option: "Red" }, @@ -93,52 +93,52 @@ const pollData = [ //////////////////////// { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 1, option: "20-29" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 2, option: "50-59" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 4, option: "40-49" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 5, option: "40-49" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 6, option: "13-19" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 7, option: "20-29" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 8, option: "<13" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 9, option: "20-29" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 10, option: "13-19" }, { - poll_id: 3, + poll_id: "Z6Y5X4", user_id: 11, option: "30-39" }, diff --git a/seeds/poll-seeds.js b/seeds/poll-seeds.js index 5781ae2..7eaca92 100644 --- a/seeds/poll-seeds.js +++ b/seeds/poll-seeds.js @@ -2,25 +2,25 @@ const { Poll } = require('../models'); const pollData = [ { - id: 1, + id: 'ABC123', poll_title: 'Sample', poll_desc: "This is a sample poll.", - poll_options: `"Option 1","Option 2","Option 3","Option 4"`, - poll_userID: 1 + poll_options: `{"options": ["Option 1", "Option 2", "Option 3", "Option 4"]}`, + user_id: 1 }, { - id: 2, + id: '987CBA', poll_title: 'Favorite color', poll_desc: "What is you favorite color?", - poll_options: `"Red","Green","Blue","Yellow","Orange","Purple"`, - poll_userID: 2 + poll_options: `{"options": ["Red", "Green", "Blue", "Yellow", "Orange", "Purple"]}`, + user_id: 2 }, { - id: 3, + id: 'Z6Y5X4', poll_title: 'How old are you?', poll_desc: "", - poll_options: `"<13","13-19","20-29","30-39","40-49","50-59","60-69","70+"`, - poll_userID: 3 + poll_options: `{"options": ["<13", "13-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70+"]}`, + user_id: 3 } ]; diff --git a/views/homepage.handlebars b/views/homepage.handlebars index 8248ce5..d00f937 100644 --- a/views/homepage.handlebars +++ b/views/homepage.handlebars @@ -1,5 +1,3 @@ -
- {{#each data.polls as |poll|}} - {{> poll-card poll}} - {{/each}} -
\ No newline at end of file +{{#each polls as |poll|}} + {{> poll-card poll}} +{{/each}} \ No newline at end of file diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index b4a528c..2aaa049 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -4,8 +4,8 @@ - - + + @@ -15,7 +15,7 @@
+ {{#if logged_in}} + Dashboard + Logout + {{else}} + Login + Register + {{/if}} + {{#if logged_in}} + + {{/if}} {{{body}}}
diff --git a/views/login.handlebars b/views/login.handlebars new file mode 100644 index 0000000..b873e24 --- /dev/null +++ b/views/login.handlebars @@ -0,0 +1,17 @@ +

Login

+ + + + From e9e22a230c1f45c65d42cf204c0fd98a7af6c764 Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Mon, 15 Aug 2022 20:14:18 -0400 Subject: [PATCH 25/86] Add create-poll page (not working yet) --- controllers/home-routes.js | 13 +++++++----- public/js/create-poll.js | 40 ++++++++++++++++++++++++++++++++++++ views/create-poll.handlebars | 26 +++++++++++++++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 public/js/create-poll.js create mode 100644 views/create-poll.handlebars diff --git a/controllers/home-routes.js b/controllers/home-routes.js index 9a76389..7c6e268 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -61,11 +61,6 @@ router.get('/poll/:id', async (req, res) => { for (let i = 0; i < poll.answers.length; i++) { poll.poll_options.find(e => e.name === poll.answers[i].option).count++; } - // let stringified_options = []; - // for (let option of poll.poll_options) { - // stringified_options.push(`${option.name}:${option.count}`); - // } - // poll.poll_options = stringified_options; res.render('poll', {poll, logged_in: req.session.loggedIn, session_user_id: req.session_user_id}) } catch (err) { @@ -74,4 +69,12 @@ router.get('/poll/:id', async (req, res) => { } }); +router.get('/create', async (req, res) => { + try { + res.render('create-poll', {loggedIn: req.session.loggedIn}); + } catch (err) { + res.status(500).json(err); + } +}); + module.exports = router; \ No newline at end of file diff --git a/public/js/create-poll.js b/public/js/create-poll.js new file mode 100644 index 0000000..7457c6a --- /dev/null +++ b/public/js/create-poll.js @@ -0,0 +1,40 @@ +const pollFormHandler = async (event) => { + event.preventDefault(); + + const poll_title = document.querySelector('input[name="poll-title"]').value.trim(); + const poll_content = document.querySelector('textarea[name="poll-desc"]').value.trim(); + + const optionsSection = $('#poll-options'); + + let poll_options = ""; + for (let option in optionsSection.children()) { + poll_options += option.value; + } + + if (poll_title && poll_content) { + const response = await fetch('/api/posts', { + method: 'POST', + body: JSON.stringify({ post_title: poll_title, post_content: poll_content }), + headers: { 'Content-Type': 'application/json' }, + }); + + if (response.ok) { + document.location.replace('/dashboard'); + } else { + alert('An error occured.'); + } + } + }; + +const addOptionToPoll = async (event) => { + let optionsSection = $('#poll-options'); + // let lineBreak = $('
'); + let newOption = $(''); + newOption.attr('class', 'poll-option'); + newOption.attr('style', 'display:block'); + // optionsSection.append(lineBreak); + optionsSection.append(newOption); +} + + document.querySelector('#submit-post').addEventListener('click', pollFormHandler); + document.querySelector('#add-option').addEventListener('click', addOptionToPoll); \ No newline at end of file diff --git a/views/create-poll.handlebars b/views/create-poll.handlebars new file mode 100644 index 0000000..6ac39fe --- /dev/null +++ b/views/create-poll.handlebars @@ -0,0 +1,26 @@ +
+
+

Create Poll

+
+
+
+ +
+
+ +
+
+ Add option +
+
+ Answer choices: + + +
+
+ +
+
+
+ + \ No newline at end of file From 9e2d72d99bb9cecc4e0d1a8ea0b5e98bad87e7a8 Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Mon, 15 Aug 2022 22:08:41 -0400 Subject: [PATCH 26/86] Add poll creation flow --- controllers/api/index.js | 4 +- controllers/api/poll-routes.js | 73 ++++++++++++++++++++++++++++++++++ controllers/home-routes.js | 5 ++- public/js/create-poll.js | 46 ++++++++++++++++----- utils/auth.js | 11 +++++ views/create-poll.handlebars | 36 +++++++++-------- views/layouts/main.handlebars | 4 +- views/poll.handlebars | 6 ++- 8 files changed, 151 insertions(+), 34 deletions(-) create mode 100644 controllers/api/poll-routes.js create mode 100644 utils/auth.js diff --git a/controllers/api/index.js b/controllers/api/index.js index 8537874..6740bbb 100644 --- a/controllers/api/index.js +++ b/controllers/api/index.js @@ -2,11 +2,11 @@ const router = require('express').Router(); const userRoutes = require('./user-routes'); -//const postRoutes = require('./post-routes'); +const pollRoutes = require('./poll-routes'); //const commentRoutes = require('./comment-routes'); router.use('/users', userRoutes); -//router.use('/posts', postRoutes); +router.use('/polls', pollRoutes); //router.use('/comments', commentRoutes); module.exports = router; \ No newline at end of file diff --git a/controllers/api/poll-routes.js b/controllers/api/poll-routes.js new file mode 100644 index 0000000..e715e6a --- /dev/null +++ b/controllers/api/poll-routes.js @@ -0,0 +1,73 @@ +const router = require('express').Router(); +const { Poll } = require('../../models'); +const withAuth = require('../../utils/auth'); + +router.post('/', withAuth, async (req, res) => { + try { + const data = await Poll.create({ + id: req.body.poll_id, + poll_title: req.body.poll_title, + poll_desc: req.body.poll_content, + poll_options: req.body.poll_options, + user_id: req.session.user_id + }); + res.status(200).json(data); + } catch (err) { + res.status(500).json(err); + } +}); + +router.put('/:id', withAuth, async (req, res) => { + try { + const data = await Post.update({ + post_title: req.body.post_title, + post_content: req.body.post_content + }, + { + where: { + id: req.params.id + } + }); + if (!data) { + res.status(404).json({message: 'No post with this ID'}); + return; + } + res.json(data); + } catch (err) { + res.status(500).json(err); + } +}); + +router.delete('/:id', withAuth, async (req, res) => { + try { + const data = await Post.destroy({ + where: { + id: req.params.id + } + }); + if (!data) { + res.status(404).json({message: 'No post with this ID'}); + return; + } + res.json(data); + } catch (err) { + res.status(500).json(err); + } +}); + +router.get('/:id', async (req, res) => { + try { + const pollData = await Poll.findByPk(req.params.id, { + attributes: ['id'], + }); + if (pollData) { + res.status(200).json(pollData); + } else { + res.status(404).json(pollData); + } + } catch (err) { + res.status(500).json(err); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/controllers/home-routes.js b/controllers/home-routes.js index 8b64702..c0a84e3 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -42,7 +42,7 @@ router.get('/', async (req, res) => { post.get({ plain: true }) ); - res.render('homepage', {polls, logged_in: req.session.loggedIn, session_user_id: req.session_user_id}); + res.render('homepage', {polls, loggedIn: req.session.loggedIn, session_user_id: req.session_user_id}); } catch (err) { console.log(err); res.status(500).json(err); @@ -56,6 +56,7 @@ router.get('/poll/:id', async (req, res) => { include: [ { model: Answer, + required: false, where: { poll_id: req.params.id}, attributes: ['poll_id', 'user_id', 'option'], include: [ @@ -78,7 +79,7 @@ router.get('/poll/:id', async (req, res) => { poll.poll_options.find(e => e.name === poll.answers[i].option).count++; } - res.render('poll', {poll, logged_in: req.session.loggedIn, session_user_id: req.session_user_id}) + res.render('poll', {poll, loggedIn: req.session.loggedIn, session_user_id: req.session_user_id}) } catch (err) { console.log(err); res.status(500).json(err); diff --git a/public/js/create-poll.js b/public/js/create-poll.js index 7457c6a..9fc6a41 100644 --- a/public/js/create-poll.js +++ b/public/js/create-poll.js @@ -1,25 +1,43 @@ const pollFormHandler = async (event) => { event.preventDefault(); + + let poll_id = ""; + let id_exists = true; + + while(id_exists) { + poll_id = await generateID(poll_id); + const checkExists = await fetch(`/api/polls/${poll_id}`, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + if (!checkExists.ok) { + id_exists = false; + } + } const poll_title = document.querySelector('input[name="poll-title"]').value.trim(); - const poll_content = document.querySelector('textarea[name="poll-desc"]').value.trim(); + let poll_desc = document.querySelector('textarea[name="poll-desc"]').value.trim(); + if (!poll_desc) { + poll_desc = ""; + } const optionsSection = $('#poll-options'); - let poll_options = ""; - for (let option in optionsSection.children()) { - poll_options += option.value; + let poll_options = `{"options": [`; + for (let option of optionsSection.children()) { + poll_options += `"${option.value}", `; } + poll_options = poll_options.slice(0, -2) + `]}`; - if (poll_title && poll_content) { - const response = await fetch('/api/posts', { + if (poll_title) { + const response = await fetch('/api/polls', { method: 'POST', - body: JSON.stringify({ post_title: poll_title, post_content: poll_content }), + body: JSON.stringify({ poll_id: poll_id, poll_title: poll_title, poll_desc: poll_desc, poll_options: poll_options }), headers: { 'Content-Type': 'application/json' }, }); if (response.ok) { - document.location.replace('/dashboard'); + document.location.replace(`/poll/${poll_id}`); } else { alert('An error occured.'); } @@ -32,9 +50,19 @@ const addOptionToPoll = async (event) => { let newOption = $(''); newOption.attr('class', 'poll-option'); newOption.attr('style', 'display:block'); + newOption.attr('required', true); // optionsSection.append(lineBreak); optionsSection.append(newOption); } - document.querySelector('#submit-post').addEventListener('click', pollFormHandler); +async function generateID(code) { + let characterSelection = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + let codeLength = code.length == 0 ? 6 : 1; + for (i = 0; i < codeLength; i++) { + code += characterSelection.charAt(Math.floor(Math.random() * characterSelection.length)) + } + return code; +} + + document.querySelector('#create-form').addEventListener('submit', pollFormHandler); document.querySelector('#add-option').addEventListener('click', addOptionToPoll); \ No newline at end of file diff --git a/utils/auth.js b/utils/auth.js new file mode 100644 index 0000000..2a9f0f1 --- /dev/null +++ b/utils/auth.js @@ -0,0 +1,11 @@ +const withAuth = (req, res, next) => { + // If the user is not logged in, redirect the request to the login route + if (!req.session.loggedIn) { + res.redirect('/login'); + } else { + next(); + } + }; + + module.exports = withAuth; + \ No newline at end of file diff --git a/views/create-poll.handlebars b/views/create-poll.handlebars index 6ac39fe..892df3a 100644 --- a/views/create-poll.handlebars +++ b/views/create-poll.handlebars @@ -3,23 +3,25 @@

Create Poll

-
- -
-
- -
-
- Add option -
-
- Answer choices: - - -
-
- -
+
+
+ +
+
+ +
+
+ Add option +
+
+ Answer choices: + + +
+
+ +
+
diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index b908656..6b72bcb 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -35,14 +35,14 @@
- {{#if logged_in}} + {{#if loggedIn}} Dashboard Logout {{else}} Login Register {{/if}} - {{#if logged_in}} + {{#if loggedIn}} {{/if}} {{{body}}} diff --git a/views/poll.handlebars b/views/poll.handlebars index 363bd92..a84d30e 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -1,4 +1,6 @@ -Poll: {{poll.poll_title}} - Made by: {{poll.user.username}}
+
+

Poll: {{poll.poll_title}} - Made by: {{poll.user.username}}

+

Share code: {{poll.id}}

>
@@ -10,6 +12,6 @@ Poll: {{poll.poll_title}} - Made by: {{poll.user.username}}
- +
\ No newline at end of file From 34aa36d380daedac1c294bcedb4ce0a4dcf9450d Mon Sep 17 00:00:00 2001 From: Jared Daniel Date: Tue, 16 Aug 2022 00:24:47 -0400 Subject: [PATCH 27/86] Add search field functionality, add option to remove extra options in poll create, add ability to register a new account, limit homepage to 5 most recent polls --- README.md | 2 +- controllers/home-routes.js | 3 ++- public/js/create-poll.js | 41 ++++++++++++++++++++++++++--------- public/js/login.js | 5 ----- public/js/logout.js | 7 +----- public/js/register.js | 23 ++++++++++++++++++++ public/js/search.js | 19 ++++++++++++++++ views/create-poll.handlebars | 4 ++-- views/layouts/main.handlebars | 12 ++++++---- views/login.handlebars | 31 +++++++++++++------------- views/register.handlebars | 27 +++++++++++++++++++++++ 11 files changed, 130 insertions(+), 44 deletions(-) create mode 100644 public/js/register.js create mode 100644 public/js/search.js create mode 100644 views/register.handlebars diff --git a/README.md b/README.md index fd22f62..eef5875 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Heroku: https://poll-together.herokuapp.com/ ```md AS A bootcam teacher I WANT to be able to get input from my students -SO THAT make sure that everyone understands and is participating +SO THAT I can make sure that everyone understands and is participating ``` ## Acceptance Criteria diff --git a/controllers/home-routes.js b/controllers/home-routes.js index c0a84e3..55ab9d5 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -35,7 +35,8 @@ router.get('/', async (req, res) => { attributes: ['username'] } ], - order: [['created_at', 'DESC']] + order: [['created_at', 'DESC']], + limit: 5 }); let polls = pollData.map((post) => diff --git a/public/js/create-poll.js b/public/js/create-poll.js index 9fc6a41..4700364 100644 --- a/public/js/create-poll.js +++ b/public/js/create-poll.js @@ -16,16 +16,13 @@ const pollFormHandler = async (event) => { } const poll_title = document.querySelector('input[name="poll-title"]').value.trim(); - let poll_desc = document.querySelector('textarea[name="poll-desc"]').value.trim(); - if (!poll_desc) { - poll_desc = ""; - } + const poll_desc = document.querySelector('textarea[name="poll-desc"]').value.trim(); const optionsSection = $('#poll-options'); let poll_options = `{"options": [`; for (let option of optionsSection.children()) { - poll_options += `"${option.value}", `; + poll_options += `"${option.children[0].value}", `; } poll_options = poll_options.slice(0, -2) + `]}`; @@ -46,15 +43,38 @@ const pollFormHandler = async (event) => { const addOptionToPoll = async (event) => { let optionsSection = $('#poll-options'); - // let lineBreak = $('
'); + let newRow = $('
'); let newOption = $(''); newOption.attr('class', 'poll-option'); - newOption.attr('style', 'display:block'); + // newOption.attr('style', 'display:block'); newOption.attr('required', true); - // optionsSection.append(lineBreak); - optionsSection.append(newOption); + newRow.append(newOption); + // optionsSection.append(newOption); + + let removeOptionLink = $(''); + removeOptionLink.attr('href', '#'); + removeOptionLink.attr('class', 'remove-option'); + removeOptionLink.text('remove'); + newRow.append(removeOptionLink); + + optionsSection.append(newRow); } +const removeOptionFromPoll = async (event) => { + if (event.target.className === 'remove-option') { + let optionList = event.target.parentNode.parentNode; + optionList.removeChild(event.target.parentNode); + } +} + +// optionsElement.on('click', function(event) { +// var clickedElement = $(event.target); +// if (clickedElement.hasClass('remove-option')) { +// let test = clickedElement.siblings()[0]; +// } +// let test = clickedElement.siblings()[0]; +// }); + async function generateID(code) { let characterSelection = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; let codeLength = code.length == 0 ? 6 : 1; @@ -65,4 +85,5 @@ async function generateID(code) { } document.querySelector('#create-form').addEventListener('submit', pollFormHandler); - document.querySelector('#add-option').addEventListener('click', addOptionToPoll); \ No newline at end of file + document.querySelector('#add-option').addEventListener('click', addOptionToPoll); + document.querySelector('#poll-options').addEventListener('click', removeOptionFromPoll); \ No newline at end of file diff --git a/public/js/login.js b/public/js/login.js index f6c2cc9..e528047 100644 --- a/public/js/login.js +++ b/public/js/login.js @@ -1,8 +1,3 @@ -// KEY VARIABLE NAMES -// #email-login (line 7) to reference the login field in the login view -// #password-login (line 8) to reference the password field in the login view -// 'submit' (line 29) for the button to initiate the login scripting - const loginFormHandler = async (event) => { event.preventDefault(); diff --git a/public/js/logout.js b/public/js/logout.js index 37d825c..a240436 100644 --- a/public/js/logout.js +++ b/public/js/logout.js @@ -1,8 +1,3 @@ -// KEY VARIABLE NAMES -// #logout (line 19) to reference the logout element -// 'click' (line 19) for the button to initiate the login scripting - - const logout = async () => { const response = await fetch('/api/users/logout', { method: 'POST', @@ -10,7 +5,7 @@ const logout = async () => { }); if (response.ok) { - document.location.replace('/login'); + document.location.replace('/'); } else { alert(response.statusText); } diff --git a/public/js/register.js b/public/js/register.js new file mode 100644 index 0000000..2c366a6 --- /dev/null +++ b/public/js/register.js @@ -0,0 +1,23 @@ +const registerFormHandler = async (event) => { + event.preventDefault(); + + const username = document.querySelector('#username-register').value.trim(); + const email = document.querySelector('#email-register').value.trim(); + const password = document.querySelector('#password-register').value.trim(); + + if (username && email && password) { + const response = await fetch('/api/users', { + method: 'POST', + body: JSON.stringify({ username, email, password }), + headers: { 'Content-Type': 'application/json' }, + }); + + if (response.ok) { + document.location.replace('/'); + } else { + alert('Failed to sign up.'); + } + } +}; + +document.querySelector('.register-form').addEventListener('submit', registerFormHandler); \ No newline at end of file diff --git a/public/js/search.js b/public/js/search.js new file mode 100644 index 0000000..a36fb34 --- /dev/null +++ b/public/js/search.js @@ -0,0 +1,19 @@ +const searchPolls = async (event) => { + + const poll_id = document.querySelector('input[name="query"]').value.trim(); + + if (poll_id) { + const checkExists = await fetch(`/api/polls/${poll_id}`, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (checkExists.ok) { + document.location.replace(`/poll/${poll_id}`); + } else { + alert('No poll with that ID.'); + } + } +}; + +document.querySelector('#poll-search').addEventListener('submit', searchPolls); \ No newline at end of file diff --git a/views/create-poll.handlebars b/views/create-poll.handlebars index 892df3a..33c137f 100644 --- a/views/create-poll.handlebars +++ b/views/create-poll.handlebars @@ -15,8 +15,8 @@
Answer choices: - - +
+
diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index 6b72bcb..1640dbf 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -16,7 +16,7 @@
-
+
@@ -43,11 +47,11 @@ Register {{/if}} {{#if loggedIn}} - + {{/if}} {{{body}}}
- {{!-- --}} + diff --git a/views/login.handlebars b/views/login.handlebars index b873e24..d8da068 100644 --- a/views/login.handlebars +++ b/views/login.handlebars @@ -1,17 +1,18 @@ -

Login

- - +
+
Login
+ +
diff --git a/views/register.handlebars b/views/register.handlebars new file mode 100644 index 0000000..a1d8ca8 --- /dev/null +++ b/views/register.handlebars @@ -0,0 +1,27 @@ +
+
+ Register +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+ \ No newline at end of file From f27130253032f4584517fc59db8ba087eb03a0fe Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 05:00:38 -0400 Subject: [PATCH 28/86] Hooks: add hash password before update --- models/User.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/models/User.js b/models/User.js index 64b9f92..0fc97d5 100644 --- a/models/User.js +++ b/models/User.js @@ -42,6 +42,12 @@ User.init( newUserData.password = await bcrypt.hash(newUserData.password, 10); return newUserData; }, + beforeUpdate: async (updatedUserData) => { + if (updatedUserData.password) { + updatedUserData.password = await bcrypt.hash(updatedUserData.password, 10); + } + return updatedUserData; + }, }, sequelize, timestamps: false, From 4f23632fdde2700da409b386c4efef55aae611c9 Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 05:04:24 -0400 Subject: [PATCH 29/86] password validation msg --- models/User.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/User.js b/models/User.js index 0fc97d5..5cf76ba 100644 --- a/models/User.js +++ b/models/User.js @@ -32,7 +32,7 @@ User.init( type: DataTypes.STRING, allowNull: false, validate: { - len: [8], + len: {args: [8], msg: 'password length should not be than 8 characters'}, }, }, }, From c03d2bb24703b80e055f38e148de008c0a643c96 Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 15:12:10 -0400 Subject: [PATCH 30/86] user linked to the poll by adding references --- config/connection.js | 11 +++++++---- models/Poll.js | 6 +++++- server.js | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/config/connection.js b/config/connection.js index 7e67099..4e6c830 100644 --- a/config/connection.js +++ b/config/connection.js @@ -1,17 +1,20 @@ -const Sequelize = require('sequelize'); -require('dotenv').config(); +// const Sequelize = require('sequelize'); +// require('dotenv').config(); + +// const sequelize = new Sequelize(process.env.JAWSDB_URL || process.env.MYSQL_URI) + let sequelize; if (process.env.JAWSDB_URL) { - sequelize = new Sequelize(process.env.JAWSDB_URL); + sequelize = new Sequelize(process.env.JAWSDB_URL) } else { sequelize = new Sequelize( process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, { - host: 'localhost', + host: '127.0.0.1', dialect: 'mysql', port: 3306, } diff --git a/models/Poll.js b/models/Poll.js index 7dd2b7c..b3186bc 100644 --- a/models/Poll.js +++ b/models/Poll.js @@ -34,7 +34,11 @@ Polls.init( user_id: { type: DataTypes.INTEGER, - allowNull: false + allowNull: false, + references: { + model: 'user', + key: 'id' + } } }, diff --git a/server.js b/server.js index 4b1e641..c506020 100644 --- a/server.js +++ b/server.js @@ -39,6 +39,6 @@ app.use(routes); sequelize.sync({ force: false }).then(() => { app.listen(PORT, () => - console.log(`\nServer running: http://localhost:${PORT}`) + console.log(`\nServer running: http://127.0.0.1:${PORT}`) ); }); \ No newline at end of file From 83377d923418f0f8a09faf45b8de6fcb9e0f58a4 Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 15:28:32 -0400 Subject: [PATCH 31/86] Poll linked to the Answer by adding references --- models/Answer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/models/Answer.js b/models/Answer.js index d9f2538..3dddf7b 100644 --- a/models/Answer.js +++ b/models/Answer.js @@ -8,7 +8,11 @@ Answer.init( poll_id: { type: DataTypes.STRING, allowNull: false, - primaryKey: true + // primaryKey: true + references: { + model: 'polls', + key: 'id' + } }, user_id: { type: DataTypes.INTEGER, From fb0fdd5705db65a9698a5facd05c5dd7caaea4aa Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 15:31:27 -0400 Subject: [PATCH 32/86] User linked to Answer by adding references --- models/Answer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/models/Answer.js b/models/Answer.js index 3dddf7b..900072b 100644 --- a/models/Answer.js +++ b/models/Answer.js @@ -17,7 +17,11 @@ Answer.init( user_id: { type: DataTypes.INTEGER, allowNull: false, - primaryKey: true + // primaryKey: true + references: { + model: 'user', + key: 'id' + } }, option: { type: DataTypes.STRING, From 290c83068d9067f806e6523698d3022cbb9e14cc Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 15:56:12 -0400 Subject: [PATCH 33/86] onDelete: CASCADE,for user --- models/index.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/models/index.js b/models/index.js index 7187ace..640dc51 100644 --- a/models/index.js +++ b/models/index.js @@ -2,9 +2,17 @@ const User = require('./User'); const Poll = require('./Poll'); const Answer = require('./Answer'); -User.hasMany(Poll, {foreignKey: 'user_id'}); +//A user might have many polls but when deleted then his polls are deleted as well +User.hasMany(Poll, { + foreignKey: 'user_id', + onDelete: 'CASCADE', +}); -User.hasMany(Answer, {foreignKey: 'user_id'}); +//A user might have many answers but when deleted then his answers are deleted as well +User.hasMany(Answer, { + foreignKey: 'user_id', + onDelete: 'CASCADE', +}); Poll.hasMany(Answer, {foreignKey: 'poll_id'}); From 6f2d0af6315ea3890de012f2c44f317ea2364bcf Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 16:30:29 -0400 Subject: [PATCH 34/86] Get all users with their polls and answers --- controllers/api/user-routes.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/controllers/api/user-routes.js b/controllers/api/user-routes.js index e19d8a1..48e6d5d 100644 --- a/controllers/api/user-routes.js +++ b/controllers/api/user-routes.js @@ -1,5 +1,5 @@ const router = require('express').Router(); -const { User } = require('../../models'); +const { User, Poll, Answer } = require('../../models'); router.post('/', async (req, res) => { try { @@ -70,6 +70,20 @@ router.post('/', async (req, res) => { res.status(404).end(); } }); + + + // GET all users with their polls and answers +router.get('/', async (req, res) => { + try { + const userData = await User.findAll({ + include: [{ model: Poll }, { model: Answer }], + }); + res.status(200).json(userData); + } catch (err) { + res.status(500).json(err); + } +}); + module.exports = router; From 9ca92a0f5494f3ec6a7c762855bf9b193720d95d Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 16:47:41 -0400 Subject: [PATCH 35/86] Get a single user by his id --- controllers/api/user-routes.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/controllers/api/user-routes.js b/controllers/api/user-routes.js index 48e6d5d..eae26d3 100644 --- a/controllers/api/user-routes.js +++ b/controllers/api/user-routes.js @@ -71,7 +71,6 @@ router.post('/', async (req, res) => { } }); - // GET all users with their polls and answers router.get('/', async (req, res) => { try { @@ -84,6 +83,23 @@ router.get('/', async (req, res) => { } }); +// GET a single user +router.get('/:id', async (req, res) => { + try { + const userData = await User.findByPk(req.params.id, { + include: [{ model: Poll }, { model: Answer }], + }); + + if (!userData) { + res.status(404).json({ message: 'No user found with that id!' }); + return; + } + + res.status(200).json(userData); + } catch (err) { + res.status(500).json(err); + } +}); module.exports = router; From c0b62835023d386a1cde710ac29888ddd2652bd0 Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 17:12:00 -0400 Subject: [PATCH 36/86] Get a poll with the pollar and his answer --- controllers/api/poll-routes.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/controllers/api/poll-routes.js b/controllers/api/poll-routes.js index e715e6a..25b4570 100644 --- a/controllers/api/poll-routes.js +++ b/controllers/api/poll-routes.js @@ -55,16 +55,20 @@ router.delete('/:id', withAuth, async (req, res) => { } }); +//Get a poll with the pollar and his answer router.get('/:id', async (req, res) => { try { const pollData = await Poll.findByPk(req.params.id, { + include: [{ model: User }, { model: Answer }], attributes: ['id'], }); - if (pollData) { - res.status(200).json(pollData); - } else { - res.status(404).json(pollData); - } + + if (!pollData) { + res.status(404).json({message: 'No poll with this ID'}); + return; + } + + res.status(200).json(pollData); } catch (err) { res.status(500).json(err); } From c427ca63a92fa9acde69e706e517026ef793bb31 Mon Sep 17 00:00:00 2001 From: Bocar Ly Date: Wed, 17 Aug 2022 17:18:27 -0400 Subject: [PATCH 37/86] Get all the polls with their pollars and answers --- controllers/api/poll-routes.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/controllers/api/poll-routes.js b/controllers/api/poll-routes.js index 25b4570..210b5ce 100644 --- a/controllers/api/poll-routes.js +++ b/controllers/api/poll-routes.js @@ -55,6 +55,21 @@ router.delete('/:id', withAuth, async (req, res) => { } }); + + // GET all the polls with their pollars and answer + router.get('/', async (req, res) => { + try { + const pollData = await Poll.findAll({ + include: [{ model: User }, { model: Answer }], + }); + res.status(200).json(pollData); + } catch (err) { + res.status(500).json(err); + } + }); + + + //Get a poll with the pollar and his answer router.get('/:id', async (req, res) => { try { From 741aa56da171e5f2814240384c59f46db76d65ff Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Wed, 17 Aug 2022 18:45:20 -0400 Subject: [PATCH 38/86] Update homepage --- controllers/api/poll-routes.js | 2 +- controllers/home-routes.js | 8 +++++ public/css/style.css | 36 +++++++++++++++++++++ public/js/poll-cards.js | 49 +++++++++++++++++++++++++++++ public/js/poll.js | 2 +- views/homepage.handlebars | 4 ++- views/layouts/main.handlebars | 8 ++--- views/partials/poll-card.handlebars | 27 ++++++++++++++-- views/poll.handlebars | 8 +++-- 9 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 public/js/poll-cards.js diff --git a/controllers/api/poll-routes.js b/controllers/api/poll-routes.js index e715e6a..dddeea1 100644 --- a/controllers/api/poll-routes.js +++ b/controllers/api/poll-routes.js @@ -7,7 +7,7 @@ router.post('/', withAuth, async (req, res) => { const data = await Poll.create({ id: req.body.poll_id, poll_title: req.body.poll_title, - poll_desc: req.body.poll_content, + poll_desc: req.body.poll_desc, poll_options: req.body.poll_options, user_id: req.session.user_id }); diff --git a/controllers/home-routes.js b/controllers/home-routes.js index 55ab9d5..55f5a13 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -43,6 +43,14 @@ router.get('/', async (req, res) => { post.get({ plain: true }) ); + for(let poll of polls) { + poll.poll_options = JSON.parse(poll.poll_options); + poll.poll_options = poll.poll_options.options.map((o) => JSON.parse(`{"name": "${o}","count": 0}`)); + for (let i = 0; i < poll.answers.length; i++) { + poll.poll_options.find(e => e.name === poll.answers[i].option).count++; + } + } + res.render('homepage', {polls, loggedIn: req.session.loggedIn, session_user_id: req.session_user_id}); } catch (err) { console.log(err); diff --git a/public/css/style.css b/public/css/style.css index cacf0a4..e24421a 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,3 +1,39 @@ +.poll-card { + border: 1px solid black; + border-radius: 10px; + width: 600px; + margin: 10px auto; + /* padding: 10px; */ +} + +.poll-card-desc a:link, .poll-card-desc a:visited { + text-decoration: none; + color: black; +} + +.poll-card-desc { + padding: 10px; +} + +.poll-card-header { + display: flex; + justify-content: space-between; + padding-top: 6px; + padding-bottom: 6px; + padding-left: 10px; + padding-right: 10px; + background: #b2e7d1; + color: black; + border-top-left-radius: 10px; + border-top-right-radius: 10px; +} + +.poll-card-header a { + text-decoration: none; + color: black; + font-weight: bold; +} + .navbar-no-shadow-container { z-index: 5; width: 100%; diff --git a/public/js/poll-cards.js b/public/js/poll-cards.js new file mode 100644 index 0000000..9bc4aa2 --- /dev/null +++ b/public/js/poll-cards.js @@ -0,0 +1,49 @@ +const pollIDs = document.querySelectorAll('input[name="poll-id"'); +const pollTitles = document.querySelectorAll('input[name="poll-title"'); +const pollContents = document.querySelectorAll('textarea[name="poll-content"'); +for (let i = 0; i < pollTitles.length; i++) { + let pollID = pollIDs[i].value; + let pollTitle = pollTitles[i].value; + let pollContent = pollContents[i].value.trim(); + + const pollValues = pollContent.split('\n'); + + const labels = []; + const answers = []; + + for (let option of pollValues) { + labels.push(option.substring(0, option.lastIndexOf(':'))); + answers.push(option.substring(option.lastIndexOf(':') + 1)); + } + + const data = { + labels: labels, + datasets: [{ + axis: 'y', + label: pollTitle, + backgroundColor: 'rgb(255, 99, 132)', + borderColor: 'rgb(255, 99, 132)', + borderWidth: 1, + data: answers, + }] + }; + + const config = { + type: 'bar', + data: data, + options: { + indexAxis: 'y', + // categoryThickness: 40, + // barThickness: 30, + responsive: true, + plugins: { + legend: {display: false}, + } + } + }; + + const myChart = new Chart( + document.getElementById(`chart-${pollID}`), + config + ); +} \ No newline at end of file diff --git a/public/js/poll.js b/public/js/poll.js index 604ffb9..969e388 100644 --- a/public/js/poll.js +++ b/public/js/poll.js @@ -29,6 +29,6 @@ for (let option of pollValues) { }; const myChart = new Chart( - document.getElementById('test-chart'), + document.getElementById('chart'), config ); \ No newline at end of file diff --git a/views/homepage.handlebars b/views/homepage.handlebars index d00f937..acc761f 100644 --- a/views/homepage.handlebars +++ b/views/homepage.handlebars @@ -1,3 +1,5 @@ {{#each polls as |poll|}} {{> poll-card poll}} -{{/each}} \ No newline at end of file +{{/each}} + + \ No newline at end of file diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index 1640dbf..4e0a783 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -45,13 +45,13 @@ {{else}} Login Register - {{/if}} - {{#if loggedIn}} - - {{/if}} + {{/if}} {{{body}}}
+ {{#if loggedIn}} + + {{/if}} diff --git a/views/partials/poll-card.handlebars b/views/partials/poll-card.handlebars index d5245d1..87ced85 100644 --- a/views/partials/poll-card.handlebars +++ b/views/partials/poll-card.handlebars @@ -1,3 +1,24 @@ -
- Poll: {{poll_title}} - Made by: {{user.username}} -
\ No newline at end of file +
+
+ + {{!-- Need user profile link here --}} +
+
+ +
+ {{poll_desc}} + +
+ + + +
+ Click here to vote! +
+
+
+
diff --git a/views/poll.handlebars b/views/poll.handlebars index a84d30e..55cd228 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -1,7 +1,9 @@

Poll: {{poll.poll_title}} - Made by: {{poll.user.username}}

-

Share code: {{poll.id}}

> - +

Share code: {{poll.id}}

+
+ {{poll.poll_desc}} +
@@ -10,7 +12,7 @@ {{option.name}}:{{option.count}} {{/each}} - +
From f2258e957ef879e179c745aa9cdf5be890156803 Mon Sep 17 00:00:00 2001 From: VT_AOE_91 Date: Wed, 17 Aug 2022 19:13:02 -0400 Subject: [PATCH 39/86] Added model config for poll expiration date --- models/Poll.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/models/Poll.js b/models/Poll.js index 7dd2b7c..2fb1773 100644 --- a/models/Poll.js +++ b/models/Poll.js @@ -35,7 +35,12 @@ Polls.init( user_id: { type: DataTypes.INTEGER, allowNull: false - } + }, + + poll_expire: { + type: DataTypes.DATE, + allowNull: true + } }, { From 34435dc8e47cd583aa3ce7e340a77a3d650d785c Mon Sep 17 00:00:00 2001 From: Michael Sullivan <104106828+ms13380@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:27:01 -0400 Subject: [PATCH 40/86] Update main.handlebars --- views/layouts/main.handlebars | 1 + 1 file changed, 1 insertion(+) diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index 4e0a783..9225089 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -47,6 +47,7 @@ Register {{/if}} {{{body}}} +
From 49db059c356af9e2b8be8189b0fae36c3e3f233c Mon Sep 17 00:00:00 2001 From: VT_AOE_91 Date: Wed, 17 Aug 2022 19:40:07 -0400 Subject: [PATCH 41/86] Added expiration date functionality --- controllers/api/poll-routes.js | 3 ++- public/js/create-poll.js | 3 ++- views/create-poll.handlebars | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/controllers/api/poll-routes.js b/controllers/api/poll-routes.js index dddeea1..ffa5f19 100644 --- a/controllers/api/poll-routes.js +++ b/controllers/api/poll-routes.js @@ -9,7 +9,8 @@ router.post('/', withAuth, async (req, res) => { poll_title: req.body.poll_title, poll_desc: req.body.poll_desc, poll_options: req.body.poll_options, - user_id: req.session.user_id + user_id: req.session.user_id, + poll_expire: req.body.poll_expire }); res.status(200).json(data); } catch (err) { diff --git a/public/js/create-poll.js b/public/js/create-poll.js index 4700364..c1a96e4 100644 --- a/public/js/create-poll.js +++ b/public/js/create-poll.js @@ -17,6 +17,7 @@ const pollFormHandler = async (event) => { const poll_title = document.querySelector('input[name="poll-title"]').value.trim(); const poll_desc = document.querySelector('textarea[name="poll-desc"]').value.trim(); + const poll_expire = document.querySelector('input[name="poll-exp"]').value.trim(); const optionsSection = $('#poll-options'); @@ -29,7 +30,7 @@ const pollFormHandler = async (event) => { if (poll_title) { const response = await fetch('/api/polls', { method: 'POST', - body: JSON.stringify({ poll_id: poll_id, poll_title: poll_title, poll_desc: poll_desc, poll_options: poll_options }), + body: JSON.stringify({ poll_id: poll_id, poll_expire: poll_expire, poll_title: poll_title, poll_desc: poll_desc, poll_options: poll_options }), headers: { 'Content-Type': 'application/json' }, }); diff --git a/views/create-poll.handlebars b/views/create-poll.handlebars index 33c137f..1e8c6b4 100644 --- a/views/create-poll.handlebars +++ b/views/create-poll.handlebars @@ -15,6 +15,7 @@
Answer choices: +
From ba3074049d8d240bec464a94a3fc0bbf7b7f016b Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:53:26 -0400 Subject: [PATCH 42/86] Hompage has 6 polls --- controllers/api/poll-routes.js | 5 ++--- controllers/home-routes.js | 2 +- views/homepage.handlebars | 8 +++++--- views/poll.handlebars | 4 ++++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/controllers/api/poll-routes.js b/controllers/api/poll-routes.js index dddeea1..92537b5 100644 --- a/controllers/api/poll-routes.js +++ b/controllers/api/poll-routes.js @@ -19,9 +19,8 @@ router.post('/', withAuth, async (req, res) => { router.put('/:id', withAuth, async (req, res) => { try { - const data = await Post.update({ - post_title: req.body.post_title, - post_content: req.body.post_content + const data = await Poll.update({ + poll_desc: req.body.poll_content }, { where: { diff --git a/controllers/home-routes.js b/controllers/home-routes.js index 55f5a13..be9be90 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -36,7 +36,7 @@ router.get('/', async (req, res) => { } ], order: [['created_at', 'DESC']], - limit: 5 + limit: 6 }); let polls = pollData.map((post) => diff --git a/views/homepage.handlebars b/views/homepage.handlebars index acc761f..dd06acb 100644 --- a/views/homepage.handlebars +++ b/views/homepage.handlebars @@ -1,5 +1,7 @@ -{{#each polls as |poll|}} - {{> poll-card poll}} -{{/each}} +
+ {{#each polls as |poll|}} + {{> poll-card poll}} + {{/each}} +
\ No newline at end of file diff --git a/views/poll.handlebars b/views/poll.handlebars index 55cd228..c7e2cf6 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -5,6 +5,10 @@ {{poll.poll_desc}} +
+ +
+
+
+ Click here to vote! + + + + From d5431c89f529983432ae4ded4cb1a27e983fcae7 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Wed, 17 Aug 2022 23:10:19 -0400 Subject: [PATCH 57/86] Voting completed and check poll_expire before allowing vote --- controllers/api/answer-routes.js | 1 - controllers/home-routes.js | 23 ++++++++++++++++++++--- public/js/create-poll.js | 5 +++++ public/js/poll-cards.js | 2 -- public/js/poll.js | 7 ++++++- utils/helpers.js | 20 ++++++++++++++++++++ utils/helpers/randID.js | 12 ------------ views/create-poll.handlebars | 5 ++++- views/poll.handlebars | 7 +++---- 9 files changed, 58 insertions(+), 24 deletions(-) delete mode 100644 utils/helpers/randID.js diff --git a/controllers/api/answer-routes.js b/controllers/api/answer-routes.js index 6e0388a..c6cc1a0 100644 --- a/controllers/api/answer-routes.js +++ b/controllers/api/answer-routes.js @@ -15,5 +15,4 @@ router.post('/', withAuth, async (req, res) => { } }); - module.exports = router; \ No newline at end of file diff --git a/controllers/home-routes.js b/controllers/home-routes.js index be9be90..1ddb83b 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -61,12 +61,12 @@ router.get('/', async (req, res) => { router.get('/poll/:id', async (req, res) => { try { const pollData = await Poll.findByPk(req.params.id, { - attributes: ['id', 'poll_title', 'poll_desc', 'poll_options', 'user_id', 'created_at'], + attributes: ['id', 'poll_title', 'poll_desc', 'poll_options', 'user_id', 'poll_expire', 'created_at'], include: [ { model: Answer, required: false, - where: { poll_id: req.params.id}, + where: { poll_id: req.params.id }, attributes: ['poll_id', 'user_id', 'option'], include: [ { @@ -88,7 +88,24 @@ router.get('/poll/:id', async (req, res) => { poll.poll_options.find(e => e.name === poll.answers[i].option).count++; } - res.render('poll', {poll, loggedIn: req.session.loggedIn, session_user_id: req.session_user_id}) + let userCanVote = false; + if (req.session.loggedIn) { + const expiration = poll.poll_expire ? new Date(new Date(poll.poll_expire).toUTCString()) : null; + const today = new Date(new Date().toUTCString()); + if(expiration == null || expiration > today) { + const voteExists = await Answer.findOne({ + where: { + poll_id: poll.id, + user_id: req.session.user_id + } + }); + if (voteExists == null) { + userCanVote = true; + } + } + } + + res.render('poll', {poll, loggedIn: req.session.loggedIn, userCanVote: userCanVote, session_user_id: req.session_user_id}) } catch (err) { console.log(err); res.status(500).json(err); diff --git a/public/js/create-poll.js b/public/js/create-poll.js index 9adeb27..b13eb1e 100644 --- a/public/js/create-poll.js +++ b/public/js/create-poll.js @@ -20,6 +20,11 @@ const pollFormHandler = async (event) => { let poll_expire = document.querySelector('input[name="poll-exp"]').value.trim(); if (poll_expire == '') { poll_expire = null; + } else { + poll_expire = new Date(poll_expire); + // poll_expire = Date.UTC(poll_expire.getUTCFullYear(), poll_expire.getUTCMonth(), poll_expire.getUTCDate(), poll_expire.getUTCHours(), + // poll_expire.getUTCMinutes(), poll_expire.getUTCSeconds()); + poll_expire = poll_expire.toUTCString(); } const optionsSection = $('#poll-options'); diff --git a/public/js/poll-cards.js b/public/js/poll-cards.js index 9bc4aa2..6aac918 100644 --- a/public/js/poll-cards.js +++ b/public/js/poll-cards.js @@ -33,8 +33,6 @@ for (let i = 0; i < pollTitles.length; i++) { data: data, options: { indexAxis: 'y', - // categoryThickness: 40, - // barThickness: 30, responsive: true, plugins: { legend: {display: false}, diff --git a/public/js/poll.js b/public/js/poll.js index 969e388..7182753 100644 --- a/public/js/poll.js +++ b/public/js/poll.js @@ -25,7 +25,12 @@ for (let option of pollValues) { const config = { type: 'bar', data: data, - options: {indexAxis: 'y'} + options: { + indexAxis: 'y', + plugins: { + legend: {display: false}, + } + } }; const myChart = new Chart( diff --git a/utils/helpers.js b/utils/helpers.js index e69de29..6d20a24 100644 --- a/utils/helpers.js +++ b/utils/helpers.js @@ -0,0 +1,20 @@ +const { options } = require("../controllers"); + +module.exports = { + format_date: (date) => { + return `${new Date(date).getMonth() + 1}/${new Date(date).getDate()}/${new Date(date).getFullYear()} (${new Date(date).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})})`; + }, + possessive_grammar: (name) => { + if(name) { + if (name.charAt(name.length - 1) === 's') + return name + '\''; + else { + return name + '\'s'; + } + } + return ""; + }, + format_content: (text) => { + return text.replace(/(?:\r\n|\r|\n)/g, '
'); + } +}; diff --git a/utils/helpers/randID.js b/utils/helpers/randID.js deleted file mode 100644 index 8a47f3a..0000000 --- a/utils/helpers/randID.js +++ /dev/null @@ -1,12 +0,0 @@ -// Sets upper and lower bounds for random ID generation -const idMin = 100000; -const idMax = 999999; - -// Function for generating random ID > takes min and max range as inputs -function randID(idMin,idMax){ - return Math.floor(Math.random()*(idMax - idMin + 1))+idMin; -} - -let ID = randID(idMin,idMax); // Random number between min and max - -console.log("Random ID: "+ID); // Console logging the function result diff --git a/views/create-poll.handlebars b/views/create-poll.handlebars index 9d29983..c7e7bd2 100644 --- a/views/create-poll.handlebars +++ b/views/create-poll.handlebars @@ -10,12 +10,15 @@
+
+ Poll expiration: + +
Add option
Answer choices: -
diff --git a/views/poll.handlebars b/views/poll.handlebars index ef2af43..5a221a0 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -1,20 +1,19 @@

Poll: {{poll.poll_title}} - Made by: {{poll.user.username}}

Share code: {{poll.id}}

+

Ends at: {{format_date poll.poll_expire}}

{{poll.poll_desc}}
+{{#if userCanVote}}
- {{!--
--}} {{#each poll.poll_options as |option|}} {{option.name}}
{{/each}} - {{!--
--}} - {{!-- --}} -
+{{/if}}
From a90dbcf9a4ee565dada3ba3a27276c15b9d5d8e6 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Wed, 17 Aug 2022 23:30:02 -0400 Subject: [PATCH 58/86] Answer post route now validates expiration date, hide expiration date on poll page if null --- controllers/api/answer-routes.js | 7 +++++++ views/poll.handlebars | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/controllers/api/answer-routes.js b/controllers/api/answer-routes.js index c6cc1a0..f084fa1 100644 --- a/controllers/api/answer-routes.js +++ b/controllers/api/answer-routes.js @@ -4,6 +4,13 @@ const withAuth = require('../../utils/auth'); router.post('/', withAuth, async (req, res) => { try { + const poll = await Poll.findByPk(req.body.poll_id, { + }); + const expiration = poll.poll_expire ? new Date(new Date(poll.poll_expire).toUTCString()) : null; + const today = new Date(new Date().toUTCString()); + if (expiration && expiration > today) { + throw 'Poll expired.'; + } const data = await Answer.create({ poll_id: req.body.poll_id, user_id: req.session.user_id, diff --git a/views/poll.handlebars b/views/poll.handlebars index 5a221a0..1f7a81c 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -1,7 +1,9 @@

Poll: {{poll.poll_title}} - Made by: {{poll.user.username}}

Share code: {{poll.id}}

-

Ends at: {{format_date poll.poll_expire}}

+{{#if poll.poll_expire}} +

Ends at: {{format_date poll.poll_expire}}

+{{/if}}
{{poll.poll_desc}}
From de6740227f68b6a0ab6da4c45126ee473a2777f7 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Thu, 18 Aug 2022 21:01:20 -0400 Subject: [PATCH 59/86] Add styling --- controllers/home-routes.js | 11 +- package-lock.json | 41 + package.json | 1 + public/css/style.css | 653 +------ public/css/wstyle.css | 1765 ------------------ public/images/logo_transparent.png | Bin 0 -> 112243 bytes public/js/create-poll.js | 15 +- public/js/search.js | 2 +- server.js | 1 + views/{about-us.html => about-us.handlebars} | 0 views/create-poll.handlebars | 62 +- views/homepage.handlebars | 10 +- views/layouts/main.handlebars | 72 +- views/partials/poll-card.handlebars | 45 +- 14 files changed, 253 insertions(+), 2425 deletions(-) delete mode 100644 public/css/wstyle.css create mode 100644 public/images/logo_transparent.png rename views/{about-us.html => about-us.handlebars} (100%) diff --git a/controllers/home-routes.js b/controllers/home-routes.js index 1ddb83b..ad802b3 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -1,5 +1,6 @@ const router = require('express').Router(); const { Poll, User, Answer } = require('../models'); +const withAuth = require('../utils/auth'); router.get('/login', (req, res) => { if (req.session.loggedIn) { @@ -112,7 +113,7 @@ router.get('/poll/:id', async (req, res) => { } }); -router.get('/create', async (req, res) => { +router.get('/create', withAuth, async (req, res) => { try { res.render('create-poll', {loggedIn: req.session.loggedIn}); } catch (err) { @@ -120,4 +121,12 @@ router.get('/create', async (req, res) => { } }); +router.get('/about-us', withAuth, async (req, res) => { + try { + res.render('about-us', {loggedIn: req.session.loggedIn}); + } catch (err) { + res.status(500).json(err); + } +}); + module.exports = router; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 874776c..4331fcc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "bcrypt": "^5.0.1", + "bootstrap": "^5.2.0", "chart.js": "^3.9.1", "connect-session-sequelize": "^7.1.4", "dotenv": "^16.0.1", @@ -39,6 +40,16 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -182,6 +193,24 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/bootstrap": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.0.tgz", + "integrity": "sha512-qlnS9GL6YZE6Wnef46GxGv1UpGGzAwO0aPL1yOjzDIJpeApeMvqV24iL+pjr2kU4dduoBA9fINKWKgMToobx9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.5" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1662,6 +1691,12 @@ "tar": "^6.1.11" } }, + "@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "peer": true + }, "@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -1779,6 +1814,12 @@ "unpipe": "1.0.0" } }, + "bootstrap": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.0.tgz", + "integrity": "sha512-qlnS9GL6YZE6Wnef46GxGv1UpGGzAwO0aPL1yOjzDIJpeApeMvqV24iL+pjr2kU4dduoBA9fINKWKgMToobx9A==", + "requires": {} + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", diff --git a/package.json b/package.json index a00f953..c0f3a5a 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "homepage": "https://github.com/ms13380/PollTogether#readme", "dependencies": { "bcrypt": "^5.0.1", + "bootstrap": "^5.2.0", "chart.js": "^3.9.1", "connect-session-sequelize": "^7.1.4", "dotenv": "^16.0.1", diff --git a/public/css/style.css b/public/css/style.css index dcfb219..6933a4c 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,602 +1,147 @@ -.poll-card { - border: 1px solid black; - border-radius: 10px; - width: 600px; - margin: 10px auto; - /* padding: 10px; */ -} - -.poll-card-desc a:link, .poll-card-desc a:visited { - text-decoration: none; - color: black; -} - -.poll-card-desc { - padding: 10px; +/* main { + margin: 0px auto; + width: 60%; + border: 1px solid; + background-color: #FFF; +} */ + +.main-header { + width: 100%; + text-align: center; } -.poll-card-header { +.navbar { + /* container d-inline-flex justify-center */ display: flex; - justify-content: space-between; - padding-top: 6px; - padding-bottom: 6px; - padding-left: 10px; - padding-right: 10px; - background: #b2e7d1; - color: black; - border-top-left-radius: 10px; - border-top-right-radius: 10px; + justify-content: center; + /* width: 200px; */ } -.poll-card-header a { +.navbar a { text-decoration: none; - color: black; font-weight: bold; + color: white; + padding: 0px 10px; } -.navbar-no-shadow-container { - z-index: 5; - width: 100%; - max-width: 1140px; - margin-right: auto; - margin-left: auto; - padding: 20px; - background-color: transparent; -} - -.container-regular { - width: 100%; - max-width: 1260px; - min-height: 30px; - margin-right: auto; - margin-left: auto; -} - -.navbar-wrapper { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; - background-color: #b2e7d1; - color: #86dfce; -} - -.nav-menu { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - margin-bottom: 0px; - padding-bottom: 0px; - padding-left: 0px; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; +.title { + font-size: 30px; + padding: 10px; + font-family: 'Quicksand', sans-serif; } -.nav-link { - margin-right: 5px; - margin-left: 5px; - padding: 5px 10px; - font-family: Exo, sans-serif; - color: #1a1b1f; - font-size: 14px; - line-height: 20px; - font-weight: 700; - letter-spacing: 0.25px; +.main-header a:link, .main-header a:hover, .main-header a:visited { text-decoration: none; + color: black; } -.nav-link:hover { - color: rgba(26, 27, 31, 0.75); -} - -.nav-link:focus-visible { - border-radius: 4px; - outline-color: #0050bd; - outline-offset: 0px; - outline-style: solid; - outline-width: 2px; - color: #0050bd; -} - -.nav-link[data-wf-focus-visible] { - border-radius: 4px; - outline-color: #0050bd; - outline-offset: 0px; - outline-style: solid; - outline-width: 2px; - color: #0050bd; -} - -.nav-dropdown { - margin-right: 5px; - margin-left: 5px; -} - -.nav-dropdown-toggle { - padding: 5px 30px 5px 10px; - font-size: 14px; - line-height: 20px; - letter-spacing: 0.25px; -} - -.nav-dropdown-toggle:hover { - color: rgba(26, 27, 31, 0.75); -} - -.nav-dropdown-toggle:focus-visible { - border-radius: 5px; - outline-color: #0050bd; - outline-offset: 0px; - outline-style: solid; - outline-width: 2px; - color: #0050bd; -} - -.nav-dropdown-toggle[data-wf-focus-visible] { - border-radius: 5px; - outline-color: #0050bd; - outline-offset: 0px; - outline-style: solid; - outline-width: 2px; - color: #0050bd; -} - -.nav-dropdown-icon { - margin-right: 10px; -} - -.nav-dropdown-list { - border-radius: 12px; - background-color: #fff; -} - -.nav-dropdown-list.w--open { - padding-top: 10px; - padding-bottom: 10px; -} - -.nav-dropdown-link { - padding-top: 5px; - padding-bottom: 5px; - font-size: 14px; -} - -.nav-dropdown-link:focus-visible { - border-radius: 5px; - outline-color: #0050bd; - outline-offset: 0px; - outline-style: solid; - outline-width: 2px; - color: #0050bd; -} - -.nav-dropdown-link[data-wf-focus-visible] { - border-radius: 5px; - outline-color: #0050bd; - outline-offset: 0px; - outline-style: solid; - outline-width: 2px; - color: #0050bd; -} - -.mobile-margin-top-10 { - -webkit-box-flex: 0; - -webkit-flex: 0 auto; - -ms-flex: 0 auto; - flex: 0 auto; -} - -.nav-button-wrapper { - margin-left: 120px; -} - -.button-primary { - padding: 12px 25px; - background-color: #1a1b1f; - -webkit-transition: all 200ms ease; - transition: all 200ms ease; - font-family: Exo, sans-serif; - color: #fff; - font-size: 12px; - line-height: 20px; - letter-spacing: 2px; - text-transform: uppercase; +nav { + background-color: #E0E0E0; + padding-top: 8px; + padding-bottom: 8px; + padding-left: 30px; + margin-bottom: 10px; } -.button-primary:hover { - background-color: #32343a; - color: #fff; +nav a { + text-decoration: none; + font-weight: bold; + color: dodgerblue; } -.button-primary:active { - background-color: #43464d; -} +/* body a { + text-decoration: none; + font-weight: bold; +} */ -.utility-page-wrap { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; +.search-container { + margin: 0px auto; + /* width: 750px; */ + width: 40%; + padding: 5px; display: flex; - width: 100vw; - height: 100vh; - max-height: 100%; - max-width: 100%; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; justify-content: center; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; align-items: center; + margin-top: 15px; + margin-bottom: 15px; } -.utility-page-content { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - width: 260px; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - text-align: center; -} +/* .custom-button:hover { + cursor: pointer; + background-color: #43464d; +} */ -.utility-page-form { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-align: stretch; - -webkit-align-items: stretch; - -ms-flex-align: stretch; - align-items: stretch; +.poll-search { + width:65%; + height: 50px; + /* border-radius: 20px; */ + font-size: 20px; + padding: 5px; } -.team-circles { - position: relative; - padding: 80px 30px; - border-bottom: 1px solid #e4ebf3; +.custom-button { + height: 48px; } -.container { - width: 100%; - max-width: 940px; - margin-right: auto; - margin-left: auto; +.cards { + display: flex; + flex-wrap: wrap; + justify-content: center; + width: 75%; + margin: 0px auto; + background-color: #EEE; + border-radius: 10px; + padding: 30px; + margin-top: 20px; } -.centered-heading { - margin-bottom: 16px; - text-align: center; +.poll-card { + border: 1px solid black; + border-radius: 10px; + width: 600px; + margin: 10px auto; } -.centered-subheading { - max-width: 530px; - margin-right: auto; - margin-left: auto; - text-align: center; +.poll-card-desc a:link, .poll-card-desc a:visited { + text-decoration: none; + color: black; } -.team-grid { - display: -ms-grid; - display: grid; - margin-top: 50px; - grid-auto-columns: 1fr; - grid-column-gap: 64px; - grid-row-gap: 56px; - -ms-grid-columns: 1fr 1fr 1fr; - grid-template-columns: 1fr 1fr 1fr; - -ms-grid-rows: auto auto; - grid-template-rows: auto auto; +.poll-card-desc { + padding: 10px; } -.team-card { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; +.poll-card-header { display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; - font-size: 14px; - line-height: 22px; - text-align: center; + justify-content: space-between; + padding-top: 6px; + padding-bottom: 6px; + padding-left: 10px; + padding-right: 10px; + /* border-top-left-radius: 10px; + border-top-right-radius: 10px; */ } -.team-member-image { - width: 270px; - height: 270px; - margin-bottom: 24px; - border-radius: 50%; - -o-object-fit: cover; - object-fit: cover; +.poll-card-header a { + text-decoration: none; + color: white; + font-weight: bold; } -.team-member-name { - margin-bottom: 6px; +.poll-option { + height: 100%; + width: 75%; + border: none; font-size: 20px; - line-height: 32px; - font-weight: 500; -} - -.team-member-position { - margin-bottom: 24px; -} - -.heading { - font-family: Exo, sans-serif; - color: #3d4644; + padding: 8px; } -@media screen and (min-width: 1440px) { - .team-member-image { - width: 270px; - height: 270px; - max-height: none; - } +.remove-option { + padding: 8px 12px; } -@media screen and (max-width: 991px) { - .nav-menu-wrapper { - background-color: transparent; - } - - .nav-menu { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding-left: 0px; - -webkit-justify-content: space-around; - -ms-flex-pack: distribute; - justify-content: space-around; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; - background-color: #fff; - } - - .nav-link { - padding-right: 5px; - padding-left: 5px; - } - - .nav-dropdown-list.shadow-three.w--open { - position: absolute; - } - - .nav-button-wrapper { - width: 100%; - margin-left: 0px; - } - - .menu-button { - padding: 12px; - } - - .menu-button.w--open { - background-color: #a6b1bf; - color: #fff; - } - - .container { - max-width: 728px; - } - - .team-grid { - grid-column-gap: 40px; - } - - .team-member-image { - width: 190px; - height: 190px; - } -} - -@media screen and (max-width: 767px) { - .navbar-brand { - padding-left: 0px; - } - - .nav-menu { - padding-bottom: 30px; - padding-left: 0px; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - } - - .nav-link { - display: inline-block; - padding-top: 10px; - padding-bottom: 10px; - } - - .nav-dropdown { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; - } - - .nav-dropdown-toggle { - padding-top: 10px; - padding-bottom: 10px; - } - - .nav-dropdown-list.shadow-three { - box-shadow: 0 8px 50px 0 rgba(0, 0, 0, 0.05); - } - - .nav-dropdown-list.shadow-three.w--open { - position: relative; - } - - .nav-dropdown-list.shadow-three.mobile-shadow-hide { - box-shadow: none; - } - - .mobile-margin-top-10 { - margin-top: 10px; - } - - .team-circles { - padding: 60px 15px; - } - - .team-grid { - -ms-grid-columns: 1fr 1fr; - grid-template-columns: 1fr 1fr; - } -} - -@media screen and (max-width: 479px) { - .nav-menu { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - } - - .nav-button-wrapper { - width: auto; - } - - .container { - max-width: none; - } - - .centered-heading { - margin-bottom: 24px; - } - - .team-grid { - -ms-grid-columns: 1fr; - grid-template-columns: 1fr; - } -} - -#w-node-_0e22c22f-d42e-defe-779a-a9557b49c59f-563a21f7 { - -ms-grid-column: span 1; - grid-column-start: span 1; - -ms-grid-column-span: 1; - grid-column-end: span 1; - -ms-grid-row: span 1; - grid-row-start: span 1; - -ms-grid-row-span: 1; - grid-row-end: span 1; -} - -#w-node-_0e22c22f-d42e-defe-779a-a9557b49c5aa-563a21f7 { - -ms-grid-column: span 1; - grid-column-start: span 1; - -ms-grid-column-span: 1; - grid-column-end: span 1; - -ms-grid-row: span 1; - grid-row-start: span 1; - -ms-grid-row-span: 1; - grid-row-end: span 1; -} - -#w-node-_0e22c22f-d42e-defe-779a-a9557b49c5b4-563a21f7 { - -ms-grid-column: span 1; - grid-column-start: span 1; - -ms-grid-column-span: 1; - grid-column-end: span 1; - -ms-grid-row: span 1; - grid-row-start: span 1; - -ms-grid-row-span: 1; - grid-row-end: span 1; -} - -#w-node-_0e22c22f-d42e-defe-779a-a9557b49c5be-563a21f7 { - -ms-grid-column: span 1; - grid-column-start: span 1; - -ms-grid-column-span: 1; - grid-column-end: span 1; - -ms-grid-row: span 1; - grid-row-start: span 1; - -ms-grid-row-span: 1; - grid-row-end: span 1; -} - -#w-node-_0e22c22f-d42e-defe-779a-a9557b49c5d2-563a21f7 { - -ms-grid-column: span 1; - grid-column-start: span 1; - -ms-grid-column-span: 1; - grid-column-end: span 1; - -ms-grid-row: span 1; - grid-row-start: span 1; - -ms-grid-row-span: 1; - grid-row-end: span 1; -} - -@media screen and (min-width: 1440px) { - #w-node-_0e22c22f-d42e-defe-779a-a9557b49c5aa-563a21f7 { - -ms-grid-column: span 1; - grid-column-start: span 1; - -ms-grid-column-span: 1; - grid-column-end: span 1; - -ms-grid-row: span 1; - grid-row-start: span 1; - -ms-grid-row-span: 1; - grid-row-end: span 1; - } - - #w-node-_0e22c22f-d42e-defe-779a-a9557b49c5b4-563a21f7 { - -ms-grid-column: span 1; - grid-column-start: span 1; - -ms-grid-column-span: 1; - grid-column-end: span 1; - -ms-grid-row: span 1; - grid-row-start: span 1; - -ms-grid-row-span: 1; - grid-row-end: span 1; -} +.optional { + font-style: italic; + color: silver; + font-weight: lighter; } \ No newline at end of file diff --git a/public/css/wstyle.css b/public/css/wstyle.css deleted file mode 100644 index 663bec9..0000000 --- a/public/css/wstyle.css +++ /dev/null @@ -1,1765 +0,0 @@ -@font-face { - font-family: 'webflow-icons'; - src: url("data:application/x-font-ttf;charset=utf-8;base64,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") format('truetype'); - font-weight: normal; - font-style: normal; -} -[class^="w-icon-"], -[class*=" w-icon-"] { - font-family: 'webflow-icons' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.w-icon-slider-right:before { - content: "\e600"; -} -.w-icon-slider-left:before { - content: "\e601"; -} -.w-icon-nav-menu:before { - content: "\e602"; -} -.w-icon-arrow-down:before, -.w-icon-dropdown-toggle:before { - content: "\e603"; -} -.w-icon-file-upload-remove:before { - content: "\e900"; -} -.w-icon-file-upload-icon:before { - content: "\e903"; -} -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html { - height: 100%; -} -body { - margin: 0; - min-height: 100%; - background-color: #fff; - font-family: Arial, sans-serif; - font-size: 14px; - line-height: 20px; - color: #333; -} -img { - max-width: 100%; - vertical-align: middle; - display: inline-block; -} -html.w-mod-touch * { - background-attachment: scroll !important; -} -.w-block { - display: block; -} -.w-inline-block { - max-width: 100%; - display: inline-block; -} -.w-clearfix:before, -.w-clearfix:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-clearfix:after { - clear: both; -} -.w-hidden { - display: none; -} -.w-button { - display: inline-block; - padding: 9px 15px; - background-color: #3898EC; - color: white; - border: 0; - line-height: inherit; - text-decoration: none; - cursor: pointer; - border-radius: 0; -} -input.w-button { - -webkit-appearance: button; -} -html[data-w-dynpage] [data-w-cloak] { - color: transparent !important; -} -.w-webflow-badge, -.w-webflow-badge * { - position: static; - left: auto; - top: auto; - right: auto; - bottom: auto; - z-index: auto; - display: block; - visibility: visible; - overflow: visible; - overflow-x: visible; - overflow-y: visible; - box-sizing: border-box; - width: auto; - height: auto; - max-height: none; - max-width: none; - min-height: 0; - min-width: 0; - margin: 0; - padding: 0; - float: none; - clear: none; - border: 0 none transparent; - border-radius: 0; - background: none; - background-image: none; - background-position: 0% 0%; - background-size: auto auto; - background-repeat: repeat; - background-origin: padding-box; - background-clip: border-box; - background-attachment: scroll; - background-color: transparent; - box-shadow: none; - opacity: 1; - transform: none; - transition: none; - direction: ltr; - font-family: inherit; - font-weight: inherit; - color: inherit; - font-size: inherit; - line-height: inherit; - font-style: inherit; - font-variant: inherit; - text-align: inherit; - letter-spacing: inherit; - text-decoration: inherit; - text-indent: 0; - text-transform: inherit; - list-style-type: disc; - text-shadow: none; - font-smoothing: auto; - vertical-align: baseline; - cursor: inherit; - white-space: inherit; - word-break: normal; - word-spacing: normal; - word-wrap: normal; -} -.w-webflow-badge { - position: fixed !important; - display: inline-block !important; - visibility: visible !important; - z-index: 2147483647 !important; - top: auto !important; - right: 12px !important; - bottom: 12px !important; - left: auto !important; - color: #AAADB0 !important; - background-color: #fff !important; - border-radius: 3px !important; - padding: 6px 8px 6px 6px !important; - font-size: 12px !important; - opacity: 1 !important; - line-height: 14px !important; - text-decoration: none !important; - transform: none !important; - margin: 0 !important; - width: auto !important; - height: auto !important; - overflow: visible !important; - white-space: nowrap; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0px 1px 3px rgba(0, 0, 0, 0.1); - cursor: pointer; -} -.w-webflow-badge > img { - display: inline-block !important; - visibility: visible !important; - opacity: 1 !important; - vertical-align: middle !important; -} -h1, -h2, -h3, -h4, -h5, -h6 { - font-weight: bold; - margin-bottom: 10px; -} -h1 { - font-size: 38px; - line-height: 44px; - margin-top: 20px; -} -h2 { - font-size: 32px; - line-height: 36px; - margin-top: 20px; -} -h3 { - font-size: 24px; - line-height: 30px; - margin-top: 20px; -} -h4 { - font-size: 18px; - line-height: 24px; - margin-top: 10px; -} -h5 { - font-size: 14px; - line-height: 20px; - margin-top: 10px; -} -h6 { - font-size: 12px; - line-height: 18px; - margin-top: 10px; -} -p { - margin-top: 0; - margin-bottom: 10px; -} -blockquote { - margin: 0 0 10px 0; - padding: 10px 20px; - border-left: 5px solid #E2E2E2; - font-size: 18px; - line-height: 22px; -} -figure { - margin: 0; - margin-bottom: 10px; -} -figcaption { - margin-top: 5px; - text-align: center; -} -ul, -ol { - margin-top: 0px; - margin-bottom: 10px; - padding-left: 40px; -} -.w-list-unstyled { - padding-left: 0; - list-style: none; -} -.w-embed:before, -.w-embed:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-embed:after { - clear: both; -} -.w-video { - width: 100%; - position: relative; - padding: 0; -} -.w-video iframe, -.w-video object, -.w-video embed { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border: none; -} -fieldset { - padding: 0; - margin: 0; - border: 0; -} -button, -[type='button'], -[type='reset'] { - border: 0; - cursor: pointer; - -webkit-appearance: button; -} -.w-form { - margin: 0 0 15px; -} -.w-form-done { - display: none; - padding: 20px; - text-align: center; - background-color: #dddddd; -} -.w-form-fail { - display: none; - margin-top: 10px; - padding: 10px; - background-color: #ffdede; -} -label { - display: block; - margin-bottom: 5px; - font-weight: bold; -} -.w-input, -.w-select { - display: block; - width: 100%; - height: 38px; - padding: 8px 12px; - margin-bottom: 10px; - font-size: 14px; - line-height: 1.42857143; - color: #333333; - vertical-align: middle; - background-color: #ffffff; - border: 1px solid #cccccc; -} -.w-input:-moz-placeholder, -.w-select:-moz-placeholder { - color: #999; -} -.w-input::-moz-placeholder, -.w-select::-moz-placeholder { - color: #999; - opacity: 1; -} -.w-input:-ms-input-placeholder, -.w-select:-ms-input-placeholder { - color: #999; -} -.w-input::-webkit-input-placeholder, -.w-select::-webkit-input-placeholder { - color: #999; -} -.w-input:focus, -.w-select:focus { - border-color: #3898EC; - outline: 0; -} -.w-input[disabled], -.w-select[disabled], -.w-input[readonly], -.w-select[readonly], -fieldset[disabled] .w-input, -fieldset[disabled] .w-select { - cursor: not-allowed; -} -.w-input[disabled]:not(.w-input-disabled), -.w-select[disabled]:not(.w-input-disabled), -.w-input[readonly], -.w-select[readonly], -fieldset[disabled]:not(.w-input-disabled) .w-input, -fieldset[disabled]:not(.w-input-disabled) .w-select { - background-color: #eeeeee; -} -textarea.w-input, -textarea.w-select { - height: auto; -} -.w-select { - background-color: #f3f3f3; -} -.w-select[multiple] { - height: auto; -} -.w-form-label { - display: inline-block; - cursor: pointer; - font-weight: normal; - margin-bottom: 0px; -} -.w-radio { - display: block; - margin-bottom: 5px; - padding-left: 20px; -} -.w-radio:before, -.w-radio:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-radio:after { - clear: both; -} -.w-radio-input { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal; - float: left; - margin-left: -20px; -} -.w-radio-input { - margin-top: 3px; -} -.w-file-upload { - display: block; - margin-bottom: 10px; -} -.w-file-upload-input { - width: 0.1px; - height: 0.1px; - opacity: 0; - overflow: hidden; - position: absolute; - z-index: -100; -} -.w-file-upload-default, -.w-file-upload-uploading, -.w-file-upload-success { - display: inline-block; - color: #333333; -} -.w-file-upload-error { - display: block; - margin-top: 10px; -} -.w-file-upload-default.w-hidden, -.w-file-upload-uploading.w-hidden, -.w-file-upload-error.w-hidden, -.w-file-upload-success.w-hidden { - display: none; -} -.w-file-upload-uploading-btn { - display: flex; - font-size: 14px; - font-weight: normal; - cursor: pointer; - margin: 0; - padding: 8px 12px; - border: 1px solid #cccccc; - background-color: #fafafa; -} -.w-file-upload-file { - display: flex; - flex-grow: 1; - justify-content: space-between; - margin: 0; - padding: 8px 9px 8px 11px; - border: 1px solid #cccccc; - background-color: #fafafa; -} -.w-file-upload-file-name { - font-size: 14px; - font-weight: normal; - display: block; -} -.w-file-remove-link { - margin-top: 3px; - margin-left: 10px; - width: auto; - height: auto; - padding: 3px; - display: block; - cursor: pointer; -} -.w-icon-file-upload-remove { - margin: auto; - font-size: 10px; -} -.w-file-upload-error-msg { - display: inline-block; - color: #ea384c; - padding: 2px 0; -} -.w-file-upload-info { - display: inline-block; - line-height: 38px; - padding: 0 12px; -} -.w-file-upload-label { - display: inline-block; - font-size: 14px; - font-weight: normal; - cursor: pointer; - margin: 0; - padding: 8px 12px; - border: 1px solid #cccccc; - background-color: #fafafa; -} -.w-icon-file-upload-icon, -.w-icon-file-upload-uploading { - display: inline-block; - margin-right: 8px; - width: 20px; -} -.w-icon-file-upload-uploading { - height: 20px; -} -.w-container { - margin-left: auto; - margin-right: auto; - max-width: 940px; -} -.w-container:before, -.w-container:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-container:after { - clear: both; -} -.w-container .w-row { - margin-left: -10px; - margin-right: -10px; -} -.w-row:before, -.w-row:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-row:after { - clear: both; -} -.w-row .w-row { - margin-left: 0; - margin-right: 0; -} -.w-col { - position: relative; - float: left; - width: 100%; - min-height: 1px; - padding-left: 10px; - padding-right: 10px; -} -.w-col .w-col { - padding-left: 0; - padding-right: 0; -} -.w-col-1 { - width: 8.33333333%; -} -.w-col-2 { - width: 16.66666667%; -} -.w-col-3 { - width: 25%; -} -.w-col-4 { - width: 33.33333333%; -} -.w-col-5 { - width: 41.66666667%; -} -.w-col-6 { - width: 50%; -} -.w-col-7 { - width: 58.33333333%; -} -.w-col-8 { - width: 66.66666667%; -} -.w-col-9 { - width: 75%; -} -.w-col-10 { - width: 83.33333333%; -} -.w-col-11 { - width: 91.66666667%; -} -.w-col-12 { - width: 100%; -} -.w-hidden-main { - display: none !important; -} -@media screen and (max-width: 991px) { - .w-container { - max-width: 728px; - } - .w-hidden-main { - display: inherit !important; - } - .w-hidden-medium { - display: none !important; - } - .w-col-medium-1 { - width: 8.33333333%; - } - .w-col-medium-2 { - width: 16.66666667%; - } - .w-col-medium-3 { - width: 25%; - } - .w-col-medium-4 { - width: 33.33333333%; - } - .w-col-medium-5 { - width: 41.66666667%; - } - .w-col-medium-6 { - width: 50%; - } - .w-col-medium-7 { - width: 58.33333333%; - } - .w-col-medium-8 { - width: 66.66666667%; - } - .w-col-medium-9 { - width: 75%; - } - .w-col-medium-10 { - width: 83.33333333%; - } - .w-col-medium-11 { - width: 91.66666667%; - } - .w-col-medium-12 { - width: 100%; - } - .w-col-stack { - width: 100%; - left: auto; - right: auto; - } -} -@media screen and (max-width: 767px) { - .w-hidden-main { - display: inherit !important; - } - .w-hidden-medium { - display: inherit !important; - } - .w-hidden-small { - display: none !important; - } - .w-row, - .w-container .w-row { - margin-left: 0; - margin-right: 0; - } - .w-col { - width: 100%; - left: auto; - right: auto; - } - .w-col-small-1 { - width: 8.33333333%; - } - .w-col-small-2 { - width: 16.66666667%; - } - .w-col-small-3 { - width: 25%; - } - .w-col-small-4 { - width: 33.33333333%; - } - .w-col-small-5 { - width: 41.66666667%; - } - .w-col-small-6 { - width: 50%; - } - .w-col-small-7 { - width: 58.33333333%; - } - .w-col-small-8 { - width: 66.66666667%; - } - .w-col-small-9 { - width: 75%; - } - .w-col-small-10 { - width: 83.33333333%; - } - .w-col-small-11 { - width: 91.66666667%; - } - .w-col-small-12 { - width: 100%; - } -} -@media screen and (max-width: 479px) { - .w-container { - max-width: none; - } - .w-hidden-main { - display: inherit !important; - } - .w-hidden-medium { - display: inherit !important; - } - .w-hidden-small { - display: inherit !important; - } - .w-hidden-tiny { - display: none !important; - } - .w-col { - width: 100%; - } - .w-col-tiny-1 { - width: 8.33333333%; - } - .w-col-tiny-2 { - width: 16.66666667%; - } - .w-col-tiny-3 { - width: 25%; - } - .w-col-tiny-4 { - width: 33.33333333%; - } - .w-col-tiny-5 { - width: 41.66666667%; - } - .w-col-tiny-6 { - width: 50%; - } - .w-col-tiny-7 { - width: 58.33333333%; - } - .w-col-tiny-8 { - width: 66.66666667%; - } - .w-col-tiny-9 { - width: 75%; - } - .w-col-tiny-10 { - width: 83.33333333%; - } - .w-col-tiny-11 { - width: 91.66666667%; - } - .w-col-tiny-12 { - width: 100%; - } -} -.w-widget { - position: relative; -} -.w-widget-map { - width: 100%; - height: 400px; -} -.w-widget-map label { - width: auto; - display: inline; -} -.w-widget-map img { - max-width: inherit; -} -.w-widget-map .gm-style-iw { - text-align: center; -} -.w-widget-map .gm-style-iw > button { - display: none !important; -} -.w-widget-twitter { - overflow: hidden; -} -.w-widget-twitter-count-shim { - display: inline-block; - vertical-align: top; - position: relative; - width: 28px; - height: 20px; - text-align: center; - background: white; - border: #758696 solid 1px; - border-radius: 3px; -} -.w-widget-twitter-count-shim * { - pointer-events: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.w-widget-twitter-count-shim .w-widget-twitter-count-inner { - position: relative; - font-size: 15px; - line-height: 12px; - text-align: center; - color: #999; - font-family: serif; -} -.w-widget-twitter-count-shim .w-widget-twitter-count-clear { - position: relative; - display: block; -} -.w-widget-twitter-count-shim.w--large { - width: 36px; - height: 28px; -} -.w-widget-twitter-count-shim.w--large .w-widget-twitter-count-inner { - font-size: 18px; - line-height: 18px; -} -.w-widget-twitter-count-shim:not(.w--vertical) { - margin-left: 5px; - margin-right: 8px; -} -.w-widget-twitter-count-shim:not(.w--vertical).w--large { - margin-left: 6px; -} -.w-widget-twitter-count-shim:not(.w--vertical):before, -.w-widget-twitter-count-shim:not(.w--vertical):after { - top: 50%; - left: 0; - border: solid transparent; - content: ' '; - height: 0; - width: 0; - position: absolute; - pointer-events: none; -} -.w-widget-twitter-count-shim:not(.w--vertical):before { - border-color: rgba(117, 134, 150, 0); - border-right-color: #5d6c7b; - border-width: 4px; - margin-left: -9px; - margin-top: -4px; -} -.w-widget-twitter-count-shim:not(.w--vertical).w--large:before { - border-width: 5px; - margin-left: -10px; - margin-top: -5px; -} -.w-widget-twitter-count-shim:not(.w--vertical):after { - border-color: rgba(255, 255, 255, 0); - border-right-color: white; - border-width: 4px; - margin-left: -8px; - margin-top: -4px; -} -.w-widget-twitter-count-shim:not(.w--vertical).w--large:after { - border-width: 5px; - margin-left: -9px; - margin-top: -5px; -} -.w-widget-twitter-count-shim.w--vertical { - width: 61px; - height: 33px; - margin-bottom: 8px; -} -.w-widget-twitter-count-shim.w--vertical:before, -.w-widget-twitter-count-shim.w--vertical:after { - top: 100%; - left: 50%; - border: solid transparent; - content: ' '; - height: 0; - width: 0; - position: absolute; - pointer-events: none; -} -.w-widget-twitter-count-shim.w--vertical:before { - border-color: rgba(117, 134, 150, 0); - border-top-color: #5d6c7b; - border-width: 5px; - margin-left: -5px; -} -.w-widget-twitter-count-shim.w--vertical:after { - border-color: rgba(255, 255, 255, 0); - border-top-color: white; - border-width: 4px; - margin-left: -4px; -} -.w-widget-twitter-count-shim.w--vertical .w-widget-twitter-count-inner { - font-size: 18px; - line-height: 22px; -} -.w-widget-twitter-count-shim.w--vertical.w--large { - width: 76px; -} -.w-background-video { - position: relative; - overflow: hidden; - height: 500px; - color: white; -} -.w-background-video > video { - background-size: cover; - background-position: 50% 50%; - position: absolute; - margin: auto; - width: 100%; - height: 100%; - right: -100%; - bottom: -100%; - top: -100%; - left: -100%; - object-fit: cover; - z-index: -100; -} -.w-background-video > video::-webkit-media-controls-start-playback-button { - display: none !important; - -webkit-appearance: none; -} -.w-background-video--control { - position: absolute; - bottom: 1em; - right: 1em; - background-color: transparent; - padding: 0; -} -.w-background-video--control > [hidden] { - display: none !important; -} -.w-slider { - position: relative; - height: 300px; - text-align: center; - background: #dddddd; - clear: both; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - tap-highlight-color: rgba(0, 0, 0, 0); -} -.w-slider-mask { - position: relative; - display: block; - overflow: hidden; - z-index: 1; - left: 0; - right: 0; - height: 100%; - white-space: nowrap; -} -.w-slide { - position: relative; - display: inline-block; - vertical-align: top; - width: 100%; - height: 100%; - white-space: normal; - text-align: left; -} -.w-slider-nav { - position: absolute; - z-index: 2; - top: auto; - right: 0; - bottom: 0; - left: 0; - margin: auto; - padding-top: 10px; - height: 40px; - text-align: center; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - tap-highlight-color: rgba(0, 0, 0, 0); -} -.w-slider-nav.w-round > div { - border-radius: 100%; -} -.w-slider-nav.w-num > div { - width: auto; - height: auto; - padding: 0.2em 0.5em; - font-size: inherit; - line-height: inherit; -} -.w-slider-nav.w-shadow > div { - box-shadow: 0 0 3px rgba(51, 51, 51, 0.4); -} -.w-slider-nav-invert { - color: #fff; -} -.w-slider-nav-invert > div { - background-color: rgba(34, 34, 34, 0.4); -} -.w-slider-nav-invert > div.w-active { - background-color: #222; -} -.w-slider-dot { - position: relative; - display: inline-block; - width: 1em; - height: 1em; - background-color: rgba(255, 255, 255, 0.4); - cursor: pointer; - margin: 0 3px 0.5em; - transition: background-color 100ms, color 100ms; -} -.w-slider-dot.w-active { - background-color: #fff; -} -.w-slider-dot:focus { - outline: none; - box-shadow: 0px 0px 0px 2px #fff; -} -.w-slider-dot:focus.w-active { - box-shadow: none; -} -.w-slider-arrow-left, -.w-slider-arrow-right { - position: absolute; - width: 80px; - top: 0; - right: 0; - bottom: 0; - left: 0; - margin: auto; - cursor: pointer; - overflow: hidden; - color: white; - font-size: 40px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - tap-highlight-color: rgba(0, 0, 0, 0); - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.w-slider-arrow-left [class^='w-icon-'], -.w-slider-arrow-right [class^='w-icon-'], -.w-slider-arrow-left [class*=' w-icon-'], -.w-slider-arrow-right [class*=' w-icon-'] { - position: absolute; -} -.w-slider-arrow-left:focus, -.w-slider-arrow-right:focus { - outline: 0; -} -.w-slider-arrow-left { - z-index: 3; - right: auto; -} -.w-slider-arrow-right { - z-index: 4; - left: auto; -} -.w-icon-slider-left, -.w-icon-slider-right { - top: 0; - right: 0; - bottom: 0; - left: 0; - margin: auto; - width: 1em; - height: 1em; -} -.w-slider-aria-label { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.w-slider-force-show { - display: block !important; -} -.w-dropdown { - display: inline-block; - position: relative; - text-align: left; - margin-left: auto; - margin-right: auto; - z-index: 900; -} -.w-dropdown-btn, -.w-dropdown-toggle, -.w-dropdown-link { - position: relative; - vertical-align: top; - text-decoration: none; - color: #222222; - padding: 20px; - text-align: left; - margin-left: auto; - margin-right: auto; - white-space: nowrap; -} -.w-dropdown-toggle { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - display: inline-block; - cursor: pointer; - padding-right: 40px; -} -.w-dropdown-toggle:focus { - outline: 0; -} -.w-icon-dropdown-toggle { - position: absolute; - top: 0; - right: 0; - bottom: 0; - margin: auto; - margin-right: 20px; - width: 1em; - height: 1em; -} -.w-dropdown-list { - position: absolute; - background: #dddddd; - display: none; - min-width: 100%; -} -.w-dropdown-list.w--open { - display: block; -} -.w-dropdown-link { - padding: 10px 20px; - display: block; - color: #222222; -} -.w-dropdown-link.w--current { - color: #0082f3; -} -.w-dropdown-link:focus { - outline: 0; -} -@media screen and (max-width: 767px) { - .w-nav-brand { - padding-left: 10px; - } -} -.w-lightbox-backdrop { - color: #000; - cursor: auto; - font-family: serif; - font-size: medium; - font-style: normal; - font-variant: normal; - font-weight: normal; - letter-spacing: normal; - line-height: normal; - list-style: disc; - text-align: start; - text-indent: 0; - text-shadow: none; - text-transform: none; - visibility: visible; - white-space: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - color: #fff; - font-family: "Helvetica Neue", Helvetica, Ubuntu, "Segoe UI", Verdana, sans-serif; - font-size: 17px; - line-height: 1.2; - font-weight: 300; - text-align: center; - background: rgba(0, 0, 0, 0.9); - z-index: 2000; - outline: 0; - opacity: 0; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -webkit-tap-highlight-color: transparent; - -webkit-transform: translate(0, 0); -} -.w-lightbox-backdrop, -.w-lightbox-container { - height: 100%; - overflow: auto; - -webkit-overflow-scrolling: touch; -} -.w-lightbox-content { - position: relative; - height: 100vh; - overflow: hidden; -} -.w-lightbox-view { - position: absolute; - width: 100vw; - height: 100vh; - opacity: 0; -} -.w-lightbox-view:before { - content: ""; - height: 100vh; -} -.w-lightbox-group, -.w-lightbox-group .w-lightbox-view, -.w-lightbox-group .w-lightbox-view:before { - height: 86vh; -} -.w-lightbox-frame, -.w-lightbox-view:before { - display: inline-block; - vertical-align: middle; -} -.w-lightbox-figure { - position: relative; - margin: 0; -} -.w-lightbox-group .w-lightbox-figure { - cursor: pointer; -} -.w-lightbox-img { - width: auto; - height: auto; - max-width: none; -} -.w-lightbox-image { - display: block; - float: none; - max-width: 100vw; - max-height: 100vh; -} -.w-lightbox-group .w-lightbox-image { - max-height: 86vh; -} -.w-lightbox-caption { - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 0.5em 1em; - background: rgba(0, 0, 0, 0.4); - text-align: left; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} -.w-lightbox-embed { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; -} -.w-lightbox-control { - position: absolute; - top: 0; - width: 4em; - background-size: 24px; - background-repeat: no-repeat; - background-position: center; - cursor: pointer; - -webkit-transition: all 0.3s; - transition: all 0.3s; -} -.w-lightbox-left { - display: none; - bottom: 0; - left: 0; - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0yMCAwIDI0IDQwIiB3aWR0aD0iMjQiIGhlaWdodD0iNDAiPjxnIHRyYW5zZm9ybT0icm90YXRlKDQ1KSI+PHBhdGggZD0ibTAgMGg1djIzaDIzdjVoLTI4eiIgb3BhY2l0eT0iLjQiLz48cGF0aCBkPSJtMSAxaDN2MjNoMjN2M2gtMjZ6IiBmaWxsPSIjZmZmIi8+PC9nPjwvc3ZnPg=="); -} -.w-lightbox-right { - display: none; - right: 0; - bottom: 0; - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IDAgMjQgNDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSI0MCI+PGcgdHJhbnNmb3JtPSJyb3RhdGUoNDUpIj48cGF0aCBkPSJtMC0waDI4djI4aC01di0yM2gtMjN6IiBvcGFjaXR5PSIuNCIvPjxwYXRoIGQ9Im0xIDFoMjZ2MjZoLTN2LTIzaC0yM3oiIGZpbGw9IiNmZmYiLz48L2c+PC9zdmc+"); -} -.w-lightbox-close { - right: 0; - height: 2.6em; - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IDAgMTggMTciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxNyI+PGcgdHJhbnNmb3JtPSJyb3RhdGUoNDUpIj48cGF0aCBkPSJtMCAwaDd2LTdoNXY3aDd2NWgtN3Y3aC01di03aC03eiIgb3BhY2l0eT0iLjQiLz48cGF0aCBkPSJtMSAxaDd2LTdoM3Y3aDd2M2gtN3Y3aC0zdi03aC03eiIgZmlsbD0iI2ZmZiIvPjwvZz48L3N2Zz4="); - background-size: 18px; -} - -.w-lightbox-strip { - position: absolute; - bottom: 0; - left: 0; - right: 0; - padding: 0 1vh; - line-height: 0; - white-space: nowrap; - overflow-x: auto; - overflow-y: hidden; -} - -.w-lightbox-item { - display: inline-block; - width: 10vh; - padding: 2vh 1vh; - box-sizing: content-box; - cursor: pointer; - -webkit-transform: translate3d(0, 0, 0); -} -.w-lightbox-active { - opacity: 0.3; -} -.w-lightbox-thumbnail { - position: relative; - height: 10vh; - background: #222; - overflow: hidden; -} -.w-lightbox-thumbnail-image { - position: absolute; - top: 0; - left: 0; -} -.w-lightbox-thumbnail .w-lightbox-tall { - top: 50%; - width: 100%; - -webkit-transform: translate(0, -50%); - -ms-transform: translate(0, -50%); - transform: translate(0, -50%); -} -.w-lightbox-thumbnail .w-lightbox-wide { - left: 50%; - height: 100%; - -webkit-transform: translate(-50%, 0); - -ms-transform: translate(-50%, 0); - transform: translate(-50%, 0); -} -.w-lightbox-spinner { - position: absolute; - top: 50%; - left: 50%; - box-sizing: border-box; - width: 40px; - height: 40px; - margin-top: -20px; - margin-left: -20px; - border: 5px solid rgba(0, 0, 0, 0.4); - border-radius: 50%; - -webkit-animation: spin 0.8s infinite linear; - animation: spin 0.8s infinite linear; -} -.w-lightbox-spinner:after { - content: ""; - position: absolute; - top: -4px; - right: -4px; - bottom: -4px; - left: -4px; - border: 3px solid transparent; - border-bottom-color: #fff; - border-radius: 50%; -} - -.w-lightbox-hide { - display: none; -} -.w-lightbox-noscroll { - overflow: hidden; -} -@media (min-width: 768px) { - .w-lightbox-content { - height: 96vh; - margin-top: 2vh; - } - .w-lightbox-view, - .w-lightbox-view:before { - height: 96vh; - } - .w-lightbox-group, - .w-lightbox-group .w-lightbox-view, - .w-lightbox-group .w-lightbox-view:before { - height: 84vh; - } - .w-lightbox-image { - max-width: 96vw; - max-height: 96vh; - } - .w-lightbox-group .w-lightbox-image { - max-width: 82.3vw; - max-height: 84vh; - } - .w-lightbox-left, - .w-lightbox-right { - display: block; - opacity: 0.5; - } - .w-lightbox-close { - opacity: 0.8; - } - .w-lightbox-control:hover { - opacity: 1; - } -} -.w-lightbox-inactive, -.w-lightbox-inactive:hover { - opacity: 0; -} -.w-richtext:before, -.w-richtext:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-richtext:after { - clear: both; -} -.w-richtext[contenteditable="true"]:before, -.w-richtext[contenteditable="true"]:after { - white-space: initial; -} -.w-richtext ol, -.w-richtext ul { - overflow: hidden; -} -.w-richtext .w-richtext-figure-selected.w-richtext-figure-type-video div:after, -.w-richtext .w-richtext-figure-selected[data-rt-type="video"] div:after { - outline: 2px solid #2895f7; -} -.w-richtext .w-richtext-figure-selected.w-richtext-figure-type-image div, -.w-richtext .w-richtext-figure-selected[data-rt-type="image"] div { - outline: 2px solid #2895f7; -} -.w-richtext figure.w-richtext-figure-type-video > div:after, -.w-richtext figure[data-rt-type="video"] > div:after { - content: ''; - position: absolute; - display: none; - left: 0; - top: 0; - right: 0; - bottom: 0; -} -.w-richtext figure { - position: relative; - max-width: 60%; -} -.w-richtext figure > div:before { - cursor: default!important; -} -.w-richtext figure img { - width: 100%; -} -.w-richtext figure figcaption.w-richtext-figcaption-placeholder { - opacity: 0.6; -} -.w-richtext figure div { - font-size: 0px; - color: transparent; -} -.w-richtext figure.w-richtext-figure-type-image, -.w-richtext figure[data-rt-type="image"] { - display: table; -} -.w-richtext figure.w-richtext-figure-type-image > div, -.w-richtext figure[data-rt-type="image"] > div { - display: inline-block; -} -.w-richtext figure.w-richtext-figure-type-image > figcaption, -.w-richtext figure[data-rt-type="image"] > figcaption { - display: table-caption; - caption-side: bottom; -} -.w-richtext figure.w-richtext-figure-type-video, -.w-richtext figure[data-rt-type="video"] { - width: 60%; - height: 0; -} -.w-richtext figure.w-richtext-figure-type-video iframe, -.w-richtext figure[data-rt-type="video"] iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.w-richtext figure.w-richtext-figure-type-video > div, -.w-richtext figure[data-rt-type="video"] > div { - width: 100%; -} -.w-richtext figure.w-richtext-align-center { - margin-right: auto; - margin-left: auto; - clear: both; -} -.w-richtext figure.w-richtext-align-center.w-richtext-figure-type-image > div, -.w-richtext figure.w-richtext-align-center[data-rt-type="image"] > div { - max-width: 100%; -} -.w-richtext figure.w-richtext-align-normal { - clear: both; -} -.w-richtext figure.w-richtext-align-fullwidth { - width: 100%; - max-width: 100%; - text-align: center; - clear: both; - display: block; - margin-right: auto; - margin-left: auto; -} -.w-richtext figure.w-richtext-align-fullwidth > div { - display: inline-block; - padding-bottom: inherit; -} -.w-richtext figure.w-richtext-align-fullwidth > figcaption { - display: block; -} -.w-richtext figure.w-richtext-align-floatleft { - float: left; - margin-right: 15px; - clear: none; -} -.w-richtext figure.w-richtext-align-floatright { - float: right; - margin-left: 15px; - clear: none; -} -.w-nav { - position: relative; - background: #dddddd; - z-index: 1000; -} -.w-nav:before, -.w-nav:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-nav:after { - clear: both; -} -.w-nav-brand { - position: relative; - float: left; - text-decoration: none; - color: #333333; -} -.w-nav-link { - position: relative; - display: inline-block; - vertical-align: top; - text-decoration: none; - color: #222222; - padding: 20px; - text-align: left; - margin-left: auto; - margin-right: auto; -} -.w-nav-link.w--current { - color: #0082f3; -} -.w-nav-menu { - position: relative; - float: right; -} -[data-nav-menu-open] { - display: block !important; - position: absolute; - top: 100%; - left: 0; - right: 0; - background: #C8C8C8; - text-align: center; - overflow: visible; - min-width: 200px; -} -.w--nav-link-open { - display: block; - position: relative; -} -.w-nav-overlay { - position: absolute; - overflow: hidden; - display: none; - top: 100%; - left: 0; - right: 0; - width: 100%; -} -.w-nav-overlay [data-nav-menu-open] { - top: 0; -} -.w-nav[data-animation="over-left"] .w-nav-overlay { - width: auto; -} -.w-nav[data-animation="over-left"] .w-nav-overlay, -.w-nav[data-animation="over-left"] [data-nav-menu-open] { - right: auto; - z-index: 1; - top: 0; -} -.w-nav[data-animation="over-right"] .w-nav-overlay { - width: auto; -} -.w-nav[data-animation="over-right"] .w-nav-overlay, -.w-nav[data-animation="over-right"] [data-nav-menu-open] { - left: auto; - z-index: 1; - top: 0; -} -.w-nav-button { - position: relative; - float: right; - padding: 18px; - font-size: 24px; - display: none; - cursor: pointer; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - tap-highlight-color: rgba(0, 0, 0, 0); - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.w-nav-button:focus { - outline: 0; -} -.w-nav-button.w--open { - background-color: #C8C8C8; - color: white; -} -.w-nav[data-collapse="all"] .w-nav-menu { - display: none; -} -.w-nav[data-collapse="all"] .w-nav-button { - display: block; -} -.w--nav-dropdown-open { - display: block; -} -.w--nav-dropdown-toggle-open { - display: block; -} -.w--nav-dropdown-list-open { - position: static; -} -@media screen and (max-width: 991px) { - .w-nav[data-collapse="medium"] .w-nav-menu { - display: none; - } - .w-nav[data-collapse="medium"] .w-nav-button { - display: block; - } -} -@media screen and (max-width: 767px) { - .w-nav[data-collapse="small"] .w-nav-menu { - display: none; - } - .w-nav[data-collapse="small"] .w-nav-button { - display: block; - } - .w-nav-brand { - padding-left: 10px; - } -} -@media screen and (max-width: 479px) { - .w-nav[data-collapse="tiny"] .w-nav-menu { - display: none; - } - .w-nav[data-collapse="tiny"] .w-nav-button { - display: block; - } -} -.w-tabs { - position: relative; -} -.w-tabs:before, -.w-tabs:after { - content: " "; - display: table; - grid-column-start: 1; - grid-row-start: 1; - grid-column-end: 2; - grid-row-end: 2; -} -.w-tabs:after { - clear: both; -} -.w-tab-menu { - position: relative; -} -.w-tab-link { - position: relative; - display: inline-block; - vertical-align: top; - text-decoration: none; - padding: 9px 30px; - text-align: left; - cursor: pointer; - color: #222222; - background-color: #dddddd; -} -.w-tab-link.w--current { - background-color: #C8C8C8; -} -.w-tab-link:focus { - outline: 0; -} -.w-tab-content { - position: relative; - display: block; - overflow: hidden; -} -.w-tab-pane { - position: relative; - display: none; -} -.w--tab-active { - display: block; -} -@media screen and (max-width: 479px) { - .w-tab-link { - display: block; - } -} -.w-ix-emptyfix:after { - content: ""; -} -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} -.w-dyn-empty { - padding: 10px; - background-color: #dddddd; -} -.w-dyn-hide { - display: none !important; -} -.w-dyn-bind-empty { - display: none !important; -} -.w-condition-invisible { - display: none !important; -} -.wf-layout-layout { - display: grid !important; -} -.wf-layout-cell { - display: flex !important; -} diff --git a/public/images/logo_transparent.png b/public/images/logo_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..d3313f03598980c93401e37e774311ccedee1688 GIT binary patch literal 112243 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

9C7jje#&J|xBbYUDIL98 z`p^nn>lJZ*S&Uxj?{&~4p-}yRqOWlz8QHoxNDWPd7R|69@DJePQUpS2TSr#w@qA!e zrtbqgfZoJ#WyU*8n-Jt43glPXehSZuj@Sqy$a~BAQjQ%v*s(FuhGqA@eWZdg-s|JG z8-3(#9}_qJW`6)TpM_Et)m+$E9XPh#(%)9xwYYC5{~jVYmF4b@8&h)i$8Y0Jy;+8v)eNqBVFtruLG_Z&SLez^>|~ujE>7L(b+5>DQY3(tFxHd(s>y;-9U%WIkk2O~itQ~!3^ z$nycaizVsI5w>KnuyX8`o#g9Rv8hMOh`;u0u6$HX88F*?WSe0Ml8w>VR4v zlDDb0pZK$;E4&iGs_-SU^jsZuHgY~T?d7(#G50)r#5M4}33jh)ZAr*woi5i7<;^X0 zpqb+MlZPD7wAhXCDyhxYOf1>}of)AHF(m(fhbe#EbA#Sn7pCBjg(KXf6QJ|HGyfUH z5YUT!#G3g#;Nr2^$0Lz{6w6D{L3c~LgkM*cXFMbL!-aNo+Xz6`8PS>*prh3){tRAD zNE~zXe+Ro!wR5uuT{=qS-v;Ou$x}F_$5#c6=biz41MPT zU6pI;??7*Z-2kNuw~M#-0`x(R5NFP}KK??O$BKm$aGFa6?5hO&B$a3$Y2=FHom=}m z$U8JUu+v1w?l3t3dR)wCeS!KHQ;Oo|lLfA~e^F4psjRrk;CaFR7(X=Z<2nWzQUH>Q z*%vM88F%x^SC66+-q4(f;EX!)6B(#HyO%eG=!Dn%V)iJn%;^v`gpM-=K{adq1x?-l YKknnQww^dh2LJ#707*qoM6N<$f| { poll_expire = null; } else { poll_expire = new Date(poll_expire); - // poll_expire = Date.UTC(poll_expire.getUTCFullYear(), poll_expire.getUTCMonth(), poll_expire.getUTCDate(), poll_expire.getUTCHours(), - // poll_expire.getUTCMinutes(), poll_expire.getUTCSeconds()); poll_expire = poll_expire.toUTCString(); } @@ -52,13 +50,12 @@ const pollFormHandler = async (event) => { const addOptionToPoll = async (event) => { let optionsSection = $('#poll-options'); - let newRow = $('

+
'); + let newRow = $('
  • '); + newRow.attr('class', 'list-group-item d-flex justify-content-between lh-condensed p-0 align-middle'); let newOption = $(''); newOption.attr('class', 'poll-option'); - // newOption.attr('style', 'display:block'); newOption.attr('required', true); newRow.append(newOption); - // optionsSection.append(newOption); let removeOptionLink = $(''); removeOptionLink.attr('href', '#'); @@ -76,14 +73,6 @@ const removeOptionFromPoll = async (event) => { } } -// optionsElement.on('click', function(event) { -// var clickedElement = $(event.target); -// if (clickedElement.hasClass('remove-option')) { -// let test = clickedElement.siblings()[0]; -// } -// let test = clickedElement.siblings()[0]; -// }); - async function generateID(code) { let characterSelection = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; let codeLength = code.length == 0 ? 6 : 1; diff --git a/public/js/search.js b/public/js/search.js index 6fad755..67e5421 100644 --- a/public/js/search.js +++ b/public/js/search.js @@ -17,4 +17,4 @@ const searchPolls = async (event) => { } }; -document.querySelector('#poll-search').addEventListener('submit', searchPolls); \ No newline at end of file +document.querySelector('#submit-search').addEventListener('click', searchPolls); \ No newline at end of file diff --git a/server.js b/server.js index 4b1e641..e0ad8f9 100644 --- a/server.js +++ b/server.js @@ -34,6 +34,7 @@ app.set('view engine', 'handlebars'); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.static(path.join(__dirname, "node_modules/bootstrap/dist/"))); app.use(routes); diff --git a/views/about-us.html b/views/about-us.handlebars similarity index 100% rename from views/about-us.html rename to views/about-us.handlebars diff --git a/views/create-poll.handlebars b/views/create-poll.handlebars index c7e7bd2..51bd45d 100644 --- a/views/create-poll.handlebars +++ b/views/create-poll.handlebars @@ -1,32 +1,44 @@ -
    -
    +
    +

    Create Poll

    +

    This is some sample text

    -
    -
    -
    - + +
    +
    +

    Details

    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    -
    - +
    +

    Answer choices

    +
      +
    • +
    • +
    +
    -
    - Poll expiration: - -
    -
    - Add option -
    -
    - Answer choices: -
    -
    -
    -
    - -
    - -
    +
    +
    \ No newline at end of file diff --git a/views/homepage.handlebars b/views/homepage.handlebars index 37fe9c7..8735112 100644 --- a/views/homepage.handlebars +++ b/views/homepage.handlebars @@ -1,11 +1,9 @@ -
    +
    +
    {{#each polls as |poll|}} -
    -
    {{> poll-card poll}} -
    -
    {{/each}} -
    +
  • diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index ff30956..15bf5c4 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -6,54 +6,48 @@ + + + + -
    + + + + \ No newline at end of file From 7f2ea836f0e771104459ba7bcf12797175c72973 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Fri, 19 Aug 2022 00:02:35 -0400 Subject: [PATCH 60/86] Add ability to edit poll descriptions, make chartjs only show whole numbers on charts --- controllers/api/poll-routes.js | 2 +- models/Poll.js | 2 +- public/css/style.css | 17 ++++- public/js/edit-poll.js | 90 ++++++++++++++---------- public/js/poll-cards.js | 16 +++++ public/js/poll.js | 16 +++++ views/layouts/main.handlebars | 2 - views/partials/dash-poll-card.handlebars | 8 +-- views/partials/poll-card.handlebars | 2 +- 9 files changed, 106 insertions(+), 49 deletions(-) diff --git a/controllers/api/poll-routes.js b/controllers/api/poll-routes.js index 5aaf1f7..279d580 100644 --- a/controllers/api/poll-routes.js +++ b/controllers/api/poll-routes.js @@ -21,7 +21,7 @@ router.post('/', withAuth, async (req, res) => { router.put('/:id', withAuth, async (req, res) => { try { const data = await Poll.update({ - poll_desc: req.body.poll_content + poll_desc: req.body.poll_desc }, { where: { diff --git a/models/Poll.js b/models/Poll.js index 4855b2b..8e0d084 100644 --- a/models/Poll.js +++ b/models/Poll.js @@ -23,7 +23,7 @@ Polls.init( }, poll_desc: { - type: DataTypes.STRING, + type: DataTypes.TEXT, allowNull: true }, diff --git a/public/css/style.css b/public/css/style.css index 6933a4c..814cc84 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -17,7 +17,7 @@ /* width: 200px; */ } -.navbar a { +.navbar a, .navbar a:hover { text-decoration: none; font-weight: bold; color: white; @@ -104,7 +104,8 @@ nav a { .poll-card-desc a:link, .poll-card-desc a:visited { text-decoration: none; - color: black; + font-weight: bold; + color: dodgerblue; } .poll-card-desc { @@ -122,7 +123,13 @@ nav a { border-top-right-radius: 10px; */ } -.poll-card-header a { +.blue-link { + color: dodgerblue; + font-weight: bold; + text-decoration: none; +} + +.poll-card-header a, .poll-card-header a:hover { text-decoration: none; color: white; font-weight: bold; @@ -144,4 +151,8 @@ nav a { font-style: italic; color: silver; font-weight: lighter; +} + +.hidden { + display: none; } \ No newline at end of file diff --git a/public/js/edit-poll.js b/public/js/edit-poll.js index 4fd588d..7d17ea2 100644 --- a/public/js/edit-poll.js +++ b/public/js/edit-poll.js @@ -2,46 +2,62 @@ const pollEdit = async (event) => { event.preventDefault(); - - const edit = event.target; - if(edit.className == "desc_edit"){ - - - - //const new_desc = edit.parentNode; - - // const poll_id = document.querySelector('input[name="id"]').value; - + if (edit.className == "desc_edit") { let textField = $(" - Click here to vote! + Click here to vote! diff --git a/views/partials/poll-card.handlebars b/views/partials/poll-card.handlebars index a95de3a..cbb6338 100644 --- a/views/partials/poll-card.handlebars +++ b/views/partials/poll-card.handlebars @@ -18,7 +18,7 @@ {{/each}} - Click here to vote! + Click here to vote! From 2a959c1a24dcd01322e6f6da3775c0f0b54ebdbc Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Fri, 19 Aug 2022 00:33:37 -0400 Subject: [PATCH 61/86] Add length limits to inputs, make poll_options a TEXT datatype, fix bug where editing description would change the wrong poll's description --- controllers/api/answer-routes.js | 2 +- models/Poll.js | 2 +- public/js/create-poll.js | 1 + public/js/edit-poll.js | 3 ++- views/create-poll.handlebars | 12 ++++++++---- views/poll.handlebars | 2 +- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/controllers/api/answer-routes.js b/controllers/api/answer-routes.js index f084fa1..475d768 100644 --- a/controllers/api/answer-routes.js +++ b/controllers/api/answer-routes.js @@ -8,7 +8,7 @@ router.post('/', withAuth, async (req, res) => { }); const expiration = poll.poll_expire ? new Date(new Date(poll.poll_expire).toUTCString()) : null; const today = new Date(new Date().toUTCString()); - if (expiration && expiration > today) { + if (expiration && expiration < today) { throw 'Poll expired.'; } const data = await Answer.create({ diff --git a/models/Poll.js b/models/Poll.js index 8e0d084..8b81dbf 100644 --- a/models/Poll.js +++ b/models/Poll.js @@ -28,7 +28,7 @@ Polls.init( }, poll_options: { - type: DataTypes.STRING, + type: DataTypes.TEXT, allowNull: false }, diff --git a/public/js/create-poll.js b/public/js/create-poll.js index 26e7aba..97f9d6c 100644 --- a/public/js/create-poll.js +++ b/public/js/create-poll.js @@ -55,6 +55,7 @@ const addOptionToPoll = async (event) => { let newOption = $(''); newOption.attr('class', 'poll-option'); newOption.attr('required', true); + newOption.attr('maxlength', '70'); newRow.append(newOption); let removeOptionLink = $(''); diff --git a/public/js/edit-poll.js b/public/js/edit-poll.js index 7d17ea2..da4f27d 100644 --- a/public/js/edit-poll.js +++ b/public/js/edit-poll.js @@ -8,6 +8,7 @@ const pollEdit = async (event) => { let textField = $(" +
    @@ -30,8 +30,12 @@

    Answer choices

      -
    • -
    • +
    • + +
    • +
    • + +
    Add option diff --git a/views/poll.handlebars b/views/poll.handlebars index 1f7a81c..93c1d17 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -17,7 +17,7 @@
    {{/if}} -
    +
    - Click here to vote! + Click here to vote!
    - +
    diff --git a/views/poll.handlebars b/views/poll.handlebars index 93c1d17..aa86c4c 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -1,33 +1,63 @@
    -

    Poll: {{poll.poll_title}} - Made by: {{poll.user.username}}

    -

    Share code: {{poll.id}}

    -{{#if poll.poll_expire}} -

    Ends at: {{format_date poll.poll_expire}}

    -{{/if}} -
    - {{poll.poll_desc}} -
    +
    +

    {{poll.poll_title}}

    +

    By {{poll.user.username}}

    + {{#if poll.poll_expire}} +

    Ends at: {{format_date poll.poll_expire}}

    + {{/if}} +

    Share code: + +

    +
    +
    + {{poll.poll_desc}} +
    +
    + + {{#if userCanVote}} +
    +
    +
    + +
    +
      + {{#each poll.poll_options as |option|}} + + + {{/each}} + +
    +
    +
    +
    +
    + {{else}} +
    +
    + + + + +
    +
    + {{/if}} -{{#if userCanVote}} -
    - {{#each poll.poll_options as |option|}} - {{option.name}}
    - {{/each}} - -
    -{{/if}} -
    - - - - -
    +
    - - \ No newline at end of file +{{#if userCanVote}} + +{{else}} + + +{{/if}} + \ No newline at end of file From 6291a2843de5f331a1bfe082afd45219129eea7f Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Fri, 19 Aug 2022 19:46:19 -0400 Subject: [PATCH 63/86] limit display of descriptions in card view, enable linebreaks to work on full view --- utils/helpers.js | 6 ++++++ views/partials/dash-poll-card.handlebars | 2 +- views/partials/poll-card.handlebars | 2 +- views/poll.handlebars | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/utils/helpers.js b/utils/helpers.js index 6d20a24..f13c689 100644 --- a/utils/helpers.js +++ b/utils/helpers.js @@ -16,5 +16,11 @@ module.exports = { }, format_content: (text) => { return text.replace(/(?:\r\n|\r|\n)/g, '
    '); + }, + desc_preview: (text) => { + if (text.length > 200) { + return text.slice(0, 200).trim() + '...'; + } + return text; } }; diff --git a/views/partials/dash-poll-card.handlebars b/views/partials/dash-poll-card.handlebars index 69c8a88..bd682a5 100644 --- a/views/partials/dash-poll-card.handlebars +++ b/views/partials/dash-poll-card.handlebars @@ -8,7 +8,7 @@
    - {{poll_desc}} + {{desc_preview poll_desc}} Edit Description diff --git a/views/partials/poll-card.handlebars b/views/partials/poll-card.handlebars index 91844b0..1d1fbbf 100644 --- a/views/partials/poll-card.handlebars +++ b/views/partials/poll-card.handlebars @@ -7,7 +7,7 @@
    - {{poll_desc}} + {{desc_preview poll_desc}}
    diff --git a/views/poll.handlebars b/views/poll.handlebars index aa86c4c..5b5a31b 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -10,7 +10,7 @@

    - {{poll.poll_desc}} + {{{format_content poll.poll_desc}}}
    From 551d6e1847532d427b3a2da5c9a95c0d637acdf6 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Fri, 19 Aug 2022 21:38:21 -0400 Subject: [PATCH 64/86] Add user pages, update about us page --- controllers/dashboard-routes.js | 2 +- controllers/home-routes.js | 4 +- controllers/index.js | 4 +- controllers/user-page-routes.js | 52 ++++++++++++++ public/css/style.css | 21 ++---- views/about-us.handlebars | 87 ++++++++++-------------- views/dashboard.handlebars | 1 + views/partials/dash-poll-card.handlebars | 2 +- views/partials/poll-card.handlebars | 2 +- views/user-page.handlebars | 15 ++++ 10 files changed, 119 insertions(+), 71 deletions(-) create mode 100644 controllers/user-page-routes.js create mode 100644 views/user-page.handlebars diff --git a/controllers/dashboard-routes.js b/controllers/dashboard-routes.js index 08a6453..8d48de7 100644 --- a/controllers/dashboard-routes.js +++ b/controllers/dashboard-routes.js @@ -20,7 +20,7 @@ router.get('/', withAuth, async (req, res) => { }, { model: User, - attributes: ['username'] + attributes: ['id', 'username'] } ], order: [['created_at', 'DESC']], diff --git a/controllers/home-routes.js b/controllers/home-routes.js index b9d1dd0..e597939 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -33,7 +33,7 @@ router.get('/', async (req, res) => { }, { model: User, - attributes: ['username'] + attributes: ['id', 'username'] } ], order: [['created_at', 'DESC']], @@ -78,7 +78,7 @@ router.get('/poll/:id', async (req, res) => { }, { model: User, - attributes: ['username'] + attributes: ['id', 'username'] } ] }); diff --git a/controllers/index.js b/controllers/index.js index 4a100cd..b010b72 100644 --- a/controllers/index.js +++ b/controllers/index.js @@ -3,9 +3,9 @@ const router = require('express').Router(); const apiRoutes = require('./api'); const homeRoutes = require('./home-routes.js'); const dashRoutes = require('./dashboard-routes.js') -// const userPageRoutes = require('./user-page-routes.js'); +const userPageRoutes = require('./user-page-routes.js'); -// router.use('/user-page', userPageRoutes); +router.use('/user', userPageRoutes); router.use('/api', apiRoutes); router.use('/', homeRoutes); router.use('/dashboard', dashRoutes); diff --git a/controllers/user-page-routes.js b/controllers/user-page-routes.js new file mode 100644 index 0000000..f5ae450 --- /dev/null +++ b/controllers/user-page-routes.js @@ -0,0 +1,52 @@ +const router = require('express').Router(); +const { Poll, User, Answer } = require('../models'); +const withAuth = require('../utils/auth'); + +router.get('/:id', withAuth, async (req, res) => { + try { + const pollData = await Poll.findAll({ + attributes: ['id', 'poll_title', 'poll_desc', 'poll_options', 'user_id', 'created_at'], + where:{ + user_id: req.params.id + }, + include: [ + { + model: Answer, + attributes: ['poll_id', 'user_id', 'option'], + include: [{ + model: User, + attributes: ['username'] + }] + }, + { + model: User, + attributes: ['username'] + } + ], + order: [['created_at', 'DESC']], + }); + + let polls = pollData.map((post) => + post.get({ plain: true }) + ); + + for(let poll of polls) { + poll.poll_options = JSON.parse(poll.poll_options); + poll.poll_options = poll.poll_options.options.map((o) => JSON.parse(`{"name": "${o}","count": 0}`)); + for (let i = 0; i < poll.answers.length; i++) { + poll.poll_options.find(e => e.name === poll.answers[i].option).count++; + } + } + + const user = await User.findByPk(req.params.id, { + attributes: ['id', 'username'] + }); + + res.render('user-page', {polls, loggedIn: req.session.loggedIn, user_name: user.username}); + } catch (err) { + console.log(err); + res.status(500).json(err); + } + }); + + module.exports = router; \ No newline at end of file diff --git a/public/css/style.css b/public/css/style.css index 3ea2309..c752034 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -45,20 +45,6 @@ border-bottom-right-radius: 5px; } -nav { - background-color: #E0E0E0; - padding-top: 8px; - padding-bottom: 8px; - padding-left: 30px; - margin-bottom: 10px; -} - -nav a { - text-decoration: none; - font-weight: bold; - color: dodgerblue; -} - #create-form textarea { min-height: 200px; } @@ -188,3 +174,10 @@ nav a { background-color: white !important; color: black !important; } + +.team-card { + padding: 20px; + background-color: #EEF0F1; + width: 250px; + height: 280px; +} \ No newline at end of file diff --git a/views/about-us.handlebars b/views/about-us.handlebars index d72616b..e3b5b2e 100644 --- a/views/about-us.handlebars +++ b/views/about-us.handlebars @@ -1,52 +1,39 @@ - - - - - User Examples - - - - - - - - - - - -
    -
    -

    About Us

    -
    -
    -
    Michael S.
    -
    Gitlink
    LinkedIn
    -

    SAMPLE TEXT.

    -
    -
    -
    Ellis J.
    -
    Gitlink
    LinkedIn
    -

    SAMPLE TEXT

    -
    -
    -
    Jared D.
    -
    Gitlink
    LinkedIn
    -

    SAMPLE TEXT

    -
    -
    -
    Bocar L.
    -
    Gitlink
    LinkedIn
    -

    SAMPLE TEXT

    -
    -
    -
    Adam M.
    -
    Gitlink
    LinkedIn
    -

    SAMPLE TEXT

    -
    +
    +
    +

    About Us

    +
    +
    +
    +
    + Jared D. +
    +
    +

    Michael S.
    Github: ms13380

    +
    +
    +
    +
    + Jared D. +
    +
    +

    Jared D.
    Github: jareddaniel95

    +
    +
    +
    +
    + Jared D. +
    +
    +

    Adam M.
    Github: AmartinVT

    +
    +
    +
    +
    + Jared D. +
    +
    +

    Bocar L.
    Github: bl-engineer

    -
    - - - - \ No newline at end of file +
    +
    \ No newline at end of file diff --git a/views/dashboard.handlebars b/views/dashboard.handlebars index a5bff43..488cbf1 100644 --- a/views/dashboard.handlebars +++ b/views/dashboard.handlebars @@ -1,5 +1,6 @@
    +

    My Polls

    {{#if polls}} {{#each polls as |poll|}} {{> dash-poll-card poll}} diff --git a/views/partials/dash-poll-card.handlebars b/views/partials/dash-poll-card.handlebars index bd682a5..f4b6182 100644 --- a/views/partials/dash-poll-card.handlebars +++ b/views/partials/dash-poll-card.handlebars @@ -2,7 +2,7 @@
    - {{!-- Need user profile link here --}} + {{!-- --}}
    diff --git a/views/partials/poll-card.handlebars b/views/partials/poll-card.handlebars index 1d1fbbf..7985472 100644 --- a/views/partials/poll-card.handlebars +++ b/views/partials/poll-card.handlebars @@ -2,7 +2,7 @@
    - {{!-- Need user profile link here --}} +
    diff --git a/views/user-page.handlebars b/views/user-page.handlebars new file mode 100644 index 0000000..f33417b --- /dev/null +++ b/views/user-page.handlebars @@ -0,0 +1,15 @@ +
    +
    +

    {{possessive_grammar user_name}} Polls

    + {{#if polls}} + {{#each polls as |poll|}} + {{> poll-card poll}} + {{/each}} + {{else}} +

    Your polls will appear here.

    + {{/if}} +
    +
    + + + \ No newline at end of file From 4df3cb0f8cc7a854092c62c085fca336a7e94fd5 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Fri, 19 Aug 2022 21:44:51 -0400 Subject: [PATCH 65/86] Fix issue with voting in heroku --- views/poll.handlebars | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/poll.handlebars b/views/poll.handlebars index 5b5a31b..c0e9ce0 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -29,7 +29,7 @@ {{/each}} - +
    From cb7dc4d8ba83b080ffd195aebc90cb062c2da3a1 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Fri, 19 Aug 2022 22:33:32 -0400 Subject: [PATCH 66/86] styling for login/register pages, update create poll page, stop forcing users to log in to see about us page --- controllers/home-routes.js | 2 +- public/css/style.css | 2 +- views/create-poll.handlebars | 27 +++++++++++---------- views/login.handlebars | 35 ++++++++++++++------------- views/register.handlebars | 46 +++++++++++++++++------------------- 5 files changed, 58 insertions(+), 54 deletions(-) diff --git a/controllers/home-routes.js b/controllers/home-routes.js index e597939..49b6c21 100644 --- a/controllers/home-routes.js +++ b/controllers/home-routes.js @@ -121,7 +121,7 @@ router.get('/create', withAuth, async (req, res) => { } }); -router.get('/about-us', withAuth, async (req, res) => { +router.get('/about-us', async (req, res) => { try { res.render('about-us', {loggedIn: req.session.loggedIn}); } catch (err) { diff --git a/public/css/style.css b/public/css/style.css index c752034..1ded6fc 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -142,7 +142,7 @@ .optional { font-style: italic; - color: silver; + color: #AAA; font-weight: lighter; } diff --git a/views/create-poll.handlebars b/views/create-poll.handlebars index be01e20..6475dc1 100644 --- a/views/create-poll.handlebars +++ b/views/create-poll.handlebars @@ -1,10 +1,9 @@

    Create Poll

    -

    This is some sample text

    -
    +

    Details

    @@ -15,20 +14,24 @@
    -
    - +
    +
    -
    -
    - -
    -
    -

    Answer choices

    +
    +
    +
    +

    Answer choices

    +
    + +
    +
    • @@ -37,8 +40,8 @@
    -
    - Add option +
    +
    diff --git a/views/login.handlebars b/views/login.handlebars index d8da068..63af675 100644 --- a/views/login.handlebars +++ b/views/login.handlebars @@ -1,18 +1,21 @@ -
    -
    Login
    - - -
    - - -
    -
    - - -
    -
    - -
    - +
    +
    +

    Login

    +
    +
    + +
    diff --git a/views/register.handlebars b/views/register.handlebars index a1d8ca8..fd1e5c4 100644 --- a/views/register.handlebars +++ b/views/register.handlebars @@ -1,27 +1,25 @@ -
    -
    - Register +
    +
    +

    Register

    -
    -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - -
    -
    -
    -
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    \ No newline at end of file From c3f0ffecfb5c034423383f09926206146bd6fec0 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Sat, 20 Aug 2022 00:20:02 -0400 Subject: [PATCH 67/86] Fix bug that caused links to be unusable on dashboard/user pages, Adjust size of poll chart based on question count --- public/js/edit-poll.js | 115 +++++++++++------------ utils/helpers.js | 3 + views/partials/dash-poll-card.handlebars | 2 +- views/poll.handlebars | 6 +- views/user-page.handlebars | 3 +- 5 files changed, 64 insertions(+), 65 deletions(-) diff --git a/public/js/edit-poll.js b/public/js/edit-poll.js index da4f27d..0ea0c4f 100644 --- a/public/js/edit-poll.js +++ b/public/js/edit-poll.js @@ -1,64 +1,63 @@ const pollEdit = async (event) => { - - event.preventDefault(); - - const edit = event.target; - - if (edit.className == "desc_edit") { - let textField = $(" - +
    {{/if}} -
    diff --git a/views/user-page.handlebars b/views/user-page.handlebars index f33417b..28f4f9a 100644 --- a/views/user-page.handlebars +++ b/views/user-page.handlebars @@ -11,5 +11,4 @@
    - - \ No newline at end of file + \ No newline at end of file From b267f1f2badd7ae8a117619eb33fcf62e8d555a8 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Sat, 20 Aug 2022 01:24:19 -0400 Subject: [PATCH 68/86] Add seeds, show poll results when able to vote --- public/js/create-poll.js | 10 +- seeds/answer-seeds.js | 344 +++++++++++++++++++++++++++++++++++---- seeds/poll-seeds.js | 47 ++++-- seeds/user-seeds.js | 32 +++- views/poll.handlebars | 32 ++-- 5 files changed, 399 insertions(+), 66 deletions(-) diff --git a/public/js/create-poll.js b/public/js/create-poll.js index 2f4b8c1..243b523 100644 --- a/public/js/create-poll.js +++ b/public/js/create-poll.js @@ -49,8 +49,8 @@ const pollFormHandler = async (event) => { }; const addOptionToPoll = async (event) => { + event.preventDefault(); let optionsSection = $('#poll-options'); - let existingOptionCount = document.querySelector('#poll-options').querySelectorAll('li').length; if (existingOptionCount >= 9) { @@ -60,6 +60,7 @@ const addOptionToPoll = async (event) => { let newRow = $('
  • '); newRow.attr('class', 'list-group-item d-flex justify-content-between lh-condensed p-0 align-middle'); + let newOption = $(''); newOption.attr('class', 'poll-option'); newOption.attr('required', true); @@ -77,10 +78,11 @@ const addOptionToPoll = async (event) => { const removeOptionFromPoll = async (event) => { if (event.target.className === 'remove-option') { + event.preventDefault(); let optionList = event.target.parentNode.parentNode; - optionList.removeChild(event.target.parentNode); - let addLink = $('#add-option'); - addLink.removeClass('hidden'); + optionList.removeChild(event.target.parentNode); + let addLink = $('#add-option'); + addLink.removeClass('hidden'); } } diff --git a/seeds/answer-seeds.js b/seeds/answer-seeds.js index f9270c4..c280b41 100644 --- a/seeds/answer-seeds.js +++ b/seeds/answer-seeds.js @@ -2,92 +2,172 @@ const { Answer } = require('../models'); const pollData = [ { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 2, - option: "Option 1" + option: "1" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 3, - option: "Option 1" + option: "2" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 4, - option: "Option 2" + option: "2" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 5, - option: "Option 4" + option: "3" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 6, - option: "Option 4" + option: "3" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 7, - option: "Option 3" + option: "4" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 8, - option: "Option 1" + option: "4" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 9, - option: "Option 2" + option: "4" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 10, - option: "Option 2" + option: "5" }, { - poll_id: "ABC123", + poll_id: "F49K0S", user_id: 11, - option: "Option 1" + option: "5" + }, + { + poll_id: "F49K0S", + user_id: 12, + option: "5" + }, + { + poll_id: "F49K0S", + user_id: 13, + option: "5" + }, + { + poll_id: "F49K0S", + user_id: 14, + option: "5" + }, + { + poll_id: "F49K0S", + user_id: 15, + option: "5" + }, + { + poll_id: "F49K0S", + user_id: 16, + option: "5" + }, + { + poll_id: "F49K0S", + user_id: 17, + option: "5" }, //////////////////////// { - poll_id: "987CBA", + poll_id: "97CQAB", user_id: 1, - option: "Blue" + option: "East Coast" + }, + { + poll_id: "97CQAB", + user_id: 2, + option: "East Coast" }, { - poll_id: "987CBA", + poll_id: "97CQAB", user_id: 3, - option: "Purple" + option: "East Coast" }, { - poll_id: "987CBA", + poll_id: "97CQAB", + user_id: 4, + option: "East Coast" + }, + { + poll_id: "97CQAB", user_id: 5, - option: "Red" + option: "East Coast" }, { - poll_id: "987CBA", + poll_id: "97CQAB", user_id: 6, - option: "Blue" + option: "East Coast" }, { - poll_id: "987CBA", + poll_id: "97CQAB", user_id: 7, - option: "Red" + option: "East Coast" }, { - poll_id: "987CBA", + poll_id: "97CQAB", + user_id: 8, + option: "West Coast" + }, + { + poll_id: "97CQAB", + user_id: 9, + option: "West Coast" + }, + { + poll_id: "97CQAB", user_id: 10, - option: "Green" + option: "Central (No Coast)" }, { - poll_id: "987CBA", + poll_id: "97CQAB", user_id: 11, - option: "Red" + option: "Central (No Coast)" + }, + { + poll_id: "97CQAB", + user_id: 12, + option: "West Coast" + }, + { + poll_id: "97CQAB", + user_id: 13, + option: "West Coast" + }, + { + poll_id: "97CQAB", + user_id: 14, + option: "West Coast" + }, + { + poll_id: "97CQAB", + user_id: 15, + option: "West Coast" + }, + { + poll_id: "97CQAB", + user_id: 16, + option: "West Coast" + }, + { + poll_id: "97CQAB", + user_id: 17, + option: "Central (No Coast)" }, //////////////////////// @@ -194,6 +274,202 @@ const pollData = [ poll_id: "T4JG51", user_id: 11, option: "Yes" + }, + { + poll_id: "T4JG51", + user_id: 12, + option: "Yes" + }, + { + poll_id: "T4JG51", + user_id: 13, + option: "Yes" + }, + { + poll_id: "T4JG51", + user_id: 14, + option: "Yes" + }, + { + poll_id: "T4JG51", + user_id: 15, + option: "Yes" + }, + { + poll_id: "T4JG51", + user_id: 16, + option: "Yes" + }, + { + poll_id: "T4JG51", + user_id: 17, + option: "No" + }, + + //////////////////////////// + + { + poll_id: "43R09Z", + user_id: 1, + option: "Python" + }, + { + poll_id: "43R09Z", + user_id: 2, + option: "Javascript" + }, + { + poll_id: "43R09Z", + user_id: 3, + option: "Javascript" + }, + { + poll_id: "43R09Z", + user_id: 4, + option: "Javascript" + }, + { + poll_id: "43R09Z", + user_id: 5, + option: "Javascript" + }, + { + poll_id: "43R09Z", + user_id: 6, + option: "Javascript" + }, + { + poll_id: "43R09Z", + user_id: 7, + option: "Java" + }, + { + poll_id: "43R09Z", + user_id: 8, + option: "Java" + }, + { + poll_id: "43R09Z", + user_id: 9, + option: "C#" + }, + { + poll_id: "43R09Z", + user_id: 10, + option: "C#" + }, + { + poll_id: "43R09Z", + user_id: 11, + option: "Go" + }, + { + poll_id: "43R09Z", + user_id: 12, + option: "R" + }, + { + poll_id: "43R09Z", + user_id: 13, + option: "R" + }, + { + poll_id: "43R09Z", + user_id: 14, + option: "Swift" + }, + { + poll_id: "43R09Z", + user_id: 15, + option: "PHP" + }, + { + poll_id: "43R09Z", + user_id: 16, + option: "C" + }, + { + poll_id: "43R09Z", + user_id: 17, + option: "C++" + }, + + //////////////////////////// + + { + poll_id: "Y6RFY1", + user_id: 1, + option: "Blue" + }, + { + poll_id: "Y6RFY1", + user_id: 2, + option: "Red" + }, + { + poll_id: "Y6RFY1", + user_id: 3, + option: "Red" + }, + { + poll_id: "Y6RFY1", + user_id: 4, + option: "Red" + }, + { + poll_id: "Y6RFY1", + user_id: 5, + option: "Red" + }, + { + poll_id: "Y6RFY1", + user_id: 6, + option: "Red" + }, + { + poll_id: "Y6RFY1", + user_id: 7, + option: "Orange" + }, + { + poll_id: "Y6RFY1", + user_id: 8, + option: "Orange" + }, + { + poll_id: "Y6RFY1", + user_id: 9, + option: "Yellow" + }, + { + poll_id: "Y6RFY1", + user_id: 10, + option: "Blue" + }, + { + poll_id: "Y6RFY1", + user_id: 11, + option: "Blue" + }, + { + poll_id: "Y6RFY1", + user_id: 12, + option: "Blue" + }, + { + poll_id: "Y6RFY1", + user_id: 13, + option: "Green" + }, + { + poll_id: "Y6RFY1", + user_id: 14, + option: "Green" + }, + { + poll_id: "Y6RFY1", + user_id: 15, + option: "Brown" } ]; diff --git a/seeds/poll-seeds.js b/seeds/poll-seeds.js index ba01021..a5ce90e 100644 --- a/seeds/poll-seeds.js +++ b/seeds/poll-seeds.js @@ -2,18 +2,19 @@ const { Poll } = require('../models'); const pollData = [ { - id: 'ABC123', - poll_title: 'Sample', - poll_desc: "This is a sample poll.", - poll_options: `{"options": ["Option 1", "Option 2", "Option 3", "Option 4"]}`, + id: 'F49K0S', + poll_title: 'Fist of Five', + poll_desc: "How do you feel about the content covered in class today?", + poll_options: `{"options": ["1", "2", "3", "4", "5"]}`, user_id: 1 }, { - id: '987CBA', - poll_title: 'Favorite color', - poll_desc: "What is you favorite color?", - poll_options: `{"options": ["Red", "Green", "Blue", "Yellow", "Orange", "Purple"]}`, - user_id: 2 + id: '97CQAB', + poll_title: 'Best Coast', + poll_desc: "", + poll_options: `{"options": ["East Coast", "Central (No Coast)", "West Coast"]}`, + user_id: 2, + poll_expire: "2022-08-20 9:30:00" }, { id: 'Z6Y5X4', @@ -27,8 +28,32 @@ const pollData = [ poll_title: 'Will the Braves win the World Series this year?', poll_desc: "", poll_options: `{"options": ["Yes", "No"]}`, - user_id: 4 - } + user_id: 4, + poll_expire: "2022-08-30 22:37:00" + }, + { + id: '43R09Z', + poll_title: 'Favorite Lang', + poll_desc: "What is your favorite programming language? Poll closes on the 22nd.", + poll_options: `{"options": ["Python", "Javascript", "Java", "C#", "C", "C++", "Go", "R", "Swift", "PHP"]}`, + user_id: 5, + poll_expire: "2022-08-22 00:00:00" + }, + { + id: 'Y6RFY1', + poll_title: 'Favorite Color Of M&M', + poll_desc: `And what it says about you. +Red: You are bold, adventurous, and energetic. +Orange: You are creative, social, and happy. +Yellow: You are optimistic, cheerful, and calming. +Blue: You are gentle, trustworthy, and stable. +Green: You are practical, helpful, and productive. +Brown: You are wrong. +`, + poll_options: `{"options": ["Red", "Orange", "Yellow", "Blue", "Green", "Brown"]}`, + user_id: 14 + }, + ]; const seedPolls = () => Poll.bulkCreate(pollData); diff --git a/seeds/user-seeds.js b/seeds/user-seeds.js index 68dbc65..1d877be 100644 --- a/seeds/user-seeds.js +++ b/seeds/user-seeds.js @@ -55,7 +55,37 @@ const userData = [ username: 'Ruth_Conley', email: 'ruth.c@example.com', password: 'test.pass11' - } + }, + { + username: 'Sidney.Montoya', + email: 'sidney.m@example.com', + password: 'test.pass12' + }, + { + username: 'Tegan_Richards', + email: 'tegan.r@example.com', + password: 'test.pass13' + }, + { + username: 'Gary Barajas', + email: 'gary.b@example.com', + password: 'test.pass14' + }, + { + username: 'Reece Campbell', + email: 'reece.c@example.com', + password: 'test.pass15' + }, + { + username: 'Michelle.Friedman', + email: 'michelle.f@example.com', + password: 'test.pass16' + }, + { + username: 'Maddison-Diaz', + email: 'maddison.d@example.com', + password: 'test.pass17' + }, ]; const seedUsers = () => User.bulkCreate(userData, {individualHooks: true}); diff --git a/views/poll.handlebars b/views/poll.handlebars index 1f9bb5a..ac72357 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -34,28 +34,28 @@ - {{else}} -
    -
    - - - - -
    -
    {{/if}} +

    Results

    +
    + +
    + + + + +
    +
    +
  • {{#if userCanVote}} -{{else}} - - {{/if}} + \ No newline at end of file From 97229e217c59089f0231a8ad6148b684b7cef97d Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 06:05:53 -0400 Subject: [PATCH 69/86] Changing the title and font in the md Customizing our README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eef5875..4f8f6ff 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Project -Together or together? For that is the question +# PollTogether +Together or together? For THAT is the question ### https://ms13380.github.io/PollTogether/ ======= Heroku: https://poll-together.herokuapp.com/ From 8dcbdc8501f289e3281e5e7d26e4ee47a0739697 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 06:08:19 -0400 Subject: [PATCH 70/86] Creating User Story Tell the story of our group in such a way that it pulls the user in. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f8f6ff..fbf8ea9 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Heroku: https://poll-together.herokuapp.com/ ## User Story ```md -AS A bootcam teacher -I WANT to be able to get input from my students +AS A bootcamp teacher or for anyone who cares to create a poll, PollTogether is here for you + SO THAT I can make sure that everyone understands and is participating ``` From 708e78a09fa6c12f1b776b9b5560883b7bd4aded Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 06:21:47 -0400 Subject: [PATCH 71/86] Restructure the layout Made some additional markdowns and edited story --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fbf8ea9..9ed7703 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,11 @@ Heroku: https://poll-together.herokuapp.com/ ## User Story ```md -AS A bootcamp teacher or for anyone who cares to create a poll, PollTogether is here for you - -SO THAT I can make sure that everyone understands and is participating +Our inspiration was simple - how can you gauge how people are thinking or what do they want to do? +AS A bootcamp instructor or for anyone who cares easily create a poll, PollTogether is here for you! +For a bootcamp instructor with many students how do you know INSTANTLY that they understand the material? +How do you know that everyone is following along? +What is a fast, accurate, and reliable way I can take a poll of if we want to work together...or together ``` ## Acceptance Criteria From b995b7fc8ee5c41302e50dd0d387ce72beaadf82 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 06:28:01 -0400 Subject: [PATCH 72/86] Revamp heading Wanted to style our differently to set it apart from previous examples. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9ed7703..ef0e480 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ Heroku: https://poll-together.herokuapp.com/ ## User Story ```md -Our inspiration was simple - how can you gauge how people are thinking or what do they want to do? +Our inspiration was simple - A fun way, accurate, and user-friendly way to get your "Fist-of-Five" +HOW can you gauge what your students are thinking or what do they want to do? AS A bootcamp instructor or for anyone who cares easily create a poll, PollTogether is here for you! -For a bootcamp instructor with many students how do you know INSTANTLY that they understand the material? -How do you know that everyone is following along? -What is a fast, accurate, and reliable way I can take a poll of if we want to work together...or together + +The question is, "Together or together?" The answer is PollTogether ``` ## Acceptance Criteria From 9f44cd7eba4667775117bdd8a6247d9397d4ac6b Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 06:35:16 -0400 Subject: [PATCH 73/86] Insertion of emojis Utlizied emojipedia to add character --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ef0e480..ee01b76 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ Heroku: https://poll-together.herokuapp.com/ ## User Story ```md -Our inspiration was simple - A fun way, accurate, and user-friendly way to get your "Fist-of-Five" -HOW can you gauge what your students are thinking or what do they want to do? +OUR INSPIRATION was simple - To CREATE a fun way, accurate, and user-friendly way to get your "Fist-of-Five" +HOW can you gauge what your students are thinking or what do they want to do? 🤔 AS A bootcamp instructor or for anyone who cares easily create a poll, PollTogether is here for you! -The question is, "Together or together?" The answer is PollTogether +THE QUESTION is, "Together or together?" The answer is PollTogether 👍 ``` ## Acceptance Criteria From 2f0162f33e22827116e03cdb3218412c5a068768 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 06:57:54 -0400 Subject: [PATCH 74/86] Title Change and font change Coded font differently and personalized the title --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ee01b76..40239d4 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,15 @@ Together or together? For THAT is the question Heroku: https://poll-together.herokuapp.com/ ## Made by the Polars -## User Story +## How PollTogether Came to Be ```md -OUR INSPIRATION was simple - To CREATE a fun way, accurate, and user-friendly way to get your "Fist-of-Five" -HOW can you gauge what your students are thinking or what do they want to do? 🤔 +OUR INSPIRATION was simple - To CREATE a fun way, accurate, and graphically-appealing way to get your "Fist-of-Five"! +IT SOLVES - HOW can you gauge what your students are thinking or what do they want to do instantly? 🤔 AS A bootcamp instructor or for anyone who cares easily create a poll, PollTogether is here for you! -THE QUESTION is, "Together or together?" The answer is PollTogether 👍 +THE QUESTION is, "Together or together?" +The SOLUTION is PollTogether 👍 ``` ## Acceptance Criteria From 0604f1a86da7314b06f1fe50a8c6df300076f1cd Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 07:01:54 -0400 Subject: [PATCH 75/86] README Repository storage of visuals --- README visuals | 1 + 1 file changed, 1 insertion(+) create mode 100644 README visuals diff --git a/README visuals b/README visuals new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/README visuals @@ -0,0 +1 @@ + From 9da25fc5ea777224fba03b04c879ac3c0594e25d Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 07:07:50 -0400 Subject: [PATCH 76/86] Picture of website Input visual of project --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 40239d4..f8a5482 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ AS A bootcamp instructor or for anyone who cares easily create a poll, PollToget THE QUESTION is, "Together or together?" The SOLUTION is PollTogether 👍 ``` +![image](https://user-images.githubusercontent.com/103905661/185743118-751bf828-f95e-4e09-8ab9-a10704058d2c.png) ## Acceptance Criteria From ec5a8e8a0b1bf8b28e5b947b570b3e0e83119666 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 07:31:32 -0400 Subject: [PATCH 77/86] Customize how to Give user step by step instructions on using PollTogether --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f8a5482..d5bd676 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,13 @@ The SOLUTION is PollTogether 👍 ``` ![image](https://user-images.githubusercontent.com/103905661/185743118-751bf828-f95e-4e09-8ab9-a10704058d2c.png) -## Acceptance Criteria +## How-To: Polling made fun and easy ```md -GIVEN a polling site -WHEN I visit the site for the first time -THEN I am presented with the homepage, which allows me to search for a poll and allows me to log in -WHEN I click on the homepage option +WHEN you first visit our site you're given 6 examples of polls +REGISTER to start your journey - Upper Right hand corner, middle option, click to register +ONCE your LOGGED IN the fun begins. The current page will now show the most recent polls +CHOOSE to use your recent polls, search for your past polls, or create your own poll THEN I am taken to the homepage WHEN I choose to sign up THEN I am prompted to create a username and password From 9a44b206dbdabc30a8567878815276d0040b95f4 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 07:46:43 -0400 Subject: [PATCH 78/86] Description of site functionality Brief detail on how to use our site --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d5bd676..96c720f 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,15 @@ The SOLUTION is PollTogether 👍 ```md WHEN you first visit our site you're given 6 examples of polls REGISTER to start your journey - Upper Right hand corner, middle option, click to register -ONCE your LOGGED IN the fun begins. The current page will now show the most recent polls -CHOOSE to use your recent polls, search for your past polls, or create your own poll -THEN I am taken to the homepage -WHEN I choose to sign up -THEN I am prompted to create a username and password +LOGIN the fun begins. Once you login current page will now show the most recent polls +CLICK TO SEARCH Now you're in the driver seat. Find past polls you've conducted to see the results or use the polls again +BUTTONS of creative fun. We've made creating a poll easy. +You'll be presented options for: + WHAT you want to take a poll on + WHO can take the poll + WHAT options of answers your users can have +NO FIST-OF-TEN In our code we created your user can only answer once per their credentials + WHEN I click on the sign-up button THEN my user credentials are saved and I am logged into the site WHEN I revisit the site at a later time and choose to sign in From 7ab76e8557079865d08a6da69061a73825c57dd5 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 07:55:07 -0400 Subject: [PATCH 79/86] Technology used Giving credit to different languages and technology utilized to make our polls --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 96c720f..2209c63 100644 --- a/README.md +++ b/README.md @@ -29,23 +29,23 @@ You'll be presented options for: WHAT you want to take a poll on WHO can take the poll WHAT options of answers your users can have -NO FIST-OF-TEN In our code we created your user can only answer once per their credentials - -WHEN I click on the sign-up button -THEN my user credentials are saved and I am logged into the site -WHEN I revisit the site at a later time and choose to sign in -THEN I am prompted to enter my username and password -WHEN I am signed in to the site -THEN I see the polls I have created, and the option to log out -WHEN I click on the homepage option in the navigation -THEN I am taken to the homepage and presented with existing polls I have created -WHEN I click on an existing poll I have created -THEN I am presented with the results of the poll -WHEN I type a poll's id into the search bar, it brings up the poll's page. -WHEN I click on an answer choice +SHARE your poll. Your users will now have a poll's ID that you shared with them so they can answer +NO FIST-OF-TEN We've got you covered because we coded it in such a way that your user can only answer once per their credentials THEN an answer is recorded in the database +SEE the results. Once the polling is comnplete, you now have a graphical representation of what your users chose +THEN I see the polls I have created, and the option to log out + +``` +### Technology Utilized + +```md + +Bootstrap +JS + ``` + ### Database Models Your database should contain the following four models, including the requirements listed for each model: From a59721ee12c643ee30de8b63f6bc26ddb4b9b1b7 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 08:04:18 -0400 Subject: [PATCH 80/86] Style changes Added a few changes to the styling to make it more interesting to read. --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2209c63..2efc8c0 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ The SOLUTION is PollTogether 👍 ```md WHEN you first visit our site you're given 6 examples of polls REGISTER to start your journey - Upper Right hand corner, middle option, click to register -LOGIN the fun begins. Once you login current page will now show the most recent polls +LOGIN the fun begins. ❤️ Once you login current page will now show the most recent polls CLICK TO SEARCH Now you're in the driver seat. Find past polls you've conducted to see the results or use the polls again -BUTTONS of creative fun. We've made creating a poll easy. +BUTTONS of creative fun. 😀 We've made creating a poll easy. You'll be presented options for: WHAT you want to take a poll on WHO can take the poll @@ -32,7 +32,7 @@ You'll be presented options for: SHARE your poll. Your users will now have a poll's ID that you shared with them so they can answer NO FIST-OF-TEN We've got you covered because we coded it in such a way that your user can only answer once per their credentials THEN an answer is recorded in the database -SEE the results. Once the polling is comnplete, you now have a graphical representation of what your users chose +SEE the results. 📊 Once the polling is comnplete, you now have a graphical representation of what your users chose THEN I see the polls I have created, and the option to log out ``` @@ -40,9 +40,15 @@ THEN I see the polls I have created, and the option to log out ```md +API's Bootstrap +Express JS - +MVC +NODE.JS +Obj Oriented +ORM +SQL ``` From 1bbec4f1742e4b99e1d5cb48a2300f3e3495456e Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 08:19:59 -0400 Subject: [PATCH 81/86] Final edits check of each section and made some changes --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2efc8c0..5125556 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Heroku: https://poll-together.herokuapp.com/ ## How PollTogether Came to Be ```md -OUR INSPIRATION was simple - To CREATE a fun way, accurate, and graphically-appealing way to get your "Fist-of-Five"! +OUR INSPIRATION was simple - To CREATE an easy, fun, and graphical way to get your "Fist-of-Five"! IT SOLVES - HOW can you gauge what your students are thinking or what do they want to do instantly? 🤔 -AS A bootcamp instructor or for anyone who cares easily create a poll, PollTogether is here for you! +AS A bootcamp instructor, or for anyone who cares to easily create a poll, PollTogether is here for you! THE QUESTION is, "Together or together?" The SOLUTION is PollTogether 👍 @@ -20,20 +20,21 @@ The SOLUTION is PollTogether 👍 ## How-To: Polling made fun and easy ```md + WHEN you first visit our site you're given 6 examples of polls REGISTER to start your journey - Upper Right hand corner, middle option, click to register LOGIN the fun begins. ❤️ Once you login current page will now show the most recent polls CLICK TO SEARCH Now you're in the driver seat. Find past polls you've conducted to see the results or use the polls again BUTTONS of creative fun. 😀 We've made creating a poll easy. -You'll be presented options for: - WHAT you want to take a poll on +YOUR CHOICE OF: + WHAT you want to take a poll on. Create exactly what you will be taking a poll on WHO can take the poll WHAT options of answers your users can have SHARE your poll. Your users will now have a poll's ID that you shared with them so they can answer -NO FIST-OF-TEN We've got you covered because we coded it in such a way that your user can only answer once per their credentials -THEN an answer is recorded in the database +NO FIST-OF-TEN ✊✊❌ We've got you covered because we coded it in such a way that your user can only answer once per their credentials +THEN an answer is recorded in the database 💽 SEE the results. 📊 Once the polling is comnplete, you now have a graphical representation of what your users chose -THEN I see the polls I have created, and the option to log out + ``` ### Technology Utilized From b41e1e2d1896982eda41042b66d922f972b47ccd Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 08:40:14 -0400 Subject: [PATCH 82/86] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 5125556..f5a8516 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,11 @@ SEE the results. 📊 Once the polling is comnplete, you now have a graphical re API's Bootstrap +CSS Express +Handlebars +HTML +Javascript JS MVC NODE.JS From e1592a06fcadac2b16320ca32671a25d7cba7738 Mon Sep 17 00:00:00 2001 From: EdoubleL <103905661+EdoubleL@users.noreply.github.com> Date: Sat, 20 Aug 2022 08:42:01 -0400 Subject: [PATCH 83/86] Review and correction of edits Corrected some issues and added text --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f5a8516..12ee8d9 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ NODE.JS Obj Oriented ORM SQL + ``` From cde7a4140734407042558ca3221ce843fd79fd39 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Sat, 20 Aug 2022 09:13:09 -0400 Subject: [PATCH 84/86] Add link to user's profile on poll page --- README visuals | 1 - views/poll.handlebars | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 README visuals diff --git a/README visuals b/README visuals deleted file mode 100644 index 8b13789..0000000 --- a/README visuals +++ /dev/null @@ -1 +0,0 @@ - diff --git a/views/poll.handlebars b/views/poll.handlebars index ac72357..662b2df 100644 --- a/views/poll.handlebars +++ b/views/poll.handlebars @@ -1,7 +1,7 @@

    {{poll.poll_title}}

    -

    By {{poll.user.username}}

    +

    By {{poll.user.username}}

    {{#if poll.poll_expire}}

    Ends at: {{format_date poll.poll_expire}}

    {{/if}} From efa331bc544ef58cf3075ab989036bb56d3e2794 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:18:29 -0400 Subject: [PATCH 85/86] Update README.md --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 12ee8d9..2e06c48 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # PollTogether Together or together? For THAT is the question -### https://ms13380.github.io/PollTogether/ -======= -Heroku: https://poll-together.herokuapp.com/ +### https://poll-together.herokuapp.com/ + ## Made by the Polars ## How PollTogether Came to Be @@ -124,6 +123,12 @@ Your database should contain the following four models, including the requiremen * References the `User` model's `id`. + * `poll_expire` + + * Date. + + * Allow null values. + * `Answer` * `poll_id` @@ -143,8 +148,6 @@ Your database should contain the following four models, including the requiremen ### Associations -You'll need to execute association methods on your Sequelize models to create the following relationships between them: - * `Poll` belongs to `User`, and `User` has many `Poll` models. * `Answer` belongs to `Poll` model, and `Poll` has many `Answer` models. From 22dc9f694ebce435eb571aa2688281ebabc31b10 Mon Sep 17 00:00:00 2001 From: Jared Daniel <60400956+jareddaniel95@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:21:54 -0400 Subject: [PATCH 86/86] Update README.md --- README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2e06c48..57fdf76 100644 --- a/README.md +++ b/README.md @@ -40,19 +40,15 @@ SEE the results. 📊 Once the polling is comnplete, you now have a graphical re ```md -API's +Javascript +NODE.JS Bootstrap -CSS Express Handlebars -HTML -Javascript -JS -MVC -NODE.JS -Obj Oriented -ORM SQL +Sequelize +Chart.js +jQuery ```