diff --git a/package-lock.json b/package-lock.json index ff66994e8..ecce49ec7 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", @@ -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,7 +3350,7 @@ "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", @@ -4264,7 +4264,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", @@ -4445,7 +4445,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": { @@ -4575,7 +4575,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", @@ -4585,7 +4585,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", @@ -4968,7 +4968,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": { @@ -4980,7 +4980,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" @@ -5085,7 +5085,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", @@ -5187,13 +5187,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", @@ -5231,7 +5231,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": { @@ -5552,7 +5552,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", @@ -5729,7 +5729,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", @@ -5743,7 +5743,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", @@ -5754,7 +5754,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", @@ -5765,7 +5765,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", @@ -5945,7 +5945,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": { @@ -6085,7 +6085,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", @@ -6804,7 +6804,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" } @@ -6834,7 +6834,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": { @@ -6879,7 +6879,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", @@ -6894,7 +6894,7 @@ "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", @@ -6910,7 +6910,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", @@ -6957,7 +6957,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", @@ -6968,7 +6968,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", @@ -6979,7 +6979,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" @@ -7021,7 +7021,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": { @@ -7499,7 +7499,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" @@ -7508,7 +7508,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", @@ -7903,7 +7903,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": { @@ -7934,19 +7934,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", @@ -7973,7 +7973,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", @@ -8091,7 +8091,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": { @@ -8138,7 +8138,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", @@ -8152,17 +8152,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", @@ -8185,17 +8185,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" @@ -8313,7 +8313,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", diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js index 6f872f338..a76dcf4a2 100644 --- a/src/controllers/reasonSchedulingController.js +++ b/src/controllers/reasonSchedulingController.js @@ -1,23 +1,19 @@ - -const moment = require('moment-timezone'); -const UserModel = require('../models/userProfile'); -const ReasonModel = require('../models/reason'); -const emailSender = require('../utilities/emailSender'); - +const moment = require("moment-timezone"); +const UserModel = require("../models/userProfile"); +const ReasonModel = require("../models/reason"); +const emailSender = require("../utilities/emailSender"); const postReason = async (req, res) => { try { const { userId, requestor, reasonData } = req.body; const newDate = moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day'); - const currentDate = moment - .tz('America/Los_Angeles') - .startOf('day'); + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day"); + const currentDate = moment.tz("America/Los_Angeles").startOf("day"); // error case 0 - if (moment.tz(reasonData.date, 'America/Los_Angeles').day() !== 0) { + if (moment.tz(reasonData.date, "America/Los_Angeles").day() !== 0) { return res.status(400).json({ message: "You must choose the Sunday YOU'LL RETURN as your date. This is so your reason ends up as a note on that blue square.", @@ -27,19 +23,19 @@ const postReason = async (req, res) => { if (newDate.isBefore(currentDate)) { return res.status(400).json({ - message: 'You should select a date that is yet to come', + message: "You should select a date that is yet to come", errorCode: 7, }); } if (!reasonData.message) { return res.status(400).json({ - message: 'You must provide a reason.', + message: "You must provide a reason.", errorCode: 6, }); } - // Commented this condition to make reason scheduler available to all the users. + // Commented this condition to make reason scheduler available to all the users. // error case 1 // if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') { // return res.status(403).json({ @@ -54,15 +50,64 @@ const postReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } + // conditions added to check if timeOffFrom and timeOffTill fields existed + + if ( + foundUser.hasOwnProperty("timeOffFrom") && + foundUser.hasOwnProperty("timeOffTill") + ) { + // if currentDate is greater than or equal to the last timeOffTill date then both the fields will be updated + if (currentDate >= foundUser.timeOffTill) { + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffFrom: currentDate, + timeOffTill: newDate, + }, + } + ); + } else { + // else only timeOffTill will be updated + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffTill: newDate, + }, + } + ); + } + } else { + // if both the fields are not present then these fields will be added to mongoDB for that user + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffFrom: currentDate, + timeOffTill: newDate, + }, + } + ); + } + + // + const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); @@ -70,14 +115,14 @@ const postReason = async (req, res) => { // error case 3 if (foundReason) { return res.status(403).json({ - message: 'The reason must be unique to the date', + message: "The reason must be unique to the date", errorCode: 3, }); } const savingDate = moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(); const newReason = new ReasonModel({ @@ -86,14 +131,13 @@ const postReason = async (req, res) => { userId, }); - // await newReason.save(); - const savedData = await newReason.save(); + const savedData = await newReason.save(); if (savedData) { // Upon clicking the "Save" button in the Blue Square Reason Scheduler, an email will be automatically sent to the user and Jae. - const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been set`; + const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been set`; - const emailBody = `

Hi !

+ const emailBody = `

Hi !

This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has set their Blue Square Reason.

@@ -103,21 +147,20 @@ const postReason = async (req, res) => {

Thank you,
One Community

`; + // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - - // 2 user email - - emailSender(`${foundUser.email}`, subject, emailBody, null, null); + // 2 user email - + emailSender(`${foundUser.email}`, subject, emailBody, null, null); - // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) - // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); - } + // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) + // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); + } return res.sendStatus(200); } catch (error) { console.log(error); return res.status(400).json({ - errMessage: 'Something went wrong', + errMessage: "Something went wrong", }); } }; @@ -140,7 +183,7 @@ const getAllReasons = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", }); } @@ -154,7 +197,7 @@ const getAllReasons = async (req, res) => { } catch (error) { console.log(error); return res.status(400).json({ - errMessage: 'Something went wrong while fetching the user', + errMessage: "Something went wrong while fetching the user", }); } }; @@ -178,24 +221,24 @@ const getSingleReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(queryDate, 'America/Los_Angeles') - .startOf('day') + .tz(queryDate, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); if (!foundReason) { return res.status(200).json({ - reason: '', - date: '', - userId: '', + reason: "", + date: "", + userId: "", isSet: false, }); } @@ -204,7 +247,7 @@ const getSingleReason = async (req, res) => { } catch (error) { console.log(error); return res.status(400).json({ - message: 'Something went wrong while fetching single reason', + message: "Something went wrong while fetching single reason", }); } }; @@ -225,7 +268,7 @@ const patchReason = async (req, res) => { if (!reasonData.message) { return res.status(400).json({ - message: 'You must provide a reason.', + message: "You must provide a reason.", errorCode: 6, }); } @@ -235,22 +278,22 @@ const patchReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); // error case 4 if (!foundReason) { return res.status(404).json({ - message: 'Reason not found', + message: "Reason not found", errorCode: 4, }); } @@ -260,9 +303,9 @@ const patchReason = async (req, res) => { const savedData = await foundReason.save(); if (savedData) { // Upon clicking the "Save" button in the Blue Square Reason Scheduler, an email will be automatically sent to the user and Jae. - const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been updated`; + const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been updated`; - const emailBody = `

Hi !

+ const emailBody = `

Hi !

This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has updated their Blue Square Reason.

@@ -272,22 +315,22 @@ const patchReason = async (req, res) => {

Thank you,
One Community

`; + // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); + // 2 user email - + emailSender(`${foundUser.email}`, subject, emailBody, null, null); - // 2 user email - - emailSender(`${foundUser.email}`, subject, emailBody, null, null); - - // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) - // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); - } + // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) + // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); + } return res.status(200).json({ - message: 'Reason Updated!', + message: "Reason Updated!", + message: "Reason Updated!", }); } catch (error) { return res.status(400).json({ - message: 'something went wrong while patching the reason', + message: "something went wrong while patching the reason", }); } }; @@ -298,10 +341,11 @@ const deleteReason = async (req, res) => { const { userId } = req.params; // error case 1 - if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') { + if (requestor.role !== "Owner" && requestor.role !== "Administrator") { return res.status(403).json({ message: - 'You must be an Owner or Administrator to schedule a reason for a Blue Square', + "You must be an Owner or Administrator to schedule a reason for a Blue Square", + errorCode: 1, }); } @@ -311,21 +355,21 @@ const deleteReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), }); if (!foundReason) { return res.status(404).json({ - message: 'Reason not found', + message: "Reason not found", errorCode: 4, }); } @@ -333,13 +377,13 @@ const deleteReason = async (req, res) => { foundReason.remove((err) => { if (err) { return res.status(500).json({ - message: 'Error while deleting document', + message: "Error while deleting document", errorCode: 5, }); } return res.status(200).json({ - message: 'Document deleted', + message: "Document deleted", }); }); } catch (error) {} diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 9bedb0e8f..9f172dd2a 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -1,28 +1,27 @@ -const moment = require('moment-timezone'); -const mongoose = require('mongoose'); -const userProfile = require('../models/userProfile'); -const timeentry = require('../models/timeentry'); -const myTeam = require('../helpers/helperModels/myTeam'); -const team = require('../models/team'); - +const moment = require("moment-timezone"); +const mongoose = require("mongoose"); +const userProfile = require("../models/userProfile"); +const timeentry = require("../models/timeentry"); +const myTeam = require("../helpers/helperModels/myTeam"); +const team = require("../models/team"); const dashboardhelper = function () { const personaldetails = function (userId) { return userProfile.findById( userId, - '_id firstName lastName role profilePic badgeCollection', + "_id firstName lastName role profilePic badgeCollection" ); }; const getOrgData = async function () { 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"); /** * Previous aggregate pipeline had two issues: @@ -41,40 +40,43 @@ const dashboardhelper = function () { $gte: 1, }, role: { - $ne: 'Mentor', + $ne: "Mentor", }, }, }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { $project: { - personId: '$_id', + personId: "$_id", name: 1, weeklycommittedHours: 1, role: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, { $not: [ { - $in: ['$$timeentry.entryType', ['person', 'team', 'project']], + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], }, ], }, @@ -86,7 +88,7 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -97,27 +99,27 @@ const dashboardhelper = function () { totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, tangibletime: { $cond: [ { - $eq: ['$timeEntryData.isTangible', true], + $eq: ["$timeEntryData.isTangible", true], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, intangibletime: { $cond: [ { - $eq: ['$timeEntryData.isTangible', false], + $eq: ["$timeEntryData.isTangible", false], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, @@ -126,17 +128,17 @@ const dashboardhelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", }, time_hrs: { - $sum: { $divide: ['$totalSeconds', 3600] }, + $sum: { $divide: ["$totalSeconds", 3600] }, }, tangibletime_hrs: { - $sum: { $divide: ['$tangibletime', 3600] }, + $sum: { $divide: ["$tangibletime", 3600] }, }, intangibletime_hrs: { - $sum: { $divide: ['$intangibletime', 3600] }, + $sum: { $divide: ["$intangibletime", 3600] }, }, }, }, @@ -144,15 +146,19 @@ const dashboardhelper = function () { $group: { _id: 0, memberCount: { $sum: 1 }, - totalweeklycommittedHours: { $sum: '$_id.weeklycommittedHours' }, + totalweeklycommittedHours: { $sum: "$_id.weeklycommittedHours" }, + totalweeklycommittedHours: { $sum: "$_id.weeklycommittedHours" }, totaltime_hrs: { - $sum: '$time_hrs', + $sum: "$time_hrs", + $sum: "$time_hrs", }, totaltangibletime_hrs: { - $sum: '$tangibletime_hrs', + $sum: "$tangibletime_hrs", + $sum: "$tangibletime_hrs", }, totalintangibletime_hrs: { - $sum: '$intangibletime_hrs', + $sum: "$intangibletime_hrs", + $sum: "$intangibletime_hrs", }, }, }, @@ -163,55 +169,119 @@ const dashboardhelper = function () { const getLeaderboard = async function (userId) { const userid = mongoose.Types.ObjectId(userId); - const userById = await userProfile.findOne({ _id: userid, isActive: true }, { role: 1 }) - .then(res => res).catch((e) => {}); + const userById = await userProfile + .findOne({ _id: userid, isActive: true }, { role: 1 }) + .then((res) => res) + .catch((e) => {}); if (userById == null) return null; const userRole = userById.role; 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"); let teamMemberIds = [userid]; let teamMembers = []; - if (userRole != 'Administrator' && userRole != 'Owner' && userRole != 'Core Team') // Manager , Mentor , Volunteer ... , Show only team members - { - const teamsResult = await team.find({ 'members.userId': { $in: [userid] } }, { members: 1 }) - .then(res => res).catch((e) => {}); + if ( + userRole != "Administrator" && + userRole != "Owner" && + userRole != "Core Team" + ) { + // Manager , Mentor , Volunteer ... , Show only team members + const teamsResult = await team + .find({ "members.userId": { $in: [userid] } }, { members: 1 }) + .then((res) => res) + .catch((e) => {}); teamsResult.map((_myTeam) => { _myTeam.members.map((teamMember) => { - if (!teamMember.userId.equals(userid)) teamMemberIds.push(teamMember.userId); - }); + if (!teamMember.userId.equals(userid)) + teamMemberIds.push(teamMember.userId); + }); }); - teamMembers = await userProfile.find({ _id: { $in: teamMemberIds }, isActive: true }, + teamMembers = await userProfile + .find( + { _id: { $in: teamMemberIds }, isActive: true }, { - role: 1, firstName: 1, lastName: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); - } else if (userRole == 'Administrator') { // All users except Owner and Core Team - const excludedRoles = ['Core Team', 'Owner']; - teamMembers = await userProfile.find({ isActive: true, role: { $nin: excludedRoles } }, + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else if (userRole == "Administrator") { + // All users except Owner and Core Team + const excludedRoles = ["Core Team", "Owner"]; + teamMembers = await userProfile + .find( + { isActive: true, role: { $nin: excludedRoles } }, { - role: 1, firstName: 1, lastName: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); - } else { // 'Core Team', 'Owner' //All users - teamMembers = await userProfile.find({ isActive: true }, + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else if (userRole == "Administrator") { + // All users except Owner and Core Team + const excludedRoles = ["Core Team", "Owner"]; + teamMembers = await userProfile + .find( + { isActive: true, role: { $nin: excludedRoles } }, { - role: 1, firstName: 1, lastName: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); - } + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else { + // 'Core Team', 'Owner' //All users + teamMembers = await userProfile + .find( + { isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } - teamMemberIds = teamMembers.map(member => member._id); + teamMemberIds = teamMembers.map((member) => member._id); const timeEntries = await timeentry.find({ dateOfWork: { @@ -225,36 +295,58 @@ const dashboardhelper = function () { timeEntries.map((timeEntry) => { const personIdStr = timeEntry.personId.toString(); - if (timeEntryByPerson[personIdStr] == null) { timeEntryByPerson[personIdStr] = { tangibleSeconds: 0, intangibleSeconds: 0, totalSeconds: 0 }; } + if (timeEntryByPerson[personIdStr] == null) { + timeEntryByPerson[personIdStr] = { + tangibleSeconds: 0, + intangibleSeconds: 0, + totalSeconds: 0, + }; + } if (timeEntry.isTangible === true) { - timeEntryByPerson[personIdStr].tangibleSeconds += timeEntry.totalSeconds; + timeEntryByPerson[personIdStr].tangibleSeconds += + timeEntry.totalSeconds; } else { - timeEntryByPerson[personIdStr].intangibleSeconds += timeEntry.totalSeconds; + timeEntryByPerson[personIdStr].intangibleSeconds += + timeEntry.totalSeconds; } timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; }); - const leaderBoardData = []; teamMembers.map((teamMember) => { - const obj = { - personId: teamMember._id, - role: teamMember.role, - name: `${teamMember.firstName } ${ teamMember.lastName}`, - isVisible: teamMember.isVisible, - hasSummary: teamMember.weeklySummaries?.length > 0 ? teamMember.weeklySummaries[0].summary != '' : false, - weeklycommittedHours: teamMember.weeklycommittedHours, - totaltangibletime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / 3600) || 0), - totalintangibletime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.intangibleSeconds / 3600) || 0), - totaltime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600) || 0), - percentagespentintangible: - (timeEntryByPerson[teamMember._id.toString()] && timeEntryByPerson[teamMember._id.toString()]?.totalSeconds != 0 && timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds != 0) - ? (timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / timeEntryByPerson[teamMember._id.toString()]?.totalSeconds) * 100 - : 0, - }; - leaderBoardData.push(obj); + const obj = { + personId: teamMember._id, + role: teamMember.role, + name: `${teamMember.firstName} ${teamMember.lastName}`, + isVisible: teamMember.isVisible, + hasSummary: + teamMember.weeklySummaries?.length > 0 + ? teamMember.weeklySummaries[0].summary != "" + : false, + weeklycommittedHours: teamMember.weeklycommittedHours, + totaltangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + 3600 || 0, + totalintangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.intangibleSeconds / + 3600 || 0, + totaltime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 || + 0, + percentagespentintangible: + timeEntryByPerson[teamMember._id.toString()] && + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds != 0 && + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds != 0 + ? (timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds) * + 100 + : 0, + timeOffFrom: teamMember.timeOffFrom || null, + timeOffTill: teamMember.timeOffTill || null, + }; + leaderBoardData.push(obj); }); const sortedLBData = leaderBoardData.sort((a, b) => { @@ -532,14 +624,14 @@ const dashboardhelper = function () { const getUserLaborData = async function (userId) { try { 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"); const user = await userProfile.findById({ _id: userId, @@ -550,7 +642,7 @@ const dashboardhelper = function () { $gte: pdtStart, $lte: pdtEnd, }, - entryType: { $in: ['default', null] }, + entryType: { $in: ["default", null] }, personId: userId, }); @@ -570,7 +662,7 @@ const dashboardhelper = function () { personId: userId, role: user.role, isVisible: user.isVisible, - hasSummary: user.weeklySummaries[0].summary !== '', + hasSummary: user.weeklySummaries[0].summary !== "", weeklycommittedHours: user.weeklycommittedHours, name: `${user.firstName} ${user.lastName}`, totaltime_hrs: (tangibleSeconds + intangibleSeconds) / 3600, @@ -578,13 +670,15 @@ const dashboardhelper = function () { totalintangibletime_hrs: intangibleSeconds / 3600, percentagespentintangible: (intangibleSeconds / tangibleSeconds) * 100, + timeOffFrom: user.timeOffFrom, + timeOffTill: user.timeOffTill, }, ]; } catch (err) { return [ { - personId: 'error', - name: 'Error Error', + personId: "error", + name: "Error Error", totaltime_hrs: 0, totaltangibletime_hrs: 0, totalintangibletime_hrs: 0, @@ -595,8 +689,8 @@ const dashboardhelper = function () { }; const laborthismonth = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return timeentry.aggregate([ { @@ -612,19 +706,19 @@ const dashboardhelper = function () { { $group: { _id: { - projectId: '$projectId', + projectId: "$projectId", }, labor: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, }, }, { $lookup: { - from: 'projects', - localField: '_id.projectId', - foreignField: '_id', - as: 'project', + from: "projects", + localField: "_id.projectId", + foreignField: "_id", + as: "project", }, }, { @@ -633,13 +727,13 @@ const dashboardhelper = function () { projectName: { $ifNull: [ { - $arrayElemAt: ['$project.projectName', 0], + $arrayElemAt: ["$project.projectName", 0], }, - 'Undefined', + "Undefined", ], }, timeSpent_hrs: { - $divide: ['$labor', 3600], + $divide: ["$labor", 3600], }, }, }, @@ -647,8 +741,8 @@ const dashboardhelper = function () { }; const laborthisweek = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return userProfile.aggregate([ { @@ -664,10 +758,10 @@ const dashboardhelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -675,23 +769,26 @@ const dashboardhelper = function () { weeklycommittedHours: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $eq: ['$$timeentry.isTangible', true], + $eq: ["$$timeentry.isTangible", true], }, { - $gte: ['$$timeentry.dateOfWork', fromdate], + $gte: ["$$timeentry.dateOfWork", fromdate], }, { - $lte: ['$$timeentry.dateOfWork', todate], + $lte: ["$$timeentry.dateOfWork", todate], }, { $not: [ { - $in: ['$$timeentry.entryType', ['person', 'team', 'project']], + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], }, ], }, @@ -703,27 +800,27 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, { $group: { _id: { - _id: '$_id', - weeklycommittedHours: '$weeklycommittedHours', + _id: "$_id", + weeklycommittedHours: "$weeklycommittedHours", }, effort: { - $sum: '$timeEntryData.totalSeconds', + $sum: "$timeEntryData.totalSeconds", }, }, }, { $project: { _id: 0, - weeklycommittedHours: '$_id.weeklycommittedHours', + weeklycommittedHours: "$_id.weeklycommittedHours", timeSpent_hrs: { - $divide: ['$effort', 3600], + $divide: ["$effort", 3600], }, }, }, @@ -731,8 +828,8 @@ const dashboardhelper = function () { }; const laborThisWeekByCategory = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return userProfile.aggregate([ { @@ -748,10 +845,10 @@ const dashboardhelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -759,23 +856,26 @@ const dashboardhelper = function () { weeklycommittedHours: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $eq: ['$$timeentry.isTangible', true], + $eq: ["$$timeentry.isTangible", true], }, { - $gte: ['$$timeentry.dateOfWork', fromdate], + $gte: ["$$timeentry.dateOfWork", fromdate], }, { - $lte: ['$$timeentry.dateOfWork', todate], + $lte: ["$$timeentry.dateOfWork", todate], }, { $not: [ { - $in: ['$$timeentry.entryType', ['person', 'team', 'project']], + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], }, ], }, @@ -787,37 +887,37 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, { $group: { - _id: '$timeEntryData.projectId', + _id: "$timeEntryData.projectId", effort: { - $sum: '$timeEntryData.totalSeconds', + $sum: "$timeEntryData.totalSeconds", }, }, }, { $lookup: { - from: 'projects', - localField: '_id', - foreignField: '_id', - as: 'project', + from: "projects", + localField: "_id", + foreignField: "_id", + as: "project", }, }, { $unwind: { - path: '$project', + path: "$project", preserveNullAndEmptyArrays: true, }, }, { $group: { - _id: '$project.category', + _id: "$project.category", effort: { - $sum: '$effort', + $sum: "$effort", }, }, }, @@ -825,7 +925,7 @@ const dashboardhelper = function () { $project: { _id: 1, timeSpent_hrs: { - $divide: ['$effort', 3600], + $divide: ["$effort", 3600], }, }, }, diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js index 3826aa8ed..eac0a71a1 100644 --- a/src/helpers/reporthelper.js +++ b/src/helpers/reporthelper.js @@ -121,7 +121,13 @@ const reporthelper = function () { }, }, teamCode: { - $ifNull: ['$teamCode', ''], + $ifNull: ["$teamCode", ""], + }, + timeOffFrom: { + $ifNull: ["$timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$timeOffTill", null], }, role: 1, weeklySummaries: { diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index 800d1ee6b..372c960dd 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -1,149 +1,223 @@ -const moment = require('moment-timezone'); -const mongoose = require('mongoose'); -const userProfile = require('../models/userProfile'); -const timeentry = require('../models/timeentry'); -const myTeam = require('../helpers/helperModels/myTeam'); -const team = require('../models/team'); -const Task = require('../models/task'); -const TaskNotification = require('../models/taskNotification'); -const Wbs = require('../models/wbs'); +const moment = require("moment-timezone"); +const mongoose = require("mongoose"); +const userProfile = require("../models/userProfile"); +const timeentry = require("../models/timeentry"); +const myTeam = require("../helpers/helperModels/myTeam"); +const team = require("../models/team"); +const Task = require("../models/task"); +const TaskNotification = require("../models/taskNotification"); +const Wbs = require("../models/wbs"); const taskHelper = function () { const getTasksForTeams = async function (userId) { const userid = mongoose.Types.ObjectId(userId); - const userById = await userProfile.findOne({ _id: userid, isActive: true }, { - role: 1, firstName: 1, lastName: 1, role: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); + const userById = await userProfile + .findOne( + { _id: userid, isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + role: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); if (userById == null) return null; const userRole = userById.role; 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"); - let teamMemberIds = [userid]; - let teamMembers = []; + let teamMemberIds = [userid]; + let teamMembers = []; - if (userRole != 'Administrator' && userRole != 'Owner' && userRole != 'Core Team') // Manager , Mentor , Volunteer ... , Show only team members - { - const teamsResult = await team.find({ 'members.userId': { $in: [userid] } }, { members: 1 }) - .then(res => res).catch((e) => {}); + if ( + userRole != "Administrator" && + userRole != "Owner" && + userRole != "Core Team" + ) { + // Manager , Mentor , Volunteer ... , Show only team members + const teamsResult = await team + .find({ "members.userId": { $in: [userid] } }, { members: 1 }) + .then((res) => res) + .catch((e) => {}); - teamsResult.map((_myTeam) => { - _myTeam.members.map((teamMember) => { - if (!teamMember.userId.equals(userid)) teamMemberIds.push(teamMember.userId); - }); - }); + teamsResult.map((_myTeam) => { + _myTeam.members.map((teamMember) => { + if (!teamMember.userId.equals(userid)) + teamMemberIds.push(teamMember.userId); + }); + }); + teamsResult.map((_myTeam) => { + _myTeam.members.map((teamMember) => { + if (!teamMember.userId.equals(userid)) + teamMemberIds.push(teamMember.userId); + }); + }); - teamMembers = await userProfile.find({ _id: { $in: teamMemberIds }, isActive: true }, - { - role: 1, firstName: 1, lastName: 1, weeklycommittedHours: 1, -}) - .then(res => res).catch((e) => {}); - } else if (userRole == 'Administrator') { // All users except Owner and Core Team - const excludedRoles = ['Core Team', 'Owner']; - teamMembers = await userProfile.find({ isActive: true, role: { $nin: excludedRoles } }, - { - role: 1, firstName: 1, lastName: 1, weeklycommittedHours: 1, -}) - .then(res => res).catch((e) => {}); - } else { // 'Core Team', 'Owner' //All users - teamMembers = await userProfile.find({ isActive: true }, - { - role: 1, firstName: 1, lastName: 1, weeklycommittedHours: 1, -}) - .then(res => res).catch((e) => {}); - } + teamMembers = await userProfile + .find( + { _id: { $in: teamMemberIds }, isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else if (userRole == "Administrator") { + // All users except Owner and Core Team + const excludedRoles = ["Core Team", "Owner"]; + teamMembers = await userProfile + .find( + { isActive: true, role: { $nin: excludedRoles } }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else { + // 'Core Team', 'Owner' //All users + teamMembers = await userProfile + .find( + { isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } - teamMemberIds = teamMembers.map(member => member._id); + teamMemberIds = teamMembers.map((member) => member._id); - const timeEntries = await timeentry.find({ - dateOfWork: { - $gte: pdtstart, - $lte: pdtend, - }, - personId: { $in: teamMemberIds }, - }); + const timeEntries = await timeentry.find({ + dateOfWork: { + $gte: pdtstart, + $lte: pdtend, + }, + personId: { $in: teamMemberIds }, + }); - const timeEntryByPerson = {}; - timeEntries.map((timeEntry) => { - const personIdStr = timeEntry.personId.toString(); + const timeEntryByPerson = {}; + timeEntries.map((timeEntry) => { + const personIdStr = timeEntry.personId.toString(); - if (timeEntryByPerson[personIdStr] == null) { timeEntryByPerson[personIdStr] = { tangibleSeconds: 0, intangibleSeconds: 0, totalSeconds: 0 }; } + if (timeEntryByPerson[personIdStr] == null) { + timeEntryByPerson[personIdStr] = { + tangibleSeconds: 0, + intangibleSeconds: 0, + totalSeconds: 0, + }; + } - if (timeEntry.isTangible === true) { - timeEntryByPerson[personIdStr].tangibleSeconds += timeEntry.totalSeconds; - } - timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; - }); + if (timeEntry.isTangible === true) { + timeEntryByPerson[personIdStr].tangibleSeconds += + timeEntry.totalSeconds; + } + timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; + }); - const teamMemberTasks = await Task.find({ 'resources.userID': { $in: teamMemberIds } }, { 'resources.profilePic': 0 }) - .populate({ - path: 'wbsId', - select: 'projectId', - }); - const teamMemberTaskIds = teamMemberTasks.map(task => task._id); - const teamMemberTaskNotifications = await TaskNotification.find({ taskId: { $in: teamMemberTaskIds } }); + const teamMemberTasks = await Task.find( + { "resources.userID": { $in: teamMemberIds } }, + { "resources.profilePic": 0 } + ).populate({ + path: "wbsId", + select: "projectId", + }); + const teamMemberTaskIds = teamMemberTasks.map((task) => task._id); + const teamMemberTaskNotifications = await TaskNotification.find({ + taskId: { $in: teamMemberTaskIds }, + }); - const taskNotificationByTaskNdUser = []; - teamMemberTaskNotifications.map((teamMemberTaskNotification) => { - const taskIdStr = teamMemberTaskNotification.taskId.toString(); - const userIdStr = teamMemberTaskNotification.userId.toString(); - const taskNdUserID = `${taskIdStr},${userIdStr}`; + const taskNotificationByTaskNdUser = []; + teamMemberTaskNotifications.map((teamMemberTaskNotification) => { + const taskIdStr = teamMemberTaskNotification.taskId.toString(); + const userIdStr = teamMemberTaskNotification.userId.toString(); + const taskNdUserID = `${taskIdStr},${userIdStr}`; - if (taskNotificationByTaskNdUser[taskNdUserID]) { - taskNotificationByTaskNdUser[taskNdUserID].push(teamMemberTaskNotification); - } else { - taskNotificationByTaskNdUser[taskNdUserID] = [teamMemberTaskNotification]; - } - }); + if (taskNotificationByTaskNdUser[taskNdUserID]) { + taskNotificationByTaskNdUser[taskNdUserID].push( + teamMemberTaskNotification + ); + } else { + taskNotificationByTaskNdUser[taskNdUserID] = [ + teamMemberTaskNotification, + ]; + } + }); - const taskByPerson = []; + const taskByPerson = []; - teamMemberTasks.map((teamMemberTask) => { - const projId = teamMemberTask.wbsId?.projectId; - const _teamMemberTask = { ...teamMemberTask._doc }; - _teamMemberTask.projectId = projId; - const taskIdStr = _teamMemberTask._id.toString(); + teamMemberTasks.map((teamMemberTask) => { + const projId = teamMemberTask.wbsId?.projectId; + const _teamMemberTask = { ...teamMemberTask._doc }; + _teamMemberTask.projectId = projId; + const taskIdStr = _teamMemberTask._id.toString(); - teamMemberTask.resources.map((resource) => { - const resourceIdStr = resource.userID.toString(); - const taskNdUserID = `${taskIdStr},${resourceIdStr}`; - _teamMemberTask.taskNotifications = taskNotificationByTaskNdUser[taskNdUserID] || []; - if (taskByPerson[resourceIdStr]) { - taskByPerson[resourceIdStr].push(_teamMemberTask); - } else { - taskByPerson[resourceIdStr] = [_teamMemberTask]; - } - }); + teamMemberTask.resources.map((resource) => { + const resourceIdStr = resource.userID.toString(); + const taskNdUserID = `${taskIdStr},${resourceIdStr}`; + _teamMemberTask.taskNotifications = + taskNotificationByTaskNdUser[taskNdUserID] || []; + if (taskByPerson[resourceIdStr]) { + taskByPerson[resourceIdStr].push(_teamMemberTask); + } else { + taskByPerson[resourceIdStr] = [_teamMemberTask]; + } }); - + }); const teamMemberTasksData = []; teamMembers.map((teamMember) => { - const obj = { - personId: teamMember._id, - role: teamMember.role, - name: `${teamMember.firstName } ${ teamMember.lastName}`, - weeklycommittedHours: teamMember.weeklycommittedHours, - totaltangibletime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / 3600) || 0), - totaltime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600) || 0), - tasks: taskByPerson[teamMember._id.toString()] || [], - }; - teamMemberTasksData.push(obj); + const obj = { + personId: teamMember._id, + role: teamMember.role, + name: `${teamMember.firstName} ${teamMember.lastName}`, + weeklycommittedHours: teamMember.weeklycommittedHours, + totaltangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + 3600 || 0, + totaltime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 || + 0, + tasks: taskByPerson[teamMember._id.toString()] || [], + timeOffFrom: teamMember.timeOffFrom || null, + timeOffTill: teamMember.timeOffTill || null, + }; + teamMemberTasksData.push(obj); }); - return teamMemberTasksData; - // return myteam.aggregate([ // { // $match: { @@ -429,13 +503,13 @@ const taskHelper = function () { }; const getTasksForSingleUser = function (userId) { 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 userProfile.aggregate([ { $match: { @@ -444,31 +518,33 @@ const taskHelper = function () { }, { $project: { - personId: '$_id', - role: '$role', + personId: "$_id", + role: "$role", name: { - $concat: [ - '$firstName', - ' ', - '$lastName', - ], + $concat: ["$firstName", " ", "$lastName"], }, weeklycommittedHours: { $sum: [ - '$weeklycommittedHours', + "$weeklycommittedHours", { - $ifNull: ['$missedHours', 0], + $ifNull: ["$missedHours", 0], }, ], }, + timeOffFrom: { + $ifNull: ["$timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$timeOffTill", null], + }, }, }, { $lookup: { - from: 'timeEntries', - localField: 'personId', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "personId", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -476,21 +552,23 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, role: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, { - $in: ['$$timeentry.entryType', ['default', null]], + $in: ["$$timeentry.entryType", ["default", null]], }, ], }, @@ -500,7 +578,7 @@ const taskHelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -509,22 +587,24 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, role: 1, totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, isTangible: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.isTangible', + "$timeEntryData.isTangible", false, ], }, @@ -535,9 +615,9 @@ const taskHelper = function () { tangibletime: { $cond: [ { - $eq: ['$isTangible', true], + $eq: ["$isTangible", true], }, - '$totalSeconds', + "$totalSeconds", 0, ], }, @@ -546,40 +626,44 @@ const taskHelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', - name: '$name', - role: '$role', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", + timeOffFrom: "$timeOffFrom", + timeOffTill: "$timeOffTill", + name: "$name", + role: "$role", }, totalSeconds: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, tangibletime: { - $sum: '$tangibletime', + $sum: "$tangibletime", }, }, }, { $project: { _id: 0, - personId: '$_id.personId', - name: '$_id.name', - weeklycommittedHours: '$_id.weeklycommittedHours', - role: '$_id.role', + personId: "$_id.personId", + name: "$_id.name", + weeklycommittedHours: "$_id.weeklycommittedHours", + timeOffFrom: "$_id.timeOffFrom", + timeOffTill: "$_id.timeOffTill", + role: "$_id.role", totaltime_hrs: { - $divide: ['$totalSeconds', 3600], + $divide: ["$totalSeconds", 3600], }, totaltangibletime_hrs: { - $divide: ['$tangibletime', 3600], + $divide: ["$tangibletime", 3600], }, }, }, { $lookup: { - from: 'tasks', - localField: 'personId', - foreignField: 'resources.userID', - as: 'tasks', + from: "tasks", + localField: "personId", + foreignField: "resources.userID", + as: "tasks", }, }, { @@ -593,25 +677,25 @@ const taskHelper = function () { }, { $unwind: { - path: '$tasks', + path: "$tasks", preserveNullAndEmptyArrays: true, }, }, { $lookup: { - from: 'wbs', - localField: 'tasks.wbsId', - foreignField: '_id', - as: 'projectId', + from: "wbs", + localField: "tasks.wbsId", + foreignField: "_id", + as: "projectId", }, }, { $addFields: { - 'tasks.projectId': { + "tasks.projectId": { $cond: [ - { $ne: ['$projectId', []] }, - { $arrayElemAt: ['$projectId', 0] }, - '$tasks.projectId', + { $ne: ["$projectId", []] }, + { $arrayElemAt: ["$projectId", 0] }, + "$tasks.projectId", ], }, }, @@ -633,40 +717,40 @@ const taskHelper = function () { }, { $addFields: { - 'tasks.projectId': '$tasks.projectId.projectId', + "tasks.projectId": "$tasks.projectId.projectId", }, }, { $lookup: { - from: 'taskNotifications', - localField: 'tasks._id', - foreignField: 'taskId', - as: 'tasks.taskNotifications', + from: "taskNotifications", + localField: "tasks._id", + foreignField: "taskId", + as: "tasks.taskNotifications", }, }, { $group: { - _id: '$personId', - tasks: { $push: '$tasks' }, + _id: "$personId", + tasks: { $push: "$tasks" }, data: { - $first: '$$ROOT', + $first: "$$ROOT", }, }, }, { $addFields: { - 'data.tasks': { + "data.tasks": { $filter: { - input: '$tasks', - as: 'task', - cond: { $ne: ['$$task', {}] }, + input: "$tasks", + as: "task", + cond: { $ne: ["$$task", {}] }, }, }, }, }, { $replaceRoot: { - newRoot: '$data', + newRoot: "$data", }, }, ]); @@ -674,7 +758,7 @@ const taskHelper = function () { const getUserProfileFirstAndLastName = function (userId) { return userProfile.findById(userId).then((results) => { if (!results) { - return ' '; + return " "; } return `${results.firstName} ${results.lastName}`; }); diff --git a/src/models/userProfile.js b/src/models/userProfile.js index 8a8de2e18..aaa3923f5 100644 --- a/src/models/userProfile.js +++ b/src/models/userProfile.js @@ -1,9 +1,9 @@ -const mongoose = require('mongoose'); -const moment = require('moment-timezone'); +const mongoose = require("mongoose"); +const moment = require("moment-timezone"); const { Schema } = mongoose; -const validate = require('mongoose-validator'); -const bcrypt = require('bcryptjs'); +const validate = require("mongoose-validator"); +const bcrypt = require("bcryptjs"); const SALT_ROUNDS = 10; const nextDay = new Date(); @@ -15,11 +15,12 @@ const userProfileSchema = new Schema({ required: true, validate: { validator(v) { - const passwordregex = /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; + const passwordregex = + /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; return passwordregex.test(v); }, message: - '{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.', + "{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.", }, }, isActive: { type: Boolean, required: true, default: true }, @@ -47,7 +48,9 @@ const userProfileSchema = new Schema({ type: String, required: true, unique: true, - validate: [validate({ validator: 'isEmail', message: 'Email address is invalid' })], + validate: [ + validate({ validator: "isEmail", message: "Email address is invalid" }), + ], }, weeklycommittedHours: { type: Number, default: 10 }, weeklycommittedHoursHistory: [ @@ -60,13 +63,15 @@ const userProfileSchema = new Schema({ createdDate: { type: Date, required: true, default: nextDay }, lastModifiedDate: { type: Date, required: true, default: Date.now() }, reactivationDate: { type: Date }, - personalLinks: [{ _id: Schema.Types.ObjectId, Name: String, Link: { type: String } }], + personalLinks: [ + { _id: Schema.Types.ObjectId, Name: String, Link: { type: String } }, + ], adminLinks: [{ _id: Schema.Types.ObjectId, Name: String, Link: String }], - teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'team' }], - projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'project' }], + teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: "team" }], + projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: "project" }], badgeCollection: [ { - badge: { type: mongoose.SchemaTypes.ObjectId, ref: 'badge' }, + badge: { type: mongoose.SchemaTypes.ObjectId, ref: "badge" }, count: { type: Number, default: 0 }, earnedDate: { type: Array, default: [] }, lastModified: { type: Date, required: true, default: Date.now() }, @@ -79,20 +84,29 @@ const userProfileSchema = new Schema({ ], profilePic: { type: String }, infringements: [ - { date: { type: String, required: true }, description: { type: String, required: true } }, + { + date: { type: String, required: true }, + description: { type: String, required: true }, + }, ], location: { - userProvided: { type: String, default: '' }, + userProvided: { type: String, default: "" }, coords: { - lat: { type: Number, default: '' }, - lng: { type: Number, default: '' }, + lat: { type: Number, default: "" }, + lng: { type: Number, default: "" }, }, - country: { type: String, default: '' }, - city: { type: String, default: '' }, - + country: { type: String, default: "" }, + city: { type: String, default: "" }, }, oldInfringements: [ - { date: { type: String, required: true }, description: { type: String, required: true } }, + { + date: { type: String, required: true }, + description: { type: String, required: true }, + }, + { + date: { type: String, required: true }, + description: { type: String, required: true }, + }, ], privacySettings: { blueSquares: { type: Boolean, default: true }, @@ -104,7 +118,7 @@ const userProfileSchema = new Schema({ dueDate: { type: Date, required: true, - default: moment().tz('America/Los_Angeles').endOf('week'), + default: moment().tz("America/Los_Angeles").endOf("week"), }, summary: { type: String }, uploadDate: { type: Date }, @@ -134,17 +148,17 @@ const userProfileSchema = new Schema({ category: { type: String, enum: [ - 'Food', - 'Energy', - 'Housing', - 'Education', - 'Society', - 'Economics', - 'Stewardship', - 'Other', - 'Unspecified', + "Food", + "Energy", + "Housing", + "Education", + "Society", + "Economics", + "Stewardship", + "Other", + "Unspecified", ], - default: 'Other', + default: "Other", }, hrs: { type: Number, default: 0 }, }, @@ -152,48 +166,58 @@ const userProfileSchema = new Schema({ savedTangibleHrs: [Number], timeEntryEditHistory: [ { - date: { type: Date, required: true, default: moment().tz('America/Los_Angeles').toDate() }, + date: { + type: Date, + required: true, + default: moment().tz("America/Los_Angeles").toDate(), + }, initialSeconds: { type: Number, required: true }, newSeconds: { type: Number, required: true }, }, ], weeklySummaryNotReq: { type: Boolean, default: false }, - timeZone: { type: String, required: true, default: 'America/Los_Angeles' }, + timeZone: { type: String, required: true, default: "America/Los_Angeles" }, isVisible: { type: Boolean, default: false }, weeklySummaryOption: { type: String }, - bioPosted: { type: String, default: 'default' }, + bioPosted: { type: String, default: "default" }, isFirstTimelog: { type: Boolean, default: true }, teamCode: { type: String, - default: '', + default: "", validate: { validator(v) { const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$|^$/; return teamCoderegex.test(v); }, - message: - 'Please enter a code in the format of A-AAA or AAAAA', + message: "Please enter a code in the format of A-AAA or AAAAA", }, }, infoCollections: [ { areaName: { type: String }, areaContent: { type: String }, - }], + }, + ], + timeOffFrom: { type: Date, default: undefined }, + timeOffTill: { type: Date, default: undefined }, }); -userProfileSchema.pre('save', function (next) { +userProfileSchema.pre("save", function (next) { const user = this; - if (!user.isModified('password')) return next(); + if (!user.isModified("password")) return next(); return bcrypt .genSalt(SALT_ROUNDS) - .then(result => bcrypt.hash(user.password, result)) + .then((result) => bcrypt.hash(user.password, result)) .then((hash) => { user.password = hash; return next(); }) - .catch(error => next(error)); + .catch((error) => next(error)); }); -module.exports = mongoose.model('userProfile', userProfileSchema, 'userProfiles'); +module.exports = mongoose.model( + "userProfile", + userProfileSchema, + "userProfiles" +);