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"
+);