diff --git a/package-lock.json b/package-lock.json index 860c7bb58..9b311372b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1568,7 +1568,7 @@ "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, "@types/mime": { @@ -1729,7 +1729,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "array-includes": { "version": "3.1.6", @@ -2768,7 +2768,7 @@ "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" }, "bignumber.js": { "version": "9.0.2", @@ -2863,7 +2863,7 @@ "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, "buffer-from": { "version": "1.1.2", @@ -2995,7 +2995,7 @@ "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" }, "clone-deep": { "version": "4.0.1", @@ -3023,7 +3023,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colorette": { "version": "2.0.19", @@ -3039,12 +3039,12 @@ "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "concat-stream": { "version": "1.6.2", @@ -3100,7 +3100,7 @@ "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "core-js": { "version": "3.21.1", @@ -3253,7 +3253,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { "version": "1.4.81", @@ -3269,7 +3269,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "es-abstract": { "version": "1.19.1", @@ -3350,12 +3350,12 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { "version": "8.47.0", @@ -4273,7 +4273,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-target-shim": { "version": "5.0.1", @@ -4454,7 +4454,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fast-text-encoding": { @@ -4584,7 +4584,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs-readdir-recursive": { "version": "1.1.0", @@ -4594,7 +4594,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "fsevents": { "version": "2.3.2", @@ -4879,7 +4879,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-property-descriptors": { "version": "1.0.0", @@ -4977,7 +4977,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "indent-string": { @@ -4989,7 +4989,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -5094,7 +5094,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, "is-glob": { "version": "4.0.3", @@ -5196,13 +5196,13 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, "js-tokens": { "version": "4.0.0", @@ -5240,7 +5240,7 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "json5": { @@ -5561,7 +5561,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "lodash.merge": { "version": "4.6.2", @@ -5738,7 +5738,7 @@ "lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=" + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" }, "make-dir": { "version": "2.1.0", @@ -5752,7 +5752,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memory-pager": { "version": "1.5.0", @@ -5763,7 +5763,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "merge-stream": { "version": "2.0.0", @@ -5774,7 +5774,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { "version": "4.0.5", @@ -5954,7 +5954,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "negotiator": { @@ -6094,7 +6094,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { "version": "1.12.0", @@ -6813,7 +6813,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -6843,7 +6843,7 @@ "os-shim": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", - "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", + "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==", "dev": true }, "p-limit": { @@ -6888,7 +6888,7 @@ "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==" }, "parseurl": { "version": "1.3.3", @@ -6898,12 +6898,12 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-key": { "version": "3.1.1", @@ -6919,7 +6919,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "picocolors": { "version": "1.0.0", @@ -6966,7 +6966,7 @@ "pre-commit": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz", - "integrity": "sha1-287g7p3nI15X95xW186UZBpp7sY=", + "integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==", "dev": true, "requires": { "cross-spawn": "^5.0.1", @@ -6977,7 +6977,7 @@ "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", "dev": true, "requires": { "lru-cache": "^4.0.1", @@ -6988,7 +6988,7 @@ "which": { "version": "1.2.14", "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -7030,7 +7030,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, "pstree.remy": { @@ -7508,7 +7508,7 @@ "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "optional": true, "requires": { "memory-pager": "^1.0.2" @@ -7517,7 +7517,7 @@ "spawn-sync": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", - "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", + "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==", "dev": true, "requires": { "concat-stream": "^1.4.7", @@ -7912,7 +7912,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, "strip-final-newline": { @@ -7943,19 +7943,19 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, "to-regex-range": { "version": "5.0.1", @@ -7982,7 +7982,7 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "tsconfig-paths": { "version": "3.14.2", @@ -8100,7 +8100,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true }, "unbox-primitive": { @@ -8147,7 +8147,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -8161,17 +8161,17 @@ "url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "3.4.0", @@ -8194,17 +8194,17 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "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": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "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": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -8322,7 +8322,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "ws": { "version": "8.8.1", @@ -8332,7 +8332,7 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yaml": { diff --git a/src/controllers/bmdashboard/bmIssueController.js b/src/controllers/bmdashboard/bmIssueController.js index 3341be22d..8bcbe3d00 100644 --- a/src/controllers/bmdashboard/bmIssueController.js +++ b/src/controllers/bmdashboard/bmIssueController.js @@ -6,8 +6,8 @@ const bmIssueController = function (BuildingIssue) { BuildingIssue .find() .populate() - .then(result => res.status(200).send(result)) - .catch(error => res.status(500).send(error)); + .then((result) => res.status(200).send(result)) + .catch((error) => res.status(500).send(error)); } catch (err) { res.json(err); } @@ -16,8 +16,8 @@ const bmIssueController = function (BuildingIssue) { const bmPostIssue = async (req, res) => { try { const newIssue = BuildingIssue.create(req.body) - .then(result => res.status(201).send(result)) - .catch(error => res.status(500).send(error)); + .then((result) => res.status(201).send(result)) + .catch((error) => res.status(500).send(error)); } catch (err) { res.json(err); } diff --git a/src/controllers/reportsController.js b/src/controllers/reportsController.js index c5f678586..8cfbe4fc1 100644 --- a/src/controllers/reportsController.js +++ b/src/controllers/reportsController.js @@ -1,9 +1,12 @@ +const mongoose = require('mongoose'); const reporthelper = require('../helpers/reporthelper')(); const { hasPermission } = require('../utilities/permissions'); +const UserProfile = require('../models/userProfile'); +const userhelper = require('../helpers/userHelper')(); const reportsController = function () { const getWeeklySummaries = async function (req, res) { - if (!await hasPermission(req.body.requestor, 'getWeeklySummaries')) { + if (!(await hasPermission(req.body.requestor, 'getWeeklySummaries'))) { res.status(403).send('You are not authorized to view all users'); return; } @@ -17,8 +20,108 @@ const reportsController = function () { .catch((error) => res.status(404).send(error)); }; + /** + * Gets the Recipients added by the owner to receive the Weekly Summary Reports + * @param {*} req + * @param {*} res + */ + + const getReportRecipients = function (req, res) { + try { + UserProfile.find( + { getWeeklyReport: true }, + { + email: 1, + firstName: 1, + lastName: 1, + createdDate: 1, + getWeeklyReport: 1, + }, + ) + .then((results) => { + res.status(200).send(results); + }) + .catch((error) => { + console.log('error:', error); // need to delete later * + res.status(404).send({ error }); + }); + } catch (err) { + console.log('error:', err); // need to delete later * + res.status(404).send(err); + } + }; + + /** + * Function deletes slected Recipients from the list + * @param {*} req + * @param {*} res + * @returns + */ + const deleteReportsRecepients = (req, res) => { + const { userid } = req.params; + const id = userid; + try { + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(404).json({ + msg: `No task with id :${id}`, + }); + } + + UserProfile.updateOne({ _id: id }, { $set: { getWeeklyReport: false } }) + .then((record) => { + if (!record) { + console.log("'No valid records found'"); + res.status(404).send('No valid records found'); + return; + } + res.status(200).send({ + message: 'updated user record with getWeeklyReport false', + }); + }) + .catch((err) => { + console.log('error in catch block last:', err); + res.status(404).send(err); + }); + } catch (error) { + res.status(404).send(error); + } + }; + + const saveReportsRecepients = (req, res) => { + const { userid } = req.params; + const id = userid; + try { + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(404).json({ + msg: `No task with id :${id}`, + }); + } + + UserProfile.updateOne({ _id: id }, { $set: { getWeeklyReport: true } }) + .then((record) => { + if (!record) { + console.log("'No valid records found'"); + res.status(404).send('No valid records found'); + return; + } + res + .status(200) + .send({ message: 'updated user record with getWeeklyReport true' }); + }) + .catch((err) => { + console.log('error in catch block last:', err); + res.status(404).send(err); + }); + } catch (error) { + res.status(404).send(error); + } + }; + return { getWeeklySummaries, + getReportRecipients, + deleteReportsRecepients, + saveReportsRecepients, }; }; diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js index 7fabddb70..120b00026 100644 --- a/src/controllers/userProfileController.js +++ b/src/controllers/userProfileController.js @@ -668,9 +668,9 @@ const userProfileController = function (UserProfile) { cache.removeCache(`user-${userId}`); if (!key || value === undefined) { return res.status(400).send({ error: 'Missing property or value' }); -} + } - return UserProfile.findById(userId) + return UserProfile.findById(userId) .then((user) => { user.set({ [key]: value, @@ -954,7 +954,7 @@ const userProfileController = function (UserProfile) { // Search for user by first name const getUserBySingleName = (req, res) => { - const pattern = new RegExp(`^${ req.params.singleName}`, 'i'); + const pattern = new RegExp(`^${req.params.singleName}`, 'i'); // Searches for first or last name UserProfile.find({ @@ -984,8 +984,8 @@ const userProfileController = function (UserProfile) { .split(' ') .filter((name) => name !== ''); // Creates a partial match regex for both first and last name - const firstNameRegex = new RegExp(`^${ escapeRegExp(fullName[0])}`, 'i'); - const lastNameRegex = new RegExp(`^${ escapeRegExp(fullName[1])}`, 'i'); + const firstNameRegex = new RegExp(`^${escapeRegExp(fullName[0])}`, 'i'); + const lastNameRegex = new RegExp(`^${escapeRegExp(fullName[1])}`, 'i'); // Verfies both the first and last name are present if (fullName.length < 2) { @@ -1010,6 +1010,38 @@ const userProfileController = function (UserProfile) { .catch((error) => res.status(500).send(error)); }; + /** + * Authorizes user to be able to add Weekly Report Recipients + */ + const authorizeUser = async (req, res) => { + try { + await UserProfile.findOne({ + email: { + $regex: escapeRegex('jae@onecommunityglobal.org'), // PLEASE CHANGE THIS EMAIL TO MATCH THE USER PROFILE WHILE TESTING THE PR + $options: 'i', + }, + }).then(async (user) => { + await bcrypt + .compare(req.body.currentPassword, user.password) + .then((passwordMatch) => { + if (!passwordMatch) { + return res.status(400).send({ + error: 'Incorrect current password', + }); + } + return res + .status(200) + .send({ message: 'Correct Password, Password matches!' }); + }) + .catch((error) => { + res.status(500).send(error); + }); + }); + } catch (err) { + res.status(500).send(err); + } + }; + return { postUserProfile, getUserProfiles, @@ -1029,6 +1061,7 @@ const userProfileController = function (UserProfile) { refreshToken, getUserBySingleName, getUserByFullName, + authorizeUser, }; }; diff --git a/src/cronjobs/userProfileJobs.js b/src/cronjobs/userProfileJobs.js index 8bc94c0f1..92e0d0e5d 100644 --- a/src/cronjobs/userProfileJobs.js +++ b/src/cronjobs/userProfileJobs.js @@ -7,6 +7,7 @@ const userProfileJobs = () => { const allUserProfileJobs = new CronJob( // '* * * * *', // Comment out for testing. Run Every minute. '1 0 * * 0', // Every Sunday, 1 minute past midnight. + async () => { const SUNDAY = 0; if (moment().tz('America/Los_Angeles').day() === SUNDAY) { diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js index 6e5ca2bd9..9342b6136 100644 --- a/src/helpers/reporthelper.js +++ b/src/helpers/reporthelper.js @@ -1,5 +1,6 @@ -const moment = require('moment-timezone'); -const userProfile = require('../models/userProfile'); +/* eslint-disable quotes */ +const moment = require("moment-timezone"); +const userProfile = require("../models/userProfile"); /** * @@ -8,9 +9,9 @@ const userProfile = require('../models/userProfile'); * @returns The absolute value of the difference in weeks between the two input dates. */ const absoluteDifferenceInWeeks = (dateOfWork, pstEnd) => { - dateOfWork = moment(dateOfWork).endOf('week'); - pstEnd = moment(pstEnd).tz('America/Los_Angeles').endOf('week'); - return Math.abs(dateOfWork.diff(pstEnd, 'weeks')); + dateOfWork = moment(dateOfWork).endOf("week"); + pstEnd = moment(pstEnd).tz("America/Los_Angeles").endOf("week"); + return Math.abs(dateOfWork.diff(pstEnd, "weeks")); }; const reporthelper = function () { @@ -23,14 +24,14 @@ const reporthelper = function () { */ const weeklySummaries = async (startWeekIndex, endWeekIndex) => { const pstStart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .subtract(startWeekIndex, 'week') + .tz("America/Los_Angeles") + .startOf("week") + .subtract(startWeekIndex, "week") .toDate(); const pstEnd = moment() - .tz('America/Los_Angeles') - .endOf('week') - .subtract(endWeekIndex, 'week') + .tz("America/Los_Angeles") + .endOf("week") + .subtract(endWeekIndex, "week") .toDate(); const results = await userProfile.aggregate([ @@ -39,33 +40,33 @@ const reporthelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntries', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntries", }, }, { - $set: { totalTangibleHrs: { $objectToArray: '$hoursByCategory' } }, + $set: { totalTangibleHrs: { $objectToArray: "$hoursByCategory" } }, }, { $project: { timeEntries: { $filter: { - input: '$timeEntries', - as: 'timeEntry', + input: "$timeEntries", + as: "timeEntry", cond: { $and: [ { $gte: [ - '$$timeEntry.dateOfWork', - moment(pstStart).format('YYYY-MM-DD'), + "$$timeEntry.dateOfWork", + moment(pstStart).format("YYYY-MM-DD"), ], }, { $lte: [ - '$$timeEntry.dateOfWork', - moment(pstEnd).format('YYYY-MM-DD'), + "$$timeEntry.dateOfWork", + moment(pstEnd).format("YYYY-MM-DD"), ], }, ], @@ -86,22 +87,22 @@ const reporthelper = function () { bioPosted: 1, badgeCollection: { $filter: { - input: '$badgeCollection', - as: 'badge', + input: "$badgeCollection", + as: "badge", cond: { $or: [ { $and: [ { $gte: [ - '$$badge.earnedDate', - moment(pstStart).format('YYYY-MM-DD'), + "$$badge.earnedDate", + moment(pstStart).format("YYYY-MM-DD"), ], }, { $lte: [ - '$$badge.earnedDate', - moment(pstEnd).format('YYYY-MM-DD'), + "$$badge.earnedDate", + moment(pstEnd).format("YYYY-MM-DD"), ], }, ], @@ -109,10 +110,10 @@ const reporthelper = function () { { $and: [ { - $gte: ['$$badge.lastModified', pstStart], + $gte: ["$$badge.lastModified", pstStart], }, { - $lte: ['$$badge.lastModified', pstEnd], + $lte: ["$$badge.lastModified", pstEnd], }, ], }, @@ -121,26 +122,26 @@ const reporthelper = function () { }, }, teamCode: { - $ifNull: ['$teamCode', ''], + $ifNull: ["$teamCode", ""], }, timeOffFrom: { - $ifNull: ['$timeOffFrom', null], + $ifNull: ["$timeOffFrom", null], }, timeOffTill: { - $ifNull: ['$timeOffTill', null], + $ifNull: ["$timeOffTill", null], }, role: 1, weeklySummaries: { $filter: { - input: '$weeklySummaries', - as: 'ws', + input: "$weeklySummaries", + as: "ws", cond: { $and: [ { - $gte: ['$$ws.dueDate', pstStart], + $gte: ["$$ws.dueDate", pstStart], }, { - $lte: ['$$ws.dueDate', pstEnd], + $lte: ["$$ws.dueDate", pstEnd], }, ], }, @@ -148,13 +149,13 @@ const reporthelper = function () { }, weeklySummariesCount: 1, isTangible: 1, - totalTangibleHrs: { $sum: '$totalTangibleHrs.v' }, + totalTangibleHrs: { $sum: "$totalTangibleHrs.v" }, daysInTeam: { $dateDiff: { - startDate: '$createdDate', + startDate: "$createdDate", endDate: new Date(), - unit: 'day', - timezone: 'America/Los_Angeles', + unit: "day", + timezone: "America/Los_Angeles", }, }, }, @@ -184,7 +185,20 @@ const reporthelper = function () { return results; }; - + const getReportReceipents = () => { + let mappedResults; + userProfile + .find({ getWeeklyReport: true }, { email: 1, _id: 0 }) + .then((results) => { + mappedResults = results.map((ele) => ele.email); + mappedResults.push( + "onecommunityglobal@gmail.com", + "onecommunityhospitality@gmail.com", + ); + console.log("results:", mappedResults); + }); + return mappedResults; + }; /** * Checks whether a date belongs to a specific week based on week index. * @@ -195,16 +209,16 @@ const reporthelper = function () { */ const doesDateBelongToWeek = function (dueDate, weekIndex) { const pstStartOfWeek = moment() - .tz('America/Los_Angeles') - .startOf('week') - .subtract(weekIndex, 'week'); + .tz("America/Los_Angeles") + .startOf("week") + .subtract(weekIndex, "week"); const pstEndOfWeek = moment() - .tz('America/Los_Angeles') - .endOf('week') - .subtract(weekIndex, 'week'); + .tz("America/Los_Angeles") + .endOf("week") + .subtract(weekIndex, "week"); const fromDate = moment(pstStartOfWeek).toDate(); const toDate = moment(pstEndOfWeek).toDate(); - return moment(dueDate).isBetween(fromDate, toDate, undefined, '[]'); + return moment(dueDate).isBetween(fromDate, toDate, undefined, "[]"); }; /** @@ -268,6 +282,7 @@ const reporthelper = function () { return { weeklySummaries, formatSummaries, + getReportReceipents, }; }; diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js index 761ce178b..1acc9ece6 100644 --- a/src/helpers/userHelper.js +++ b/src/helpers/userHelper.js @@ -1,53 +1,54 @@ +/* eslint-disable quotes */ /* eslint-disable no-continue */ /* eslint-disable no-await-in-loop */ -const mongoose = require('mongoose'); -const moment = require('moment-timezone'); -const _ = require('lodash'); -const userProfile = require('../models/userProfile'); -const timeEntries = require('../models/timeentry'); -const badge = require('../models/badge'); -const myTeam = require('./helperModels/myTeam'); -const dashboardHelper = require('./dashboardhelper')(); -const reportHelper = require('./reporthelper')(); -const emailSender = require('../utilities/emailSender'); -const logger = require('../startup/logger'); -const Reason = require('../models/reason'); -const token = require('../models/profileInitialSetupToken'); -const cache = require('../utilities/nodeCache')(); -const timeOffRequest = require('../models/timeOffRequest'); +const mongoose = require("mongoose"); +const moment = require("moment-timezone"); +const _ = require("lodash"); +const userProfile = require("../models/userProfile"); +const timeEntries = require("../models/timeentry"); +const badge = require("../models/badge"); +const myTeam = require("./helperModels/myTeam"); +const dashboardHelper = require("./dashboardhelper")(); +const reportHelper = require("./reporthelper")(); +const emailSender = require("../utilities/emailSender"); +const logger = require("../startup/logger"); +const Reason = require("../models/reason"); +const token = require("../models/profileInitialSetupToken"); +const cache = require("../utilities/nodeCache")(); +const timeOffRequest = require("../models/timeOffRequest"); const userHelper = function () { // Update format to "MMM-DD-YY" from "YYYY-MMM-DD" (Confirmed with Jae) const earnedDateBadge = () => { const currentDate = new Date(Date.now()); - return moment(currentDate).tz('America/Los_Angeles').format('MMM-DD-YY'); + return moment(currentDate).tz("America/Los_Angeles").format("MMM-DD-YY"); }; const getTeamMembers = function (user) { const userId = mongoose.Types.ObjectId(user._id); // var teamid = userdetails.teamId; return myTeam.findById(userId).select({ - 'myTeam._id': 0, - 'myTeam.role': 0, - 'myTeam.fullName': 0, + "myTeam._id": 0, + "myTeam.role": 0, + "myTeam.fullName": 0, _id: 0, }); }; const getUserName = async function (userId) { const userid = mongoose.Types.ObjectId(userId); - return userProfile.findById(userid, 'firstName lastName'); + return userProfile.findById(userid, "firstName lastName"); }; const validateProfilePic = function (profilePic) { - const picParts = profilePic.split(','); + const picParts = profilePic.split(","); let result = true; const errors = []; if (picParts.length < 2) { return { result: false, - errors: 'Invalid image', + errors: "Invalid image", }; } @@ -55,13 +56,13 @@ const userHelper = function () { const imageSize = picParts[1].length; const sizeInBytes = (Math.ceil(imageSize / 4) * 3) / 1024; if (sizeInBytes > 50) { - errors.push('Image size should not exceed 50KB'); + errors.push("Image size should not exceed 50KB"); result = false; } - const imageType = picParts[0].split('/')[1].split(';')[0]; - if (imageType !== 'jpeg' && imageType !== 'png') { - errors.push('Image type shoud be either jpeg or png.'); + const imageType = picParts[0].split("/")[1].split(";")[0]; + if (imageType !== "jpeg" && imageType !== "png") { + errors.push("Image type shoud be either jpeg or png."); result = false; } @@ -72,7 +73,7 @@ const userHelper = function () { }; const formatTimeOffRequestsDescription = (inputString) => { - const searchTerm = 'Notice:'; + const searchTerm = "Notice:"; if (inputString.includes(searchTerm)) { const parts = inputString.split(searchTerm); const formattedString = `${parts[0]}
${searchTerm}` @@ -91,12 +92,14 @@ const userHelper = function () { coreTeamExtraHour, requestForTimeOffEmailBody, ) { - let finalParagraph = ''; + let finalParagraph = ""; if (timeRemaining === undefined) { - finalParagraph = '

Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.

'; + finalParagraph = "

Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.

"; } else { - finalParagraph = `Please complete ALL owed time this week (${timeRemaining + coreTeamExtraHour} hours) to avoid receiving another blue square. If you have any questions about any of this, please see the "One Community Core Team Policies and Procedures" page.`; + finalParagraph = `Please complete ALL owed time this week (${ + timeRemaining + coreTeamExtraHour + } hours) to avoid receiving another blue square. If you have any questions about any of this, please see the "One Community Core Team Policies and Procedures" page.`; } const text = `Dear ${firstName} ${lastName}, @@ -105,7 +108,7 @@ const userHelper = function () { ${ requestForTimeOffEmailBody ? `\n

Reason Time Requested Off: ${requestForTimeOffEmailBody}

` - : '' + : "" }

Description: ${formatTimeOffRequestsDescription( infringement.description, @@ -130,18 +133,30 @@ const userHelper = function () { * @return {void} */ const emailWeeklySummariesForAllUsers = async (weekIndex = 1) => { - const currentFormattedDate = moment().tz('America/Los_Angeles').format(); + const currentFormattedDate = moment().tz("America/Los_Angeles").format(); logger.logInfo( `Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`, ); const emails = []; + let mappedResults; // this contains the emails try { const results = await reportHelper.weeklySummaries(weekIndex, weekIndex); + // checks for userProfiles who are eligible to receive the weeklySummary Reports + await userProfile + .find({ getWeeklyReport: true }, { email: 1, _id: 0 }) + .then((results) => { + mappedResults = results.map((ele) => ele.email); + mappedResults.push( + "onecommunityglobal@gmail.com", + "onecommunityhospitality@gmail.com", + ); + mappedResults = mappedResults.toString(); + }); - let emailBody = '

Weekly Summaries for all active users:

'; + let emailBody = "

Weekly Summaries for all active users:

"; const weeklySummaryNotProvidedMessage = '
Weekly Summary: Not provided!
'; @@ -175,19 +190,19 @@ const userHelper = function () { const mediaUrlLink = mediaUrl ? `${mediaUrl}` - : 'Not provided!'; + : "Not provided!"; let weeklySummaryMessage = weeklySummaryNotProvidedMessage; const colorStyle = (() => { switch (weeklySummaryOption) { - case 'Team': + case "Team": return 'style="color: magenta;"'; - case 'Not Required': + case "Not Required": return 'style="color: green"'; - case 'Required': - return ''; + case "Required": + return ""; default: - return result.weeklySummaryNotReq ? 'style="color: green"' : ''; + return result.weeklySummaryNotReq ? 'style="color: green"' : ""; } })(); // weeklySummaries array should only have one item if any, hence weeklySummaries[0] needs be used to access it. @@ -198,15 +213,15 @@ const userHelper = function () {
Weekly Summary (for the week ending on ${moment(dueDate) - .tz('America/Los_Angeles') - .format('YYYY-MMM-DD')}): + .tz("America/Los_Angeles") + .format("YYYY-MMM-DD")}):
${summary}
`; } else if ( - weeklySummaryOption === 'Not Required' + weeklySummaryOption === "Not Required" || (!weeklySummaryOption && result.weeklySummaryNotReq) ) { weeklySummaryMessage = weeklySummaryNotRequiredMessage; @@ -228,7 +243,7 @@ const userHelper = function () { weeklySummariesCount === 8 ? `

Total Valid Weekly Summaries: ${weeklySummariesCount}

` : `

Total Valid Weekly Summaries: ${ - weeklySummariesCount || 'No valid submissions yet!' + weeklySummariesCount || "No valid submissions yet!" }

` } ${ @@ -247,11 +262,11 @@ const userHelper = function () { // Necessary because our version of node is outdated // and doesn't have String.prototype.replaceAll let emailString = [...new Set(emails)].toString(); - while (emailString.includes(',')) { - emailString = emailString.replace(',', '\n'); + while (emailString.includes(",")) { + emailString = emailString.replace(",", "\n"); } - while (emailString.includes('\n')) { - emailString = emailString.replace('\n', ', '); + while (emailString.includes("\n")) { + emailString = emailString.replace("\n", ", "); } emailBody += `\n @@ -263,9 +278,11 @@ const userHelper = function () { `; + const mailList = mappedResults; + emailSender( - 'onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com', - 'Weekly Summaries for all active users...', + mailList, + "Weekly Summaries for all active users...", emailBody, null, null, @@ -290,8 +307,8 @@ const userHelper = function () { weeklySummaries: { $each: [ { - dueDate: moment().tz('America/Los_Angeles').endOf('week'), - summary: '', + dueDate: moment().tz("America/Los_Angeles").endOf("week"), + summary: "", }, ], $position: 0, @@ -310,10 +327,10 @@ const userHelper = function () { */ const assignBlueSquareForTimeNotMet = async () => { try { - const currentFormattedDate = moment().tz('America/Los_Angeles').format(); + const currentFormattedDate = moment().tz("America/Los_Angeles").format(); const currentUTCDate = moment - .tz('America/Los_Angeles') - .startOf('day') + .tz("America/Los_Angeles") + .startOf("day") .toISOString(); logger.logInfo( @@ -321,18 +338,18 @@ const userHelper = function () { ); const pdtStartOfLastWeek = moment() - .tz('America/Los_Angeles') - .startOf('week') - .subtract(1, 'week'); + .tz("America/Los_Angeles") + .startOf("week") + .subtract(1, "week"); const pdtEndOfLastWeek = moment() - .tz('America/Los_Angeles') - .endOf('week') - .subtract(1, 'week'); + .tz("America/Los_Angeles") + .endOf("week") + .subtract(1, "week"); const users = await userProfile.find( { isActive: true }, - '_id weeklycommittedHours weeklySummaries missedHours', + "_id weeklycommittedHours weeklySummaries missedHours", ); // this part is supposed to be a for, so it'll be slower when sending emails, so the emails will not be @@ -401,13 +418,13 @@ const userHelper = function () { ); if ( - updateResult?.weeklySummaryOption === 'Not Required' + updateResult?.weeklySummaryOption === "Not Required" || updateResult?.weeklySummaryNotReq ) { hasWeeklySummary = true; } - const cutOffDate = moment().subtract(1, 'year'); + const cutOffDate = moment().subtract(1, "year"); const oldInfringements = []; for (let k = 0; k < updateResult?.infringements.length; k += 1) { @@ -436,8 +453,8 @@ const userHelper = function () { // length +1 is because new infringement hasn't been created at this stage. const coreTeamExtraHour = Math.max(0, oldInfringements.length + 1 - 5); - const utcStartMoment = moment(pdtStartOfLastWeek).add(1, 'second'); - const utcEndMoment = moment(pdtEndOfLastWeek).subtract(1, 'second'); + const utcStartMoment = moment(pdtStartOfLastWeek).add(1, "second"); + const utcEndMoment = moment(pdtEndOfLastWeek).subtract(1, "second"); const requestsForTimeOff = await timeOffRequest.find({ requestFor: personId, @@ -456,10 +473,10 @@ const userHelper = function () { [requestForTimeOff] = requestsForTimeOff; requestForTimeOffStartingDate = moment( requestForTimeOff.startingDate, - ).format('dddd YYYY-MM-DD'); + ).format("dddd YYYY-MM-DD"); requestForTimeOffEndingDate = moment( requestForTimeOff.endingDate, - ).format('dddd YYYY-MM-DD'); + ).format("dddd YYYY-MM-DD"); requestForTimeOffreason = requestForTimeOff.reason; requestForTimeOffEmailBody = `Unavailable from ${requestForTimeOffStartingDate}, to ${requestForTimeOffEndingDate}, due to ${requestForTimeOffreason}`; } @@ -468,82 +485,65 @@ const userHelper = function () { if (foundReason) { description = foundReason.reason; } else if (timeNotMet && !hasWeeklySummary) { - if (person.role === 'Core Team') { - description = ( - `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. In the week starting ${ - pdtStartOfLastWeek.format('dddd YYYY-MM-DD') - } and ending ${ - pdtEndOfLastWeek.format('dddd YYYY-MM-DD') - }, you logged ${ - timeSpent.toFixed(2) - } hours against a committed effort of ${ - person.weeklycommittedHours - } hours + ${ - person.missedHours ?? 0 - } hours owed for last week + ${ - coreTeamExtraHour - } hours owed for this being your ${ - moment.localeData().ordinal(oldInfringements.length + 1) - } blue square. So you should have completed ${ - weeklycommittedHours - } hours and you completed ${ - timeSpent.toFixed(2) - } hours.` - ); + if (person.role === "Core Team") { + description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. In the week starting ${pdtStartOfLastWeek.format( + "dddd YYYY-MM-DD", + )} and ending ${pdtEndOfLastWeek.format( + "dddd YYYY-MM-DD", + )}, you logged ${timeSpent.toFixed( + 2, + )} hours against a committed effort of ${ + person.weeklycommittedHours + } hours + ${ + person.missedHours ?? 0 + } hours owed for last week + ${coreTeamExtraHour} hours owed for this being your ${moment + .localeData() + .ordinal( + oldInfringements.length + 1, + )} blue square. So you should have completed ${weeklycommittedHours} hours and you completed ${timeSpent.toFixed( + 2, + )} hours.`; } else { - description = ( - `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${ - timeSpent.toFixed(2) - } hours against a committed effort of ${ - weeklycommittedHours - } hours in the week starting ${ - pdtStartOfLastWeek.format('dddd YYYY-MM-DD') - } and ending ${ - pdtEndOfLastWeek.format('dddd YYYY-MM-DD') - }.`); + description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${timeSpent.toFixed( + 2, + )} hours against a committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format( + "dddd YYYY-MM-DD", + )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`; } } else if (timeNotMet) { - if (person.role === 'Core Team') { - description = ( - `System auto-assigned infringement for not meeting weekly volunteer time commitment. In the week starting ${ - pdtStartOfLastWeek.format('dddd YYYY-MM-DD') - } and ending ${ - pdtEndOfLastWeek.format('dddd YYYY-MM-DD') - }, you logged ${ - timeSpent.toFixed(2) - } hours against a committed effort of ${ - user.weeklycommittedHours - } hours + ${ - person.missedHours ?? 0 - } hours owed for last week + ${ - coreTeamExtraHour - } hours owed for this being your ${ - moment.localeData().ordinal(oldInfringements.length + 1) - } blue square. So you should have completed ${ - weeklycommittedHours - } hours and you completed ${ - timeSpent.toFixed(2) - } hours.`); + if (person.role === "Core Team") { + description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. In the week starting ${pdtStartOfLastWeek.format( + "dddd YYYY-MM-DD", + )} and ending ${pdtEndOfLastWeek.format( + "dddd YYYY-MM-DD", + )}, you logged ${timeSpent.toFixed( + 2, + )} hours against a committed effort of ${ + user.weeklycommittedHours + } hours + ${ + person.missedHours ?? 0 + } hours owed for last week + ${coreTeamExtraHour} hours owed for this being your ${moment + .localeData() + .ordinal( + oldInfringements.length + 1, + )} blue square. So you should have completed ${weeklycommittedHours} hours and you completed ${timeSpent.toFixed( + 2, + )} hours.`; } else { - description = ( - `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${ - timeSpent.toFixed(2) - } hours against a committed effort of ${ - weeklycommittedHours - } hours in the week starting ${ - pdtStartOfLastWeek.format('dddd YYYY-MM-DD') - } and ending ${ - pdtEndOfLastWeek.format('dddd YYYY-MM-DD') - }.`); + description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${timeSpent.toFixed( + 2, + )} hours against a committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format( + "dddd YYYY-MM-DD", + )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`; } } else { description = `System auto-assigned infringement for not submitting a weekly summary for the week starting ${pdtStartOfLastWeek.format( - 'dddd YYYY-MM-DD', - )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`; + "dddd YYYY-MM-DD", + )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`; } const infringement = { - date: moment().utc().format('YYYY-MM-DD'), + date: moment().utc().format("YYYY-MM-DD"), description, }; @@ -557,8 +557,8 @@ const userHelper = function () { { new: true }, ); - let emailBody = ''; - if (person.role === 'Core Team' && timeRemaining > 0) { + let emailBody = ""; + if (person.role === "Core Team" && timeRemaining > 0) { emailBody = getInfringementEmailBody( status.firstName, status.lastName, @@ -582,10 +582,10 @@ const userHelper = function () { emailSender( status.email, - 'New Infringement Assigned', + "New Infringement Assigned", emailBody, null, - 'onecommunityglobal@gmail.com', + "onecommunityglobal@gmail.com", status.email, null, ); @@ -609,12 +609,12 @@ const userHelper = function () { const elem = categories[j]; if (elem._id == null) { - elem._id = 'Other'; + elem._id = "Other"; } const updateResult2 = await userProfile.findOneAndUpdate( - { _id: personId, 'categoryTangibleHrs.category': elem._id }, - { $inc: { 'categoryTangibleHrs.$.hrs': elem.timeSpent_hrs } }, + { _id: personId, "categoryTangibleHrs.category": elem._id }, + { $inc: { "categoryTangibleHrs.$.hrs": elem.timeSpent_hrs } }, { new: true }, ); @@ -622,7 +622,7 @@ const userHelper = function () { await userProfile.findOneAndUpdate( { _id: personId, - 'categoryTangibleHrs.category': { $ne: elem._id }, + "categoryTangibleHrs.category": { $ne: elem._id }, }, { $addToSet: { @@ -644,7 +644,7 @@ const userHelper = function () { // processWeeklySummaries for nonActive users try { - const inactiveUsers = await userProfile.find({ isActive: false }, '_id'); + const inactiveUsers = await userProfile.find({ isActive: false }, "_id"); for (let i = 0; i < inactiveUsers.length; i += 1) { const user = inactiveUsers[i]; @@ -660,50 +660,50 @@ const userHelper = function () { const applyMissedHourForCoreTeam = async () => { try { - const currentDate = moment().tz('America/Los_Angeles').format(); + const currentDate = moment().tz("America/Los_Angeles").format(); logger.logInfo( `Job for applying missed hours for Core Team members starting at ${currentDate}`, ); const startOfLastWeek = moment() - .tz('America/Los_Angeles') - .startOf('week') - .subtract(1, 'week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .subtract(1, "week") + .format("YYYY-MM-DD"); const endOfLastWeek = moment() - .tz('America/Los_Angeles') - .endOf('week') - .subtract(1, 'week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .subtract(1, "week") + .format("YYYY-MM-DD"); const missedHours = await userProfile.aggregate([ { $match: { - role: 'Core Team', + role: "Core Team", isActive: true, }, }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', + from: "timeEntries", + localField: "_id", + foreignField: "personId", pipeline: [ { $match: { $expr: { $and: [ - { $eq: ['$isTangible', true] }, - { $gte: ['$dateOfWork', startOfLastWeek] }, - { $lte: ['$dateOfWork', endOfLastWeek] }, + { $eq: ["$isTangible", true] }, + { $gte: ["$dateOfWork", startOfLastWeek] }, + { $lte: ["$dateOfWork", endOfLastWeek] }, ], }, }, }, ], - as: 'timeEntries', + as: "timeEntries", }, }, { @@ -715,8 +715,8 @@ const userHelper = function () { $subtract: [ { $sum: [ - { $ifNull: ['$missedHours', 0] }, - '$weeklycommittedHours', + { $ifNull: ["$missedHours", 0] }, + "$weeklycommittedHours", ], }, { @@ -724,8 +724,8 @@ const userHelper = function () { { $sum: { $map: { - input: '$timeEntries', - in: '$$this.totalSeconds', + input: "$timeEntries", + in: "$$this.totalSeconds", }, }, }, @@ -759,13 +759,13 @@ const userHelper = function () { }; const deleteBlueSquareAfterYear = async () => { - const currentFormattedDate = moment().tz('America/Los_Angeles').format(); + const currentFormattedDate = moment().tz("America/Los_Angeles").format(); logger.logInfo( `Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`, ); - const cutOffDate = moment().subtract(1, 'year').format('YYYY-MM-DD'); + const cutOffDate = moment().subtract(1, "year").format("YYYY-MM-DD"); try { const results = await userProfile.updateMany( @@ -788,7 +788,7 @@ const userHelper = function () { }; const reActivateUser = async () => { - const currentFormattedDate = moment().tz('America/Los_Angeles').format(); + const currentFormattedDate = moment().tz("America/Los_Angeles").format(); logger.logInfo( `Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`, @@ -797,7 +797,7 @@ const userHelper = function () { try { const users = await userProfile.find( { isActive: false, reactivationDate: { $exists: true } }, - '_id isActive reactivationDate', + "_id isActive reactivationDate", ); for (let i = 0; i < users.length; i += 1) { const user = users[i]; @@ -816,13 +816,13 @@ const userHelper = function () { ); logger.logInfo( `User with id: ${user._id} was re-acticated at ${moment() - .tz('America/Los_Angeles') + .tz("America/Los_Angeles") .format()}.`, ); const id = user._id; const person = await userProfile.findById(id); - const endDate = moment(person.endDate).format('YYYY-MM-DD'); + const endDate = moment(person.endDate).format("YYYY-MM-DD"); logger.logInfo( `User with id: ${ user._id @@ -842,7 +842,7 @@ const userHelper = function () {

The HGN A.I. (and One Community)

`; emailSender( - 'onecommunityglobal@gmail.com', + "onecommunityglobal@gmail.com", subject, emailBody, null, @@ -877,7 +877,7 @@ const userHelper = function () { newInfringements.forEach((element) => { emailSender( emailAddress, - 'New Infringement Assigned', + "New Infringement Assigned", getInfringementEmailBody( firstName, lastName, @@ -886,7 +886,7 @@ const userHelper = function () { ), null, - 'onecommunityglobal@gmail.com', + "onecommunityglobal@gmail.com", emailAddress, ); }); @@ -894,13 +894,13 @@ const userHelper = function () { const replaceBadge = async function (personId, oldBadgeId, newBadgeId) { userProfile.updateOne( - { _id: personId, 'badgeCollection.badge': oldBadgeId }, + { _id: personId, "badgeCollection.badge": oldBadgeId }, { $set: { - 'badgeCollection.$.badge': newBadgeId, - 'badgeCollection.$.lastModified': Date.now().toString(), - 'badgeCollection.$.count': 1, - 'badgeCollection.$.earnedDate': [earnedDateBadge()], + "badgeCollection.$.badge": newBadgeId, + "badgeCollection.$.lastModified": Date.now().toString(), + "badgeCollection.$.count": 1, + "badgeCollection.$.earnedDate": [earnedDateBadge()], }, }, (err) => { @@ -913,11 +913,11 @@ const userHelper = function () { const increaseBadgeCount = async function (personId, badgeId) { userProfile.updateOne( - { _id: personId, 'badgeCollection.badge': badgeId }, + { _id: personId, "badgeCollection.badge": badgeId }, { - $inc: { 'badgeCollection.$.count': 1 }, - $set: { 'badgeCollection.$.lastModified': Date.now().toString() }, - $push: { 'badgeCollection.$.earnedDate': earnedDateBadge() }, + $inc: { "badgeCollection.$.count": 1 }, + $set: { "badgeCollection.$.lastModified": Date.now().toString() }, + $push: { "badgeCollection.$.earnedDate": earnedDateBadge() }, }, (err) => { if (err) { @@ -983,7 +983,7 @@ const userHelper = function () { (item) => item.badge._id.toString() === badgeId.toString(), ); if (!recordToUpdate) { - throw new Error('Badge not found'); + throw new Error("Badge not found"); } // If the count is the same, do nothing if (recordToUpdate.count === count) { @@ -995,7 +995,7 @@ const userHelper = function () { // preventing oversight of any mismatches caused by bugs. if (recordToUpdate.count < count) { let dateToAdd = count - recordToUpdate.count; - // if the EarnedDate count is less than the new count, add a earned date to the end of the collection + // if the EarnedDate count is less than the new count, add a earned date to the end of the collection while (dateToAdd > 0) { copyOfEarnedDate.push(earnedDateBadge()); dateToAdd -= 1; @@ -1003,13 +1003,14 @@ const userHelper = function () { } newEarnedDate = [...copyOfEarnedDate]; userProfile.updateOne( - { _id: personId, 'badgeCollection.badge': badgeId }, + { _id: personId, "badgeCollection.badge": badgeId }, { $set: { - 'badgeCollection.$.count': count, - 'badgeCollection.$.lastModified': Date.now().toString(), - 'badgeCollection.$.earnedDate': newEarnedDate, - 'badgeCollection.$.hasBadgeDeletionImpact': recordToUpdate.count > count, // badge deletion impact set to true if the new count is less than the old count + "badgeCollection.$.count": count, + "badgeCollection.$.lastModified": Date.now().toString(), + "badgeCollection.$.earnedDate": newEarnedDate, + "badgeCollection.$.hasBadgeDeletionImpact": + recordToUpdate.count > count, // badge deletion impact set to true if the new count is less than the old count }, }, (err) => { @@ -1042,7 +1043,7 @@ const userHelper = function () { .aggregate([ { $match: { - type: 'X Hours for X Week Streak', + type: "X Hours for X Week Streak", weeks: { $gt: 1, $lt: weeks }, totalHrs: hrs, }, @@ -1050,9 +1051,9 @@ const userHelper = function () { { $sort: { weeks: -1, totalHrs: -1 } }, { $group: { - _id: '$weeks', + _id: "$weeks", badges: { - $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' }, + $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" }, }, }, }, @@ -1063,7 +1064,7 @@ const userHelper = function () { for (let i = 0; i < badgeCollection.length; i += 1) { if ( badgeCollection[i].badge?.type - === 'X Hours for X Week Streak' + === "X Hours for X Week Streak" && badgeCollection[i].badge?.weeks === bdge.weeks && bdge.hrs === hrs && !removed @@ -1091,7 +1092,7 @@ const userHelper = function () { ) { let badgeOfType; for (let i = 0; i < badgeCollection.length; i += 1) { - if (badgeCollection[i].badge?.type === 'No Infringement Streak') { + if (badgeCollection[i].badge?.type === "No Infringement Streak") { if ( badgeOfType && badgeOfType.months <= badgeCollection[i].badge.months @@ -1109,7 +1110,7 @@ const userHelper = function () { } } await badge - .find({ type: 'No Infringement Streak' }) + .find({ type: "No Infringement Streak" }) .sort({ months: -1 }) .then((results) => { if (!Array.isArray(results) || !results.length) { @@ -1121,7 +1122,7 @@ const userHelper = function () { if (elem.months <= 12) { if ( - moment().diff(moment(user.createdDate), 'months', true) + moment().diff(moment(user.createdDate), "months", true) >= elem.months ) { if ( @@ -1131,7 +1132,7 @@ const userHelper = function () { moment( user.infringements[user.infringements?.length - 1].date, ), - 'months', + "months", true, ), ) >= elem.months @@ -1152,7 +1153,7 @@ const userHelper = function () { } } else if (user?.infringements?.length === 0) { if ( - moment().diff(moment(user.createdDate), 'months', true) + moment().diff(moment(user.createdDate), "months", true) >= elem.months ) { if ( @@ -1163,7 +1164,7 @@ const userHelper = function () { user.oldInfringements[user.oldInfringements?.length - 1] .date, ), - 'months', + "months", true, ), ) @@ -1197,9 +1198,9 @@ const userHelper = function () { ) { const badgesOfType = badgeCollection .map((obj) => obj.badge) - .filter((badgeItem) => badgeItem.type === 'Minimum Hours Multiple'); + .filter((badgeItem) => badgeItem.type === "Minimum Hours Multiple"); await badge - .find({ type: 'Minimum Hours Multiple' }) + .find({ type: "Minimum Hours Multiple" }) .sort({ multiple: -1 }) .then((results) => { if (!Array.isArray(results) || !results.length) { @@ -1233,7 +1234,7 @@ const userHelper = function () { const duplicateBadges = []; for (let i = 0; i < badgeCollection.length; i += 1) { - if (badgeCollection[i].badge?.type === 'Personal Max') { + if (badgeCollection[i].badge?.type === "Personal Max") { if (!badgeOfType) { badgeOfType = badgeCollection[i]; } else { @@ -1244,7 +1245,7 @@ const userHelper = function () { await removeDupBadge(personId, b._id); } } - await badge.findOne({ type: 'Personal Max' }).then((results) => { + await badge.findOne({ type: "Personal Max" }).then((results) => { if ( user.lastWeekTangibleHrs && user.lastWeekTangibleHrs >= 1 @@ -1275,13 +1276,13 @@ const userHelper = function () { && user.lastWeekTangibleHrs > user.weeklycommittedHours ) { const badgeOfType = badgeCollection - .filter((object) => object.badge.type === 'Most Hrs in Week') + .filter((object) => object.badge.type === "Most Hrs in Week") .map((object) => object.badge); - await badge.findOne({ type: 'Most Hrs in Week' }).then((results) => { + await badge.findOne({ type: "Most Hrs in Week" }).then((results) => { userProfile .aggregate([ { $match: { isActive: true } }, - { $group: { _id: 1, maxHours: { $max: '$lastWeekTangibleHrs' } } }, + { $group: { _id: 1, maxHours: { $max: "$lastWeekTangibleHrs" } } }, ]) .then((userResults) => { if (badgeOfType.length > 1) { @@ -1311,12 +1312,12 @@ const userHelper = function () { // Handle Increasing the 1 week streak badges const badgesOfType = []; for (let i = 0; i < badgeCollection.length; i += 1) { - if (badgeCollection[i].badge?.type === 'X Hours for X Week Streak') { + if (badgeCollection[i].badge?.type === "X Hours for X Week Streak") { badgesOfType.push(badgeCollection[i].badge); } } await badge - .find({ type: 'X Hours for X Week Streak', weeks: 1 }) + .find({ type: "X Hours for X Week Streak", weeks: 1 }) .sort({ totalHrs: -1 }) .then((results) => { results.every((elem) => { @@ -1341,13 +1342,13 @@ const userHelper = function () { // Check each Streak Greater than One to check if it works await badge .aggregate([ - { $match: { type: 'X Hours for X Week Streak', weeks: { $gt: 1 } } }, + { $match: { type: "X Hours for X Week Streak", weeks: { $gt: 1 } } }, { $sort: { weeks: -1, totalHrs: -1 } }, { $group: { - _id: '$weeks', + _id: "$weeks", badges: { - $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' }, + $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" }, }, }, }, @@ -1360,7 +1361,7 @@ const userHelper = function () { for (let i = 0; i < badgeCollection.length; i += 1) { if ( badgeCollection[i].badge?.type - === 'X Hours for X Week Streak' + === "X Hours for X Week Streak" && badgeCollection[i].badge?.weeks === bdge.weeks ) { if ( @@ -1445,13 +1446,13 @@ const userHelper = function () { badgeCollection, ) { const leaderRoles = [ - 'Mentor', - 'Manager', - 'Administrator', - 'Owner', - 'Core Team', + "Mentor", + "Manager", + "Administrator", + "Owner", + "Core Team", ]; - const approvedRoles = ['Mentor', 'Manager']; + const approvedRoles = ["Mentor", "Manager"]; if (!approvedRoles.includes(user.role)) return; let teamMembers; @@ -1476,7 +1477,7 @@ const userHelper = function () { }); let badgeOfType; for (let i = 0; i < badgeCollection.length; i += 1) { - if (badgeCollection[i].badge?.type === 'Lead a team of X+') { + if (badgeCollection[i].badge?.type === "Lead a team of X+") { if ( badgeOfType && badgeOfType.people <= badgeCollection[i].badge.people @@ -1494,7 +1495,7 @@ const userHelper = function () { } } await badge - .find({ type: 'Lead a team of X+' }) + .find({ type: "Lead a team of X+" }) .sort({ people: -1 }) .then((results) => { if (!Array.isArray(results) || !results.length) { @@ -1528,17 +1529,17 @@ const userHelper = function () { const checkTotalHrsInCat = async function (personId, user, badgeCollection) { const hoursByCategory = user.hoursByCategory || {}; const categories = [ - 'food', - 'energy', - 'housing', - 'education', - 'society', - 'economics', - 'stewardship', + "food", + "energy", + "housing", + "education", + "society", + "economics", + "stewardship", ]; const badgesOfType = badgeCollection - .filter((object) => object.badge.type === 'Total Hrs in Category') + .filter((object) => object.badge.type === "Total Hrs in Category") .map((object) => object.badge); categories.forEach(async (category) => { @@ -1549,7 +1550,7 @@ const userHelper = function () { let badgeOfType; for (let i = 0; i < badgeCollection.length; i += 1) { if ( - badgeCollection[i].badge?.type === 'Total Hrs in Category' + badgeCollection[i].badge?.type === "Total Hrs in Category" && badgeCollection[i].badge?.category === category ) { if ( @@ -1572,7 +1573,7 @@ const userHelper = function () { const newCatg = category.charAt(0).toUpperCase() + category.slice(1); await badge - .find({ type: 'Total Hrs in Category', category: newCatg }) + .find({ type: "Total Hrs in Category", category: newCatg }) .sort({ totalHrs: -1 }) .then((results) => { @@ -1622,7 +1623,7 @@ const userHelper = function () { try { const users = await userProfile .find({ isActive: true }) - .populate('badgeCollection.badge'); + .populate("badgeCollection.badge"); for (let i = 0; i < users.length; i += 1) { const user = users[i]; const { _id, badgeCollection } = user; @@ -1649,13 +1650,13 @@ const userHelper = function () { const userId = mongoose.Types.ObjectId(personId); const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); return timeEntries .find( @@ -1664,7 +1665,7 @@ const userHelper = function () { dateOfWork: { $gte: pdtstart, $lte: pdtend }, isTangible: true, }, - 'totalSeconds', + "totalSeconds", ) .then((results) => { const totalTangibleWeeklySeconds = results.reduce( @@ -1679,13 +1680,13 @@ const userHelper = function () { try { const users = await userProfile.find( { isActive: true, endDate: { $exists: true } }, - '_id isActive endDate', + "_id isActive endDate", ); for (let i = 0; i < users.length; i += 1) { const user = users[i]; const { endDate } = user; endDate.setHours(endDate.getHours() + 7); - if (moment().isAfter(moment(endDate).add(1, 'days'))) { + if (moment().isAfter(moment(endDate).add(1, "days"))) { await userProfile.findByIdAndUpdate( user._id, user.set({ @@ -1696,7 +1697,7 @@ const userHelper = function () { const id = user._id; const person = await userProfile.findById(id); - const lastDay = moment(person.endDate).format('YYYY-MM-DD'); + const lastDay = moment(person.endDate).format("YYYY-MM-DD"); logger.logInfo( `User with id: ${ user._id @@ -1716,7 +1717,7 @@ const userHelper = function () {

The HGN A.I. (and One Community)

`; emailSender( - 'onecommunityglobal@gmail.com', + "onecommunityglobal@gmail.com", subject, emailBody, null, @@ -1742,16 +1743,16 @@ const userHelper = function () { const deleteOldTimeOffRequests = async () => { const endOfLastWeek = moment() - .tz('America/Los_Angeles') - .endOf('week') - .subtract(1, 'week'); + .tz("America/Los_Angeles") + .endOf("week") + .subtract(1, "week"); - const utcEndMoment = moment(endOfLastWeek).add(1, 'second'); + const utcEndMoment = moment(endOfLastWeek).add(1, "second"); try { await timeOffRequest.deleteMany({ endingDate: { $lte: utcEndMoment } }); - console.log('Deleted expired time off requests.'); + console.log("Deleted expired time off requests."); } catch (error) { - console.error('Error deleting expired time off requests:', error); + console.error("Error deleting expired time off requests:", error); } }; diff --git a/src/models/bmdashboard/buildingIssue.js b/src/models/bmdashboard/buildingIssue.js index 089117ce1..976f3fb33 100644 --- a/src/models/bmdashboard/buildingIssue.js +++ b/src/models/bmdashboard/buildingIssue.js @@ -14,4 +14,4 @@ const buildingIssue = new Schema({ // relatedLesson: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingNewLesson', required: true }, }); -module.exports = mongoose.model('buildingIssue', buildingIssue, 'buildingIssues'); \ No newline at end of file +module.exports = mongoose.model('buildingIssue', buildingIssue, 'buildingIssues'); diff --git a/src/models/userProfile.js b/src/models/userProfile.js index 64e4b8245..5e63205cb 100644 --- a/src/models/userProfile.js +++ b/src/models/userProfile.js @@ -41,8 +41,11 @@ const userProfileSchema = new Schema({ index: true, }, lastName: { - type: String, required: true, minlength: 2, index: true, -}, + type: String, + required: true, + minlength: 2, + index: true, + }, phoneNumber: [{ type: String, phoneNumber: String }], jobTitle: [{ type: String, jobTitle: String }], bio: { type: String }, @@ -229,6 +232,7 @@ const userProfileSchema = new Schema({ actualEmail: { type: String }, timeOffFrom: { type: Date, default: undefined }, timeOffTill: { type: Date, default: undefined }, + getWeeklyReport: { type: Boolean }, }); userProfileSchema.pre('save', function (next) { diff --git a/src/routes/reportsRouter.js b/src/routes/reportsRouter.js index 01bc8795b..7a98fca8b 100644 --- a/src/routes/reportsRouter.js +++ b/src/routes/reportsRouter.js @@ -1,11 +1,22 @@ -const express = require('express'); +/* eslint-disable quotes */ +const express = require("express"); const route = function () { - const controller = require('../controllers/reportsController')(); + const controller = require("../controllers/reportsController")(); const reportsRouter = express.Router(); - reportsRouter.route('/reports/weeklysummaries') + reportsRouter + .route("/reports/recepients/:userid") + .patch(controller.saveReportsRecepients) + .delete(controller.deleteReportsRecepients); + + reportsRouter + .route("/reports/getrecepients") + .get(controller.getReportRecipients); + + reportsRouter + .route("/reports/weeklysummaries") .get(controller.getWeeklySummaries); return reportsRouter; diff --git a/src/routes/userProfileRouter.js b/src/routes/userProfileRouter.js index 74610ec50..1e930fbf9 100644 --- a/src/routes/userProfileRouter.js +++ b/src/routes/userProfileRouter.js @@ -95,6 +95,10 @@ const routes = function (userProfile) { .route('/userProfile/socials/facebook') .get(controller.getAllUsersWithFacebookLink); + userProfileRouter + .route('/userProfile/authorizeUser/weeeklySummaries') + .post(controller.authorizeUser); + return userProfileRouter; }; diff --git a/src/utilities/createInitialPermissions.js b/src/utilities/createInitialPermissions.js index 7cf4be76b..e72905f58 100644 --- a/src/utilities/createInitialPermissions.js +++ b/src/utilities/createInitialPermissions.js @@ -1,229 +1,229 @@ -const Role = require("../models/role"); -const RolePreset = require("../models/rolePreset"); -const User = require("../models/userProfile"); +const Role = require('../models/role'); +const RolePreset = require('../models/rolePreset'); +const User = require('../models/userProfile'); const permissionsRoles = [ { - roleName: "Administrator", + roleName: 'Administrator', permissions: [ // Reports - "getWeeklySummaries", - "getReports", // Doesn't do anything on back-end. - "totalValidWeeklySummaries", + 'getWeeklySummaries', + 'getReports', // Doesn't do anything on back-end. + 'totalValidWeeklySummaries', // Badges - "seeBadges", - "assignBadges", - "createBadges", - "deleteBadges", - "updateBadges", + 'seeBadges', + 'assignBadges', + 'createBadges', + 'deleteBadges', + 'updateBadges', // Popups - "createPopup", - "updatePopup", + 'createPopup', + 'updatePopup', // Projects - "deleteProject", - "postProject", - "putProject", - "assignProjectToUsers", + 'deleteProject', + 'postProject', + 'putProject', + 'assignProjectToUsers', // Tasks - "importTask", - "postTask", - "updateTask", - "swapTask", - "deleteTask", - "updateNum", + 'importTask', + 'postTask', + 'updateTask', + 'swapTask', + 'deleteTask', + 'updateNum', // Teams - "postTeam", - "deleteTeam", - "putTeam", - "assignTeamToUsers", + 'postTeam', + 'deleteTeam', + 'putTeam', + 'assignTeamToUsers', // Time Entries - "editTimeEntry", - "deleteTimeEntry", + 'editTimeEntry', + 'deleteTimeEntry', // 'postTimeEntry',? // User Profile - "putRole", - "postUserProfile", - "putUserProfile", - "putUserProfileImportantInfo", - "changeUserStatus", - "updatePassword", - "deleteUserProfile", - "infringementAuthorizer", + 'putRole', + 'postUserProfile', + 'putUserProfile', + 'putUserProfileImportantInfo', + 'changeUserStatus', + 'updatePassword', + 'deleteUserProfile', + 'infringementAuthorizer', // WBS - "postWbs", - "deleteWbs", + 'postWbs', + 'deleteWbs', // Inv - "getAllInvInProjectWBS", - "postInvInProjectWBS", - "getAllInvInProject", - "postInvInProject", - "transferInvById", - "delInvById", - "unWasteInvById", - "getInvIdInfo", - "putInvById", - "getInvTypeById", - "putInvType", - "getAllInvType", - "postInvType", + 'getAllInvInProjectWBS', + 'postInvInProjectWBS', + 'getAllInvInProject', + 'postInvInProject', + 'transferInvById', + 'delInvById', + 'unWasteInvById', + 'getInvIdInfo', + 'putInvById', + 'getInvTypeById', + 'putInvType', + 'getAllInvType', + 'postInvType', // General - "getUserProfiles", - "getProjectMembers", + 'getUserProfiles', + 'getProjectMembers', - "getTimeZoneAPIKey", - "checkLeadTeamOfXplus", + 'getTimeZoneAPIKey', + 'checkLeadTeamOfXplus', ], }, { - roleName: "Volunteer", - permissions: ["getReporteesLimitRoles", "suggestTask"], + roleName: 'Volunteer', + permissions: ['getReporteesLimitRoles', 'suggestTask'], }, { - roleName: "Core Team", + roleName: 'Core Team', permissions: [ - "getUserProfiles", - "getProjectMembers", - "getAllInvInProjectWBS", - "postInvInProjectWBS", - "getAllInvInProject", - "postInvInProject", - "transferInvById", - "delInvById", - "unWasteInvById", - "getInvIdInfo", - "putInvById", - "getInvTypeById", - "putInvType", - "getAllInvType", - "postInvType", - "getWeeklySummaries", - "getReports", - "getTimeZoneAPIKey", - "checkLeadTeamOfXplus", + 'getUserProfiles', + 'getProjectMembers', + 'getAllInvInProjectWBS', + 'postInvInProjectWBS', + 'getAllInvInProject', + 'postInvInProject', + 'transferInvById', + 'delInvById', + 'unWasteInvById', + 'getInvIdInfo', + 'putInvById', + 'getInvTypeById', + 'putInvType', + 'getAllInvType', + 'postInvType', + 'getWeeklySummaries', + 'getReports', + 'getTimeZoneAPIKey', + 'checkLeadTeamOfXplus', ], }, { - roleName: "Manager", + roleName: 'Manager', permissions: [ - "getUserProfiles", - "getProjectMembers", - "putUserProfile", - "infringementAuthorizer", - "getReporteesLimitRoles", - "updateTask", - "putTeam", - "getAllInvInProjectWBS", - "postInvInProjectWBS", - "getAllInvInProject", - "postInvInProject", - "transferInvById", - "delInvById", - "unWasteInvById", - "getInvIdInfo", - "putInvById", - "getInvTypeById", - "putInvType", - "getAllInvType", - "postInvType", - "getTimeZoneAPIKey", - "checkLeadTeamOfXplus", + 'getUserProfiles', + 'getProjectMembers', + 'putUserProfile', + 'infringementAuthorizer', + 'getReporteesLimitRoles', + 'updateTask', + 'putTeam', + 'getAllInvInProjectWBS', + 'postInvInProjectWBS', + 'getAllInvInProject', + 'postInvInProject', + 'transferInvById', + 'delInvById', + 'unWasteInvById', + 'getInvIdInfo', + 'putInvById', + 'getInvTypeById', + 'putInvType', + 'getAllInvType', + 'postInvType', + 'getTimeZoneAPIKey', + 'checkLeadTeamOfXplus', ], }, { - roleName: "Mentor", + roleName: 'Mentor', permissions: [ - "suggestTask", - "getUserProfiles", - "getProjectMembers", - "putUserProfile", - "infringementAuthorizer", - "getReporteesLimitRoles", - "getAllInvInProjectWBS", - "postInvInProjectWBS", - "getAllInvInProject", - "postInvInProject", - "transferInvById", - "delInvById", - "unWasteInvById", - "getInvIdInfo", - "putInvById", - "getInvTypeById", - "putInvType", - "getAllInvType", - "postInvType", - "getTimeZoneAPIKey", - "checkLeadTeamOfXplus", + 'suggestTask', + 'getUserProfiles', + 'getProjectMembers', + 'putUserProfile', + 'infringementAuthorizer', + 'getReporteesLimitRoles', + 'getAllInvInProjectWBS', + 'postInvInProjectWBS', + 'getAllInvInProject', + 'postInvInProject', + 'transferInvById', + 'delInvById', + 'unWasteInvById', + 'getInvIdInfo', + 'putInvById', + 'getInvTypeById', + 'putInvType', + 'getAllInvType', + 'postInvType', + 'getTimeZoneAPIKey', + 'checkLeadTeamOfXplus', ], }, { - roleName: "Owner", + roleName: 'Owner', permissions: [ - "postRole", - "deleteRole", - "putRole", - "addDeleteEditOwners", - "putUserProfilePermissions", - "changeUserStatus", - "seeBadges", - "assignBadges", - "createBadges", - "deleteBadges", - "updateBadges", - "createPopup", - "updatePopup", - "deleteProject", - "postProject", - "putProject", - "assignProjectToUsers", - "importTask", - "postTask", - "updateNum", - "updateTask", - "swapTask", - "deleteTask", - "postTeam", - "deleteTeam", - "putTeam", - "assignTeamToUsers", - "editTimeEntry", - "deleteTimeEntry", - "updatePassword", - "getUserProfiles", - "getProjectMembers", - "postUserProfile", - "putUserProfile", - "putUserProfileImportantInfo", - "deleteUserProfile", - "infringementAuthorizer", - "postWbs", - "deleteWbs", - "getAllInvInProjectWBS", - "postInvInProjectWBS", - "getAllInvInProject", - "postInvInProject", - "transferInvById", - "delInvById", - "unWasteInvById", - "getInvIdInfo", - "putInvById", - "getInvTypeById", - "putInvType", - "getAllInvType", - "postInvType", - "getWeeklySummaries", - "getReports", - "getTimeZoneAPIKey", - "checkLeadTeamOfXplus", - "editTeamCode", - "totalValidWeeklySummaries", + 'postRole', + 'deleteRole', + 'putRole', + 'addDeleteEditOwners', + 'putUserProfilePermissions', + 'changeUserStatus', + 'seeBadges', + 'assignBadges', + 'createBadges', + 'deleteBadges', + 'updateBadges', + 'createPopup', + 'updatePopup', + 'deleteProject', + 'postProject', + 'putProject', + 'assignProjectToUsers', + 'importTask', + 'postTask', + 'updateNum', + 'updateTask', + 'swapTask', + 'deleteTask', + 'postTeam', + 'deleteTeam', + 'putTeam', + 'assignTeamToUsers', + 'editTimeEntry', + 'deleteTimeEntry', + 'updatePassword', + 'getUserProfiles', + 'getProjectMembers', + 'postUserProfile', + 'putUserProfile', + 'putUserProfileImportantInfo', + 'deleteUserProfile', + 'infringementAuthorizer', + 'postWbs', + 'deleteWbs', + 'getAllInvInProjectWBS', + 'postInvInProjectWBS', + 'getAllInvInProject', + 'postInvInProject', + 'transferInvById', + 'delInvById', + 'unWasteInvById', + 'getInvIdInfo', + 'putInvById', + 'getInvTypeById', + 'putInvType', + 'getAllInvType', + 'postInvType', + 'getWeeklySummaries', + 'getReports', + 'getTimeZoneAPIKey', + 'checkLeadTeamOfXplus', + 'editTeamCode', + 'totalValidWeeklySummaries', ], }, ]; const createInitialPermissions = async () => { // Create Initial Owner - const userEmail = { email: "jae@onecommunityglobal.org" }; - const update = { role: "Owner" }; + const userEmail = { email: 'jae@onecommunityglobal.org' }; + const update = { role: 'Owner' }; await User.findOneAndUpdate(userEmail, update); // Get Roles From DB @@ -236,9 +236,7 @@ const createInitialPermissions = async () => { for (let i = 0; i < permissionsRoles.length; i += 1) { const { roleName, permissions } = permissionsRoles[i]; - if (!onlyUpdateOwner || roleName === 'Owner') { - const roleDataBase = allRoles.find((role) => role.roleName === roleName); // If role does not exist in db, create it @@ -248,10 +246,8 @@ const createInitialPermissions = async () => { role.permissions = permissions; role.save(); - // If role exists in db and does not have every permission, add the missing permissions } else if (!permissions.every((perm) => roleDataBase.permissions.includes(perm))) { - const roleId = roleDataBase._id; promises.push( @@ -262,7 +258,7 @@ const createInitialPermissions = async () => { } }); record.save(); - }) + }), ); } } @@ -271,26 +267,23 @@ const createInitialPermissions = async () => { const presetDataBase = allPresets.find((preset) => preset.roleName === roleName && preset.presetName === 'default'); - // If role does not exist in db, create it if (!presetDataBase) { const defaultPreset = new RolePreset(); defaultPreset.roleName = roleName; - defaultPreset.presetName = "default"; + defaultPreset.presetName = 'default'; defaultPreset.permissions = permissions; defaultPreset.save(); - // If role exists in db and is not updated, update default } else if (!presetDataBase.permissions.every((perm) => permissions.includes(perm)) || !permissions.every((perm) => presetDataBase.permissions.includes(perm))) { - const presetId = presetDataBase._id; promises.push( RolePreset.findById(presetId, (_, record) => { record.permissions = permissions; record.save(); - }) + }), ); } }