Date: Thu, 14 Sep 2023 18:25:18 +0000
Subject: [PATCH 022/272] added error handling to easily deduce errors in
production
---
package-lock.json | 2743 +++++++++++++++++++-----
package.json | 7 +-
src/controllers/dashBoardController.js | 248 ++-
3 files changed, 2379 insertions(+), 619 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 5c6bd6db5..cdfa61193 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -115,12 +115,28 @@
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz",
- "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz",
+ "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==",
"requires": {
- "@babel/helper-explode-assignable-expression": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.22.15"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-compilation-targets": {
@@ -142,47 +158,229 @@
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.17.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz",
- "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.16.7",
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-function-name": "^7.16.7",
- "@babel/helper-member-expression-to-functions": "^7.16.7",
- "@babel/helper-optimise-call-expression": "^7.16.7",
- "@babel/helper-replace-supers": "^7.16.7",
- "@babel/helper-split-export-declaration": "^7.16.7"
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz",
+ "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-member-expression-to-functions": "^7.22.15",
+ "@babel/helper-optimise-call-expression": "^7.22.5",
+ "@babel/helper-replace-supers": "^7.22.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "semver": "^6.3.1"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "requires": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/highlight": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+ "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.22.16",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+ "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ }
}
},
"@babel/helper-create-regexp-features-plugin": {
- "version": "7.17.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz",
- "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz",
+ "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.16.7",
- "regexpu-core": "^5.0.1"
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "regexpu-core": "^5.3.1",
+ "semver": "^6.3.1"
+ },
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ }
}
},
"@babel/helper-define-polyfill-provider": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
- "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz",
+ "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==",
"requires": {
- "@babel/helper-compilation-targets": "^7.13.0",
- "@babel/helper-module-imports": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/traverse": "^7.13.0",
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-plugin-utils": "^7.22.5",
"debug": "^4.1.1",
"lodash.debounce": "^4.0.8",
- "resolve": "^1.14.2",
- "semver": "^6.1.2"
+ "resolve": "^1.14.2"
},
"dependencies": {
+ "@babel/compat-data": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+ "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
+ "requires": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+ "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
+ },
+ "browserslist": {
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.11"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001532",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
+ "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
+ },
+ "electron-to-chromium": {
+ "version": "1.4.513",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+ "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
+ },
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
@@ -194,14 +392,6 @@
"@babel/types": "^7.16.7"
}
},
- "@babel/helper-explode-assignable-expression": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz",
- "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==",
- "requires": {
- "@babel/types": "^7.16.7"
- }
- },
"@babel/helper-function-name": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
@@ -229,11 +419,28 @@
}
},
"@babel/helper-member-expression-to-functions": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz",
- "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz",
+ "integrity": "sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA==",
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.22.15"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-module-imports": {
@@ -260,11 +467,28 @@
}
},
"@babel/helper-optimise-call-expression": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz",
- "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
+ "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-plugin-utils": {
@@ -283,15 +507,20 @@
}
},
"@babel/helper-replace-supers": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz",
- "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==",
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz",
+ "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==",
"requires": {
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-member-expression-to-functions": "^7.16.7",
- "@babel/helper-optimise-call-expression": "^7.16.7",
- "@babel/traverse": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-member-expression-to-functions": "^7.22.5",
+ "@babel/helper-optimise-call-expression": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ }
}
},
"@babel/helper-simple-access": {
@@ -303,11 +532,28 @@
}
},
"@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz",
- "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
+ "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
"requires": {
- "@babel/types": "^7.16.0"
+ "@babel/types": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-split-export-declaration": {
@@ -318,6 +564,11 @@
"@babel/types": "^7.16.7"
}
},
+ "@babel/helper-string-parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
+ },
"@babel/helper-validator-identifier": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
@@ -378,165 +629,41 @@
"integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA=="
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz",
- "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz",
+ "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz",
- "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
- "@babel/plugin-proposal-optional-chaining": "^7.16.7"
- }
- },
- "@babel/plugin-proposal-async-generator-functions": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz",
- "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-remap-async-to-generator": "^7.16.8",
- "@babel/plugin-syntax-async-generators": "^7.8.4"
- }
- },
- "@babel/plugin-proposal-class-properties": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz",
- "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==",
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7"
- }
- },
- "@babel/plugin-proposal-class-static-block": {
- "version": "7.17.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz",
- "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz",
+ "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==",
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.17.6",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-class-static-block": "^7.14.5"
- }
- },
- "@babel/plugin-proposal-dynamic-import": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz",
- "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-export-namespace-from": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz",
- "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-json-strings": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz",
- "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-json-strings": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-logical-assignment-operators": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz",
- "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-nullish-coalescing-operator": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz",
- "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-numeric-separator": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz",
- "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4"
- }
- },
- "@babel/plugin-proposal-object-rest-spread": {
- "version": "7.17.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz",
- "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==",
- "requires": {
- "@babel/compat-data": "^7.17.0",
- "@babel/helper-compilation-targets": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.16.7"
- }
- },
- "@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz",
- "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-optional-chaining": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz",
- "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3"
- }
- },
- "@babel/plugin-proposal-private-methods": {
- "version": "7.16.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz",
- "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==",
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.16.10",
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/plugin-transform-optional-chaining": "^7.22.15"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-proposal-private-property-in-object": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz",
- "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.16.7",
- "@babel/helper-create-class-features-plugin": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
- }
- },
- "@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz",
- "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==",
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7"
- }
+ "version": "7.21.0-placeholder-for-preset-env.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
+ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w=="
},
"@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
@@ -578,6 +705,44 @@
"@babel/helper-plugin-utils": "^7.8.3"
}
},
+ "@babel/plugin-syntax-import-assertions": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz",
+ "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-syntax-import-attributes": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz",
+ "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
"@babel/plugin-syntax-json-strings": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
@@ -650,339 +815,1585 @@
"@babel/helper-plugin-utils": "^7.14.5"
}
},
- "@babel/plugin-transform-arrow-functions": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz",
- "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
- }
- },
- "@babel/plugin-transform-async-to-generator": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz",
- "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==",
- "requires": {
- "@babel/helper-module-imports": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-remap-async-to-generator": "^7.16.8"
- }
- },
- "@babel/plugin-transform-block-scoped-functions": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz",
- "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==",
+ "@babel/plugin-syntax-unicode-sets-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
+ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-block-scoping": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz",
- "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==",
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz",
+ "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-classes": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz",
- "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==",
+ "@babel/plugin-transform-async-generator-functions": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz",
+ "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.16.7",
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-function-name": "^7.16.7",
- "@babel/helper-optimise-call-expression": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-replace-supers": "^7.16.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "globals": "^11.1.0"
- }
- },
- "@babel/plugin-transform-computed-properties": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz",
- "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.9",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "requires": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
+ "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-wrap-function": "^7.22.17"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
+ "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
+ "requires": {
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.22.17"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+ "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.22.16",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+ "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz",
+ "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-remap-async-to-generator": "^7.16.8"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz",
+ "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz",
+ "integrity": "sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-class-properties": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz",
+ "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-class-static-block": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz",
+ "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.22.11",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz",
+ "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-compilation-targets": "^7.22.15",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-optimise-call-expression": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-replace-supers": "^7.22.9",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "globals": "^11.1.0"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+ "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
+ "requires": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "requires": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+ "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
+ },
+ "@babel/highlight": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+ "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.22.16",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+ "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "browserslist": {
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.11"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001532",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
+ "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
+ },
+ "electron-to-chromium": {
+ "version": "1.4.513",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+ "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ }
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz",
+ "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/template": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/highlight": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+ "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.22.16",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+ "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.17.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz",
- "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz",
+ "integrity": "sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-dotall-regex": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz",
- "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz",
+ "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-duplicate-keys": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz",
- "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz",
+ "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-dynamic-import": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz",
+ "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-exponentiation-operator": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz",
- "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz",
+ "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==",
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-export-namespace-from": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz",
+ "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==",
"requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz",
- "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz",
+ "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz",
- "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz",
+ "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==",
"requires": {
- "@babel/helper-compilation-targets": "^7.16.7",
- "@babel/helper-function-name": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-compilation-targets": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+ "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
+ "requires": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "requires": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+ "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
+ },
+ "@babel/highlight": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+ "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.22.16",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+ "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "browserslist": {
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.11"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001532",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
+ "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
+ },
+ "electron-to-chromium": {
+ "version": "1.4.513",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+ "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ }
+ }
+ },
+ "@babel/plugin-transform-json-strings": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz",
+ "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-literals": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz",
- "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz",
+ "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz",
+ "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-member-expression-literals": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz",
- "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz",
+ "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz",
+ "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+ "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+ "requires": {
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
+ "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.15"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz",
+ "integrity": "sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.22.15",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-simple-access": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+ "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+ "requires": {
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
+ "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.15"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz",
+ "integrity": "sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==",
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-module-transforms": "^7.22.9",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+ "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+ "requires": {
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
+ "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.15"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz",
+ "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+ "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+ "requires": {
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
+ "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.15"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz",
+ "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz",
+ "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz",
+ "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-modules-amd": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz",
- "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==",
+ "@babel/plugin-transform-numeric-separator": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz",
+ "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==",
"requires": {
- "@babel/helper-module-transforms": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "babel-plugin-dynamic-import-node": "^2.3.3"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-modules-commonjs": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
- "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
+ "@babel/plugin-transform-object-rest-spread": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz",
+ "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==",
"requires": {
- "@babel/helper-module-transforms": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-simple-access": "^7.16.7",
- "babel-plugin-dynamic-import-node": "^2.3.3"
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.15",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.22.15"
+ },
+ "dependencies": {
+ "@babel/compat-data": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+ "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
+ "requires": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+ "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
+ },
+ "browserslist": {
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.11"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001532",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
+ "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
+ },
+ "electron-to-chromium": {
+ "version": "1.4.513",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+ "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ }
}
},
- "@babel/plugin-transform-modules-systemjs": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz",
- "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==",
+ "@babel/plugin-transform-object-super": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz",
+ "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==",
"requires": {
- "@babel/helper-hoist-variables": "^7.16.7",
- "@babel/helper-module-transforms": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-validator-identifier": "^7.16.7",
- "babel-plugin-dynamic-import-node": "^2.3.3"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-replace-supers": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-modules-umd": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz",
- "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==",
+ "@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz",
+ "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==",
"requires": {
- "@babel/helper-module-transforms": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz",
- "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==",
+ "@babel/plugin-transform-optional-chaining": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.15.tgz",
+ "integrity": "sha512-ngQ2tBhq5vvSJw2Q2Z9i7ealNkpDMU0rGWnHPKqRZO0tzZ5tlaoz4hDvhXioOoaE0X2vfNss1djwg0DXlfu30A==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-new-target": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz",
- "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==",
+ "@babel/plugin-transform-parameters": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz",
+ "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-object-super": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz",
- "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==",
+ "@babel/plugin-transform-private-methods": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz",
+ "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-replace-supers": "^7.16.7"
+ "@babel/helper-create-class-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/plugin-transform-parameters": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz",
- "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==",
+ "@babel/plugin-transform-private-property-in-object": {
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz",
+ "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-create-class-features-plugin": "^7.22.11",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ },
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/plugin-transform-property-literals": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz",
- "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz",
+ "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-regenerator": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz",
- "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz",
+ "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==",
"requires": {
- "regenerator-transform": "^0.14.2"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "regenerator-transform": "^0.15.2"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-reserved-words": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz",
- "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz",
+ "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-runtime": {
- "version": "7.17.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz",
- "integrity": "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==",
- "requires": {
- "@babel/helper-module-imports": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "babel-plugin-polyfill-corejs2": "^0.3.0",
- "babel-plugin-polyfill-corejs3": "^0.5.0",
- "babel-plugin-polyfill-regenerator": "^0.3.0",
- "semver": "^6.3.0"
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.15.tgz",
+ "integrity": "sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "babel-plugin-polyfill-corejs2": "^0.4.5",
+ "babel-plugin-polyfill-corejs3": "^0.8.3",
+ "babel-plugin-polyfill-regenerator": "^0.5.2",
+ "semver": "^6.3.1"
},
"dependencies": {
+ "@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+ "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+ "requires": {
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
"@babel/plugin-transform-shorthand-properties": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz",
- "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz",
+ "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-spread": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz",
- "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz",
+ "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0"
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-sticky-regex": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz",
- "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz",
+ "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-template-literals": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz",
- "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz",
+ "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-typeof-symbol": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz",
- "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz",
+ "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-unicode-escapes": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz",
- "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz",
+ "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/plugin-transform-unicode-property-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz",
+ "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==",
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
"@babel/plugin-transform-unicode-regex": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz",
- "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz",
+ "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
}
},
- "@babel/preset-env": {
- "version": "7.16.11",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz",
- "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==",
+ "@babel/plugin-transform-unicode-sets-regex": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz",
+ "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==",
"requires": {
- "@babel/compat-data": "^7.16.8",
- "@babel/helper-compilation-targets": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-validator-option": "^7.16.7",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7",
- "@babel/plugin-proposal-async-generator-functions": "^7.16.8",
- "@babel/plugin-proposal-class-properties": "^7.16.7",
- "@babel/plugin-proposal-class-static-block": "^7.16.7",
- "@babel/plugin-proposal-dynamic-import": "^7.16.7",
- "@babel/plugin-proposal-export-namespace-from": "^7.16.7",
- "@babel/plugin-proposal-json-strings": "^7.16.7",
- "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7",
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",
- "@babel/plugin-proposal-numeric-separator": "^7.16.7",
- "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
- "@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
- "@babel/plugin-proposal-optional-chaining": "^7.16.7",
- "@babel/plugin-proposal-private-methods": "^7.16.11",
- "@babel/plugin-proposal-private-property-in-object": "^7.16.7",
- "@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
+ "@babel/helper-create-regexp-features-plugin": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ }
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.15.tgz",
+ "integrity": "sha512-tZFHr54GBkHk6hQuVA8w4Fmq+MSPsfvMG0vPnOYyTnJpyfMqybL8/MbNCPRT9zc2KBO2pe4tq15g6Uno4Jpoag==",
+ "requires": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.15",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-validator-option": "^7.22.15",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
"@babel/plugin-syntax-async-generators": "^7.8.4",
"@babel/plugin-syntax-class-properties": "^7.12.13",
"@babel/plugin-syntax-class-static-block": "^7.14.5",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-import-assertions": "^7.22.5",
+ "@babel/plugin-syntax-import-attributes": "^7.22.5",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
"@babel/plugin-syntax-json-strings": "^7.8.3",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
@@ -992,62 +2403,252 @@
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
"@babel/plugin-syntax-private-property-in-object": "^7.14.5",
"@babel/plugin-syntax-top-level-await": "^7.14.5",
- "@babel/plugin-transform-arrow-functions": "^7.16.7",
- "@babel/plugin-transform-async-to-generator": "^7.16.8",
- "@babel/plugin-transform-block-scoped-functions": "^7.16.7",
- "@babel/plugin-transform-block-scoping": "^7.16.7",
- "@babel/plugin-transform-classes": "^7.16.7",
- "@babel/plugin-transform-computed-properties": "^7.16.7",
- "@babel/plugin-transform-destructuring": "^7.16.7",
- "@babel/plugin-transform-dotall-regex": "^7.16.7",
- "@babel/plugin-transform-duplicate-keys": "^7.16.7",
- "@babel/plugin-transform-exponentiation-operator": "^7.16.7",
- "@babel/plugin-transform-for-of": "^7.16.7",
- "@babel/plugin-transform-function-name": "^7.16.7",
- "@babel/plugin-transform-literals": "^7.16.7",
- "@babel/plugin-transform-member-expression-literals": "^7.16.7",
- "@babel/plugin-transform-modules-amd": "^7.16.7",
- "@babel/plugin-transform-modules-commonjs": "^7.16.8",
- "@babel/plugin-transform-modules-systemjs": "^7.16.7",
- "@babel/plugin-transform-modules-umd": "^7.16.7",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8",
- "@babel/plugin-transform-new-target": "^7.16.7",
- "@babel/plugin-transform-object-super": "^7.16.7",
- "@babel/plugin-transform-parameters": "^7.16.7",
- "@babel/plugin-transform-property-literals": "^7.16.7",
- "@babel/plugin-transform-regenerator": "^7.16.7",
- "@babel/plugin-transform-reserved-words": "^7.16.7",
- "@babel/plugin-transform-shorthand-properties": "^7.16.7",
- "@babel/plugin-transform-spread": "^7.16.7",
- "@babel/plugin-transform-sticky-regex": "^7.16.7",
- "@babel/plugin-transform-template-literals": "^7.16.7",
- "@babel/plugin-transform-typeof-symbol": "^7.16.7",
- "@babel/plugin-transform-unicode-escapes": "^7.16.7",
- "@babel/plugin-transform-unicode-regex": "^7.16.7",
- "@babel/preset-modules": "^0.1.5",
- "@babel/types": "^7.16.8",
- "babel-plugin-polyfill-corejs2": "^0.3.0",
- "babel-plugin-polyfill-corejs3": "^0.5.0",
- "babel-plugin-polyfill-regenerator": "^0.3.0",
- "core-js-compat": "^3.20.2",
- "semver": "^6.3.0"
+ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
+ "@babel/plugin-transform-arrow-functions": "^7.22.5",
+ "@babel/plugin-transform-async-generator-functions": "^7.22.15",
+ "@babel/plugin-transform-async-to-generator": "^7.22.5",
+ "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
+ "@babel/plugin-transform-block-scoping": "^7.22.15",
+ "@babel/plugin-transform-class-properties": "^7.22.5",
+ "@babel/plugin-transform-class-static-block": "^7.22.11",
+ "@babel/plugin-transform-classes": "^7.22.15",
+ "@babel/plugin-transform-computed-properties": "^7.22.5",
+ "@babel/plugin-transform-destructuring": "^7.22.15",
+ "@babel/plugin-transform-dotall-regex": "^7.22.5",
+ "@babel/plugin-transform-duplicate-keys": "^7.22.5",
+ "@babel/plugin-transform-dynamic-import": "^7.22.11",
+ "@babel/plugin-transform-exponentiation-operator": "^7.22.5",
+ "@babel/plugin-transform-export-namespace-from": "^7.22.11",
+ "@babel/plugin-transform-for-of": "^7.22.15",
+ "@babel/plugin-transform-function-name": "^7.22.5",
+ "@babel/plugin-transform-json-strings": "^7.22.11",
+ "@babel/plugin-transform-literals": "^7.22.5",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.22.11",
+ "@babel/plugin-transform-member-expression-literals": "^7.22.5",
+ "@babel/plugin-transform-modules-amd": "^7.22.5",
+ "@babel/plugin-transform-modules-commonjs": "^7.22.15",
+ "@babel/plugin-transform-modules-systemjs": "^7.22.11",
+ "@babel/plugin-transform-modules-umd": "^7.22.5",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
+ "@babel/plugin-transform-new-target": "^7.22.5",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11",
+ "@babel/plugin-transform-numeric-separator": "^7.22.11",
+ "@babel/plugin-transform-object-rest-spread": "^7.22.15",
+ "@babel/plugin-transform-object-super": "^7.22.5",
+ "@babel/plugin-transform-optional-catch-binding": "^7.22.11",
+ "@babel/plugin-transform-optional-chaining": "^7.22.15",
+ "@babel/plugin-transform-parameters": "^7.22.15",
+ "@babel/plugin-transform-private-methods": "^7.22.5",
+ "@babel/plugin-transform-private-property-in-object": "^7.22.11",
+ "@babel/plugin-transform-property-literals": "^7.22.5",
+ "@babel/plugin-transform-regenerator": "^7.22.10",
+ "@babel/plugin-transform-reserved-words": "^7.22.5",
+ "@babel/plugin-transform-shorthand-properties": "^7.22.5",
+ "@babel/plugin-transform-spread": "^7.22.5",
+ "@babel/plugin-transform-sticky-regex": "^7.22.5",
+ "@babel/plugin-transform-template-literals": "^7.22.5",
+ "@babel/plugin-transform-typeof-symbol": "^7.22.5",
+ "@babel/plugin-transform-unicode-escapes": "^7.22.10",
+ "@babel/plugin-transform-unicode-property-regex": "^7.22.5",
+ "@babel/plugin-transform-unicode-regex": "^7.22.5",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "@babel/types": "^7.22.15",
+ "babel-plugin-polyfill-corejs2": "^0.4.5",
+ "babel-plugin-polyfill-corejs3": "^0.8.3",
+ "babel-plugin-polyfill-regenerator": "^0.5.2",
+ "core-js-compat": "^3.31.0",
+ "semver": "^6.3.1"
},
"dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+ "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
+ "requires": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
+ },
+ "@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "requires": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+ "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+ "requires": {
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
+ "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-wrap-function": "^7.22.17"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+ "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+ "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
+ "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
+ "requires": {
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.22.17"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+ "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.22.16",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+ "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz",
+ "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.22.5",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.5"
+ }
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/types": {
+ "version": "7.22.17",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+ "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.15",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "browserslist": {
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.11"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001532",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
+ "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
+ },
+ "electron-to-chromium": {
+ "version": "1.4.513",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+ "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
+ },
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
"@babel/preset-modules": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
- "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "version": "0.1.6-no-external-plugins",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
- "@babel/plugin-transform-dotall-regex": "^7.4.4",
"@babel/types": "^7.4.4",
"esutils": "^2.0.2"
}
@@ -1064,6 +2665,11 @@
"source-map-support": "^0.5.16"
}
},
+ "@babel/regjsgen": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
+ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
+ },
"@babel/runtime": {
"version": "7.17.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
@@ -2516,14 +4122,6 @@
}
}
},
- "babel-plugin-dynamic-import-node": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
- "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
- "requires": {
- "object.assign": "^4.1.0"
- }
- },
"babel-plugin-module-resolver": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz",
@@ -2585,37 +4183,42 @@
}
},
"babel-plugin-polyfill-corejs2": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
- "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz",
+ "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==",
"requires": {
- "@babel/compat-data": "^7.13.11",
- "@babel/helper-define-polyfill-provider": "^0.3.1",
- "semver": "^6.1.1"
+ "@babel/compat-data": "^7.22.6",
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
+ "semver": "^6.3.1"
},
"dependencies": {
+ "@babel/compat-data": {
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
+ },
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
"babel-plugin-polyfill-corejs3": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz",
- "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==",
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz",
+ "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==",
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.3.1",
- "core-js-compat": "^3.21.0"
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
+ "core-js-compat": "^3.31.0"
}
},
"babel-plugin-polyfill-regenerator": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
- "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz",
+ "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==",
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.3.1"
+ "@babel/helper-define-polyfill-provider": "^0.4.2"
}
},
"balanced-match": {
@@ -2973,18 +4576,38 @@
"integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig=="
},
"core-js-compat": {
- "version": "3.21.1",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz",
- "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==",
+ "version": "3.32.2",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
+ "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
"requires": {
- "browserslist": "^4.19.1",
- "semver": "7.0.0"
+ "browserslist": "^4.21.10"
},
"dependencies": {
- "semver": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
- "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="
+ "browserslist": {
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.11"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001532",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
+ "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
+ },
+ "electron-to-chromium": {
+ "version": "1.4.513",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+ "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
+ },
+ "node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
}
}
},
@@ -5104,9 +6727,9 @@
}
},
"semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"requires": {
"lru-cache": "^6.0.0"
}
@@ -5397,7 +7020,7 @@
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"lodash.merge": {
"version": "4.6.2",
@@ -5681,15 +7304,15 @@
}
},
"mongoose": {
- "version": "5.13.15",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz",
- "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==",
+ "version": "5.13.20",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.20.tgz",
+ "integrity": "sha512-TjGFa/XnJYt+wLmn8y9ssjyO2OhBMeEBtOHb9iJM16EWu2Du6L1Q6zSiEK2ziyYQM8agb4tumNIQFzqbxId7MA==",
"requires": {
"@types/bson": "1.x || 4.0.x",
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4",
"kareem": "2.3.2",
- "mongodb": "3.7.3",
+ "mongodb": "3.7.4",
"mongoose-legacy-pluralize": "1.0.2",
"mpath": "0.8.4",
"mquery": "3.2.5",
@@ -5701,6 +7324,29 @@
"sliced": "1.0.1"
},
"dependencies": {
+ "mongodb": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.4.tgz",
+ "integrity": "sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw==",
+ "requires": {
+ "bl": "^2.2.1",
+ "bson": "^1.1.4",
+ "denque": "^1.4.1",
+ "optional-require": "^1.1.8",
+ "safe-buffer": "^5.1.2",
+ "saslprep": "^1.0.0"
+ },
+ "dependencies": {
+ "optional-require": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
+ "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
+ "requires": {
+ "require-at": "^1.0.6"
+ }
+ }
+ }
+ },
"optional-require": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
@@ -6753,6 +8399,11 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
+ "prettier": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+ "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg=="
+ },
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -6865,9 +8516,9 @@
"integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="
},
"regenerate-unicode-properties": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz",
- "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==",
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz",
+ "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==",
"requires": {
"regenerate": "^1.4.2"
}
@@ -6878,9 +8529,9 @@
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"regenerator-transform": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
- "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
+ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
"requires": {
"@babel/runtime": "^7.8.4"
}
@@ -6914,27 +8565,22 @@
}
},
"regexpu-core": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz",
- "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz",
+ "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
"requires": {
+ "@babel/regjsgen": "^0.8.0",
"regenerate": "^1.4.2",
- "regenerate-unicode-properties": "^10.0.1",
- "regjsgen": "^0.6.0",
- "regjsparser": "^0.8.2",
+ "regenerate-unicode-properties": "^10.1.0",
+ "regjsparser": "^0.9.1",
"unicode-match-property-ecmascript": "^2.0.0",
- "unicode-match-property-value-ecmascript": "^2.0.0"
+ "unicode-match-property-value-ecmascript": "^2.1.0"
}
},
- "regjsgen": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz",
- "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA=="
- },
"regjsparser": {
- "version": "0.8.4",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz",
- "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==",
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
+ "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
"requires": {
"jsesc": "~0.5.0"
},
@@ -6942,7 +8588,7 @@
"jsesc": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA=="
}
}
},
@@ -7831,20 +9477,29 @@
}
},
"unicode-match-property-value-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
- "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw=="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
+ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA=="
},
"unicode-property-aliases-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
- "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ=="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
+ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w=="
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
+ "update-browserslist-db": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
+ "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
diff --git a/package.json b/package.json
index f9387e933..509755c88 100644
--- a/package.json
+++ b/package.json
@@ -40,8 +40,8 @@
"@babel/core": "^7.10.2",
"@babel/node": "^7.14.9",
"@babel/plugin-transform-async-to-generator": "^7.10.1",
- "@babel/plugin-transform-runtime": "^7.10.1",
- "@babel/preset-env": "^7.10.2",
+ "@babel/plugin-transform-runtime": "^7.22.15",
+ "@babel/preset-env": "^7.22.15",
"@babel/runtime": "^7.10.2",
"@sentry/node": "^5.17.0",
"async-exit-hook": "^2.0.1",
@@ -58,11 +58,12 @@
"moment": "^2.29.4",
"moment-timezone": "^0.5.35",
"mongodb": "^3.7.3",
- "mongoose": "^5.13.15",
+ "mongoose": "^5.13.20",
"mongoose-validator": "^2.1.0",
"node-cache": "^5.1.2",
"node-datetime": "^2.0.3",
"nodemailer": "^6.4.16",
+ "prettier": "^3.0.3",
"redis": "^4.2.0",
"uuid": "^3.4.0",
"ws": "^8.8.1"
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 4bd05b91e..742bfe4d8 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -1,8 +1,8 @@
-const mongoose = require('mongoose');
-const path = require('path');
-const fs = require('fs/promises');
-const dashboardhelper = require('../helpers/dashboardhelper')();
-const emailSender = require('../utilities/emailSender');
+const mongoose = require("mongoose");
+const path = require("path");
+const fs = require("fs/promises");
+const dashboardhelper = require("../helpers/dashboardhelper")();
+const emailSender = require("../utilities/emailSender");
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -10,18 +10,26 @@ const dashboardcontroller = function () {
const snapshot = dashboardhelper.personaldetails(userId);
- snapshot.then((results) => { res.send(results).status(200); });
+ snapshot.then((results) => {
+ res.send(results).status(200);
+ });
};
const monthlydata = function (req, res) {
const userId = mongoose.Types.ObjectId(req.params.userId);
- const laborthismonth = dashboardhelper.laborthismonth(userId, req.params.fromDate, req.params.toDate);
+ const laborthismonth = dashboardhelper.laborthismonth(
+ userId,
+ req.params.fromDate,
+ req.params.toDate
+ );
laborthismonth.then((results) => {
if (!results || results.length === 0) {
- const emptyresult = [{
- projectName: '',
- timeSpent_hrs: 0,
- }];
+ const emptyresult = [
+ {
+ projectName: "",
+ timeSpent_hrs: 0,
+ },
+ ];
res.status(200).send(emptyresult);
return;
}
@@ -31,35 +39,54 @@ const dashboardcontroller = function () {
const weeklydata = function (req, res) {
const userId = mongoose.Types.ObjectId(req.params.userId);
- const laborthisweek = dashboardhelper.laborthisweek(userId, req.params.fromDate, req.params.toDate);
- laborthisweek.then((results) => { res.send(results).status(200); });
+ const laborthisweek = dashboardhelper.laborthisweek(
+ userId,
+ req.params.fromDate,
+ req.params.toDate
+ );
+ laborthisweek.then((results) => {
+ res.send(results).status(200);
+ });
};
-
const leaderboarddata = function (req, res) {
const userId = mongoose.Types.ObjectId(req.params.userId);
const leaderboard = dashboardhelper.getLeaderboard(userId);
- leaderboard.then((results) => {
- if (results.length > 0) {
- res.status(200).send(results);
- } else {
- const { getUserLaborData } = dashboardhelper;
- getUserLaborData(userId).then((r) => {
- res.status(200).send(r);
- });
- }
- })
- .catch(error => res.status(400).send(error));
+ leaderboard
+ .then((results) => {
+ if (results.length > 0) {
+ res.status(200).send(results);
+ } else {
+ const { getUserLaborData } = dashboardhelper;
+ getUserLaborData(userId).then((r) => {
+ res.status(200).send(r);
+ });
+ }
+ })
+ .catch((error) => res.status(400).send(error));
};
const orgData = function (req, res) {
const fullOrgData = dashboardhelper.getOrgData();
- fullOrgData.then((results) => { res.status(200).send(results[0]); })
- .catch(error => res.status(400).send(error));
+ fullOrgData
+ .then((results) => {
+ res.status(200).send(results[0]);
+ })
+ .catch((error) => res.status(400).send(error));
};
- const getBugReportEmailBody = function (firstName, lastName, title, environment, reproduction, expected, actual, visual, severity) {
+ const getBugReportEmailBody = function (
+ firstName,
+ lastName,
+ title,
+ environment,
+ reproduction,
+ expected,
+ actual,
+ visual,
+ severity
+ ) {
const text = `New Bug Report From ${firstName} ${lastName}:
[Feature Name] Bug Title:
${title}
@@ -83,43 +110,90 @@ const dashboardcontroller = function () {
const sendBugReport = function (req, res) {
const {
- firstName, lastName, title, environment, reproduction, expected, actual, visual, severity, email,
+ firstName,
+ lastName,
+ title,
+ environment,
+ reproduction,
+ expected,
+ actual,
+ visual,
+ severity,
+ email,
} = req.body;
- const emailBody = getBugReportEmailBody(firstName, lastName, title, environment, reproduction, expected, actual, visual, severity);
+ const emailBody = getBugReportEmailBody(
+ firstName,
+ lastName,
+ title,
+ environment,
+ reproduction,
+ expected,
+ actual,
+ visual,
+ severity
+ );
try {
emailSender(
- 'onecommunityglobal@gmail.com',
+ "onecommunityglobal@gmail.com",
`Bug Rport from ${firstName} ${lastName}`,
emailBody,
- email,
+ email
);
- res.status(200).send('Success');
+ res.status(200).send("Success");
} catch {
- res.status(500).send('Failed');
+ res.status(500).send("Failed");
}
};
- // read suggestion data from file
+
+ const getSuggestionFilePath = async () => {
+ // Define a base path based on the process.cwd()
+ const basePath = process.cwd();
+ console.log(basePath, "basePath");
+
+ // Define the relative path to the JSON file (adjust as needed)
+ const relativePath = "src/constants/suggestionModalData.json";
+
+ // Combine the base path and relative path to create the full path
+ const fullPath = path.join(basePath, relativePath);
+
+ return fullPath;
+ };
+
const readSuggestionFile = async () => {
- const filepath = path.join(process.cwd(), 'src', 'constants', 'suggestionModalData.json');
- let readfile = await fs.readFile(filepath).catch(err => console.log(err));
- readfile = JSON.parse(readfile);
- return readfile;
+ // Specify the absolute path to the JSON file
+ const filepath = await getSuggestionFilePath();
+
+ try {
+ // Check if the file exists
+ await fs.access(filepath);
+
+ // Read and parse the file
+ const readfile = await fs.readFile(filepath, "utf8");
+ const parsedData = JSON.parse(readfile);
+ return parsedData;
+ } catch (err) {
+ console.error("Error reading suggestionModalData.json:", err);
+ return null; // Handle the error appropriately
+ }
};
+
// create suggestion emailbody
const getsuggestionEmailBody = async (...args) => {
const readfile = await readSuggestionFile();
let fieldaaray = [];
if (readfile.field.length) {
- fieldaaray = readfile.field.map(item => `${item}
- ${args[3][item]}
`);
+ fieldaaray = readfile.field.map(
+ (item) => `${item}
+ ${args[3][item]}
`
+ );
}
const text = `New Suggestion:
Suggestion Category:
${args[0]}
Suggestion:
${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ''}
+ ${fieldaaray.length > 0 ? fieldaaray : ""}
Wants Feedback:
${args[2]}
Thank you,
@@ -130,50 +204,80 @@ const dashboardcontroller = function () {
// send suggestion email
const sendMakeSuggestion = async (req, res) => {
- const {
- suggestioncate, suggestion, confirm, ...rest
- } = req.body;
- const emailBody = await getsuggestionEmailBody(suggestioncate, suggestion, confirm, rest);
+ const { suggestioncate, suggestion, confirm, ...rest } = req.body;
+ const emailBody = await getsuggestionEmailBody(
+ suggestioncate,
+ suggestion,
+ confirm,
+ rest
+ );
try {
emailSender(
- 'onecommunityglobal@gmail.com',
- 'A new suggestion',
- emailBody,
+ "onecommunityglobal@gmail.com",
+ "A new suggestion",
+ emailBody
);
- res.status(200).send('Success');
+ res.status(200).send("Success");
} catch {
- res.status(500).send('Failed');
+ res.status(500).send("Failed");
}
};
-
const getSuggestionOption = async (req, res) => {
- const readfile = await readSuggestionFile();
- res.status(200).send(readfile);
+ try {
+ const readfile = await readSuggestionFile();
+ if (readfile) {
+ res.status(200).send(readfile);
+ } else {
+ res.status(404).send("Suggestion file not found.");
+ }
+ } catch (error) {
+ console.error("Error reading suggestion file:", error);
+ res.status(500).send("Internal Server Error");
+ }
};
+
// add new suggestion category or field
const editSuggestionOption = async (req, res) => {
- let readfile = await readSuggestionFile();
- if (req.body.suggestion) {
- if (req.body.action === 'add') readfile.suggestion.unshift(req.body.newField);
- if (req.body.action === 'delete') {
- readfile = {
- ...readfile,
- suggestion: readfile.suggestion.filter((item, index) => index + 1 !== +req.body.newField),
- };
+ try {
+ // Read the current suggestion data
+ let readfile = await readSuggestionFile();
+
+ if (req.body.suggestion) {
+ if (req.body.action === "add") {
+ readfile.suggestion.unshift(req.body.newField);
+ }
+ if (req.body.action === "delete") {
+ readfile = {
+ ...readfile,
+ suggestion: readfile.suggestion.filter(
+ (item, index) => index + 1 !== +req.body.newField
+ ),
+ };
+ }
+ } else {
+ if (req.body.action === "add") {
+ readfile.field.unshift(req.body.newField);
}
- } else {
- if (req.body.action === 'add') readfile.field.unshift(req.body.newField);
- if (req.body.action === 'delete') {
- readfile = {
- ...readfile,
- field: readfile.field.filter(item => item !== req.body.newField),
- };
+ if (req.body.action === "delete") {
+ readfile = {
+ ...readfile,
+ field: readfile.field.filter((item) => item !== req.body.newField),
+ };
}
+ }
+
+ // Get the file path
+ const filepath = await getSuggestionFilePath();
+
+ // Write the updated data back to the file
+ await fs.writeFile(filepath, JSON.stringify(readfile, null, 2));
+
+ res.status(200).send("success");
+ } catch (error) {
+ console.error("Error editing suggestion option:", error);
+ res.status(500).send("Internal Server Error");
}
- const filepath = path.join(process.cwd(), 'src', 'constants', 'suggestionModalData.json');
- await fs.writeFile(filepath, JSON.stringify(readfile)).catch(err => console.log(err));
- res.status(200).send('success');
};
return {
From 95015c4ebb613ed81f152a2c67d171f9713eac8d Mon Sep 17 00:00:00 2001
From: leonzh2k
Date: Thu, 6 Jul 2023 17:55:26 -0400
Subject: [PATCH 023/272] add new fields to send in UserProfileController
Add jobTitle and location fields to the userProfile objects
that are sent back to the client when requesting all userProfiles.
These two bits of info are displayed on the interactive map.
---
src/controllers/userProfileController.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 5f36e91a2..8a866401a 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -62,10 +62,10 @@ const userProfileController = function (UserProfile) {
res.status(200).send(getData);
return;
}
-
+
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate',
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
)
.sort({
lastName: 1,
From 9600e9dee200bf32bcc52c5757adc53a231a94f2 Mon Sep 17 00:00:00 2001
From: xaanders
Date: Thu, 14 Sep 2023 16:40:41 -0400
Subject: [PATCH 024/272] feat: adding location object to user profile schema
---
src/models/userProfile.js | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index fbb59e6e3..faeef3a86 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -7,7 +7,7 @@ const bcrypt = require('bcryptjs');
const SALT_ROUNDS = 10;
const nextDay = new Date();
-nextDay.setDate(nextDay.getDate()+1);
+nextDay.setDate(nextDay.getDate() + 1);
const userProfileSchema = new Schema({
password: {
@@ -81,7 +81,16 @@ const userProfileSchema = new Schema({
infringements: [
{ date: { type: String, required: true }, description: { type: String, required: true } },
],
- location: { type: String, default: '' },
+ location: {
+ userProvided: { type: String, default: '' },
+ coords: {
+ lat: { type: Number, default: '' },
+ lng: { type: Number, default: '' },
+ },
+ country: { type: String, default: '' },
+ city: { type: String, default: '' }
+
+ },
oldInfringements: [
{ date: { type: String, required: true }, description: { type: String, required: true } },
],
@@ -153,12 +162,12 @@ const userProfileSchema = new Schema({
isVisible: { type: Boolean, default: false },
weeklySummaryOption: { type: String },
bioPosted: { type: String, default: 'default' },
- isFirstTimelog: { type: Boolean, default: true},
+ isFirstTimelog: { type: Boolean, default: true },
infoCollections: [
{
- areaName: { type: String },
+ areaName: { type: String },
areaContent: { type: String },
- }],
+ }],
});
userProfileSchema.pre('save', function (next) {
From 2d1e82c56bce45d24d31eafab3eca2297b03dd2c Mon Sep 17 00:00:00 2001
From: xaanders
Date: Sat, 16 Sep 2023 12:02:02 -0400
Subject: [PATCH 025/272] fix: editing email message after new user creating
---
src/controllers/profileInitialSetupController.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index d5c955d88..c35230dbe 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -59,7 +59,7 @@ function informManagerMessage(user) {
Location: |
- ${user.location} |
+ ${user.location.userProvided}, ${user.location.country} |
Please check the details provided by the user. If any errors were made, kindly ask them to correct the information accordingly.
@@ -184,8 +184,8 @@ const profileInitialSetupController = function (ProfileInitialSetupToken, userPr
newUser.bioPosted = 'default';
newUser.privacySettings.email = req.body.privacySettings.email
newUser.privacySettings.phoneNumber = req.body.privacySettings.phoneNumber
- const savedUser = await newUser.save();
+ const savedUser = await newUser.save();
emailSender(
process.env.MANAGER_EMAIL,
'New User Profile Created',
From 15ec92739130b6d5743fd3f55e41489a0d04bf93 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Tue, 19 Sep 2023 18:15:29 -0700
Subject: [PATCH 026/272] add hasIndividualPermission to badgeController, which
checks seeBadge permission from userProfile db
---
src/controllers/badgeController.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 4777297dd..6238c381e 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -1,11 +1,11 @@
const mongoose = require('mongoose');
const UserProfile = require('../models/userProfile');
-const { hasPermission } = require('../utilities/permissions');
+const { hasPermission, hasIndividualPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const badgeController = function (Badge) {
const getAllBadges = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'seeBadges')) {
+ if (!await hasPermission(req.body.requestor.role, 'seeBadges') && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeBadges')) {
res.status(403).send('You are not authorized to view all badge data.');
return;
}
From 464a4eef488e01c3a368580082651dc40e710702 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 20 Sep 2023 12:30:58 -0700
Subject: [PATCH 027/272] add bm login route, router, controller
---
.../bmdashboard/bmLoginController.js | 44 +++++++++++++++++++
src/controllers/logincontroller.js | 3 ++
src/controllers/userProfileController.js | 3 ++
src/routes/bmdashboard/bmLoginRouter.js | 13 ++++++
src/startup/routes.js | 7 ++-
5 files changed, 69 insertions(+), 1 deletion(-)
create mode 100644 src/controllers/bmdashboard/bmLoginController.js
create mode 100644 src/routes/bmdashboard/bmLoginRouter.js
diff --git a/src/controllers/bmdashboard/bmLoginController.js b/src/controllers/bmdashboard/bmLoginController.js
new file mode 100644
index 000000000..b8db7286c
--- /dev/null
+++ b/src/controllers/bmdashboard/bmLoginController.js
@@ -0,0 +1,44 @@
+const jwt = require('jsonwebtoken');
+const bcrypt = require('bcryptjs');
+
+const config = require('../../config');
+
+const userprofile = require('../../models/userProfile');
+
+const bmLoginController = function () {
+ const { JWT_SECRET } = config;
+ const bmLogin = async function _login(req, res) {
+ const { email: _email, password: _password } = req.body;
+ const currentToken = req.headers.authorization;
+ try {
+ const decode = jwt.verify(currentToken, JWT_SECRET);
+ const user = await userprofile.findOne({ _id: decode.userid });
+
+ // check email
+ if (user.email !== _email) {
+ res.status(422);
+ return res.json({ label: 'email', message: 'Email must match current login. Please try again.' });
+ }
+ // check password
+ const check = await bcrypt.compare(_password, user.password);
+ if (!check) {
+ res.status(422);
+ return res.json({ label: 'password', message: 'Password must match current login. Please try again.' });
+ }
+ // create new token
+ const jwtPayload = {
+ ...decode,
+ access: {
+ canAccessBMPortal: true,
+ },
+ };
+ const newToken = jwt.sign(jwtPayload, JWT_SECRET);
+ return res.json({ token: newToken });
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return { bmLogin };
+};
+
+module.exports = bmLoginController;
diff --git a/src/controllers/logincontroller.js b/src/controllers/logincontroller.js
index 27a09edee..cdeae9b37 100644
--- a/src/controllers/logincontroller.js
+++ b/src/controllers/logincontroller.js
@@ -49,6 +49,9 @@ const logincontroller = function () {
userid: user._id,
role: user.role,
permissions: user.permissions,
+ access: {
+ canAccessBMPortal: false,
+ },
expiryTimestamp: moment().add(config.TOKEN.Lifetime, config.TOKEN.Units),
};
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 5f36e91a2..5000e36ad 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -808,6 +808,9 @@ const userProfileController = function (UserProfile) {
userid: user._id,
role: user.role,
permissions: user.permissions,
+ access: {
+ canAccessBMPortal: false,
+ },
expiryTimestamp: moment_().add(config.TOKEN.Lifetime, config.TOKEN.Units),
};
const currentRefreshToken = jwt.sign(jwtPayload, JWT_SECRET);
diff --git a/src/routes/bmdashboard/bmLoginRouter.js b/src/routes/bmdashboard/bmLoginRouter.js
new file mode 100644
index 000000000..c87e46c41
--- /dev/null
+++ b/src/routes/bmdashboard/bmLoginRouter.js
@@ -0,0 +1,13 @@
+const express = require('express');
+
+const routes = function () {
+ const loginrouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmLoginController')();
+
+ loginrouter.route('/login')
+ .post(controller.bmLogin);
+
+ return loginrouter;
+};
+
+module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 6e000002e..43cd226bd 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -53,6 +53,9 @@ const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter
const reasonRouter = require('../routes/reasonRouter')(reason, userProfile);
const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverText);
+// bm dashboard
+const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
+
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -79,8 +82,10 @@ module.exports = function (app) {
app.use('/api', roleRouter);
app.use('/api', ownerMessageRouter);
app.use('/api', ownerStandardMessageRouter);
- app.use('/api', profileInitialSetupRouter)
+ app.use('/api', profileInitialSetupRouter);
app.use('/api', reasonRouter);
app.use('/api', informationRouter);
app.use('/api', mouseoverTextRouter);
+ // bm dashboard
+ app.use('/api/bm', bmLoginRouter);
};
From ea1d82eba3d326d5e40d422778f6458d72ee9551 Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Wed, 20 Sep 2023 21:53:16 +0000
Subject: [PATCH 028/272] packages
---
package-lock.json | 2721 +++++++++------------------------------------
package.json | 7 +-
2 files changed, 536 insertions(+), 2192 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index cdfa61193..5c6bd6db5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -115,28 +115,12 @@
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz",
- "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz",
+ "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==",
"requires": {
- "@babel/types": "^7.22.15"
- },
- "dependencies": {
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
+ "@babel/helper-explode-assignable-expression": "^7.16.7",
+ "@babel/types": "^7.16.7"
}
},
"@babel/helper-compilation-targets": {
@@ -158,229 +142,47 @@
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz",
- "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
- "@babel/helper-member-expression-to-functions": "^7.22.15",
- "@babel/helper-optimise-call-expression": "^7.22.5",
- "@babel/helper-replace-supers": "^7.22.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "semver": "^6.3.1"
- },
- "dependencies": {
- "@babel/code-frame": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
- "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
- "requires": {
- "@babel/highlight": "^7.22.13",
- "chalk": "^2.4.2"
- }
- },
- "@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
- "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
- "requires": {
- "@babel/template": "^7.22.5",
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/highlight": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
- "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.22.16",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
- "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
- },
- "@babel/template": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
- "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
- "requires": {
- "@babel/code-frame": "^7.22.13",
- "@babel/parser": "^7.22.15",
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- },
- "semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
- }
+ "version": "7.17.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz",
+ "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/helper-member-expression-to-functions": "^7.16.7",
+ "@babel/helper-optimise-call-expression": "^7.16.7",
+ "@babel/helper-replace-supers": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7"
}
},
"@babel/helper-create-regexp-features-plugin": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz",
- "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz",
+ "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "regexpu-core": "^5.3.1",
- "semver": "^6.3.1"
- },
- "dependencies": {
- "@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- },
- "semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
- }
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "regexpu-core": "^5.0.1"
}
},
"@babel/helper-define-polyfill-provider": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz",
- "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
+ "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
"requires": {
- "@babel/helper-compilation-targets": "^7.22.6",
- "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-compilation-targets": "^7.13.0",
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/helper-plugin-utils": "^7.13.0",
+ "@babel/traverse": "^7.13.0",
"debug": "^4.1.1",
"lodash.debounce": "^4.0.8",
- "resolve": "^1.14.2"
+ "resolve": "^1.14.2",
+ "semver": "^6.1.2"
},
"dependencies": {
- "@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
- },
- "@babel/helper-compilation-targets": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
- "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
- "requires": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-validator-option": "^7.22.15",
- "browserslist": "^4.21.9",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-validator-option": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
- "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
- },
- "browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001532",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
- "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
- },
- "electron-to-chromium": {
- "version": "1.4.513",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
- "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
- },
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
- },
"semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}
}
},
@@ -392,6 +194,14 @@
"@babel/types": "^7.16.7"
}
},
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz",
+ "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==",
+ "requires": {
+ "@babel/types": "^7.16.7"
+ }
+ },
"@babel/helper-function-name": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
@@ -419,28 +229,11 @@
}
},
"@babel/helper-member-expression-to-functions": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz",
- "integrity": "sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz",
+ "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==",
"requires": {
- "@babel/types": "^7.22.15"
- },
- "dependencies": {
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
+ "@babel/types": "^7.16.7"
}
},
"@babel/helper-module-imports": {
@@ -467,28 +260,11 @@
}
},
"@babel/helper-optimise-call-expression": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
- "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz",
+ "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==",
"requires": {
- "@babel/types": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
+ "@babel/types": "^7.16.7"
}
},
"@babel/helper-plugin-utils": {
@@ -507,20 +283,15 @@
}
},
"@babel/helper-replace-supers": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz",
- "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz",
+ "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==",
"requires": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-member-expression-to-functions": "^7.22.5",
- "@babel/helper-optimise-call-expression": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- }
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-member-expression-to-functions": "^7.16.7",
+ "@babel/helper-optimise-call-expression": "^7.16.7",
+ "@babel/traverse": "^7.16.7",
+ "@babel/types": "^7.16.7"
}
},
"@babel/helper-simple-access": {
@@ -532,28 +303,11 @@
}
},
"@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
- "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz",
+ "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==",
"requires": {
- "@babel/types": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
+ "@babel/types": "^7.16.0"
}
},
"@babel/helper-split-export-declaration": {
@@ -564,11 +318,6 @@
"@babel/types": "^7.16.7"
}
},
- "@babel/helper-string-parser": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
- "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
- },
"@babel/helper-validator-identifier": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
@@ -629,41 +378,165 @@
"integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA=="
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz",
- "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz",
+ "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz",
- "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz",
+ "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
- "@babel/plugin-transform-optional-chaining": "^7.22.15"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
+ "@babel/plugin-proposal-optional-chaining": "^7.16.7"
+ }
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz",
+ "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-remap-async-to-generator": "^7.16.8",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ }
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz",
+ "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ }
+ },
+ "@babel/plugin-proposal-class-static-block": {
+ "version": "7.17.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz",
+ "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.17.6",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ }
+ },
+ "@babel/plugin-proposal-dynamic-import": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz",
+ "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz",
+ "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz",
+ "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz",
+ "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ }
+ },
+ "@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz",
+ "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-numeric-separator": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz",
+ "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.17.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz",
+ "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==",
+ "requires": {
+ "@babel/compat-data": "^7.17.0",
+ "@babel/helper-compilation-targets": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.16.7"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz",
+ "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-optional-chaining": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz",
+ "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-private-methods": {
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz",
+ "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.16.10",
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-proposal-private-property-in-object": {
- "version": "7.21.0-placeholder-for-preset-env.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
- "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w=="
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz",
+ "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-create-class-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz",
+ "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ }
},
"@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
@@ -705,44 +578,6 @@
"@babel/helper-plugin-utils": "^7.8.3"
}
},
- "@babel/plugin-syntax-import-assertions": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz",
- "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-syntax-import-attributes": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz",
- "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
- "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
"@babel/plugin-syntax-json-strings": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
@@ -815,1585 +650,339 @@
"@babel/helper-plugin-utils": "^7.14.5"
}
},
- "@babel/plugin-syntax-unicode-sets-regex": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
- "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz",
+ "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
- "@babel/plugin-transform-arrow-functions": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz",
- "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==",
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz",
+ "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-remap-async-to-generator": "^7.16.8"
}
},
- "@babel/plugin-transform-async-generator-functions": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz",
- "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==",
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz",
+ "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==",
"requires": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.9",
- "@babel/plugin-syntax-async-generators": "^7.8.4"
- },
- "dependencies": {
- "@babel/code-frame": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
- "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
- "requires": {
- "@babel/highlight": "^7.22.13",
- "chalk": "^2.4.2"
- }
- },
- "@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
- "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
- "requires": {
- "@babel/template": "^7.22.5",
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-remap-async-to-generator": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
- "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-wrap-function": "^7.22.17"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/helper-wrap-function": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
- "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
- "requires": {
- "@babel/helper-function-name": "^7.22.5",
- "@babel/template": "^7.22.15",
- "@babel/types": "^7.22.17"
- }
- },
- "@babel/highlight": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
- "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.22.16",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
- "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
- },
- "@babel/template": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
- "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
- "requires": {
- "@babel/code-frame": "^7.22.13",
- "@babel/parser": "^7.22.15",
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
- }
- },
- "@babel/plugin-transform-async-to-generator": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz",
- "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==",
- "requires": {
- "@babel/helper-module-imports": "^7.16.7",
- "@babel/helper-plugin-utils": "^7.16.7",
- "@babel/helper-remap-async-to-generator": "^7.16.8"
- }
- },
- "@babel/plugin-transform-block-scoped-functions": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz",
- "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz",
- "integrity": "sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-class-properties": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz",
- "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==",
- "requires": {
- "@babel/helper-create-class-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-class-static-block": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz",
- "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz",
+ "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==",
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.22.11",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-class-static-block": "^7.14.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-classes": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz",
- "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
- "@babel/helper-optimise-call-expression": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-replace-supers": "^7.22.9",
- "@babel/helper-split-export-declaration": "^7.22.6",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz",
+ "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/helper-optimise-call-expression": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-replace-supers": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
"globals": "^11.1.0"
- },
- "dependencies": {
- "@babel/code-frame": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
- "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
- "requires": {
- "@babel/highlight": "^7.22.13",
- "chalk": "^2.4.2"
- }
- },
- "@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
- },
- "@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-compilation-targets": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
- "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
- "requires": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-validator-option": "^7.22.15",
- "browserslist": "^4.21.9",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
- "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
- "requires": {
- "@babel/template": "^7.22.5",
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/helper-validator-option": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
- "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
- },
- "@babel/highlight": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
- "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.22.16",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
- "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
- },
- "@babel/template": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
- "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
- "requires": {
- "@babel/code-frame": "^7.22.13",
- "@babel/parser": "^7.22.15",
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- },
- "browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001532",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
- "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
- },
- "electron-to-chromium": {
- "version": "1.4.513",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
- "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
- },
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
- },
- "semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
- }
}
},
"@babel/plugin-transform-computed-properties": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz",
- "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz",
+ "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/template": "^7.22.5"
- },
- "dependencies": {
- "@babel/code-frame": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
- "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
- "requires": {
- "@babel/highlight": "^7.22.13",
- "chalk": "^2.4.2"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/highlight": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
- "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.22.16",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
- "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
- },
- "@babel/template": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
- "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
- "requires": {
- "@babel/code-frame": "^7.22.13",
- "@babel/parser": "^7.22.15",
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz",
- "integrity": "sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ==",
+ "version": "7.17.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz",
+ "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-dotall-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz",
- "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz",
+ "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-duplicate-keys": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz",
- "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz",
+ "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-dynamic-import": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz",
- "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-exponentiation-operator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz",
- "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz",
+ "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==",
"requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-export-namespace-from": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz",
- "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz",
- "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz",
+ "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz",
- "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==",
- "requires": {
- "@babel/helper-compilation-targets": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/code-frame": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
- "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
- "requires": {
- "@babel/highlight": "^7.22.13",
- "chalk": "^2.4.2"
- }
- },
- "@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
- },
- "@babel/helper-compilation-targets": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
- "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
- "requires": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-validator-option": "^7.22.15",
- "browserslist": "^4.21.9",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- }
- },
- "@babel/helper-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
- "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
- "requires": {
- "@babel/template": "^7.22.5",
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/helper-validator-option": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
- "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
- },
- "@babel/highlight": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
- "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.22.16",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
- "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
- },
- "@babel/template": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
- "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
- "requires": {
- "@babel/code-frame": "^7.22.13",
- "@babel/parser": "^7.22.15",
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- },
- "browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001532",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
- "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
- },
- "electron-to-chromium": {
- "version": "1.4.513",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
- "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
- },
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
- },
- "semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
- }
- }
- },
- "@babel/plugin-transform-json-strings": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz",
- "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz",
+ "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-json-strings": "^7.8.3"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-compilation-targets": "^7.16.7",
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz",
- "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz",
- "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz",
+ "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-member-expression-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz",
- "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-modules-amd": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz",
- "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==",
- "requires": {
- "@babel/helper-module-transforms": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-module-imports": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
- "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
- "requires": {
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
- "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
- "requires": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-simple-access": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/helper-validator-identifier": "^7.22.15"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-simple-access": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
- "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
- }
- },
- "@babel/plugin-transform-modules-commonjs": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz",
- "integrity": "sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg==",
- "requires": {
- "@babel/helper-module-transforms": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-simple-access": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-module-imports": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
- "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
- "requires": {
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
- "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
- "requires": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-simple-access": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/helper-validator-identifier": "^7.22.15"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-simple-access": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
- "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
- }
- },
- "@babel/plugin-transform-modules-systemjs": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz",
- "integrity": "sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==",
- "requires": {
- "@babel/helper-hoist-variables": "^7.22.5",
- "@babel/helper-module-transforms": "^7.22.9",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-hoist-variables": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
- "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
- "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
- "requires": {
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
- "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
- "requires": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-simple-access": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/helper-validator-identifier": "^7.22.15"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-simple-access": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
- "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
- }
- },
- "@babel/plugin-transform-modules-umd": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz",
- "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==",
- "requires": {
- "@babel/helper-module-transforms": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-module-imports": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
- "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
- "requires": {
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
- "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
- "requires": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-simple-access": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/helper-validator-identifier": "^7.22.15"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-simple-access": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
- "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
- }
- },
- "@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz",
- "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==",
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-new-target": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz",
- "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz",
- "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz",
+ "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
- "@babel/plugin-transform-numeric-separator": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz",
- "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==",
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz",
+ "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
}
},
- "@babel/plugin-transform-object-rest-spread": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz",
- "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==",
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
+ "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
"requires": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.22.15"
- },
- "dependencies": {
- "@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
- },
- "@babel/helper-compilation-targets": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
- "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
- "requires": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-validator-option": "^7.22.15",
- "browserslist": "^4.21.9",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-validator-option": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
- "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
- },
- "browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001532",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
- "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
- },
- "electron-to-chromium": {
- "version": "1.4.513",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
- "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
- },
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
- },
- "semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
- }
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-simple-access": "^7.16.7",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
}
},
- "@babel/plugin-transform-object-super": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz",
- "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==",
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz",
+ "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-replace-supers": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-hoist-variables": "^7.16.7",
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
}
},
- "@babel/plugin-transform-optional-catch-binding": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz",
- "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==",
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz",
+ "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
- "@babel/plugin-transform-optional-chaining": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.15.tgz",
- "integrity": "sha512-ngQ2tBhq5vvSJw2Q2Z9i7ealNkpDMU0rGWnHPKqRZO0tzZ5tlaoz4hDvhXioOoaE0X2vfNss1djwg0DXlfu30A==",
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz",
+ "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7"
}
},
- "@babel/plugin-transform-parameters": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz",
- "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==",
+ "@babel/plugin-transform-new-target": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz",
+ "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
- "@babel/plugin-transform-private-methods": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz",
- "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==",
+ "@babel/plugin-transform-object-super": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz",
+ "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==",
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-replace-supers": "^7.16.7"
}
},
- "@babel/plugin-transform-private-property-in-object": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz",
- "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==",
+ "@babel/plugin-transform-parameters": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz",
+ "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-create-class-features-plugin": "^7.22.11",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
- },
- "dependencies": {
- "@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-property-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz",
- "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz",
+ "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-regenerator": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz",
- "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz",
+ "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "regenerator-transform": "^0.15.2"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "regenerator-transform": "^0.14.2"
}
},
"@babel/plugin-transform-reserved-words": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz",
- "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz",
+ "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-runtime": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.15.tgz",
- "integrity": "sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g==",
- "requires": {
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.22.5",
- "babel-plugin-polyfill-corejs2": "^0.4.5",
- "babel-plugin-polyfill-corejs3": "^0.8.3",
- "babel-plugin-polyfill-regenerator": "^0.5.2",
- "semver": "^6.3.1"
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz",
+ "integrity": "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "babel-plugin-polyfill-corejs2": "^0.3.0",
+ "babel-plugin-polyfill-corejs3": "^0.5.0",
+ "babel-plugin-polyfill-regenerator": "^0.3.0",
+ "semver": "^6.3.0"
},
"dependencies": {
- "@babel/helper-module-imports": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
- "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
- "requires": {
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- },
"semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}
}
},
"@babel/plugin-transform-shorthand-properties": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz",
- "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz",
+ "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-spread": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz",
- "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz",
+ "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0"
}
},
"@babel/plugin-transform-sticky-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz",
- "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz",
+ "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-template-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz",
- "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz",
+ "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-typeof-symbol": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz",
- "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz",
+ "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-unicode-escapes": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz",
- "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==",
- "requires": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-unicode-property-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz",
- "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz",
+ "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-unicode-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz",
- "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==",
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
- }
- },
- "@babel/plugin-transform-unicode-sets-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz",
- "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==",
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz",
+ "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "dependencies": {
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- }
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/preset-env": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.15.tgz",
- "integrity": "sha512-tZFHr54GBkHk6hQuVA8w4Fmq+MSPsfvMG0vPnOYyTnJpyfMqybL8/MbNCPRT9zc2KBO2pe4tq15g6Uno4Jpoag==",
- "requires": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-validator-option": "^7.22.15",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15",
- "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz",
+ "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==",
+ "requires": {
+ "@babel/compat-data": "^7.16.8",
+ "@babel/helper-compilation-targets": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-validator-option": "^7.16.7",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7",
+ "@babel/plugin-proposal-async-generator-functions": "^7.16.8",
+ "@babel/plugin-proposal-class-properties": "^7.16.7",
+ "@babel/plugin-proposal-class-static-block": "^7.16.7",
+ "@babel/plugin-proposal-dynamic-import": "^7.16.7",
+ "@babel/plugin-proposal-export-namespace-from": "^7.16.7",
+ "@babel/plugin-proposal-json-strings": "^7.16.7",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",
+ "@babel/plugin-proposal-numeric-separator": "^7.16.7",
+ "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
+ "@babel/plugin-proposal-optional-chaining": "^7.16.7",
+ "@babel/plugin-proposal-private-methods": "^7.16.11",
+ "@babel/plugin-proposal-private-property-in-object": "^7.16.7",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
"@babel/plugin-syntax-async-generators": "^7.8.4",
"@babel/plugin-syntax-class-properties": "^7.12.13",
"@babel/plugin-syntax-class-static-block": "^7.14.5",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3",
- "@babel/plugin-syntax-import-assertions": "^7.22.5",
- "@babel/plugin-syntax-import-attributes": "^7.22.5",
- "@babel/plugin-syntax-import-meta": "^7.10.4",
"@babel/plugin-syntax-json-strings": "^7.8.3",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
@@ -2403,252 +992,62 @@
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
"@babel/plugin-syntax-private-property-in-object": "^7.14.5",
"@babel/plugin-syntax-top-level-await": "^7.14.5",
- "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
- "@babel/plugin-transform-arrow-functions": "^7.22.5",
- "@babel/plugin-transform-async-generator-functions": "^7.22.15",
- "@babel/plugin-transform-async-to-generator": "^7.22.5",
- "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
- "@babel/plugin-transform-block-scoping": "^7.22.15",
- "@babel/plugin-transform-class-properties": "^7.22.5",
- "@babel/plugin-transform-class-static-block": "^7.22.11",
- "@babel/plugin-transform-classes": "^7.22.15",
- "@babel/plugin-transform-computed-properties": "^7.22.5",
- "@babel/plugin-transform-destructuring": "^7.22.15",
- "@babel/plugin-transform-dotall-regex": "^7.22.5",
- "@babel/plugin-transform-duplicate-keys": "^7.22.5",
- "@babel/plugin-transform-dynamic-import": "^7.22.11",
- "@babel/plugin-transform-exponentiation-operator": "^7.22.5",
- "@babel/plugin-transform-export-namespace-from": "^7.22.11",
- "@babel/plugin-transform-for-of": "^7.22.15",
- "@babel/plugin-transform-function-name": "^7.22.5",
- "@babel/plugin-transform-json-strings": "^7.22.11",
- "@babel/plugin-transform-literals": "^7.22.5",
- "@babel/plugin-transform-logical-assignment-operators": "^7.22.11",
- "@babel/plugin-transform-member-expression-literals": "^7.22.5",
- "@babel/plugin-transform-modules-amd": "^7.22.5",
- "@babel/plugin-transform-modules-commonjs": "^7.22.15",
- "@babel/plugin-transform-modules-systemjs": "^7.22.11",
- "@babel/plugin-transform-modules-umd": "^7.22.5",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
- "@babel/plugin-transform-new-target": "^7.22.5",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11",
- "@babel/plugin-transform-numeric-separator": "^7.22.11",
- "@babel/plugin-transform-object-rest-spread": "^7.22.15",
- "@babel/plugin-transform-object-super": "^7.22.5",
- "@babel/plugin-transform-optional-catch-binding": "^7.22.11",
- "@babel/plugin-transform-optional-chaining": "^7.22.15",
- "@babel/plugin-transform-parameters": "^7.22.15",
- "@babel/plugin-transform-private-methods": "^7.22.5",
- "@babel/plugin-transform-private-property-in-object": "^7.22.11",
- "@babel/plugin-transform-property-literals": "^7.22.5",
- "@babel/plugin-transform-regenerator": "^7.22.10",
- "@babel/plugin-transform-reserved-words": "^7.22.5",
- "@babel/plugin-transform-shorthand-properties": "^7.22.5",
- "@babel/plugin-transform-spread": "^7.22.5",
- "@babel/plugin-transform-sticky-regex": "^7.22.5",
- "@babel/plugin-transform-template-literals": "^7.22.5",
- "@babel/plugin-transform-typeof-symbol": "^7.22.5",
- "@babel/plugin-transform-unicode-escapes": "^7.22.10",
- "@babel/plugin-transform-unicode-property-regex": "^7.22.5",
- "@babel/plugin-transform-unicode-regex": "^7.22.5",
- "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
- "@babel/preset-modules": "0.1.6-no-external-plugins",
- "@babel/types": "^7.22.15",
- "babel-plugin-polyfill-corejs2": "^0.4.5",
- "babel-plugin-polyfill-corejs3": "^0.8.3",
- "babel-plugin-polyfill-regenerator": "^0.5.2",
- "core-js-compat": "^3.31.0",
- "semver": "^6.3.1"
+ "@babel/plugin-transform-arrow-functions": "^7.16.7",
+ "@babel/plugin-transform-async-to-generator": "^7.16.8",
+ "@babel/plugin-transform-block-scoped-functions": "^7.16.7",
+ "@babel/plugin-transform-block-scoping": "^7.16.7",
+ "@babel/plugin-transform-classes": "^7.16.7",
+ "@babel/plugin-transform-computed-properties": "^7.16.7",
+ "@babel/plugin-transform-destructuring": "^7.16.7",
+ "@babel/plugin-transform-dotall-regex": "^7.16.7",
+ "@babel/plugin-transform-duplicate-keys": "^7.16.7",
+ "@babel/plugin-transform-exponentiation-operator": "^7.16.7",
+ "@babel/plugin-transform-for-of": "^7.16.7",
+ "@babel/plugin-transform-function-name": "^7.16.7",
+ "@babel/plugin-transform-literals": "^7.16.7",
+ "@babel/plugin-transform-member-expression-literals": "^7.16.7",
+ "@babel/plugin-transform-modules-amd": "^7.16.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.16.8",
+ "@babel/plugin-transform-modules-systemjs": "^7.16.7",
+ "@babel/plugin-transform-modules-umd": "^7.16.7",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8",
+ "@babel/plugin-transform-new-target": "^7.16.7",
+ "@babel/plugin-transform-object-super": "^7.16.7",
+ "@babel/plugin-transform-parameters": "^7.16.7",
+ "@babel/plugin-transform-property-literals": "^7.16.7",
+ "@babel/plugin-transform-regenerator": "^7.16.7",
+ "@babel/plugin-transform-reserved-words": "^7.16.7",
+ "@babel/plugin-transform-shorthand-properties": "^7.16.7",
+ "@babel/plugin-transform-spread": "^7.16.7",
+ "@babel/plugin-transform-sticky-regex": "^7.16.7",
+ "@babel/plugin-transform-template-literals": "^7.16.7",
+ "@babel/plugin-transform-typeof-symbol": "^7.16.7",
+ "@babel/plugin-transform-unicode-escapes": "^7.16.7",
+ "@babel/plugin-transform-unicode-regex": "^7.16.7",
+ "@babel/preset-modules": "^0.1.5",
+ "@babel/types": "^7.16.8",
+ "babel-plugin-polyfill-corejs2": "^0.3.0",
+ "babel-plugin-polyfill-corejs3": "^0.5.0",
+ "babel-plugin-polyfill-regenerator": "^0.3.0",
+ "core-js-compat": "^3.20.2",
+ "semver": "^6.3.0"
},
"dependencies": {
- "@babel/code-frame": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
- "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
- "requires": {
- "@babel/highlight": "^7.22.13",
- "chalk": "^2.4.2"
- }
- },
- "@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
- },
- "@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "requires": {
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-compilation-targets": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
- "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
- "requires": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-validator-option": "^7.22.15",
- "browserslist": "^4.21.9",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q=="
- },
- "@babel/helper-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
- "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
- "requires": {
- "@babel/template": "^7.22.5",
- "@babel/types": "^7.22.5"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
- "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
- "requires": {
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
- },
- "@babel/helper-remap-async-to-generator": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
- "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-wrap-function": "^7.22.17"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
- },
- "@babel/helper-validator-option": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
- "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
- },
- "@babel/helper-wrap-function": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
- "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
- "requires": {
- "@babel/helper-function-name": "^7.22.5",
- "@babel/template": "^7.22.15",
- "@babel/types": "^7.22.17"
- }
- },
- "@babel/highlight": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
- "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- }
- },
- "@babel/parser": {
- "version": "7.22.16",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
- "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
- },
- "@babel/plugin-transform-async-to-generator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz",
- "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==",
- "requires": {
- "@babel/helper-module-imports": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.5"
- }
- },
- "@babel/template": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
- "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
- "requires": {
- "@babel/code-frame": "^7.22.13",
- "@babel/parser": "^7.22.15",
- "@babel/types": "^7.22.15"
- }
- },
- "@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
- "requires": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
- "to-fast-properties": "^2.0.0"
- }
- },
- "browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001532",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
- "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
- },
- "electron-to-chromium": {
- "version": "1.4.513",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
- "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
- },
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
- },
"semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}
}
},
"@babel/preset-modules": {
- "version": "0.1.6-no-external-plugins",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
- "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
+ "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
"@babel/types": "^7.4.4",
"esutils": "^2.0.2"
}
@@ -2665,11 +1064,6 @@
"source-map-support": "^0.5.16"
}
},
- "@babel/regjsgen": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
- "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
- },
"@babel/runtime": {
"version": "7.17.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
@@ -4122,6 +2516,14 @@
}
}
},
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
"babel-plugin-module-resolver": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz",
@@ -4183,42 +2585,37 @@
}
},
"babel-plugin-polyfill-corejs2": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz",
- "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
+ "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
"requires": {
- "@babel/compat-data": "^7.22.6",
- "@babel/helper-define-polyfill-provider": "^0.4.2",
- "semver": "^6.3.1"
+ "@babel/compat-data": "^7.13.11",
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "semver": "^6.1.1"
},
"dependencies": {
- "@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
- },
"semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}
}
},
"babel-plugin-polyfill-corejs3": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz",
- "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==",
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz",
+ "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==",
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.4.2",
- "core-js-compat": "^3.31.0"
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "core-js-compat": "^3.21.0"
}
},
"babel-plugin-polyfill-regenerator": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz",
- "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
+ "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.4.2"
+ "@babel/helper-define-polyfill-provider": "^0.3.1"
}
},
"balanced-match": {
@@ -4576,38 +2973,18 @@
"integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig=="
},
"core-js-compat": {
- "version": "3.32.2",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
- "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
+ "version": "3.21.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz",
+ "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==",
"requires": {
- "browserslist": "^4.21.10"
+ "browserslist": "^4.19.1",
+ "semver": "7.0.0"
},
"dependencies": {
- "browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001532",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz",
- "integrity": "sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw=="
- },
- "electron-to-chromium": {
- "version": "1.4.513",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
- "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
- },
- "node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
+ "semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="
}
}
},
@@ -6727,9 +5104,9 @@
}
},
"semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"requires": {
"lru-cache": "^6.0.0"
}
@@ -7020,7 +5397,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",
@@ -7304,15 +5681,15 @@
}
},
"mongoose": {
- "version": "5.13.20",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.20.tgz",
- "integrity": "sha512-TjGFa/XnJYt+wLmn8y9ssjyO2OhBMeEBtOHb9iJM16EWu2Du6L1Q6zSiEK2ziyYQM8agb4tumNIQFzqbxId7MA==",
+ "version": "5.13.15",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz",
+ "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==",
"requires": {
"@types/bson": "1.x || 4.0.x",
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4",
"kareem": "2.3.2",
- "mongodb": "3.7.4",
+ "mongodb": "3.7.3",
"mongoose-legacy-pluralize": "1.0.2",
"mpath": "0.8.4",
"mquery": "3.2.5",
@@ -7324,29 +5701,6 @@
"sliced": "1.0.1"
},
"dependencies": {
- "mongodb": {
- "version": "3.7.4",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.4.tgz",
- "integrity": "sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw==",
- "requires": {
- "bl": "^2.2.1",
- "bson": "^1.1.4",
- "denque": "^1.4.1",
- "optional-require": "^1.1.8",
- "safe-buffer": "^5.1.2",
- "saslprep": "^1.0.0"
- },
- "dependencies": {
- "optional-require": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
- "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
- "requires": {
- "require-at": "^1.0.6"
- }
- }
- }
- },
"optional-require": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
@@ -8399,11 +6753,6 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
- "prettier": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
- "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg=="
- },
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -8516,9 +6865,9 @@
"integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="
},
"regenerate-unicode-properties": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz",
- "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==",
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz",
+ "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==",
"requires": {
"regenerate": "^1.4.2"
}
@@ -8529,9 +6878,9 @@
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"regenerator-transform": {
- "version": "0.15.2",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
- "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
+ "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
"requires": {
"@babel/runtime": "^7.8.4"
}
@@ -8565,22 +6914,27 @@
}
},
"regexpu-core": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz",
- "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz",
+ "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==",
"requires": {
- "@babel/regjsgen": "^0.8.0",
"regenerate": "^1.4.2",
- "regenerate-unicode-properties": "^10.1.0",
- "regjsparser": "^0.9.1",
+ "regenerate-unicode-properties": "^10.0.1",
+ "regjsgen": "^0.6.0",
+ "regjsparser": "^0.8.2",
"unicode-match-property-ecmascript": "^2.0.0",
- "unicode-match-property-value-ecmascript": "^2.1.0"
+ "unicode-match-property-value-ecmascript": "^2.0.0"
}
},
+ "regjsgen": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz",
+ "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA=="
+ },
"regjsparser": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
- "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz",
+ "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==",
"requires": {
"jsesc": "~0.5.0"
},
@@ -8588,7 +6942,7 @@
"jsesc": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA=="
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
}
}
},
@@ -9477,29 +7831,20 @@
}
},
"unicode-match-property-value-ecmascript": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
- "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA=="
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw=="
},
"unicode-property-aliases-ecmascript": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
- "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w=="
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ=="
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
- "update-browserslist-db": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
- "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
- "requires": {
- "escalade": "^3.1.1",
- "picocolors": "^1.0.0"
- }
- },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
diff --git a/package.json b/package.json
index 509755c88..f9387e933 100644
--- a/package.json
+++ b/package.json
@@ -40,8 +40,8 @@
"@babel/core": "^7.10.2",
"@babel/node": "^7.14.9",
"@babel/plugin-transform-async-to-generator": "^7.10.1",
- "@babel/plugin-transform-runtime": "^7.22.15",
- "@babel/preset-env": "^7.22.15",
+ "@babel/plugin-transform-runtime": "^7.10.1",
+ "@babel/preset-env": "^7.10.2",
"@babel/runtime": "^7.10.2",
"@sentry/node": "^5.17.0",
"async-exit-hook": "^2.0.1",
@@ -58,12 +58,11 @@
"moment": "^2.29.4",
"moment-timezone": "^0.5.35",
"mongodb": "^3.7.3",
- "mongoose": "^5.13.20",
+ "mongoose": "^5.13.15",
"mongoose-validator": "^2.1.0",
"node-cache": "^5.1.2",
"node-datetime": "^2.0.3",
"nodemailer": "^6.4.16",
- "prettier": "^3.0.3",
"redis": "^4.2.0",
"uuid": "^3.4.0",
"ws": "^8.8.1"
From 9e74615fde0dcc10c98f419361bb69755f917a51 Mon Sep 17 00:00:00 2001
From: xaanders
Date: Fri, 22 Sep 2023 19:58:43 -0400
Subject: [PATCH 029/272] feat: adding a initial functionality for adding new
people to the map(maplocation controller, maplocation router, maplocation
model)
---
src/controllers/mapLocationsController.js | 69 +++++++++++++++++++++++
src/models/mapLocation.js | 42 ++++++++++++++
src/routes/mapLocationsRouter.js | 18 ++++++
src/startup/routes.js | 4 ++
4 files changed, 133 insertions(+)
create mode 100644 src/controllers/mapLocationsController.js
create mode 100644 src/models/mapLocation.js
create mode 100644 src/routes/mapLocationsRouter.js
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
new file mode 100644
index 000000000..83526998d
--- /dev/null
+++ b/src/controllers/mapLocationsController.js
@@ -0,0 +1,69 @@
+const mongoose = require('mongoose');
+const mapLocation = require('../models/mapLocation');
+const { hasPermission } = require('../utilities/permissions');
+
+const mapLocationsController = function () {
+ const getAllLocations = function (req, res) {
+ console.log('controller:')
+ console.log(req.body)
+
+ mapLocation.find({})
+ .then(results => res.send(results).status(200))
+ .catch(error => res.send(error).status(404));
+ };
+ const deleteLocation = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'deleteTeam')) {
+ res.status(403).send({ error: 'You are not authorized to delete teams.' });
+ return;
+ }
+ const { teamId } = req.params;
+ Team.findById(teamId, (error, record) => {
+ if (error || record === null) {
+ res.status(400).send({ error: 'No valid records found' });
+ return;
+ }
+ const removeteamfromprofile = userProfile.updateMany({}, { $pull: { teams: record._id } }).exec();
+ const deleteteam = record.remove();
+
+ Promise.all([removeteamfromprofile, deleteteam])
+ .then(res.status(200).send({ message: ' Team successfully deleted and user profiles updated' }))
+ .catch((errors) => {
+ res.status(400).send(errors);
+ });
+ }).catch((error) => {
+ res.status(400).send(error);
+ });
+ };
+ const putUserLocation = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'putTeam')) {
+ res.status(403).send('You are not authorized to make changes in the teams.');
+ return;
+ }
+
+ const { teamId } = req.params;
+
+ Team.findById(teamId, (error, record) => {
+ if (error || record === null) {
+ res.status(400).send('No valid records found');
+ return;
+ }
+ record.teamName = req.body.teamName;
+ record.isActive = req.body.isActive;
+ record.createdDatetime = Date.now();
+ record.modifiedDatetime = Date.now();
+
+ record
+ .save()
+ .then(results => res.status(201).send(results._id))
+ .catch(errors => res.status(400).send(errors));
+ });
+ };
+
+ return {
+ getAllLocations,
+ deleteLocation,
+ putUserLocation
+ };
+};
+
+module.exports = mapLocationsController;
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
new file mode 100644
index 000000000..d7b9d82b5
--- /dev/null
+++ b/src/models/mapLocation.js
@@ -0,0 +1,42 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const mapLocation = new Schema({
+ firstName: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ lastName: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ title: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ userProvided: {
+ type: String,
+ required: true,
+ },
+ coords: {
+ lat: {
+ type: String,
+ required: true,
+ },
+ lng: {
+ type: String,
+ required: true,
+ }
+ },
+ country: {
+ type: String,
+ required: true,
+ },
+ city: {
+ type: String,
+ default: '',
+ }
+});
+
+module.exports = mongoose.model('MapLocation', mapLocation, 'maplocations');
diff --git a/src/routes/mapLocationsRouter.js b/src/routes/mapLocationsRouter.js
new file mode 100644
index 000000000..e2e780dac
--- /dev/null
+++ b/src/routes/mapLocationsRouter.js
@@ -0,0 +1,18 @@
+const express = require('express');
+
+const router = function (mapLocations) {
+ const controller = require('../controllers/mapLocationsController')(mapLocations);
+
+ const mapRouter = express.Router();
+
+ mapRouter.route('/mapLocations')
+ .get(controller.getAllLocations)
+ .put(controller.putUserLocation);
+
+ mapRouter.route('/mapLocations/:locationId')
+ .delete(controller.deleteLocation)
+
+ return mapRouter;
+};
+
+module.exports = router;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 6e000002e..ffe02ccc5 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -20,6 +20,7 @@ const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
+const mapLocations = require('../models/mapLocation');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -53,6 +54,8 @@ const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter
const reasonRouter = require('../routes/reasonRouter')(reason, userProfile);
const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverText);
+const mapLocationRouter = require('../routes/mapLocationsRouter')(mapLocations);
+
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -83,4 +86,5 @@ module.exports = function (app) {
app.use('/api', reasonRouter);
app.use('/api', informationRouter);
app.use('/api', mouseoverTextRouter);
+ app.use('/api', mapLocationRouter);
};
From 65f675eb60fc6de9f35274f9c4a67477596456ad Mon Sep 17 00:00:00 2001
From: navneeeth
Date: Fri, 22 Sep 2023 19:25:14 -0700
Subject: [PATCH 030/272] updated controllers to check permissions for project
management tab
---
src/controllers/projectController.js | 14 ++++++++++----
src/controllers/userProfileController.js | 5 ++++-
src/controllers/wbsController.js | 9 ++++++---
3 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/controllers/projectController.js b/src/controllers/projectController.js
index 6bac2124c..d3e849498 100644
--- a/src/controllers/projectController.js
+++ b/src/controllers/projectController.js
@@ -2,7 +2,7 @@ const mongoose = require('mongoose');
const timeentry = require('../models/timeentry');
const userProfile = require('../models/userProfile');
const userProject = require('../helpers/helperModels/userProjects');
-const { hasPermission } = require('../utilities/permissions');
+const { hasPermission, hasIndividualPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
@@ -15,7 +15,8 @@ const projectController = function (Project) {
};
const deleteProject = function (req, res) {
- if (!hasPermission(req.body.requestor.role, 'deleteProject')) {
+ if (!hasPermission(req.body.requestor.role, 'deleteProject')
+ && !hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')) {
res.status(403).send({ error: 'You are not authorized to delete projects.' });
return;
}
@@ -46,7 +47,8 @@ const projectController = function (Project) {
};
const postProject = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postProject')) {
+ if (!await hasPermission(req.body.requestor.role, 'postProject')
+ && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')) {
res.status(403).send({ error: 'You are not authorized to create new projects.' });
return;
}
@@ -77,7 +79,8 @@ const projectController = function (Project) {
const putProject = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putProject')) {
+ if (!await hasPermission(req.body.requestor.role, 'putProject')
+ && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')) {
res.status(403).send('You are not authorized to make changes in the projects.');
return;
}
@@ -125,8 +128,11 @@ const projectController = function (Project) {
// verify requestor is administrator, projectId is passed in request params and is valid mongoose objectid, and request body contains an array of users
if (!await hasPermission(req.body.requestor.role, 'assignProjectToUsers')) {
+ if (!await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')
+ && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagementTab')) {
res.status(403).send({ error: 'You are not authorized to perform this operation' });
return;
+ }
}
if (!req.params.projectId || !mongoose.Types.ObjectId.isValid(req.params.projectId) || !req.body.users || (req.body.users.length === 0)) {
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 5f36e91a2..35f3ff395 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -12,7 +12,7 @@ const Badge = require('../models/badge');
const userProfile = require('../models/userProfile');
const yearMonthDayDateValidator = require('../utilities/yearMonthDayDateValidator');
const cache = require('../utilities/nodeCache')();
-const { hasPermission, canRequestorUpdateUser } = require('../utilities/permissions');
+const { hasPermission, hasIndividualPermission, canRequestorUpdateUser } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const config = require('../config');
@@ -53,8 +53,11 @@ async function ValidatePassword(req, res) {
const userProfileController = function (UserProfile) {
const getUserProfiles = async function (req, res) {
if (!await hasPermission(req.body.requestor.role, 'getUserProfiles')) {
+ if (!await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')
+ && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagementTab')) {
res.status(403).send('You are not authorized to view all users');
return;
+ }
}
if (cache.getCache('allusers')) {
diff --git a/src/controllers/wbsController.js b/src/controllers/wbsController.js
index 48b640061..815fc59d0 100644
--- a/src/controllers/wbsController.js
+++ b/src/controllers/wbsController.js
@@ -1,4 +1,4 @@
-const { hasPermission } = require('../utilities/permissions');
+const { hasPermission, hasIndividualPermission } = require('../utilities/permissions');
const wbsController = function (WBS) {
const getAllWBS = function (req, res) {
@@ -11,7 +11,9 @@ const wbsController = function (WBS) {
};
const postWBS = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postWbs')) {
+ if (!await hasPermission(req.body.requestor.role, 'postWbs')
+ && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')
+ && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagementTab')) {
res.status(403).send({ error: 'You are not authorized to create new projects.' });
return;
}
@@ -34,7 +36,8 @@ const wbsController = function (WBS) {
};
const deleteWBS = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteWbs')) {
+ if (!await hasPermission(req.body.requestor.role, 'deleteWbs')
+ && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')) {
res.status(403).send({ error: 'You are not authorized to delete projects.' });
return;
}
From d4f4ae237dd163dd4d839ec74618058c692aeef1 Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Sat, 23 Sep 2023 13:00:23 -0500
Subject: [PATCH 031/272] A possible fix for late update of user profiles
---
src/controllers/userProfileController.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 5f36e91a2..292ee17ed 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -57,12 +57,6 @@ const userProfileController = function (UserProfile) {
return;
}
- if (cache.getCache('allusers')) {
- const getData = JSON.parse(cache.getCache('allusers'));
- res.status(200).send(getData);
- return;
- }
-
UserProfile.find(
{},
'_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate',
@@ -79,6 +73,12 @@ const userProfileController = function (UserProfile) {
res.status(200).send(results);
})
.catch(error => res.status(404).send(error));
+
+ if (cache.getCache('allusers')) {
+ const getData = JSON.parse(cache.getCache('allusers'));
+ res.status(200).send(getData);
+ return;
+ }
};
const getProjectMembers = async function (req, res) {
From 2987b20350f29e5324d13f8b65170cd70e7fef67 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Mon, 25 Sep 2023 10:22:18 +0800
Subject: [PATCH 032/272] fix create new user issue
---
src/controllers/profileInitialSetupController.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index d5c955d88..01d497865 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -184,6 +184,7 @@ const profileInitialSetupController = function (ProfileInitialSetupToken, userPr
newUser.bioPosted = 'default';
newUser.privacySettings.email = req.body.privacySettings.email
newUser.privacySettings.phoneNumber = req.body.privacySettings.phoneNumber
+ newUser.teamCode = '';
const savedUser = await newUser.save();
emailSender(
From 0b50204c4971a6688be51cb76b9d39b63530979d Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Mon, 25 Sep 2023 17:06:27 -0700
Subject: [PATCH 033/272] Create role preset model/API
---
src/controllers/rolePresetsController.js | 79 +++++++++++++++++++++++
src/models/rolePreset.js | 14 ++++
src/routes/rolePresetRouter.js | 20 ++++++
src/startup/routes.js | 5 +-
src/utilities/createInitialPermissions.js | 23 +++++++
5 files changed, 140 insertions(+), 1 deletion(-)
create mode 100644 src/controllers/rolePresetsController.js
create mode 100644 src/models/rolePreset.js
create mode 100644 src/routes/rolePresetRouter.js
diff --git a/src/controllers/rolePresetsController.js b/src/controllers/rolePresetsController.js
new file mode 100644
index 000000000..63c182577
--- /dev/null
+++ b/src/controllers/rolePresetsController.js
@@ -0,0 +1,79 @@
+const { hasPermission } = require('../utilities/permissions');
+
+const rolePresetsController = function (Preset) {
+ const getPresetsByRole = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ res.status(403).send('You are not authorized to make changes to roles.');
+ return;
+ }
+
+ const { roleName } = req.params;
+ Preset.find({ roleName })
+ .then((results) => { res.status(200).send(results); })
+ .catch((error) => { res.status(400).send(error); });
+ };
+
+ const createNewPreset = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ res.status(403).send('You are not authorized to make changes to roles.');
+ return;
+ }
+
+ if (!req.body.roleName || !req.body.presetName || !req.body.permissions) {
+ res.status(400).send({ error: 'roleName, presetName, and permissions are mandatory fields.' });
+ return;
+ }
+
+ const preset = new Preset();
+ preset.roleName = req.body.roleName;
+ preset.presetName = req.body.presetName;
+ preset.permissions = req.body.permissions;
+ preset.save()
+ .then(res.status(200).send({ message: 'New preset created' }))
+ .catch(error => res.status(400).send({ error }));
+ };
+
+ const updatePresetById = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ res.status(403).send('You are not authorized to make changes to roles.');
+ return;
+ }
+
+ const { presetId } = req.params;
+ Preset.findById(presetId)
+ .then((record) => {
+ record.roleName = req.body.roleName;
+ record.presetName = req.body.presetName;
+ record.permissions = req.body.permissions;
+ record.save()
+ .then(results => res.status(201).send(results))
+ .catch(errors => res.status(400).send(errors));
+ })
+ .catch(error => res.status(400).send({ error }));
+ };
+
+ const deletePresetById = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ res.status(403).send('You are not authorized to make changes to roles.');
+ return;
+ }
+
+ const { presetId } = req.params;
+ Preset.findById(presetId)
+ .then((result) => {
+ result.remove()
+ .then(res.status(200).send({ message: 'Deleted preset' }))
+ .catch(error => res.status(400).send({ error }));
+ })
+ .catch(error => res.status(400).send({ error }));
+ };
+
+ return {
+ getPresetsByRole,
+ createNewPreset,
+ updatePresetById,
+ deletePresetById,
+ };
+};
+
+module.exports = rolePresetsController;
diff --git a/src/models/rolePreset.js b/src/models/rolePreset.js
new file mode 100644
index 000000000..1bf785e2d
--- /dev/null
+++ b/src/models/rolePreset.js
@@ -0,0 +1,14 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+
+const RolePermissionPresets = new Schema({
+ roleName: { type: String, required: true },
+ presetName: { type: String, required: true },
+ permissions: [String],
+});
+
+// RolePermissionPresets.createIndex({ roleName: 1, presetName: 1 }, { unique: true });
+
+module.exports = mongoose.model('rolePermissionPresets', RolePermissionPresets, 'rolePermissionPresets');
diff --git a/src/routes/rolePresetRouter.js b/src/routes/rolePresetRouter.js
new file mode 100644
index 000000000..8b522c7ee
--- /dev/null
+++ b/src/routes/rolePresetRouter.js
@@ -0,0 +1,20 @@
+const express = require('express');
+
+const routes = function (rolePreset) {
+ const controller = require('../controllers/rolePresetsController')(rolePreset);
+ const PresetsRouter = express.Router();
+
+ PresetsRouter.route('/rolePreset')
+ .post(controller.createNewPreset);
+
+ PresetsRouter.route('/rolePreset/:roleName')
+ .get(controller.getPresetsByRole);
+
+ PresetsRouter.route('/rolePreset/:presetId')
+ .put(controller.updatePresetById)
+ .delete(controller.deletePresetById);
+
+return PresetsRouter;
+};
+
+module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 6e000002e..665792ba6 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -15,6 +15,7 @@ const badge = require('../models/badge');
const inventoryItem = require('../models/inventoryItem');
const inventoryItemType = require('../models/inventoryItemType');
const role = require('../models/role');
+const rolePreset = require('../models/rolePreset');
const ownerMessage = require('../models/ownerMessage');
const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
@@ -47,6 +48,7 @@ const profileInitialSetupRouter = require('../routes/profileInitialSetupRouter')
const taskEditSuggestion = require('../models/taskEditSuggestion');
const taskEditSuggestionRouter = require('../routes/taskEditSuggestionRouter')(taskEditSuggestion);
const roleRouter = require('../routes/roleRouter')(role);
+const rolePresetRouter = require('../routes/rolePresetRouter')(rolePreset);
const ownerMessageRouter = require('../routes/ownerMessageRouter')(ownerMessage);
const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter')(ownerStandardMessage);
@@ -77,9 +79,10 @@ module.exports = function (app) {
app.use('/api', timeZoneAPIRouter);
app.use('/api', taskEditSuggestionRouter);
app.use('/api', roleRouter);
+ app.use('/api', rolePresetRouter);
app.use('/api', ownerMessageRouter);
app.use('/api', ownerStandardMessageRouter);
- app.use('/api', profileInitialSetupRouter)
+ app.use('/api', profileInitialSetupRouter);
app.use('/api', reasonRouter);
app.use('/api', informationRouter);
app.use('/api', mouseoverTextRouter);
diff --git a/src/utilities/createInitialPermissions.js b/src/utilities/createInitialPermissions.js
index 9ac0f12b0..a5c69d87f 100644
--- a/src/utilities/createInitialPermissions.js
+++ b/src/utilities/createInitialPermissions.js
@@ -1,4 +1,5 @@
const Role = require('../models/role');
+const RolePreset = require('../models/rolePreset');
const User = require('../models/userProfile');
const permissionsRoles = [
@@ -222,6 +223,7 @@ const createInitialPermissions = async () => {
// Get Roles From DB
const allRoles = await Role.find();
+ const allPresets = await RolePreset.find();
const onlyUpdateOwner = false;
const promises = [];
@@ -249,6 +251,27 @@ const createInitialPermissions = async () => {
}));
}
}
+
+ // Update Default presets
+ const presetDataBase = allPresets.find(preset => preset.roleName === roleName && preset.presetName === 'default');
+
+ // If role does not exist in db, create it
+ if (!presetDataBase) {
+ const defaultPreset = new RolePreset();
+ defaultPreset.roleName = roleName;
+ defaultPreset.presetName = 'default';
+ defaultPreset.permissions = permissions;
+ defaultPreset.save();
+
+ // If role exists in db and is not updated, update default
+ } else if (!presetDataBase.permissions.every(perm => permissions.includes(perm)) || !permissions.every(perm => presetDataBase.permissions.includes(perm))) {
+ const roleId = presetDataBase._id;
+
+ promises.push(Role.findById(roleId, (_, record) => {
+ record.permissions = permissions;
+ record.save();
+ }));
+ }
}
await Promise.all(promises);
};
From 5d732a8a224579bb44af576e9f26a86bfb1d134a Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Mon, 25 Sep 2023 17:29:36 -0700
Subject: [PATCH 034/272] Fix hasPermission() to include individual perms
---
src/utilities/permissions.js | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/utilities/permissions.js b/src/utilities/permissions.js
index e00d864f2..2e2ac4194 100644
--- a/src/utilities/permissions.js
+++ b/src/utilities/permissions.js
@@ -1,15 +1,19 @@
const Role = require('../models/role');
-const UserProfile = require('../models/userProfile');
+const UserProfile = require('../models/userProfile');
-const hasPermission = async (role, action) => Role.findOne({ roleName: role })
- .exec()
- .then(({ permissions }) => permissions.includes(action));
+
+const hasRolePermission = async (role, action) => Role.findOne({ roleName: role })
+ .exec()
+ .then(({ permissions }) => permissions.includes(action));
const hasIndividualPermission = async (userId, action) => UserProfile.findById(userId)
.select('permissions')
.exec()
.then(({ permissions }) => permissions.frontPermissions.includes(action));
+
+const hasPermission = async (requestor, action) => hasRolePermission(requestor.role, action) || hasIndividualPermission(requestor.requestorId, action);
+
const canRequestorUpdateUser = (requestorId, userId) => {
const allowedIds = ['63feae337186de1898fa8f51', // dev jae@onecommunityglobal.org
'5baac381e16814009017678c', // dev one.community@me.com
@@ -29,4 +33,4 @@ const canRequestorUpdateUser = (requestorId, userId) => {
return !(protectedIds.includes(userId) && !allowedIds.includes(requestorId));
};
-module.exports = { hasPermission, hasIndividualPermission, canRequestorUpdateUser };
+module.exports = { hasPermission, canRequestorUpdateUser };
From 7c70e5de5a3655c8c98f19e5b080266793b66c3f Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Mon, 25 Sep 2023 17:30:20 -0700
Subject: [PATCH 035/272] updated hasPermission() calls for updated params
---
src/controllers/badgeController.js | 12 +++----
src/controllers/inventoryController.js | 26 ++++++++--------
.../popupEditorBackupController.js | 4 +--
src/controllers/popupEditorController.js | 4 +--
src/controllers/projectController.js | 12 +++----
src/controllers/reportsController.js | 4 +--
src/controllers/rolesController.js | 6 ++--
src/controllers/taskController.js | 14 ++++-----
src/controllers/teamController.js | 8 ++---
src/controllers/timeEntryController.js | 6 ++--
src/controllers/timeZoneAPIController.js | 3 +-
src/controllers/userProfileController.js | 31 +++++++++----------
src/controllers/wbsController.js | 4 +--
13 files changed, 66 insertions(+), 68 deletions(-)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 6238c381e..62bad6399 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -1,11 +1,11 @@
const mongoose = require('mongoose');
const UserProfile = require('../models/userProfile');
-const { hasPermission, hasIndividualPermission } = require('../utilities/permissions');
+const { hasPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const badgeController = function (Badge) {
const getAllBadges = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'seeBadges') && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeBadges')) {
+ if (!await hasPermission(req.body.requestor, 'seeBadges')) {
res.status(403).send('You are not authorized to view all badge data.');
return;
}
@@ -26,7 +26,7 @@ const badgeController = function (Badge) {
};
const assignBadges = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'assignBadges')) {
+ if (!await hasPermission(req.body.requestor, 'assignBadges')) {
res.status(403).send('You are not authorized to assign badges.');
return;
}
@@ -57,7 +57,7 @@ const badgeController = function (Badge) {
};
const postBadge = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'createBadges')) {
+ if (!await hasPermission(req.body.requestor, 'createBadges')) {
res.status(403).send({ error: 'You are not authorized to create new badges.' });
return;
}
@@ -91,7 +91,7 @@ const badgeController = function (Badge) {
};
const deleteBadge = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteBadges')) {
+ if (!await hasPermission(req.body.requestor, 'deleteBadges')) {
res.status(403).send({ error: 'You are not authorized to delete badges.' });
return;
}
@@ -112,7 +112,7 @@ const badgeController = function (Badge) {
};
const putBadge = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'updateBadges')) {
+ if (!await hasPermission(req.body.requestor, 'updateBadges')) {
res.status(403).send({ error: 'You are not authorized to update badges.' });
return;
}
diff --git a/src/controllers/inventoryController.js b/src/controllers/inventoryController.js
index bc0902aeb..f1e00402d 100644
--- a/src/controllers/inventoryController.js
+++ b/src/controllers/inventoryController.js
@@ -7,7 +7,7 @@ const escapeRegex = require('../utilities/escapeRegex');
const inventoryController = function (Item, ItemType) {
const getAllInvInProjectWBS = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getAllInvInProjectWBS')) {
+ if (!await hasPermission(req.body.requestor, 'getAllInvInProjectWBS')) {
return res.status(403).send('You are not authorized to view inventory data.');
}
// use req.params.projectId and wbsId
@@ -40,7 +40,7 @@ const inventoryController = function (Item, ItemType) {
};
const postInvInProjectWBS = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postInvInProjectWBS')) {
+ if (!await hasPermission(req.body.requestor, 'postInvInProjectWBS')) {
return res.status(403).send('You are not authorized to view inventory data.');
}
// use req.body.projectId and req.body.wbsId req.body.quantity,
@@ -108,7 +108,7 @@ const inventoryController = function (Item, ItemType) {
const getAllInvInProject = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getAllInvInProject')) {
+ if (!await hasPermission(req.body.requestor, 'getAllInvInProject')) {
return res.status(403).send('You are not authorized to view inventory data.');
}
// same as getAllInvInProjectWBS but just using only the project to find the items of inventory
@@ -140,7 +140,7 @@ const inventoryController = function (Item, ItemType) {
};
const postInvInProject = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postInvInProject')) {
+ if (!await hasPermission(req.body.requestor, 'postInvInProject')) {
return res.status(403).send('You are not authorized to post new inventory data.');
}
// same as posting an item inProjectWBS but the WBS is uanassigned(i.e. null)
@@ -194,7 +194,7 @@ const inventoryController = function (Item, ItemType) {
};
const transferInvById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'transferInvById')) {
+ if (!await hasPermission(req.body.requestor, 'transferInvById')) {
return res.status(403).send('You are not authorized to transfer inventory data.');
}
// This function transfer inventory by id
@@ -283,7 +283,7 @@ const inventoryController = function (Item, ItemType) {
const delInvById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'delInvById')) {
+ if (!await hasPermission(req.body.requestor, 'delInvById')) {
return res.status(403).send('You are not authorized to waste inventory.');
}
// send result just sending something now to have it work and not break anything
@@ -372,7 +372,7 @@ const inventoryController = function (Item, ItemType) {
};
const unWasteInvById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'unWasteInvById')) {
+ if (!await hasPermission(req.body.requestor, 'unWasteInvById')) {
return res.status(403).send('You are not authorized to unwaste inventory.');
}
const properUnWaste = await Item.findOne({ _id: req.params.invId, quantity: { $gte: req.body.quantity }, wasted: true }).select('_id').lean();
@@ -453,7 +453,7 @@ const inventoryController = function (Item, ItemType) {
};
const getInvIdInfo = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getInvIdInfo')) {
+ if (!await hasPermission(req.body.requestor, 'getInvIdInfo')) {
return res.status(403).send('You are not authorized to get inventory by id.');
}
// req.params.invId
@@ -465,7 +465,7 @@ const inventoryController = function (Item, ItemType) {
};
const putInvById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putInvById')) {
+ if (!await hasPermission(req.body.requestor, 'putInvById')) {
return res.status(403).send('You are not authorized to edit inventory by id.');
}
// update the inv by id.
@@ -493,7 +493,7 @@ const inventoryController = function (Item, ItemType) {
};
const getInvTypeById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getInvTypeById')) {
+ if (!await hasPermission(req.body.requestor, 'getInvTypeById')) {
return res.status(403).send('You are not authorized to get inv type by id.');
}
// send result just sending something now to have it work and not break anything
@@ -504,7 +504,7 @@ const inventoryController = function (Item, ItemType) {
};
const putInvType = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putInvType')) {
+ if (!await hasPermission(req.body.requestor, 'putInvType')) {
return res.status(403).send('You are not authorized to edit an inventory type.');
}
const { typeId } = req.params;
@@ -527,7 +527,7 @@ const inventoryController = function (Item, ItemType) {
};
const getAllInvType = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getAllInvType')) {
+ if (!await hasPermission(req.body.requestor, 'getAllInvType')) {
return res.status(403).send('You are not authorized to get all inventory.');
}
// send result just sending something now to have it work and not break anything
@@ -537,7 +537,7 @@ const inventoryController = function (Item, ItemType) {
};
const postInvType = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postInvType')) {
+ if (!await hasPermission(req.body.requestor, 'postInvType')) {
return res.status(403).send('You are not authorized to save an inventory type.');
}
return ItemType.find({ name: { $regex: escapeRegex(req.body.name), $options: 'i' } })
diff --git a/src/controllers/popupEditorBackupController.js b/src/controllers/popupEditorBackupController.js
index 7b2493909..21eccaf8f 100644
--- a/src/controllers/popupEditorBackupController.js
+++ b/src/controllers/popupEditorBackupController.js
@@ -20,7 +20,7 @@ const popupEditorBackupController = function (PopupEditorBackups) {
const createPopupEditorBackup = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'createPopup')) {
+ if (!await hasPermission(req.body.requestor, 'createPopup')) {
res
.status(403)
.send({ error: 'You are not authorized to create new popup' });
@@ -46,7 +46,7 @@ const popupEditorBackupController = function (PopupEditorBackups) {
};
const updatePopupEditorBackup = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'updatePopup')) {
+ if (!await hasPermission(req.body.requestor, 'updatePopup')) {
res
.status(403)
.send({ error: 'You are not authorized to create new popup' });
diff --git a/src/controllers/popupEditorController.js b/src/controllers/popupEditorController.js
index 25eed80dd..71dcb7b69 100644
--- a/src/controllers/popupEditorController.js
+++ b/src/controllers/popupEditorController.js
@@ -15,7 +15,7 @@ const popupEditorController = function (PopupEditors) {
const createPopupEditor = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'createPopup')) {
+ if (!await hasPermission(req.body.requestor, 'createPopup')) {
res
.status(403)
.send({ error: 'You are not authorized to create new popup' });
@@ -38,7 +38,7 @@ const popupEditorController = function (PopupEditors) {
};
const updatePopupEditor = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'updatePopup')) {
+ if (!await hasPermission(req.body.requestor, 'updatePopup')) {
res
.status(403)
.send({ error: 'You are not authorized to create new popup' });
diff --git a/src/controllers/projectController.js b/src/controllers/projectController.js
index 6bac2124c..a88378985 100644
--- a/src/controllers/projectController.js
+++ b/src/controllers/projectController.js
@@ -14,9 +14,9 @@ const projectController = function (Project) {
.catch(error => res.status(404).send(error));
};
- const deleteProject = function (req, res) {
- if (!hasPermission(req.body.requestor.role, 'deleteProject')) {
- res.status(403).send({ error: 'You are not authorized to delete projects.' });
+ const deleteProject = async function (req, res) {
+ if (!await hasPermission(req.body.requestor, 'deleteProject')) {
+ res.status(403).send({ error: 'You are not authorized to delete projects.' });
return;
}
const { projectId } = req.params;
@@ -46,7 +46,7 @@ const projectController = function (Project) {
};
const postProject = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postProject')) {
+ if (!await hasPermission(req.body.requestor, 'postProject')) {
res.status(403).send({ error: 'You are not authorized to create new projects.' });
return;
}
@@ -77,7 +77,7 @@ const projectController = function (Project) {
const putProject = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putProject')) {
+ if (!await hasPermission(req.body.requestor, 'putProject')) {
res.status(403).send('You are not authorized to make changes in the projects.');
return;
}
@@ -124,7 +124,7 @@ const projectController = function (Project) {
const assignProjectToUsers = async function (req, res) {
// verify requestor is administrator, projectId is passed in request params and is valid mongoose objectid, and request body contains an array of users
- if (!await hasPermission(req.body.requestor.role, 'assignProjectToUsers')) {
+ if (!await hasPermission(req.body.requestor, 'assignProjectToUsers')) {
res.status(403).send({ error: 'You are not authorized to perform this operation' });
return;
}
diff --git a/src/controllers/reportsController.js b/src/controllers/reportsController.js
index e139924fa..8f4aba87b 100644
--- a/src/controllers/reportsController.js
+++ b/src/controllers/reportsController.js
@@ -1,9 +1,9 @@
const reporthelper = require('../helpers/reporthelper')();
-const { hasPermission, hasIndividualPermission } = require('../utilities/permissions');
+const { hasPermission } = require('../utilities/permissions');
const reportsController = function () {
const getWeeklySummaries = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getWeeklySummaries') && !await hasIndividualPermission(req.body.requestor.requestorId, 'getWeeklySummaries')) {
+ if (!await hasPermission(req.body.requestor, 'getWeeklySummaries')) {
res.status(403).send('You are not authorized to view all users');
return;
}
diff --git a/src/controllers/rolesController.js b/src/controllers/rolesController.js
index a97e9408f..d3d9f8310 100644
--- a/src/controllers/rolesController.js
+++ b/src/controllers/rolesController.js
@@ -10,7 +10,7 @@ const rolesController = function (Role) {
};
const createNewRole = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postRole')) {
+ if (!await hasPermission(req.body.requestor, 'postRole')) {
res.status(403).send('You are not authorized to create new roles.');
return;
}
@@ -39,7 +39,7 @@ const rolesController = function (Role) {
const updateRoleById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ if (!await hasPermission(req.body.requestor, 'putRole')) {
res.status(403).send('You are not authorized to make changes to roles.');
return;
}
@@ -67,7 +67,7 @@ const rolesController = function (Role) {
};
const deleteRoleById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteRole')) {
+ if (!await hasPermission(req.body.requestor, 'deleteRole')) {
res.status(403).send('You are not authorized to delete roles.');
return;
}
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index 79222ed4b..d5e048537 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -390,7 +390,7 @@ const taskController = function (Task) {
};
const importTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor.role, 'importTask')) {
+ if (!await hasPermission(req.body.requestor, 'importTask')) {
res
.status(403)
.send({ error: 'You are not authorized to create new Task.' });
@@ -420,7 +420,7 @@ const taskController = function (Task) {
};
const postTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor.role, 'postTask')) {
+ if (!await hasPermission(req.body.requestor, 'postTask')) {
res
.status(403)
.send({ error: 'You are not authorized to create new Task.' });
@@ -456,7 +456,7 @@ const taskController = function (Task) {
};
const updateNum = async (req, res) => {
- if (!await hasPermission(req.body.requestor.role, 'updateNum')) {
+ if (!await hasPermission(req.body.requestor, 'updateNum')) {
res
.status(403)
.send({ error: 'You are not authorized to create new projects.' });
@@ -593,7 +593,7 @@ const taskController = function (Task) {
};
const deleteTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor.role, 'deleteTask')) {
+ if (!await hasPermission(req.body.requestor, 'deleteTask')) {
res
.status(403)
.send({ error: 'You are not authorized to deleteTasks.' });
@@ -642,7 +642,7 @@ const taskController = function (Task) {
};
const deleteTaskByWBS = async (req, res) => {
- if (!await hasPermission(req.body.requestor.role, 'deleteTask')) {
+ if (!await hasPermission(req.body.requestor, 'deleteTask')) {
res
.status(403)
.send({ error: 'You are not authorized to deleteTasks.' });
@@ -673,7 +673,7 @@ const taskController = function (Task) {
};
const updateTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor.role, 'updateTask')) {
+ if (!await hasPermission(req.body.requestor, 'updateTask')) {
res.status(403).send({ error: 'You are not authorized to update Task.' });
return;
}
@@ -689,7 +689,7 @@ const taskController = function (Task) {
};
const swap = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'swapTask')) {
+ if (!await hasPermission(req.body.requestor, 'swapTask')) {
res
.status(403)
.send({ error: 'You are not authorized to create new projects.' });
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index 1072f1fb4..0486a5df7 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -17,7 +17,7 @@ const teamcontroller = function (Team) {
.catch(error => res.send(error).status(404));
};
const postTeam = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postTeam')) {
+ if (!await hasPermission(req.body.requestor, 'postTeam')) {
res.status(403).send({ error: 'You are not authorized to create teams.' });
return;
}
@@ -34,7 +34,7 @@ const teamcontroller = function (Team) {
.catch(error => res.send(error).status(404));
};
const deleteTeam = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteTeam')) {
+ if (!await hasPermission(req.body.requestor, 'deleteTeam')) {
res.status(403).send({ error: 'You are not authorized to delete teams.' });
return;
}
@@ -57,7 +57,7 @@ const teamcontroller = function (Team) {
});
};
const putTeam = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putTeam')) {
+ if (!await hasPermission(req.body.requestor, 'putTeam')) {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
@@ -84,7 +84,7 @@ const teamcontroller = function (Team) {
const assignTeamToUsers = async function (req, res) {
// verify requestor is administrator, teamId is passed in request params and is valid mongoose objectid, and request body contains an array of users
- if (!await hasPermission(req.body.requestor.role, 'assignTeamToUsers')) {
+ if (!await hasPermission(req.body.requestor, 'assignTeamToUsers')) {
res.status(403).send({ error: 'You are not authorized to perform this operation' });
return;
}
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index e83a7e31b..6b13d9331 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -106,7 +106,7 @@ const timeEntrycontroller = function (TimeEntry) {
return res.status(400).send({ error: `No valid records found for ${req.params.timeEntryId}` });
}
- if (!(await hasPermission(req.body.requestor.role, 'editTimeEntry') || timeEntry.personId.toString() === req.body.requestor.requestorId.toString())) {
+ if (!(await hasPermission(req.body.requestor, 'editTimeEntry') || timeEntry.personId.toString() === req.body.requestor.requestorId.toString())) {
return res.status(403).send({ error: 'Unauthorized request' });
}
@@ -153,7 +153,7 @@ const timeEntrycontroller = function (TimeEntry) {
if (initialSeconds !== totalSeconds
&& timeEntry.isTangible
&& req.body.requestor.requestorId === timeEntry.personId.toString()
- && !await hasPermission(req.body.requestor.role, 'editTimeEntry')
+ && !await hasPermission(req.body.requestor, 'editTimeEntry')
) {
const requestor = await userProfile.findById(req.body.requestor.requestorId);
requestor.timeEntryEditHistory.push({
@@ -463,7 +463,7 @@ const timeEntrycontroller = function (TimeEntry) {
if (
record.personId.toString()
=== req.body.requestor.requestorId.toString()
- || await hasPermission(req.body.requestor.role, 'deleteTimeEntry')
+ || await hasPermission(req.body.requestor, 'deleteTimeEntry')
) {
// Revert this tangible timeEntry of related task's hoursLogged
if (record.isTangible === true) {
diff --git a/src/controllers/timeZoneAPIController.js b/src/controllers/timeZoneAPIController.js
index 2ed0792c9..3c4df0a22 100644
--- a/src/controllers/timeZoneAPIController.js
+++ b/src/controllers/timeZoneAPIController.js
@@ -2,14 +2,13 @@ const { hasPermission } = require('../utilities/permissions');
const timeZoneAPIController = function () {
const getTimeZoneAPIKey = async (req, res) => {
- const requestorRole = req.body.requestor.role;
const premiumKey = process.env.TIMEZONE_PREMIUM_KEY;
const commonKey = process.env.TIMEZONE_COMMON_KEY;
if (!req.body.requestor.role) {
res.status(403).send('Unauthorized Request');
return;
}
- if (await hasPermission(requestorRole, 'getTimeZoneAPIKey')) {
+ if (await hasPermission(req.body.requestor, 'getTimeZoneAPIKey')) {
res.status(200).send({ userAPIKey: premiumKey });
return;
}
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 244e7cf45..b42bf705b 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -35,7 +35,7 @@ async function ValidatePassword(req, res) {
return;
}
// Verify request is authorized by self or adminsitrator
- if (!userId === requestor.requestorId && !await hasPermission(requestor.role, 'updatePassword')) {
+ if (!userId === requestor.requestorId && !await hasPermission(req.body.requestor, 'updatePassword')) {
res.status(403).send({
error: "You are unauthorized to update this user's password",
});
@@ -52,7 +52,7 @@ async function ValidatePassword(req, res) {
const userProfileController = function (UserProfile) {
const getUserProfiles = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getUserProfiles')) {
+ if (!await hasPermission(req.body.requestor, 'getUserProfiles')) {
res.status(403).send('You are not authorized to view all users');
return;
}
@@ -82,7 +82,7 @@ const userProfileController = function (UserProfile) {
};
const getProjectMembers = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getProjectMembers')) {
+ if (!await hasPermission(req.body.requestor, 'getProjectMembers')) {
res.status(403).send('You are not authorized to view all users');
return;
}
@@ -104,12 +104,12 @@ const userProfileController = function (UserProfile) {
};
const postUserProfile = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postUserProfile')) {
+ if (!await hasPermission(req.body.requestor, 'postUserProfile')) {
res.status(403).send('You are not authorized to create new users');
return;
}
- if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor.role, 'addDeleteEditOwners')) {
+ if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
res.status(403).send('You are not authorized to create new owners');
return;
}
@@ -225,7 +225,7 @@ const userProfileController = function (UserProfile) {
const userid = req.params.userId;
const isRequestorAuthorized = !!(
canRequestorUpdateUser(req.body.requestor.requestorId, userid) && (
- await hasPermission(req.body.requestor.role, 'putUserProfile')
+ await hasPermission(req.body.requestor, 'putUserProfile')
|| req.body.requestor.requestorId === userid
)
);
@@ -235,7 +235,7 @@ const userProfileController = function (UserProfile) {
return;
}
- if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor.role, 'addDeleteEditOwners')) {
+ if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
res.status(403).send('You are not authorized to update this user');
return;
}
@@ -296,7 +296,7 @@ const userProfileController = function (UserProfile) {
userIdx = allUserData.findIndex(users => users._id === userid);
userData = allUserData[userIdx];
}
- if (await hasPermission(req.body.requestor.role, 'putUserProfileImportantInfo')) {
+ if (await hasPermission(req.body.requestor, 'putUserProfileImportantInfo')) {
record.role = req.body.role;
record.isRehireable = req.body.isRehireable;
record.isActive = req.body.isActive;
@@ -360,7 +360,7 @@ const userProfileController = function (UserProfile) {
record.bioPosted = req.body.bioPosted || 'default';
- if (await hasPermission(req.body.requestor.role, 'putUserProfilePermissions')) {
+ if (await hasPermission(req.body.requestor, 'putUserProfilePermissions')) {
record.permissions = req.body.permissions;
}
@@ -380,7 +380,7 @@ const userProfileController = function (UserProfile) {
userData.createdDate = record.createdDate.toISOString();
}
}
- if (await hasPermission(req.body.requestor.role, 'infringementAuthorizer')) {
+ if (await hasPermission(req.body.requestor, 'infringementAuthorizer')) {
record.infringements = req.body.infringements;
}
@@ -410,12 +410,12 @@ const userProfileController = function (UserProfile) {
const deleteUserProfile = async function (req, res) {
const { option, userId } = req.body;
- if (!await hasPermission(req.body.requestor.role, 'deleteUserProfile')) {
+ if (!await hasPermission(req.body.requestor, 'deleteUserProfile')) {
res.status(403).send('You are not authorized to delete users');
return;
}
- if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor.role, 'addDeleteEditOwners')) {
+ if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
res.status(403).send('You are not authorized to delete this user');
return;
}
@@ -586,7 +586,7 @@ const userProfileController = function (UserProfile) {
});
}
// Verify request is authorized by self or adminsitrator
- if (!userId === requestor.requestorId && !await hasPermission(requestor.role, 'updatePassword')) {
+ if (!userId === requestor.requestorId && !await hasPermission(req.body.requestor, 'updatePassword')) {
return res.status(403).send({
error: "You are unauthorized to update this user's password",
});
@@ -647,11 +647,10 @@ const userProfileController = function (UserProfile) {
}
const userid = mongoose.Types.ObjectId(req.params.userId);
- const { role } = req.body.requestor;
let validroles = ['Volunteer', 'Manager', 'Administrator', 'Core Team', 'Owner', 'Mentor'];
- if (await hasPermission(role, 'getReporteesLimitRoles')) {
+ if (await hasPermission(req.body.requestor, 'getReporteesLimitRoles')) {
validroles = ['Volunteer', 'Manager'];
}
@@ -722,7 +721,7 @@ const userProfileController = function (UserProfile) {
});
return;
}
- if (!await hasPermission(req.body.requestor.role, 'changeUserStatus')) {
+ if (!await hasPermission(req.body.requestor, 'changeUserStatus')) {
res.status(403).send('You are not authorized to change user status');
return;
}
diff --git a/src/controllers/wbsController.js b/src/controllers/wbsController.js
index 48b640061..fa7f4427f 100644
--- a/src/controllers/wbsController.js
+++ b/src/controllers/wbsController.js
@@ -11,7 +11,7 @@ const wbsController = function (WBS) {
};
const postWBS = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'postWbs')) {
+ if (!await hasPermission(req.body.requestor, 'postWbs')) {
res.status(403).send({ error: 'You are not authorized to create new projects.' });
return;
}
@@ -34,7 +34,7 @@ const wbsController = function (WBS) {
};
const deleteWBS = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteWbs')) {
+ if (!await hasPermission(req.body.requestor, 'deleteWbs')) {
res.status(403).send({ error: 'You are not authorized to delete projects.' });
return;
}
From bcf9fd94771bc143d3213fbe86ffa576fcfe308d Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Mon, 25 Sep 2023 17:56:24 -0700
Subject: [PATCH 036/272] Fix await
---
src/utilities/permissions.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/utilities/permissions.js b/src/utilities/permissions.js
index 2e2ac4194..7b5d4a245 100644
--- a/src/utilities/permissions.js
+++ b/src/utilities/permissions.js
@@ -11,8 +11,7 @@ const hasIndividualPermission = async (userId, action) => UserProfile.findById(u
.exec()
.then(({ permissions }) => permissions.frontPermissions.includes(action));
-
-const hasPermission = async (requestor, action) => hasRolePermission(requestor.role, action) || hasIndividualPermission(requestor.requestorId, action);
+const hasPermission = async (requestor, action) => await hasRolePermission(requestor.role, action) || hasIndividualPermission(requestor.requestorId, action);
const canRequestorUpdateUser = (requestorId, userId) => {
const allowedIds = ['63feae337186de1898fa8f51', // dev jae@onecommunityglobal.org
From dd55a3223ed8d27c2f56cd5b0094e127bee04df8 Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Wed, 27 Sep 2023 14:38:05 +0000
Subject: [PATCH 037/272] removed suggestionModalData.json file
---
src/constants/suggestionModalData.json | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 src/constants/suggestionModalData.json
diff --git a/src/constants/suggestionModalData.json b/src/constants/suggestionModalData.json
deleted file mode 100644
index e5b735091..000000000
--- a/src/constants/suggestionModalData.json
+++ /dev/null
@@ -1 +0,0 @@
-{"suggestion":["Identify and remedy poor client and/or user service experiences","Identify bright spots and enhance positive service experiences","Make fundamental changes to our programs and/or operations","Inform the development of new programs/projects","Identify where we are less inclusive or equitable across demographic groups","Strengthen relationships with the people we serve","Understand people's needs and how we can help them achieve their goals","Other"],"field":[]}
\ No newline at end of file
From a075a3697bbf3aa6862ab599ce628fdc2180e290 Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Wed, 27 Sep 2023 14:40:08 +0000
Subject: [PATCH 038/272] changed all functions to use localized suggestion
data
---
src/controllers/dashBoardController.js | 109 +++++++++----------------
1 file changed, 37 insertions(+), 72 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 742bfe4d8..c9cdbd588 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -100,7 +100,7 @@ const dashboardcontroller = function () {
${actual}
Visual Proof (screenshots, videos, text)
${visual}
- Severity/Priority (How Bad is the Bug?
+ Severity/Priority (How Bad is the Bug?)
${severity}
Thank you,
One Community
`;
@@ -146,58 +146,38 @@ const dashboardcontroller = function () {
}
};
- const getSuggestionFilePath = async () => {
- // Define a base path based on the process.cwd()
- const basePath = process.cwd();
- console.log(basePath, "basePath");
-
- // Define the relative path to the JSON file (adjust as needed)
- const relativePath = "src/constants/suggestionModalData.json";
-
- // Combine the base path and relative path to create the full path
- const fullPath = path.join(basePath, relativePath);
-
- return fullPath;
- };
-
- const readSuggestionFile = async () => {
- // Specify the absolute path to the JSON file
- const filepath = await getSuggestionFilePath();
-
- try {
- // Check if the file exists
- await fs.access(filepath);
-
- // Read and parse the file
- const readfile = await fs.readFile(filepath, "utf8");
- const parsedData = JSON.parse(readfile);
- return parsedData;
- } catch (err) {
- console.error("Error reading suggestionModalData.json:", err);
- return null; // Handle the error appropriately
- }
+ const suggestionData = {
+ suggestion: [
+ "Identify and remedy poor client and/or user service experiences",
+ "Identify bright spots and enhance positive service experiences",
+ "Make fundamental changes to our programs and/or operations",
+ "Inform the development of new programs/projects",
+ "Identify where we are less inclusive or equitable across demographic groups",
+ "Strengthen relationships with the people we serve",
+ "Understand people's needs and how we can help them achieve their goals",
+ "Other",
+ ],
+ field: [],
};
- // create suggestion emailbody
const getsuggestionEmailBody = async (...args) => {
- const readfile = await readSuggestionFile();
let fieldaaray = [];
- if (readfile.field.length) {
- fieldaaray = readfile.field.map(
+ if (suggestionData.field.length) {
+ fieldaaray = suggestionData.field.map(
(item) => `${item}
- ${args[3][item]}
`
+ ${args[3][item]}
`
);
}
const text = `New Suggestion:
- Suggestion Category:
- ${args[0]}
- Suggestion:
- ${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ""}
- Wants Feedback:
- ${args[2]}
- Thank you,
- One Community
`;
+ Suggestion Category:
+ ${args[0]}
+ Suggestion:
+ ${args[1]}
+ ${fieldaaray.length > 0 ? fieldaaray : ""}
+ Wants Feedback:
+ ${args[2]}
+ Thank you,
+ One Community
`;
return text;
};
@@ -225,54 +205,39 @@ const dashboardcontroller = function () {
const getSuggestionOption = async (req, res) => {
try {
- const readfile = await readSuggestionFile();
- if (readfile) {
- res.status(200).send(readfile);
+ if (suggestionData) {
+ res.status(200).send(suggestionData);
} else {
- res.status(404).send("Suggestion file not found.");
+ res.status(404).send("Suggestion data not found.");
}
} catch (error) {
- console.error("Error reading suggestion file:", error);
+ console.error("Error getting suggestion data:", error);
res.status(500).send("Internal Server Error");
}
};
- // add new suggestion category or field
const editSuggestionOption = async (req, res) => {
try {
- // Read the current suggestion data
- let readfile = await readSuggestionFile();
-
if (req.body.suggestion) {
if (req.body.action === "add") {
- readfile.suggestion.unshift(req.body.newField);
+ suggestionData.suggestion.unshift(req.body.newField);
}
if (req.body.action === "delete") {
- readfile = {
- ...readfile,
- suggestion: readfile.suggestion.filter(
- (item, index) => index + 1 !== +req.body.newField
- ),
- };
+ suggestionData.suggestion = suggestionData.suggestion.filter(
+ (item, index) => index + 1 !== +req.body.newField
+ );
}
} else {
if (req.body.action === "add") {
- readfile.field.unshift(req.body.newField);
+ suggestionData.field.unshift(req.body.newField);
}
if (req.body.action === "delete") {
- readfile = {
- ...readfile,
- field: readfile.field.filter((item) => item !== req.body.newField),
- };
+ suggestionData.field = suggestionData.field.filter(
+ (item) => item !== req.body.newField
+ );
}
}
- // Get the file path
- const filepath = await getSuggestionFilePath();
-
- // Write the updated data back to the file
- await fs.writeFile(filepath, JSON.stringify(readfile, null, 2));
-
res.status(200).send("success");
} catch (error) {
console.error("Error editing suggestion option:", error);
From 1b9f75a788ab4290efc310d14283246ee118d549 Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Thu, 28 Sep 2023 13:02:47 -0700
Subject: [PATCH 039/272] Change HTTP status codes
---
src/controllers/rolePresetsController.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/rolePresetsController.js b/src/controllers/rolePresetsController.js
index 63c182577..3642627f7 100644
--- a/src/controllers/rolePresetsController.js
+++ b/src/controllers/rolePresetsController.js
@@ -29,7 +29,7 @@ const rolePresetsController = function (Preset) {
preset.presetName = req.body.presetName;
preset.permissions = req.body.permissions;
preset.save()
- .then(res.status(200).send({ message: 'New preset created' }))
+ .then(result => res.status(201).send({ newPreset: result, message: 'New preset created' }))
.catch(error => res.status(400).send({ error }));
};
@@ -46,7 +46,7 @@ const rolePresetsController = function (Preset) {
record.presetName = req.body.presetName;
record.permissions = req.body.permissions;
record.save()
- .then(results => res.status(201).send(results))
+ .then(results => res.status(200).send(results))
.catch(errors => res.status(400).send(errors));
})
.catch(error => res.status(400).send({ error }));
From 0c0373bf3f03c1a73370673df00f36a6ee2e6ff3 Mon Sep 17 00:00:00 2001
From: robertoooc
Date: Thu, 28 Sep 2023 16:21:55 -0700
Subject: [PATCH 040/272] added statement to clear user cache if needed so
profile page is updated immediately
---
src/controllers/teamController.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index 1072f1fb4..9fa20ab2b 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -1,6 +1,7 @@
const mongoose = require('mongoose');
const userProfile = require('../models/userProfile');
const { hasPermission } = require('../utilities/permissions');
+const cache = require('../utilities/nodeCache')();
const teamcontroller = function (Team) {
const getAllTeams = function (req, res) {
@@ -113,6 +114,8 @@ const teamcontroller = function (Team) {
users.forEach((element) => {
const { userId, operation } = element;
+ // if user's profile is stored in cache, clear it so when you visit their profile page it will be up to date
+ if(cache.hasCache(`user-${userId}`)) cache.removeCache(`user-${userId}`);
if (operation === 'Assign') {
assignlist.push(userId);
From b69dd8beb4916b15ac9eb7756bf499a18426782b Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Thu, 28 Sep 2023 19:13:38 -0500
Subject: [PATCH 041/272] update profileInitialSetupController
---
.../profileInitialSetupController.js | 334 +++++++++---------
1 file changed, 174 insertions(+), 160 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 01d497865..052915994 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -1,29 +1,28 @@
-const mongoose = require('mongoose');
-const { v4: uuidv4 } = require('uuid');
-const moment = require('moment-timezone');
-const jwt = require('jsonwebtoken');
-const emailSender = require('../utilities/emailSender');
-const config = require('../config');
-
+const mongoose = require("mongoose");
+const { v4: uuidv4 } = require("uuid");
+const moment = require("moment-timezone");
+const jwt = require("jsonwebtoken");
+const emailSender = require("../utilities/emailSender");
+const config = require("../config");
// returns the email body that includes the setup link for the recipient.
function sendLinkMessage(Link) {
- const message = `Hello,
+ const message = `Hello,
Welcome to the One Community Highest Good Network! We’re excited to have you as a new member of our team.
To work as a member of our volunteer team, you need to complete the following profile setup:
Click to Complete Profile
Please complete all fields and be accurate. If you have any questions or need assistance during the profile setup process, please contact your manager.
Thank you and welcome!
- With Gratitude,
- One Community.
`;
- return message;
+ With Gratitude,
+ One Community.
`;
+ return message;
}
// returns the email body containing the details of the newly created user.
function informManagerMessage(user) {
- const message = `
+ const message = `
Hello,
- A new user has created their profile on our platform. Below is the information provided by the user:
+ New User ${user.firstName} ${user.lastName} has completed their part of setup.
These areas need to now be completed by an Admin: Weekly Committed Hours, Admin Document, Link to Media Files, Assign Projects, and (if applicable) Assign Team.
First Name: |
@@ -39,11 +38,7 @@ function informManagerMessage(user) {
Phone Number: |
- ${user.phoneNumber} |
-
-
- Weekly Committed Hours: |
- ${user.weeklycommittedHours} |
+ +${user.phoneNumber} |
Collaboration Preference: |
@@ -62,83 +57,92 @@ function informManagerMessage(user) {
${user.location} |
- Please check the details provided by the user. If any errors were made, kindly ask them to correct the information accordingly.
+
Thank you,
One Community.
`;
- return message;
+ return message;
}
-const profileInitialSetupController = function (ProfileInitialSetupToken, userProfile, Project) {
- const { JWT_SECRET } = config;
+const profileInitialSetupController = function (
+ ProfileInitialSetupToken,
+ userProfile,
+ Project
+) {
+ const { JWT_SECRET } = config;
- /*
+ /*
Function to handle token generation and email process:
- Generates a new token and saves it to the database.
- If the email already has a token, the old one is deleted.
- Sets the token expiration to one week.
- Generates a link using the token and emails it to the recipient.
*/
- const getSetupToken = async (req, res) => {
- let { email, baseUrl } = req.body
- email = email.toLowerCase()
- const token = uuidv4();
- const expiration = moment().tz('America/Los_Angeles').add(1, 'week')
- try {
- await ProfileInitialSetupToken.findOneAndDelete({ email });
-
- const newToken = new ProfileInitialSetupToken({
- token,
- email,
- expiration: expiration.toDate(),
- });
-
- const savedToken = await newToken.save();
- const link = `${baseUrl}/ProfileInitialSetup/${savedToken.token}`
+ const getSetupToken = async (req, res) => {
+ let { email, baseUrl } = req.body;
+ email = email.toLowerCase();
+ const token = uuidv4();
+ const expiration = moment().tz("America/Los_Angeles").add(1, "week");
+ try {
+ const existingEmail = await userProfile.findOne({
+ email: email,
+ });
+ if (existingEmail) {
+ res.status(400).send("email already in use");
+ } else {
+ await ProfileInitialSetupToken.findOneAndDelete({ email });
- emailSender(
- email,
- 'NEEDED: Complete your One Community profile setup',
- sendLinkMessage(link),
- null,
- null,
- );
+ const newToken = new ProfileInitialSetupToken({
+ token,
+ email,
+ expiration: expiration.toDate(),
+ });
- res.status(200).send(link);
+ const savedToken = await newToken.save();
+ const link = `${baseUrl}/ProfileInitialSetup/${savedToken.token}`;
- } catch (error) {
- res.status(400).send(`Error: ${error}`);
- }
+ emailSender(
+ email,
+ "NEEDED: Complete your One Community profile setup",
+ sendLinkMessage(link),
+ null,
+ null
+ );
+ res.status(200).send(link);
+ }
+ } catch (error) {
+ res.status(400).send(`Error: ${error}`);
}
+ };
- /*
+ /*
Function to validate a token:
- Checks if the token exists in the database.
- Verifies that the token's expiration date has not passed yet.
*/
- const validateSetupToken = async (req, res) => {
- const { token } = req.body
- const currentMoment = moment.tz('America/Los_Angeles');
- try {
- const foundToken = await ProfileInitialSetupToken.findOne({ token });
- if (foundToken) {
- const expirationMoment = moment(foundToken.expiration);
-
- if (expirationMoment.isAfter(currentMoment)) {
- res.status(200).send("Valid token");
- } else {
- res.status(400).send("Invalid token");
- }
- } else {
- res.status(404).send("Token not found")
- }
- } catch (error) {
- res.status(500).send(`Error finding token: ${error}`);
- }
+ const validateSetupToken = async (req, res) => {
+ const { token } = req.body;
+ const currentMoment = moment.tz("America/Los_Angeles");
+ try {
+ const foundToken = await ProfileInitialSetupToken.findOne({ token });
+ if (foundToken) {
+ const expirationMoment = moment(foundToken.expiration);
+
+ if (expirationMoment.isAfter(currentMoment)) {
+ res.status(200).send(foundToken);
+ } else {
+ res.status(400).send("Invalid token");
+ }
+ } else {
+ res.status(404).send("Token not found");
+ }
+ } catch (error) {
+ res.status(500).send(`Error finding token: ${error}`);
}
+ };
- /*
+ /*
Function for creating and authenticating a new user:
- Validates the token used to submit the form.
- Creates a new user using the information received through req.body.
@@ -147,104 +151,114 @@ const profileInitialSetupController = function (ProfileInitialSetupToken, userPr
- Generates a JWT token using the newly created user information.
- Sends the JWT as a response.
*/
- const setUpNewUser = async (req, res) => {
- const { token } = req.body;
- const currentMoment = moment.tz('America/Los_Angeles');
- try {
- const foundToken = await ProfileInitialSetupToken.findOne({ token });
- if (foundToken) {
- const expirationMoment = moment(foundToken.expiration);
-
- if (expirationMoment.isAfter(currentMoment)) {
-
- const defaultProject = await Project.findOne({ projectName: "Orientation and Initial Setup" })
-
- const newUser = new userProfile();
- newUser.password = req.body.password
- newUser.role = "Volunteer";
- newUser.firstName = req.body.firstName;
- newUser.lastName = req.body.lastName;
- newUser.jobTitle = req.body.jobTitle;
- newUser.phoneNumber = req.body.phoneNumber;
- newUser.bio = "";
- newUser.weeklycommittedHours = req.body.weeklycommittedHours;
- newUser.personalLinks = [];
- newUser.adminLinks = [];
- newUser.teams = Array.from(new Set([]));
- newUser.projects = Array.from(new Set([defaultProject]));
- newUser.createdDate = Date.now();
- newUser.email = req.body.email;
- newUser.weeklySummaries = [{ summary: '' }];
- newUser.weeklySummariesCount = 0;
- newUser.weeklySummaryOption = 'Required';
- newUser.mediaUrl = '';
- newUser.collaborationPreference = req.body.collaborationPreference;
- newUser.timeZone = req.body.timeZone || 'America/Los_Angeles';
- newUser.location = req.body.location;
- newUser.bioPosted = 'default';
- newUser.privacySettings.email = req.body.privacySettings.email
- newUser.privacySettings.phoneNumber = req.body.privacySettings.phoneNumber
- newUser.teamCode = '';
- const savedUser = await newUser.save();
-
- emailSender(
- process.env.MANAGER_EMAIL,
- 'New User Profile Created',
- informManagerMessage(savedUser),
- null,
- null,
- );
- await ProfileInitialSetupToken.findByIdAndDelete(foundToken._id);
-
- const jwtPayload = {
- userid: savedUser._id,
- role: savedUser.role,
- permissions: savedUser.permissions,
- expiryTimestamp: moment().add(config.TOKEN.Lifetime, config.TOKEN.Units),
- };
-
- const token = jwt.sign(jwtPayload, JWT_SECRET);
-
- res.send({ token }).status(200);
- } else {
- res.status(400).send("Token is expired");
- }
- } else {
- res.status(400).send("Invalid token");
- }
- } catch (error) {
- res.status(500).send(`Error: ${error}`);
- }
+ const setUpNewUser = async (req, res) => {
+ const { token } = req.body;
+ const currentMoment = moment.tz("America/Los_Angeles");
+ try {
+ const foundToken = await ProfileInitialSetupToken.findOne({ token });
+ const existingEmail = await userProfile.findOne({
+ email: foundToken.email,
+ });
+ if (existingEmail) {
+ res.status(400).send("email already in use");
+ } else {
+ if (foundToken) {
+ const expirationMoment = moment(foundToken.expiration);
+ if (expirationMoment.isAfter(currentMoment)) {
+ const defaultProject = await Project.findOne({
+ projectName: "Orientation and Initial Setup",
+ });
+
+ const newUser = new userProfile();
+ newUser.password = req.body.password;
+ newUser.role = "Volunteer";
+ newUser.firstName = req.body.firstName;
+ newUser.lastName = req.body.lastName;
+ newUser.jobTitle = req.body.jobTitle;
+ newUser.phoneNumber = req.body.phoneNumber;
+ newUser.bio = "";
+ newUser.weeklycommittedHours = req.body.weeklycommittedHours;
+ newUser.personalLinks = [];
+ newUser.adminLinks = [];
+ newUser.teams = Array.from(new Set([]));
+ newUser.projects = Array.from(new Set([defaultProject]));
+ newUser.createdDate = Date.now();
+ newUser.email = req.body.email;
+ newUser.weeklySummaries = [{ summary: "" }];
+ newUser.weeklySummariesCount = 0;
+ newUser.weeklySummaryOption = "Required";
+ newUser.mediaUrl = "";
+ newUser.collaborationPreference = req.body.collaborationPreference;
+ newUser.timeZone = req.body.timeZone || "America/Los_Angeles";
+ newUser.location = req.body.location;
+ newUser.bioPosted = "default";
+ newUser.privacySettings.email = req.body.privacySettings.email;
+ newUser.privacySettings.phoneNumber =
+ req.body.privacySettings.phoneNumber;
+ newUser.teamCode = "";
+ const savedUser = await newUser.save();
+
+ emailSender(
+ process.env.MANAGER_EMAIL || "jae@onecommunityglobal.org", // "jae@onecommunityglobal.org"
+ "NEW USER REGISTERED",
+ informManagerMessage(savedUser),
+ null,
+ null
+ );
+ await ProfileInitialSetupToken.findByIdAndDelete(foundToken._id);
+
+ const jwtPayload = {
+ userid: savedUser._id,
+ role: savedUser.role,
+ permissions: savedUser.permissions,
+ expiryTimestamp: moment().add(
+ config.TOKEN.Lifetime,
+ config.TOKEN.Units
+ ),
+ };
+
+ const token = jwt.sign(jwtPayload, JWT_SECRET);
+
+ res.send({ token }).status(200);
+ } else {
+ res.status(400).send("Token is expired");
+ }
+ } else {
+ res.status(400).send("Invalid token");
+ }
+ }
+ } catch (error) {
+ res.status(500).send(`Error: ${error}`);
}
+ };
- /*
+ /*
Function for sending https://opencagedata.com API key:
- Checks if token used in the request is valid.
- sends the API Key as response
*/
- const getTimeZoneAPIKeyByToken = async (req, res) => {
- const token = req.body.token;
- const premiumKey = process.env.TIMEZONE_PREMIUM_KEY;
+ const getTimeZoneAPIKeyByToken = async (req, res) => {
+ const token = req.body.token;
+ const premiumKey = process.env.TIMEZONE_PREMIUM_KEY;
- const foundToken = await ProfileInitialSetupToken.findOne({ token });
+ const foundToken = await ProfileInitialSetupToken.findOne({ token });
- if (foundToken) {
- res.status(200).send({ userAPIKey: premiumKey });
- return;
- } else {
- res.status(403).send('Unauthorized Request');
- return;
- }
-
- };
-
- return {
- getSetupToken,
- setUpNewUser,
- validateSetupToken,
- getTimeZoneAPIKeyByToken
+ if (foundToken) {
+ res.status(200).send({ userAPIKey: premiumKey });
+ return;
+ } else {
+ res.status(403).send("Unauthorized Request");
+ return;
}
+ };
+
+ return {
+ getSetupToken,
+ setUpNewUser,
+ validateSetupToken,
+ getTimeZoneAPIKeyByToken,
+ };
};
-module.exports = profileInitialSetupController;
\ No newline at end of file
+module.exports = profileInitialSetupController;
From 165fc73cb11a963c8afa360a628e4a39a6428517 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 29 Sep 2023 13:35:30 -0700
Subject: [PATCH 042/272] add material schema, update item type schema
---
src/models/inventoryItemType.js | 21 ++++++++++++---
src/models/inventoryMaterial.js | 46 +++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+), 4 deletions(-)
create mode 100644 src/models/inventoryMaterial.js
diff --git a/src/models/inventoryItemType.js b/src/models/inventoryItemType.js
index 80e5e0d7b..92139f27d 100644
--- a/src/models/inventoryItemType.js
+++ b/src/models/inventoryItemType.js
@@ -2,11 +2,24 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
-const InventoryItemType = new Schema({
+// const InventoryItemType = new Schema({
+// name: { type: String, required: true },
+// description: { type: String },
+// imageUrl: { type: String },
+// quantifier: { type: String, default: 'each' },
+// });
+
+const InventoryItemType = new Schema({ // creates an item, tracks total amount in organization's stock
+ type: { type: String, required: true }, // ie Material, Equipment, Tool
name: { type: String, required: true },
- description: { type: String },
- imageUrl: { type: String },
- quantifier: { type: String, default: 'each' },
+ description: { type: String, required: true, maxLength: 150 },
+ uom: { type: String, required: true }, // unit of measurement
+ totalStock: { type: Number, required: true }, // total amount of all stock acquired
+ totalAvailable: { type: Number, required: true }, // amount of item available to be checked out
+ projectsUsing: [String], // ids of projects using the item
+ imageUrl: { type: String }
});
module.exports = mongoose.model('inventoryItemType', InventoryItemType, 'inventoryItemType');
+
+
diff --git a/src/models/inventoryMaterial.js b/src/models/inventoryMaterial.js
new file mode 100644
index 000000000..31b6ce069
--- /dev/null
+++ b/src/models/inventoryMaterial.js
@@ -0,0 +1,46 @@
+const mongoose = require('mongoose')
+
+const {Schema} = mongoose
+
+const InventoryMaterial = new Schema({
+ inventoryItemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'inventoryItemType', required: true },
+ projectId: {type: Number, required: true },
+ stockBought: { type: Number, required: true }, // amount bought for project, affects total stock
+ stockUsed: { type: Number, required: true },
+ stockAvailable: { type: Number, required: true },
+ stockHeld: { type: Number, required: true },
+ stockWasted: { type: Number, required: true },
+ usageRecord: [{ // daily log of amount inventory item used at job site
+ date: { type: Date, required: true, default: Date.now() },
+ createdBy: {type: String, required: true },
+ taskId: { type: String, required: true },
+ quantityUsed: { type: Number, required: true },
+ responsibleUserId: { type: String, required: true }
+ }],
+ updateRecord: [{ // incident report affecting quantity/status of inventory item
+ date: { type: Date, required: true, default: Date.now() },
+ createdBy: {type: String, required: true },
+ action: { type: String, required: true }, // ex: Add, Reduce, Hold
+ cause: { type: String, required: true }, // ex: Used, Lost, Wasted, Transfer
+ quantity: { type: Number, required: true },
+ description: { type: String, required: true, maxLength: 150 },
+ responsibleUserId: { type: String, required: true },
+ imageUrl: { type: String }
+ }],
+ purchaseRecord: [{
+ date: { type: Date, required: true, default: Date.now() },
+ createdBy: {type: String, required: true },
+ invoiceId: { type: String, required: true },
+ vendor: { type: String, required: true },
+ brand: { type: String, required: true },
+ amount: { type: Number, required: true }, // amount of item in each unit
+ quantity: { type: Number, required: true }, // number of units purchased
+ unitCost: { type: Number, required: true },
+ tax: { type: Number, required: true },
+ shipping: { type: Number, required: true },
+ totalCost: { type: Number, required: true },
+ imageUrl: { type: String },
+ }]
+})
+
+module.exports = mongoose.model('inventoryMaterial', InventoryMaterial, 'inventoryMaterial');
From 4f6be0bcec289d7f285f55f8f7546c8506a08f0d Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Fri, 29 Sep 2023 15:40:19 -0500
Subject: [PATCH 043/272] userProfileController checks cache if no results from
the database
---
src/controllers/userProfileController.js | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 855aa265a..5aabb6bf2 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -71,19 +71,20 @@ const userProfileController = function (UserProfile) {
})
.then((results) => {
if (!results) {
- res.status(500).send({ error: "User result was invalid" });
- return;
+ if (cache.getCache("allusers")) {
+ const getData = JSON.parse(cache.getCache("allusers"));
+ res.status(200).send(getData);
+ return;
+ }else{
+ res.status(500).send({ error: "User result was invalid" });
+ return;
+ }
}
cache.setCache("allusers", JSON.stringify(results));
res.status(200).send(results);
})
.catch((error) => res.status(404).send(error));
-
- if (cache.getCache('allusers')) {
- const getData = JSON.parse(cache.getCache('allusers'));
- res.status(200).send(getData);
- return;
- }
+
};
const getProjectMembers = async function (req, res) {
From cf741ad7005d84f853bdf5c6482338cae15a9759 Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Fri, 29 Sep 2023 20:58:15 -0500
Subject: [PATCH 044/272] update setup user email
---
src/controllers/profileInitialSetupController.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 052915994..b0afd7b39 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -14,7 +14,7 @@ function sendLinkMessage(Link) {
Please complete all fields and be accurate. If you have any questions or need assistance during the profile setup process, please contact your manager.
Thank you and welcome!
With Gratitude,
- One Community.
`;
+ One Community
`;
return message;
}
@@ -59,7 +59,7 @@ function informManagerMessage(user) {
Thank you,
- One Community.
`;
+ One Community
`;
return message;
}
@@ -201,7 +201,7 @@ const profileInitialSetupController = function (
emailSender(
process.env.MANAGER_EMAIL || "jae@onecommunityglobal.org", // "jae@onecommunityglobal.org"
- "NEW USER REGISTERED",
+ `NEW USER REGISTERED: ${savedUser.firstName} ${savedUser.lastName}`,
informManagerMessage(savedUser),
null,
null
From beb19d7f2ffe42733ed1b743f11589786712362e Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Sat, 30 Sep 2023 14:49:09 -0500
Subject: [PATCH 045/272] update email body for new user setup
---
src/controllers/profileInitialSetupController.js | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index b0afd7b39..b688f3963 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -22,7 +22,16 @@ function sendLinkMessage(Link) {
function informManagerMessage(user) {
const message = `
Hello,
- New User ${user.firstName} ${user.lastName} has completed their part of setup.
These areas need to now be completed by an Admin: Weekly Committed Hours, Admin Document, Link to Media Files, Assign Projects, and (if applicable) Assign Team.
+ New User ${user.firstName} ${user.lastName} has completed their part of setup.
+ These areas need to now be completed by an Admin:
+
+ - Weekly Committed Hours
+ - Admin Document
+ - Link to Media Files
+ - Assign Projects
+ - 4-digit Admin Code
+ - And (if applicable) Assign Team
+
First Name: |
From e120df9dc7601cf92efd2022e5d09d5a24cadc6f Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Sat, 30 Sep 2023 15:27:46 -0500
Subject: [PATCH 046/272] add style
---
src/controllers/profileInitialSetupController.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index b688f3963..f671e06a3 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -21,10 +21,10 @@ function sendLinkMessage(Link) {
// returns the email body containing the details of the newly created user.
function informManagerMessage(user) {
const message = `
- Hello,
- New User ${user.firstName} ${user.lastName} has completed their part of setup.
+ Hello,
+ New User ${user.firstName} ${user.lastName} has completed their part of setup.
These areas need to now be completed by an Admin:
-
+
- Weekly Committed Hours
- Admin Document
- Link to Media Files
From e2540140d889b31aede0656722eed32c5306d75e Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Mon, 2 Oct 2023 11:46:14 -0700
Subject: [PATCH 047/272] add materials route, router, controller
---
.../bmdashboard/bmMaterialsController.js | 12 ++++++++++++
src/routes/bmdashboard/bmMaterialsRouter.js | 13 +++++++++++++
src/startup/routes.js | 2 ++
3 files changed, 27 insertions(+)
create mode 100644 src/controllers/bmdashboard/bmMaterialsController.js
create mode 100644 src/routes/bmdashboard/bmMaterialsRouter.js
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
new file mode 100644
index 000000000..11aa4a744
--- /dev/null
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -0,0 +1,12 @@
+const bmMaterialsController = function () {
+ const bmMaterialsList = async function _matsList(req, res) {
+ try {
+ return res.json({ message: "Hello World" })
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return { bmMaterialsList };
+};
+
+module.exports = bmMaterialsController;
\ No newline at end of file
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
new file mode 100644
index 000000000..d8cca1aca
--- /dev/null
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -0,0 +1,13 @@
+const express = require('express');
+
+const routes = function () {
+const materialsRouter = express.Router();
+const controller = require('../../controllers/bmdashboard/bmMaterialsController')();
+
+materialsRouter.route('/materials')
+ .get(controller.bmMaterialsList);
+
+ return materialsRouter;
+}
+
+module.exports = routes;
\ No newline at end of file
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 43cd226bd..e0852dac3 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -55,6 +55,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')();
module.exports = function (app) {
@@ -88,4 +89,5 @@ module.exports = function (app) {
app.use('/api', mouseoverTextRouter);
// bm dashboard
app.use('/api/bm', bmLoginRouter);
+ app.use('/api/bm', bmMaterialsRouter);
};
From 656509dcd6ab3b6c770876d68a5c70fe7eb0c566 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Mon, 2 Oct 2023 16:13:42 -0400
Subject: [PATCH 048/272] fix: jobTitle model key, feat: adding isActive
status, getting all locations, put new location to a collection
---
src/controllers/mapLocationsController.js | 72 +++++++++--------------
src/models/mapLocation.js | 38 +++++++-----
2 files changed, 49 insertions(+), 61 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 83526998d..6088de489 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,62 +1,44 @@
-const mongoose = require('mongoose');
-const mapLocation = require('../models/mapLocation');
-const { hasPermission } = require('../utilities/permissions');
-
-const mapLocationsController = function () {
+const mapLocationsController = function (mapLocation) {
const getAllLocations = function (req, res) {
- console.log('controller:')
- console.log(req.body)
mapLocation.find({})
- .then(results => res.send(results).status(200))
- .catch(error => res.send(error).status(404));
+ .then(results =>
+ res.send(results).status(200)
+ )
+ .catch(error =>
+ res.send(error).status(404));
};
const deleteLocation = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteTeam')) {
- res.status(403).send({ error: 'You are not authorized to delete teams.' });
+
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
- const { teamId } = req.params;
- Team.findById(teamId, (error, record) => {
- if (error || record === null) {
- res.status(400).send({ error: 'No valid records found' });
- return;
- }
- const removeteamfromprofile = userProfile.updateMany({}, { $pull: { teams: record._id } }).exec();
- const deleteteam = record.remove();
-
- Promise.all([removeteamfromprofile, deleteteam])
- .then(res.status(200).send({ message: ' Team successfully deleted and user profiles updated' }))
- .catch((errors) => {
- res.status(400).send(errors);
- });
- }).catch((error) => {
- res.status(400).send(error);
- });
};
const putUserLocation = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putTeam')) {
+
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
+ const locationData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ }
+ const location = new mapLocation(locationData);
- const { teamId } = req.params;
-
- Team.findById(teamId, (error, record) => {
- if (error || record === null) {
- res.status(400).send('No valid records found');
- return;
+ try {
+ const response = await location.save()
+ if(!response) {
+ throw new Error('Something went wrong during saving the location...')
}
- record.teamName = req.body.teamName;
- record.isActive = req.body.isActive;
- record.createdDatetime = Date.now();
- record.modifiedDatetime = Date.now();
-
- record
- .save()
- .then(results => res.status(201).send(results._id))
- .catch(errors => res.status(400).send(errors));
- });
+ res.status(200).send(response);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({message: err.message || 'Something went wrong...'});
+ }
};
return {
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
index d7b9d82b5..65415239f 100644
--- a/src/models/mapLocation.js
+++ b/src/models/mapLocation.js
@@ -11,32 +11,38 @@ const mapLocation = new Schema({
type: String,
default: 'Prior to HGN Data Collection',
},
- title: {
+ jobTitle: {
type: String,
default: 'Prior to HGN Data Collection',
},
- userProvided: {
- type: String,
- required: true,
+ isActive: {
+ type: Boolean,
+ default: false,
},
- coords: {
- lat: {
+ location: {
+ userProvided: {
type: String,
required: true,
},
- lng: {
+ coords: {
+ lat: {
+ type: String,
+ required: true,
+ },
+ lng: {
+ type: String,
+ required: true,
+ }
+ },
+ country: {
type: String,
required: true,
- }
- },
- country: {
- type: String,
- required: true,
+ },
+ city: {
+ type: String,
+ default: '',
+ },
},
- city: {
- type: String,
- default: '',
- }
});
module.exports = mongoose.model('MapLocation', mapLocation, 'maplocations');
From 9fdcdb8d4930421928d5deb4d825c7f5f9c6d213 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Mon, 2 Oct 2023 18:09:21 -0700
Subject: [PATCH 049/272] update route, router, controller with updated
material schema and new collection fetch
---
.../bmdashboard/bmMaterialsController.js | 8 +++-
...ryMaterial.js => inventoryItemMaterial.js} | 38 ++++++++-----------
src/routes/bmdashboard/bmMaterialsRouter.js | 4 +-
src/startup/routes.js | 4 +-
4 files changed, 25 insertions(+), 29 deletions(-)
rename src/models/{inventoryMaterial.js => inventoryItemMaterial.js} (51%)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 11aa4a744..797d5730d 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,7 +1,11 @@
-const bmMaterialsController = function () {
+const mongoose = require('mongoose')
+
+const bmMaterialsController = function (ItemMaterial, ItemType) {
const bmMaterialsList = async function _matsList(req, res) {
try {
- return res.json({ message: "Hello World" })
+ ItemMaterial.find()
+ .then(results => res.status(200).send(results))
+ .catch(error => res.status(500).send(error))
} catch (err) {
res.json(err);
}
diff --git a/src/models/inventoryMaterial.js b/src/models/inventoryItemMaterial.js
similarity index 51%
rename from src/models/inventoryMaterial.js
rename to src/models/inventoryItemMaterial.js
index 31b6ce069..b795d2f63 100644
--- a/src/models/inventoryMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -1,10 +1,10 @@
-const mongoose = require('mongoose')
+const mongoose = require('mongoose');
-const {Schema} = mongoose
+const { Schema } = mongoose;
-const InventoryMaterial = new Schema({
+const InventoryItemMaterial = new Schema({
inventoryItemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'inventoryItemType', required: true },
- projectId: {type: Number, required: true },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'project', required: true },
stockBought: { type: Number, required: true }, // amount bought for project, affects total stock
stockUsed: { type: Number, required: true },
stockAvailable: { type: Number, required: true },
@@ -12,35 +12,27 @@ const InventoryMaterial = new Schema({
stockWasted: { type: Number, required: true },
usageRecord: [{ // daily log of amount inventory item used at job site
date: { type: Date, required: true, default: Date.now() },
- createdBy: {type: String, required: true },
- taskId: { type: String, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
quantityUsed: { type: Number, required: true },
- responsibleUserId: { type: String, required: true }
}],
updateRecord: [{ // incident report affecting quantity/status of inventory item
date: { type: Date, required: true, default: Date.now() },
- createdBy: {type: String, required: true },
- action: { type: String, required: true }, // ex: Add, Reduce, Hold
- cause: { type: String, required: true }, // ex: Used, Lost, Wasted, Transfer
- quantity: { type: Number, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
+ action: { type: String, required: true }, // ex: Add, Reduce, Hold (updates stock quantities)
+ cause: { type: String, required: true }, // ex: Used, Lost, Wasted, Transfer (reason for update)
+ quantity: { type: Number, required: true }, // amount of material affected
description: { type: String, required: true, maxLength: 150 },
- responsibleUserId: { type: String, required: true },
- imageUrl: { type: String }
}],
purchaseRecord: [{
date: { type: Date, required: true, default: Date.now() },
- createdBy: {type: String, required: true },
- invoiceId: { type: String, required: true },
- vendor: { type: String, required: true },
- brand: { type: String, required: true },
- amount: { type: Number, required: true }, // amount of item in each unit
- quantity: { type: Number, required: true }, // number of units purchased
- unitCost: { type: Number, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
+ poId: { type: String, required: true },
+ sellerId: { type: String, required: true },
+ quantity: { type: Number, required: true }, // adds to stockBought
+ subtotal: { type: Number, required: true },
tax: { type: Number, required: true },
shipping: { type: Number, required: true },
- totalCost: { type: Number, required: true },
- imageUrl: { type: String },
}]
})
-module.exports = mongoose.model('inventoryMaterial', InventoryMaterial, 'inventoryMaterial');
+module.exports = mongoose.model('inventoryItemMaterial', InventoryItemMaterial, 'inventoryMaterial');
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index d8cca1aca..d3e4518da 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -1,8 +1,8 @@
const express = require('express');
-const routes = function () {
+const routes = function (itemMaterial, itemType) {
const materialsRouter = express.Router();
-const controller = require('../../controllers/bmdashboard/bmMaterialsController')();
+const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial, itemType);
materialsRouter.route('/materials')
.get(controller.bmMaterialsList);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index e0852dac3..cde07c94d 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -20,6 +20,7 @@ const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
+const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -55,8 +56,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')();
-
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, inventoryItemType);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
From 9da89884167f825caf399c09ae44d0bb6fe35079 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Mon, 2 Oct 2023 20:12:37 -0700
Subject: [PATCH 050/272] update inventoryitemtype schema
---
src/models/inventoryItemType.js | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/src/models/inventoryItemType.js b/src/models/inventoryItemType.js
index 92139f27d..207ac77b0 100644
--- a/src/models/inventoryItemType.js
+++ b/src/models/inventoryItemType.js
@@ -2,21 +2,14 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
-// const InventoryItemType = new Schema({
-// name: { type: String, required: true },
-// description: { type: String },
-// imageUrl: { type: String },
-// quantifier: { type: String, default: 'each' },
-// });
-
const InventoryItemType = new Schema({ // creates an item, tracks total amount in organization's stock
type: { type: String, required: true }, // ie Material, Equipment, Tool
name: { type: String, required: true },
description: { type: String, required: true, maxLength: 150 },
uom: { type: String, required: true }, // unit of measurement
totalStock: { type: Number, required: true }, // total amount of all stock acquired
- totalAvailable: { type: Number, required: true }, // amount of item available to be checked out
- projectsUsing: [String], // ids of projects using the item
+ totalAvailable: { type: Number, required: true },
+ projectsUsing: [ {type: mongoose.SchemaTypes.ObjectId, ref: 'project'} ],
imageUrl: { type: String }
});
From 60a1fa2348c3a790b3b5c59b3297a41d6074ddb7 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Tue, 3 Oct 2023 12:46:33 +0800
Subject: [PATCH 051/272] add authorization and regex check in backend
---
src/controllers/userProfileController.js | 30 ++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 40d6eac39..c1c3a2a0a 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -244,6 +244,9 @@ const userProfileController = function (UserProfile) {
"putUserProfilePermissions"
))
);
+
+ const canEditTeamCode = req.body.requestor.role === "Owner" ||
+ req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
if (!isRequestorAuthorized) {
res.status(403).send("You are not authorized to update this user");
@@ -305,6 +308,17 @@ const userProfileController = function (UserProfile) {
record.totalIntangibleHrs = req.body.totalIntangibleHrs;
record.bioPosted = req.body.bioPosted || "default";
record.isFirstTimelog = req.body.isFirstTimelog;
+
+ if(!canEditTeamCode && record.teamCode !== req.body.teamCode){
+ res.status(403).send("You are not authorized to edit team code.");
+ return;
+ }
+
+ const teamcodeRegex = /^[A-Z]-[A-Z]{3}$/;
+ if (!teamcodeRegex.test(req.body.teamCode)) {
+ res.status(400).send("The team code is invalid");
+ return;
+ };
record.teamCode = req.body.teamCode;
// find userData in cache
@@ -591,6 +605,22 @@ const userProfileController = function (UserProfile) {
const { userId } = req.params;
const { key, value } = req.body;
+ if (key === "teamCode") {
+ const canEditTeamCode = req.body.requestor.role === "Owner" ||
+ req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
+ const teamcodeRegex = /^[A-Z]-[A-Z]{3}$/;
+
+ if(!canEditTeamCode){
+ res.status(403).send("You are not authorized to edit team code.");
+ return;
+ }
+
+ if (!teamcodeRegex.test(value)) {
+ res.status(400).send("The team code is invalid");
+ return;
+ };
+ }
+
// remove user from cache, it should be loaded next time
cache.removeCache(`user-${userId}`);
if (!key || value === undefined) return res.status(400).send({ error: 'Missing property or value' });
From 2c38d3c65d525d3265f7d64e177a28a492b865fa Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Tue, 3 Oct 2023 17:48:38 +0800
Subject: [PATCH 052/272] hotfix for code regex check
---
src/controllers/userProfileController.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index c1c3a2a0a..ad2a0efd9 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -314,7 +314,7 @@ const userProfileController = function (UserProfile) {
return;
}
- const teamcodeRegex = /^[A-Z]-[A-Z]{3}$/;
+ const teamcodeRegex = /^[a-zA-Z]-[a-zA-Z]{3}$/;
if (!teamcodeRegex.test(req.body.teamCode)) {
res.status(400).send("The team code is invalid");
return;
@@ -608,7 +608,7 @@ const userProfileController = function (UserProfile) {
if (key === "teamCode") {
const canEditTeamCode = req.body.requestor.role === "Owner" ||
req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
- const teamcodeRegex = /^[A-Z]-[A-Z]{3}$/;
+ const teamcodeRegex = /^[a-zA-Z]-[a-zA-Z]{3}$/;
if(!canEditTeamCode){
res.status(403).send("You are not authorized to edit team code.");
From 2360136d78c82b61a263b24dc5265cfc1ad04588 Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Tue, 3 Oct 2023 13:18:29 -0700
Subject: [PATCH 053/272] Fix merge conflict extra bracket
---
src/controllers/projectController.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/controllers/projectController.js b/src/controllers/projectController.js
index b0239835d..a88378985 100644
--- a/src/controllers/projectController.js
+++ b/src/controllers/projectController.js
@@ -127,7 +127,6 @@ const projectController = function (Project) {
if (!await hasPermission(req.body.requestor, 'assignProjectToUsers')) {
res.status(403).send({ error: 'You are not authorized to perform this operation' });
return;
- }
}
if (!req.params.projectId || !mongoose.Types.ObjectId.isValid(req.params.projectId) || !req.body.users || (req.body.users.length === 0)) {
From 92059d53fff2bc23a21b249f568f172d83849aca Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Tue, 3 Oct 2023 13:22:50 -0700
Subject: [PATCH 054/272] fix another extra bracket
---
src/controllers/userProfileController.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 0899ab83b..447b14d94 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -55,7 +55,6 @@ const userProfileController = function (UserProfile) {
if (!await hasPermission(req.body.requestor, 'getUserProfiles')) {
res.status(403).send('You are not authorized to view all users');
return;
- }
}
if (cache.getCache("allusers")) {
From 1e096f26a066587f7eea80e771894ecce4a3f50d Mon Sep 17 00:00:00 2001
From: Jerry Ren
Date: Wed, 4 Oct 2023 15:11:44 -0400
Subject: [PATCH 055/272] Created isEmailExists Controller and Router
---
src/controllers/isEmailExistsController.js | 25 ++++++++++++++++++++++
src/routes/isEmailExistsRouter.js | 15 +++++++++++++
src/startup/routes.js | 3 +++
3 files changed, 43 insertions(+)
create mode 100644 src/controllers/isEmailExistsController.js
create mode 100644 src/routes/isEmailExistsRouter.js
diff --git a/src/controllers/isEmailExistsController.js b/src/controllers/isEmailExistsController.js
new file mode 100644
index 000000000..2c41efc33
--- /dev/null
+++ b/src/controllers/isEmailExistsController.js
@@ -0,0 +1,25 @@
+const UserProfile = require('../models/userProfile');
+
+const isEmailExistsController = function () {
+
+ const isEmailExists = async function (req, res) {
+
+ try {
+ const userProfile = await UserProfile.findOne({ email: req.params.email }).lean().exec()
+
+ if (userProfile) {
+ res.status(200).send(`Email, ${userProfile.email}, found.`)
+ } else {
+ res.status(403).send(`Email, ${req.params.email}, not found.`)
+ }
+ } catch (err) {
+ console.log(err)
+ }
+ }
+
+ return {
+ isEmailExists
+ }
+}
+
+module.exports = isEmailExistsController
diff --git a/src/routes/isEmailExistsRouter.js b/src/routes/isEmailExistsRouter.js
new file mode 100644
index 000000000..cfb4e6033
--- /dev/null
+++ b/src/routes/isEmailExistsRouter.js
@@ -0,0 +1,15 @@
+
+const express = require('express');
+
+const routes = function () {
+ const controller = require('../controllers/isEmailExistsController')()
+
+ const isEmailExistsRouter = express.Router()
+
+ isEmailExistsRouter.route("/is-email-exists/:email")
+ .get(controller.isEmailExists)
+
+ return isEmailExistsRouter
+}
+
+module.exports = routes
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 43cd226bd..296b10b69 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -43,6 +43,8 @@ const taskNotificationRouter = require('../routes/taskNotificationRouter')(taskN
const inventoryRouter = require('../routes/inventoryRouter')(inventoryItem, inventoryItemType);
const timeZoneAPIRouter = require('../routes/timeZoneAPIRoutes')();
const profileInitialSetupRouter = require('../routes/profileInitialSetupRouter')(profileInitialSetuptoken, userProfile, project);
+const isEmailExistsRouter = require('../routes/isEmailExistsRouter')();
+
const taskEditSuggestion = require('../models/taskEditSuggestion');
const taskEditSuggestionRouter = require('../routes/taskEditSuggestionRouter')(taskEditSuggestion);
@@ -86,6 +88,7 @@ module.exports = function (app) {
app.use('/api', reasonRouter);
app.use('/api', informationRouter);
app.use('/api', mouseoverTextRouter);
+ app.use('/api', isEmailExistsRouter);
// bm dashboard
app.use('/api/bm', bmLoginRouter);
};
From d4e04bd6c970ec6c27a4b21d48ba64b1b3c8fdfc Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 4 Oct 2023 16:31:43 -0700
Subject: [PATCH 056/272] populate db fetch with project, inventoryItemType
objects
---
src/controllers/bmdashboard/bmMaterialsController.js | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 797d5730d..b55b70b7e 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -4,6 +4,14 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
const bmMaterialsList = async function _matsList(req, res) {
try {
ItemMaterial.find()
+ .populate({
+ path: 'project',
+ select: '_id projectName'
+ })
+ .populate({
+ path: 'inventoryItemType',
+ select: '_id name uom totalStock'
+ })
.then(results => res.status(200).send(results))
.catch(error => res.status(500).send(error))
} catch (err) {
From b7201d5b0a0d542510c1ed2178db7bf6da6312da Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Thu, 5 Oct 2023 16:27:37 +0800
Subject: [PATCH 057/272] allow five-letter code
---
src/controllers/userProfileController.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index ad2a0efd9..afafe2488 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -314,7 +314,7 @@ const userProfileController = function (UserProfile) {
return;
}
- const teamcodeRegex = /^[a-zA-Z]-[a-zA-Z]{3}$/;
+ const teamcodeRegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$/;
if (!teamcodeRegex.test(req.body.teamCode)) {
res.status(400).send("The team code is invalid");
return;
@@ -608,7 +608,7 @@ const userProfileController = function (UserProfile) {
if (key === "teamCode") {
const canEditTeamCode = req.body.requestor.role === "Owner" ||
req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
- const teamcodeRegex = /^[a-zA-Z]-[a-zA-Z]{3}$/;
+ const teamcodeRegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$/;
if(!canEditTeamCode){
res.status(403).send("You are not authorized to edit team code.");
From df10cce04fdf0c5aa9734d05eb3808ce2a5c02dd Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Thu, 5 Oct 2023 19:40:00 +0800
Subject: [PATCH 058/272] add new properties to timeEntry modal and update
related function
---
src/controllers/projectController.js | 2 +-
src/controllers/timeEntryController.js | 194 ++++++++++++++++++++++---
src/models/timeentry.js | 6 +-
src/routes/timeentryRouter.js | 9 ++
4 files changed, 188 insertions(+), 23 deletions(-)
diff --git a/src/controllers/projectController.js b/src/controllers/projectController.js
index 7f10b0f86..4d5626083 100644
--- a/src/controllers/projectController.js
+++ b/src/controllers/projectController.js
@@ -28,7 +28,7 @@ const projectController = function (Project) {
// find if project has any time enteries associated with it
- timeentry.find({ projectId: record._id }, '_id')
+ timeentry.find({ projectId: record._id, entryType: [ 'default', 'project', null ] }, '_id')
.then((timeentries) => {
if (timeentries.length > 0) {
res.status(400).send({ error: 'This project has associated time entries and cannot be deleted. Consider inactivaing it instead.' });
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index e83a7e31b..4e482b085 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -129,6 +129,7 @@ const timeEntrycontroller = function (TimeEntry) {
timeEntry.lastModifiedDateTime = moment().utc().toISOString();
timeEntry.projectId = mongoose.Types.ObjectId(req.body.projectId);
timeEntry.dateOfWork = moment(req.body.dateOfWork).format('YYYY-MM-DD');
+ timeEntry.entryType = req.body.entryType;
// Update the hoursLogged field of related tasks based on before and after timeEntries
// initialIsTangible is a bealoon value, req.body.isTangible is a string
@@ -224,43 +225,80 @@ const timeEntrycontroller = function (TimeEntry) {
}
const items = [];
records.forEach((element) => {
- const timeentry = new TimeEntry();
- timeentry.personId = element.personId;
- timeentry.projectId = element.projectId;
- timeentry.dateOfWork = element.dateOfWork;
- timeentry.timeSpent = moment('1900-01-01 00:00:00')
- .add(element.totalSeconds, 'seconds')
- .format('HH:mm:ss');
- timeentry.notes = element.notes;
- timeentry.isTangible = element.isTangible;
- items.push(timeentry);
+ if (element.entryType == 'default' || element.entryType == undefined) {
+ const timeentry = new TimeEntry();
+ timeentry.personId = element.personId;
+ timeentry.projectId = element.projectId;
+ timeentry.dateOfWork = element.dateOfWork;
+ timeentry.timeSpent = moment('1900-01-01 00:00:00')
+ .add(element.totalSeconds, 'seconds')
+ .format('HH:mm:ss');
+ timeentry.notes = element.notes;
+ timeentry.isTangible = element.isTangible;
+ timeentry.entryType = 'default';
+ items.push(timeentry);
+ }
});
return res.json(items).status(200);
});
};
const postTimeEntry = async function (req, res) {
- if (
- !mongoose.Types.ObjectId.isValid(req.body.personId)
- || !mongoose.Types.ObjectId.isValid(req.body.projectId)
- || !req.body.dateOfWork
+ const isInvalid = !req.body.dateOfWork
|| !moment(req.body.dateOfWork).isValid()
|| !req.body.timeSpent
- || !req.body.isTangible
- ) {
+ || !req.body.isTangible;
+
+ const returnErr = (res) => {
res.status(400).send({ error: 'Bad request' });
return;
+ };
+
+ switch (req.body.entryType) {
+ case 'default':
+ if (
+ !mongoose.Types.ObjectId.isValid(req.body.personId)
+ || !mongoose.Types.ObjectId.isValid(req.body.projectId)
+ || isInvalid
+ ) {
+ returnErr(res);
+ }
+ break;
+ case 'person':
+ if (
+ !mongoose.Types.ObjectId.isValid(req.body.personId) || isInvalid
+ ) {
+ returnErr(res);
+ }
+ break;
+ case 'project':
+ if (
+ !mongoose.Types.ObjectId.isValid(req.body.projectId) || isInvalid
+ ) {
+ returnErr(res);
+ }
+ break;
+ case 'team':
+ if (
+ !mongoose.Types.ObjectId.isValid(req.body.teamId) || isInvalid
+ ) {
+ returnErr(res);
+ }
+ break;
}
+
const timeentry = new TimeEntry();
const { dateOfWork, timeSpent } = req.body;
timeentry.personId = req.body.personId;
timeentry.projectId = req.body.projectId;
+ timeentry.teamId = req.body.teamId;
timeentry.dateOfWork = moment(dateOfWork).format('YYYY-MM-DD');
timeentry.totalSeconds = moment.duration(timeSpent).asSeconds();
timeentry.notes = req.body.notes;
timeentry.isTangible = req.body.isTangible;
timeentry.createdDateTime = moment().utc().toISOString();
timeentry.lastModifiedDateTime = moment().utc().toISOString();
+ timeentry.entryType = req.body.entryType;
timeentry
.save()
@@ -272,7 +310,7 @@ const timeEntrycontroller = function (TimeEntry) {
.catch(error => res.status(400).send(error));
// Add this tangbile time entry to related task's hoursLogged
- if (timeentry.isTangible === true) {
+ if ((timeentry.entryType == 'default') && timeentry.isTangible === true) {
try {
const currentTask = await task.findById(req.body.projectId);
currentTask.hoursLogged += (timeentry.totalSeconds / 3600);
@@ -282,9 +320,11 @@ const timeEntrycontroller = function (TimeEntry) {
}
}
// checking if logged in hours exceed estimated time after timeentry for a task
- const record = await userProfile.findById(timeentry.personId.toString());
- const currentTask = await task.findById(req.body.projectId);
- checkTaskOvertime(timeentry, record, currentTask);
+ if (timeentry.entryType == 'default') {
+ const record = await userProfile.findById(timeentry.personId.toString());
+ const currentTask = await task.findById(req.body.projectId);
+ checkTaskOvertime(timeentry, record, currentTask);
+ }
};
const getTimeEntriesForSpecifiedPeriod = function (req, res) {
@@ -307,6 +347,7 @@ const timeEntrycontroller = function (TimeEntry) {
TimeEntry.aggregate([
{
$match: {
+ entryType: { $in: [ 'default', null ] },
personId: mongoose.Types.ObjectId(userId),
dateOfWork: { $gte: fromdate, $lte: todate },
},
@@ -390,6 +431,7 @@ const timeEntrycontroller = function (TimeEntry) {
TimeEntry.find(
{
+ entryType: { $in: [ 'default', null, 'person' ] },
personId: { $in: users },
dateOfWork: { $gte: fromDate, $lte: toDate },
},
@@ -434,6 +476,7 @@ const timeEntrycontroller = function (TimeEntry) {
const { projectId } = req.params;
TimeEntry.find(
{
+ entryType: [ 'default', null ],
projectId,
dateOfWork: { $gte: fromDate, $lte: todate },
},
@@ -494,6 +537,114 @@ const timeEntrycontroller = function (TimeEntry) {
});
};
+ const getLostTimeEntriesForUserList = function (req, res) {
+ const { users, fromDate, toDate } = req.body;
+
+ TimeEntry.find(
+ {
+ entryType: 'person',
+ personId: { $in: users },
+ dateOfWork: { $gte: fromDate, $lte: toDate },
+ },
+ ' -createdDateTime',
+ )
+ .populate('personId')
+ .sort({ lastModifiedDateTime: -1 })
+ .then((results) => {
+ const data = [];
+ results.forEach((element) => {
+ console.log(element);
+ const record = {};
+
+ record._id = element._id;
+ record.notes = element.notes;
+ record.isTangible = element.isTangible;
+ record.personId = element.personId;
+ record.firstName = element.personId
+ ? element.personId.firstName
+ : '';
+ record.lastName = element.personId
+ ? element.personId.lastName
+ : '';
+ record.dateOfWork = element.dateOfWork;
+ record.entryType = element.entryType;
+ [record.hours, record.minutes] = formatSeconds(element.totalSeconds);
+ data.push(record);
+ });
+ res.status(200).send(data);
+ })
+ .catch(error => res.status(400).send(error));
+ };
+
+ const getLostTimeEntriesForProjectList = function (req, res) {
+ const { projects, fromDate, toDate } = req.body;
+
+ TimeEntry.find(
+ {
+ entryType: "project",
+ projectId: { $in: projects },
+ dateOfWork: { $gte: fromDate, $lte: toDate },
+ },
+ ' -createdDateTime',
+ )
+ .populate('projectId')
+ .sort({ lastModifiedDateTime: -1 })
+ .then((results) => {
+ const data = [];
+ results.forEach((element) => {
+ console.log(element);
+ const record = {};
+ record._id = element._id;
+ record.notes = element.notes;
+ record.isTangible = element.isTangible;
+ record.projectId = element.projectId ? element.projectId._id : '';
+ record.projectName = element.projectId
+ ? element.projectId.projectName
+ : '';
+ record.dateOfWork = element.dateOfWork;
+ record.entryType = element.entryType;
+ [record.hours, record.minutes] = formatSeconds(element.totalSeconds);
+ data.push(record);
+ });
+ res.status(200).send(data);
+ })
+ .catch(error => res.status(400).send(error));
+ };
+
+ const getLostTimeEntriesForTeamList = function (req, res) {
+ const { teams, fromDate, toDate } = req.body;
+
+ TimeEntry.find(
+ {
+ entryType: "team",
+ teamId: { $in: teams },
+ dateOfWork: { $gte: fromDate, $lte: toDate },
+ },
+ ' -createdDateTime',
+ )
+ .populate('teamId')
+ .sort({ lastModifiedDateTime: -1 })
+ .then((results) => {
+ const data = [];
+ results.forEach((element) => {
+ console.log(element);
+ const record = {};
+ record._id = element._id;
+ record.notes = element.notes;
+ record.isTangible = element.isTangible;
+ record.teamId = element.teamId;
+ record.teamName = element.teamId
+ ? element.teamId.teamName
+ : '';
+ record.dateOfWork = element.dateOfWork;
+ record.entryType = element.entryType;
+ [record.hours, record.minutes] = formatSeconds(element.totalSeconds);
+ data.push(record);
+ });
+ res.status(200).send(data);
+ })
+ .catch(error => res.status(400).send(error));
+ };
return {
getAllTimeEnteries,
@@ -504,6 +655,9 @@ const timeEntrycontroller = function (TimeEntry) {
deleteTimeEntry,
getTimeEntriesForSpecifiedProject,
checkTaskOvertime,
+ getLostTimeEntriesForUserList,
+ getLostTimeEntriesForProjectList,
+ getLostTimeEntriesForTeamList,
};
};
diff --git a/src/models/timeentry.js b/src/models/timeentry.js
index aeef5fdc7..83510773f 100644
--- a/src/models/timeentry.js
+++ b/src/models/timeentry.js
@@ -4,8 +4,10 @@ const { Schema } = mongoose;
const TimeEntry = new Schema({
- personId: { type: Schema.Types.ObjectId, required: [true, 'Resource is a required field'], ref: 'userProfile' },
- projectId: { type: Schema.Types.ObjectId, required: [true, 'Project is a required field'], ref: 'project' },
+ entryType: { type: String, required: true, default: 'default' },
+ personId: { type: Schema.Types.ObjectId, ref: 'userProfile' },
+ projectId: { type: Schema.Types.ObjectId, ref: 'project' },
+ teamId: { type: Schema.Types.ObjectId, ref: 'team' },
dateOfWork: { type: String, required: true },
totalSeconds: { type: Number },
notes: { type: String },
diff --git a/src/routes/timeentryRouter.js b/src/routes/timeentryRouter.js
index b319aa595..7e0a41797 100644
--- a/src/routes/timeentryRouter.js
+++ b/src/routes/timeentryRouter.js
@@ -19,6 +19,15 @@ const routes = function (TimeEntry) {
TimeEntryRouter.route('/TimeEntry/users')
.post(controller.getTimeEntriesForUsersList);
+ TimeEntryRouter.route('/TimeEntry/lostUsers')
+ .post(controller.getLostTimeEntriesForUserList);
+
+ TimeEntryRouter.route('/TimeEntry/lostProjects')
+ .post(controller.getLostTimeEntriesForProjectList);
+
+ TimeEntryRouter.route('/TimeEntry/lostTeams')
+ .post(controller.getLostTimeEntriesForTeamList);
+
TimeEntryRouter.route('/TimeEntry/projects/:projectId/:fromDate/:toDate')
.get(controller.getTimeEntriesForSpecifiedProject);
From 975a858079086a9e3e88249ca0e3f49277d620ae Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 5 Oct 2023 11:55:09 -0700
Subject: [PATCH 059/272] update populate method
---
.../bmdashboard/bmMaterialsController.js | 42 +++++++++++++++----
src/routes/bmdashboard/bmMaterialsRouter.js | 4 +-
src/startup/routes.js | 2 +-
3 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index b55b70b7e..a31ed460e 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,17 +1,41 @@
const mongoose = require('mongoose')
-const bmMaterialsController = function (ItemMaterial, ItemType) {
+const bmMaterialsController = function (ItemMaterial) {
const bmMaterialsList = async function _matsList(req, res) {
try {
ItemMaterial.find()
- .populate({
- path: 'project',
- select: '_id projectName'
- })
- .populate({
- path: 'inventoryItemType',
- select: '_id name uom totalStock'
- })
+ .populate([
+ {
+ path: 'project',
+ select: '_id projectName'
+ },
+ {
+ path: 'inventoryItemType',
+ select: '_id name uom totalStock totalAvailable'
+ },
+ {
+ path: 'usageRecord',
+ populate: {
+ path: 'createdBy',
+ select: '_id firstName lastName'
+ }
+ },
+ {
+ path: 'updateRecord',
+ populate: {
+ path: 'createdBy',
+ select: '_id firstName lastName'
+ }
+ },
+ {
+ path: 'purchaseRecord',
+ populate: {
+ path: 'createdBy',
+ select: '_id firstName lastName'
+ }
+ }
+ ])
+ .exec()
.then(results => res.status(200).send(results))
.catch(error => res.status(500).send(error))
} catch (err) {
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index d3e4518da..ab8a67388 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -1,8 +1,8 @@
const express = require('express');
-const routes = function (itemMaterial, itemType) {
+const routes = function (itemMaterial) {
const materialsRouter = express.Router();
-const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial, itemType);
+const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial);
materialsRouter.route('/materials')
.get(controller.bmMaterialsList);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index cde07c94d..bbd22b530 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -56,7 +56,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, inventoryItemType);
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
From ba03b5b00594cace86a084e12897e05b8669dbe7 Mon Sep 17 00:00:00 2001
From: GaryB93
Date: Thu, 5 Oct 2023 17:05:38 -0500
Subject: [PATCH 060/272] add material routing, inventoryItemMaterial schema
---
package-lock.json | 106 +++++++++---------
.../bmdashboard/bmMaterialsController.js | 40 +++++++
src/models/inventoryItemMaterial.js | 36 ++++++
src/routes/bmdashboard/bmMaterialsRouter.js | 14 +++
src/startup/routes.js | 4 +-
5 files changed, 146 insertions(+), 54 deletions(-)
create mode 100644 src/controllers/bmdashboard/bmMaterialsController.js
create mode 100644 src/models/inventoryItemMaterial.js
create mode 100644 src/routes/bmdashboard/bmMaterialsRouter.js
diff --git a/package-lock.json b/package-lock.json
index 5c6bd6db5..47eb32afb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1414,7 +1414,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": {
@@ -1570,7 +1570,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",
@@ -2631,7 +2631,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",
@@ -2727,7 +2727,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",
@@ -2860,7 +2860,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",
@@ -2904,12 +2904,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",
@@ -2965,7 +2965,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",
@@ -3118,7 +3118,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",
@@ -3134,7 +3134,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",
@@ -3215,7 +3215,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",
@@ -4129,7 +4129,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",
@@ -4294,7 +4294,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": {
@@ -4424,7 +4424,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",
@@ -4434,7 +4434,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",
@@ -4812,7 +4812,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": {
@@ -4824,7 +4824,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"
@@ -4930,7 +4930,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",
@@ -5032,13 +5032,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",
@@ -5076,7 +5076,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": {
@@ -5397,7 +5397,7 @@
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"lodash.merge": {
"version": "4.6.2",
@@ -5574,7 +5574,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",
@@ -5588,7 +5588,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",
@@ -5599,7 +5599,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",
@@ -5610,7 +5610,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",
@@ -5767,7 +5767,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": {
@@ -5845,7 +5845,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",
@@ -6564,7 +6564,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"
}
@@ -6594,7 +6594,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": {
@@ -6639,7 +6639,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",
@@ -6654,7 +6654,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",
@@ -6670,7 +6670,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",
@@ -6717,7 +6717,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",
@@ -6728,7 +6728,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",
@@ -6739,7 +6739,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"
@@ -6781,7 +6781,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
},
"punycode": {
@@ -7219,7 +7219,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"
@@ -7228,7 +7228,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",
@@ -7623,7 +7623,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": {
@@ -7654,19 +7654,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",
@@ -7684,7 +7684,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",
@@ -7802,7 +7802,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": {
@@ -7843,7 +7843,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",
@@ -7857,17 +7857,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",
@@ -7890,17 +7890,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"
@@ -8018,7 +8018,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/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
new file mode 100644
index 000000000..558a0f403
--- /dev/null
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -0,0 +1,40 @@
+const mongoose = require('mongoose');
+
+const bmMaterialsController = function (ItemMaterial, ItemType) {
+ const bmMaterialsList = async function (req, res) {
+ try {
+ ItemMaterial.find()
+ .populate({
+ path: 'project',
+ select: '_id projectName'
+ })
+ .populate({
+ path: 'inventoryItemType',
+ select: '_id name uom totalStock'
+ })
+ .then(results => res.status(200).send(results))
+ .catch(error => res.status(500).send(error))
+ } catch (err) {
+ res.json(err);
+ }
+ };
+
+ const bmAddMaterials = async function (req, res) {
+ console.log(req.body);
+ // if new material or new measurement, add to inventoryItemType collection first
+ const { material, requestor } = req.body;
+ if (material.newMaterial || material.newMeasurement) {
+ const materials = await ItemMaterial.find().exec();
+ console.log(materials);
+
+ }
+ // then either add item material to project or update existing item material
+ };
+
+ return {
+ bmMaterialsList,
+ bmAddMaterials
+ };
+};
+
+module.exports = bmMaterialsController;
\ No newline at end of file
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
new file mode 100644
index 000000000..0c8aed460
--- /dev/null
+++ b/src/models/inventoryItemMaterial.js
@@ -0,0 +1,36 @@
+const mongoose = require('mongoose');
+const { Schema } = mongoose;
+
+const InventoryItemMaterial = new Schema({
+ inventoryItemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'inventoryItemType', required: true },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'project', required: true },
+ stockBought: { type: Number, required: true }, // amount bought for project, affects total stock
+ stockUsed: { type: Number, required: true },
+ stockAvailable: { type: Number, required: true },
+ stockHeld: { type: Number, required: true },
+ stockWasted: { type: Number, required: true },
+ usageRecord: [{ // daily log of amount inventory item used at job site
+ date: { type: Date, required: true, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
+ quantityUsed: { type: Number, required: true },
+ }],
+ updateRecord: [{ // incident report affecting quantity/status of inventory item
+ date: { type: Date, required: true, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
+ action: { type: String, required: true }, // ex: Add, Reduce, Hold (updates stock quantities)
+ cause: { type: String, required: true }, // ex: Used, Lost, Wasted, Transfer (reason for update)
+ quantity: { type: Number, required: true }, // amount of material affected
+ description: { type: String, required: true, maxLength: 150 },
+ }],
+ purchaseRecord: [{
+ date: { type: Date, required: true, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
+ poId: { type: String, required: true },
+ sellerId: { type: String, required: true },
+ quantity: { type: Number, required: true }, // adds to stockBought
+ subtotal: { type: Number, required: true },
+ tax: { type: Number, required: true },
+ shipping: { type: Number, required: true },
+ }]
+})
+module.exports = mongoose.model('inventoryItemMaterial', InventoryItemMaterial, 'inventoryMaterial');
\ No newline at end of file
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
new file mode 100644
index 000000000..aaded5587
--- /dev/null
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -0,0 +1,14 @@
+const express = require('express');
+
+const routes = function (itemMaterial, itemType) {
+ const materialsRouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial, itemType);
+
+ materialsRouter.route('/materials')
+ .get(controller.bmMaterialsList)
+ .post(controller.bmAddMaterials);
+
+ return materialsRouter;
+};
+
+module.exports = routes;
\ No newline at end of file
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 43cd226bd..a1eed4a7a 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -20,6 +20,7 @@ const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
+const itemMaterial = require('../models/inventoryItemMaterial');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -55,7 +56,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(itemMaterial);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -88,4 +89,5 @@ module.exports = function (app) {
app.use('/api', mouseoverTextRouter);
// bm dashboard
app.use('/api/bm', bmLoginRouter);
+ app.use('/api/bm', bmMaterialsRouter);
};
From bbc244e5274541a73f198c58937eaa3ba7bc90aa Mon Sep 17 00:00:00 2001
From: GaryB93
Date: Fri, 6 Oct 2023 14:36:14 -0500
Subject: [PATCH 061/272] controller logic for adding materials, update schemas
---
.../bmdashboard/bmMaterialsController.js | 58 +++++++++++++++++--
src/models/inventoryItemMaterial.js | 8 ++-
src/models/inventoryItemType.js | 9 ++-
src/startup/routes.js | 2 +-
4 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 558a0f403..d9d1c7780 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -21,14 +21,62 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
const bmAddMaterials = async function (req, res) {
console.log(req.body);
- // if new material or new measurement, add to inventoryItemType collection first
const { material, requestor } = req.body;
+ let itemTypeId = material.material; // if new material: material name / else: itemType id
+
+ // if new material or new measurement, add new inventoryItemType
if (material.newMaterial || material.newMeasurement) {
- const materials = await ItemMaterial.find().exec();
- console.log(materials);
-
+ try {
+ const itemType = new ItemType({
+ type: 'material',
+ name: material.material,
+ description: material.description,
+ uom: material.measurement,
+ totalStock: material.quantity,
+ totalAvailable: material.quantity,
+ projectsUsing: [material.projectId],
+ imageUrl: '',
+ link: material.link,
+ });
+ const newItemType = await itemType.save();
+ itemTypeId = newItemType._id;
+ } catch (err) {
+ res.status(400).send({ error: 'Error saving new material type'});
+ }
+ }
+
+ try {
+ const invMaterial = await ItemMaterial.find({ id: material.projectId, inventoryItemType: itemTypeId }).exec();
+ // if material already exists in project, add to it
+ // else, create new material for project
+ if (invMaterial) {
+ // TODO
+ console.log(invMaterial);
+ } else {
+ const itemMaterial = new ItemMaterial({
+ inventoryItemType: itemTypeId,
+ project: material.projectId,
+ stockBought: material.quantity,
+ stockAvailable: material.quantity,
+ usageRecord: [],
+ updateRecord: [],
+ purchaseRecord: [{
+ date: material.purchaseDate,
+ createdBy: req.requestor.requestorId,
+ poId: material.invoice,
+ sellerId: material.phone,
+ quantity: material.quantity,
+ unitPrice: material.unitPrice,
+ subTotal: material.quantity * material.unitPrice,
+ tax: material.taxRate,
+ shipping: material.shippingFee,
+ }],
+ });
+ const newItemMaterial = await itemMaterial.save();
+ }
+ } catch (err) {
+ res.status(400).send({ error: 'Error adding new material to project'});
}
- // then either add item material to project or update existing item material
};
return {
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index 0c8aed460..09c521e4d 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -5,10 +5,10 @@ const InventoryItemMaterial = new Schema({
inventoryItemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'inventoryItemType', required: true },
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'project', required: true },
stockBought: { type: Number, required: true }, // amount bought for project, affects total stock
- stockUsed: { type: Number, required: true },
+ stockUsed: { type: Number, default: 0 },
stockAvailable: { type: Number, required: true },
- stockHeld: { type: Number, required: true },
- stockWasted: { type: Number, required: true },
+ stockHeld: { type: Number, default: 0 },
+ stockWasted: { type: Number, default: 0 },
usageRecord: [{ // daily log of amount inventory item used at job site
date: { type: Date, required: true, default: Date.now() },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
@@ -28,6 +28,8 @@ const InventoryItemMaterial = new Schema({
poId: { type: String, required: true },
sellerId: { type: String, required: true },
quantity: { type: Number, required: true }, // adds to stockBought
+ unitPrice: { type: Number, required: true },
+ currency: { type: String, required: true },
subtotal: { type: Number, required: true },
tax: { type: Number, required: true },
shipping: { type: Number, required: true },
diff --git a/src/models/inventoryItemType.js b/src/models/inventoryItemType.js
index 80e5e0d7b..20a58c018 100644
--- a/src/models/inventoryItemType.js
+++ b/src/models/inventoryItemType.js
@@ -3,10 +3,15 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
const InventoryItemType = new Schema({
+ type: { type: String, required: true }, // ie Material, Equipment, Tool
name: { type: String, required: true },
- description: { type: String },
+ description: { type: String, required: true, maxLength: 150 },
+ uom: { type: String, required: true }, // unit of measurement
+ totalStock: { type: Number, required: true }, // total amount of all stock acquired
+ totalAvailable: { type: Number, required: true },
+ projectsUsing: [ {type: mongoose.SchemaTypes.ObjectId, ref: 'project'} ],
imageUrl: { type: String },
- quantifier: { type: String, default: 'each' },
+ link: { type: String },
});
module.exports = mongoose.model('inventoryItemType', InventoryItemType, 'inventoryItemType');
diff --git a/src/startup/routes.js b/src/startup/routes.js
index a1eed4a7a..66f7772dd 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -56,7 +56,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(itemMaterial);
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(itemMaterial, inventoryItemType);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
From 3d56ee05c122529239361e23ed58439218accdea Mon Sep 17 00:00:00 2001
From: robertoooc
Date: Sat, 7 Oct 2023 16:51:34 -0700
Subject: [PATCH 062/272] added logic to clear cache when updating badge so
user info is up to date
---
src/controllers/badgeController.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 6238c381e..e3768884a 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -2,6 +2,7 @@ const mongoose = require('mongoose');
const UserProfile = require('../models/userProfile');
const { hasPermission, hasIndividualPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
+const cache = require('../utilities/nodeCache')();
const badgeController = function (Badge) {
const getAllBadges = async function (req, res) {
@@ -47,6 +48,8 @@ const badgeController = function (Badge) {
if (result) {
record.badgeCollection = req.body.badgeCollection;
+ if (cache.hasCache(`user-${userToBeAssigned}`)) cache.removeCache(`user-${userToBeAssigned}`);
+
record.save()
.then(results => res.status(201).send(results._id))
.catch(errors => res.status(500).send(errors));
From 1782d7446115509e54cd88f431be62f78334106a Mon Sep 17 00:00:00 2001
From: Aaron Persaud
Date: Sat, 7 Oct 2023 23:53:33 -0400
Subject: [PATCH 063/272] remove 400 errors for invalid team code
---
src/controllers/userProfileController.js | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index afafe2488..80c6d64f0 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -314,11 +314,6 @@ const userProfileController = function (UserProfile) {
return;
}
- const teamcodeRegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$/;
- if (!teamcodeRegex.test(req.body.teamCode)) {
- res.status(400).send("The team code is invalid");
- return;
- };
record.teamCode = req.body.teamCode;
// find userData in cache
@@ -608,17 +603,12 @@ const userProfileController = function (UserProfile) {
if (key === "teamCode") {
const canEditTeamCode = req.body.requestor.role === "Owner" ||
req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
- const teamcodeRegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$/;
if(!canEditTeamCode){
res.status(403).send("You are not authorized to edit team code.");
return;
}
- if (!teamcodeRegex.test(value)) {
- res.status(400).send("The team code is invalid");
- return;
- };
}
// remove user from cache, it should be loaded next time
From 61663e93b974ecb87ecea6daab9ff6fa200f011b Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Mon, 9 Oct 2023 14:09:42 -0700
Subject: [PATCH 064/272] update material, itemType schema
---
src/models/inventoryItemMaterial.js | 2 ++
src/models/inventoryItemType.js | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index b795d2f63..e6153af45 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -29,6 +29,8 @@ const InventoryItemMaterial = new Schema({
poId: { type: String, required: true },
sellerId: { type: String, required: true },
quantity: { type: Number, required: true }, // adds to stockBought
+ unitPrice: {type: Number, required: true},
+ currency: { type: String, required: true },
subtotal: { type: Number, required: true },
tax: { type: Number, required: true },
shipping: { type: Number, required: true },
diff --git a/src/models/inventoryItemType.js b/src/models/inventoryItemType.js
index 207ac77b0..321038a84 100644
--- a/src/models/inventoryItemType.js
+++ b/src/models/inventoryItemType.js
@@ -10,7 +10,8 @@ const InventoryItemType = new Schema({ // creates an item, tracks total amount i
totalStock: { type: Number, required: true }, // total amount of all stock acquired
totalAvailable: { type: Number, required: true },
projectsUsing: [ {type: mongoose.SchemaTypes.ObjectId, ref: 'project'} ],
- imageUrl: { type: String }
+ imageUrl: { type: String },
+ link: { type: String}
});
module.exports = mongoose.model('inventoryItemType', InventoryItemType, 'inventoryItemType');
From 545a2582263748f4ea2e8f3d1ff80215d6fdf2d4 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Tue, 10 Oct 2023 13:42:53 -0700
Subject: [PATCH 065/272] add nodemon package for auto restarting upon changes,
modify readme command description, change parser from babel-eslint to
@babel/eslint-parser in eslintrc
---
.eslintrc | 2 +-
README.md | 11 ++++++-----
package.json | 8 ++++++--
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/.eslintrc b/.eslintrc
index f8b746a0a..7e82fa35b 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,6 +1,6 @@
{
"extends": ["eslint:recommended", "airbnb-base"],
- "parser": "babel-eslint",
+ "parser": "@babel/eslint-parser",
"parserOptions": {
"ecmaVersion": 8,
"sourceType": "module"
diff --git a/README.md b/README.md
index 0db749fc6..0c286d922 100644
--- a/README.md
+++ b/README.md
@@ -30,11 +30,12 @@ JWT_SECRET=
To make the process easy create a .env file and put the above text in the file and replace values with the correct values, which you can get from your teammates. Then do an npm run-script build followed by an npm start. By default, the services will start on port 4500 and you can http://localhost:4500/api/ to access the methods. A tools like Postman will be your best friend here, you will need to have an auth token placed in the 'Authorization' header which you can get through the networking tab of the local frontend when you login.
-* `npm run lint` command for fixing lint
-* `npm run build` command for building server
-* `npm run buildw` command for auto rebuild upon change of src
-* `npm run start` command for running the server in dist
-* `npm run serve` command for running server in src without build
+* `npm run lint` -- fix lint
+* `npm run build` -- build src server and save in dist
+* `npm run buildw` -- auto rebuild upon change of src
+* `npm run start` -- run the server in dist
+* `npm run serve` -- run the server in src without build
+* `npm run dev` -- run the server in src and auto restart upon change of src
Note: Once you check in the code in github, the application will be publsihed to the following:
Developement : https://hgn-rest-dev.herokuapp.com
diff --git a/package.json b/package.json
index f9387e933..ec0579a20 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,8 @@
"build": "babel src -d dist",
"buildw": "babel src -d dist --watch",
"start": "node dist/server.js",
- "serve": "node src/server.js"
+ "dev": "nodemon --exec babel-node src/server.js",
+ "serve": "babel-node src/server.js"
},
"pre-commit": [
"lint"
@@ -23,7 +24,6 @@
"@babel/eslint-parser": "^7.15.0",
"@types/express": "^4.17.6",
"@types/node": "^8.10.61",
- "babel-eslint": "^10.1.0",
"eslint": "^8.47.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-base": "^13.1.0",
@@ -33,6 +33,7 @@
"eslint-plugin-react": "^7.33.1",
"eslint-plugin-react-hooks": "^4.6.0",
"lint-staged": "^13.0.3",
+ "nodemon": "^3.0.1",
"pre-commit": "^1.2.2"
},
"dependencies": {
@@ -66,5 +67,8 @@
"redis": "^4.2.0",
"uuid": "^3.4.0",
"ws": "^8.8.1"
+ },
+ "nodemonConfig": {
+ "watch": ["/src/**/*"]
}
}
From a8ebf5b19cb7cb29d27240e9cc41d34f3b391f66 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Tue, 10 Oct 2023 14:01:54 -0700
Subject: [PATCH 066/272] sync package-lock.json
---
package-lock.json | 160 +++++++++++++++++++++++++++++++++++++---------
package.json | 4 +-
2 files changed, 134 insertions(+), 30 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 5c6bd6db5..f9eb87ba6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1459,6 +1459,12 @@
"@types/node": "*"
}
},
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
"abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -1536,7 +1542,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
- "optional": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -2494,28 +2499,6 @@
"dequal": "^2.0.3"
}
},
- "babel-eslint": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
- "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "@babel/parser": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0",
- "eslint-visitor-keys": "^1.0.0",
- "resolve": "^1.12.0"
- },
- "dependencies": {
- "eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
- "dev": true
- }
- }
- },
"babel-plugin-dynamic-import-node": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
@@ -2641,8 +2624,7 @@
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "optional": true
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
"bl": {
"version": "2.2.1",
@@ -2773,7 +2755,6 @@
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
- "optional": true,
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -4538,7 +4519,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "optional": true,
"requires": {
"is-glob": "^4.0.1"
}
@@ -4799,6 +4779,12 @@
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true
},
+ "ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
+ "dev": true
+ },
"import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -4892,7 +4878,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "optional": true,
"requires": {
"binary-extensions": "^2.0.0"
}
@@ -5820,6 +5805,68 @@
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.2.tgz",
"integrity": "sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q=="
},
+ "nodemon": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz",
+ "integrity": "sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^3.5.2",
+ "debug": "^3.2.7",
+ "ignore-by-default": "^1.0.1",
+ "minimatch": "^3.1.2",
+ "pstree.remy": "^1.1.8",
+ "semver": "^7.5.3",
+ "simple-update-notifier": "^2.0.0",
+ "supports-color": "^5.5.0",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.5"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+ },
+ "nopt": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+ "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
+ "dev": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -6784,6 +6831,12 @@
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"dev": true
},
+ "pstree.remy": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
+ "dev": true
+ },
"punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
@@ -6841,7 +6894,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "optional": true,
"requires": {
"picomatch": "^2.2.1"
}
@@ -7185,6 +7237,41 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true
},
+ "simple-update-notifier": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
+ "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.5.3"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+ },
"slash": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
@@ -7681,6 +7768,15 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
+ "touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+ "dev": true,
+ "requires": {
+ "nopt": "~1.0.10"
+ }
+ },
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -7816,6 +7912,12 @@
"which-boxed-primitive": "^1.0.2"
}
},
+ "undefsafe": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
+ "dev": true
+ },
"unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
diff --git a/package.json b/package.json
index ec0579a20..1c6b8a5d4 100644
--- a/package.json
+++ b/package.json
@@ -69,6 +69,8 @@
"ws": "^8.8.1"
},
"nodemonConfig": {
- "watch": ["/src/**/*"]
+ "watch": [
+ "/src/**/*"
+ ]
}
}
From e55f980bed651b15bb0fad0202113e70a5ca4214 Mon Sep 17 00:00:00 2001
From: GaryB93
Date: Tue, 10 Oct 2023 18:52:52 -0500
Subject: [PATCH 067/272] save new item type before adding material to project
---
.../bmdashboard/bmMaterialsController.js | 33 ++++++++++---------
src/models/inventoryItemMaterial.js | 2 +-
2 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index d9d1c7780..8b53ab35f 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -20,9 +20,8 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
};
const bmAddMaterials = async function (req, res) {
- console.log(req.body);
const { material, requestor } = req.body;
- let itemTypeId = material.material; // if new material: material name / else: itemType id
+ let itemTypeId = material.material; // either new material or existing itemTypeId
// if new material or new measurement, add new inventoryItemType
if (material.newMaterial || material.newMeasurement) {
@@ -38,20 +37,20 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
imageUrl: '',
link: material.link,
});
- const newItemType = await itemType.save();
- itemTypeId = newItemType._id;
- } catch (err) {
- res.status(400).send({ error: 'Error saving new material type'});
+ const result = await itemType.save();
+ itemTypeId = result._id;
+ } catch (error) {
+ res.status(500).send(error);
}
}
try {
- const invMaterial = await ItemMaterial.find({ id: material.projectId, inventoryItemType: itemTypeId }).exec();
- // if material already exists in project, add to it
- // else, create new material for project
+ const invMaterial = await ItemMaterial.findOne(
+ { project: material.projectId, inventoryItemType: itemTypeId }).exec();
+ console.log(invMaterial);
if (invMaterial) {
- // TODO
- console.log(invMaterial);
+ // TODO: update inventoryMaterial with new purchase record
+ // and updated quantities
} else {
const itemMaterial = new ItemMaterial({
inventoryItemType: itemTypeId,
@@ -62,26 +61,28 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
updateRecord: [],
purchaseRecord: [{
date: material.purchaseDate,
- createdBy: req.requestor.requestorId,
+ createdBy: requestor.requestorId,
poId: material.invoice,
sellerId: material.phone,
quantity: material.quantity,
unitPrice: material.unitPrice,
- subTotal: material.quantity * material.unitPrice,
+ currency: material.currency,
+ subtotal: material.quantity,
tax: material.taxRate,
shipping: material.shippingFee,
}],
});
const newItemMaterial = await itemMaterial.save();
+ console.log(newItemMaterial);
}
- } catch (err) {
- res.status(400).send({ error: 'Error adding new material to project'});
+ } catch (error) {
+ res.status(500).send(error);
}
};
return {
bmMaterialsList,
- bmAddMaterials
+ bmAddMaterials,
};
};
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index 09c521e4d..2ffa1fba2 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -23,7 +23,7 @@ const InventoryItemMaterial = new Schema({
description: { type: String, required: true, maxLength: 150 },
}],
purchaseRecord: [{
- date: { type: Date, required: true, default: Date.now() },
+ date: { type: String, required: true },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
poId: { type: String, required: true },
sellerId: { type: String, required: true },
From a5f7911be6ce912e73f44f1a459231630c5b2b92 Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Wed, 11 Oct 2023 13:06:02 -0700
Subject: [PATCH 068/272] Create blue square reason scheduler for all users
---
.gitattributes | 2 +-
src/controllers/reasonSchedulingController.js | 68 +++++++++----------
2 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/.gitattributes b/.gitattributes
index d528e69e3..6cf651ce7 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,6 +1,6 @@
# https://warlord0blog.wordpress.com/2019/09/04/vscode-crlf-vs-lf-battle/
- text=lf
+# text=lf
*.css linguist-vendored eol=lf
*.scss linguist-vendored eol=lf
*.js linguist-vendored eol=lf
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 02706546b..3969f2e91 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -38,13 +38,13 @@ const postReason = async (req, res) => {
}
// error case 1
- 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',
- errorCode: 1,
- });
- }
+ // 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',
+ // errorCode: 1,
+ // });
+ // }
const foundUser = await UserModel.findById(userId);
@@ -98,12 +98,12 @@ const getAllReasons = async (req, res) => {
const { userId } = req.params;
// error case 1
- if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') {
- return res.status(403).json({
- message:
- 'You must be an Owner or Administrator to get a reason for a Blue Square',
- });
- }
+ // if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') {
+ // return res.status(403).json({
+ // message:
+ // 'You must be an Owner or Administrator to get a reason for a Blue Square',
+ // });
+ // }
const foundUser = await UserModel.findById(userId);
@@ -136,13 +136,13 @@ const getSingleReason = async (req, res) => {
const { queryDate } = req.query;
// error case 1
- if (requestor.role !== 'Administrator' && requestor.role !== 'Owner') {
- return res.status(403).json({
- message:
- "You must be an Administrator or Owner to be able to get a single reason by the user's ID",
- errorCode: 1,
- });
- }
+ // if (requestor.role !== 'Administrator' && requestor.role !== 'Owner') {
+ // return res.status(403).json({
+ // message:
+ // "You must be an Administrator or Owner to be able to get a single reason by the user's ID",
+ // errorCode: 1,
+ // });
+ // }
const foundUser = await UserModel.findById(userId);
// error case 2
@@ -185,13 +185,13 @@ const patchReason = async (req, res) => {
const { userId } = req.params;
// error case 1
- 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',
- errorCode: 1,
- });
- }
+ // 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',
+ // errorCode: 1,
+ // });
+ // }
if (!reasonData.message) {
return res.status(400).json({
@@ -244,13 +244,13 @@ const deleteReason = async (req, res) => {
const { userId } = req.params;
// error case 1
- 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',
- errorCode: 1,
- });
- }
+ // 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',
+ // errorCode: 1,
+ // });
+ // }
const foundUser = await UserModel.findById(userId);
From 31d1e39d35cf0867ea786ef7eb2e59e294d63d4b Mon Sep 17 00:00:00 2001
From: GaryB93
Date: Wed, 11 Oct 2023 17:29:28 -0500
Subject: [PATCH 069/272] update method to add inventory types
---
.../bmdashboard/bmMaterialsController.js | 31 +++----------------
src/controllers/inventoryController.js | 7 ++++-
2 files changed, 10 insertions(+), 28 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 8b53ab35f..708c4d884 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -21,39 +21,16 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
const bmAddMaterials = async function (req, res) {
const { material, requestor } = req.body;
- let itemTypeId = material.material; // either new material or existing itemTypeId
-
- // if new material or new measurement, add new inventoryItemType
- if (material.newMaterial || material.newMeasurement) {
- try {
- const itemType = new ItemType({
- type: 'material',
- name: material.material,
- description: material.description,
- uom: material.measurement,
- totalStock: material.quantity,
- totalAvailable: material.quantity,
- projectsUsing: [material.projectId],
- imageUrl: '',
- link: material.link,
- });
- const result = await itemType.save();
- itemTypeId = result._id;
- } catch (error) {
- res.status(500).send(error);
- }
- }
try {
- const invMaterial = await ItemMaterial.findOne(
- { project: material.projectId, inventoryItemType: itemTypeId }).exec();
- console.log(invMaterial);
+ const invMaterial = await ItemMaterial.findOne({ project: material.projectId, inventoryItemType: material.material }).exec();
if (invMaterial) {
+ console.log('found item material in project');
// TODO: update inventoryMaterial with new purchase record
// and updated quantities
} else {
const itemMaterial = new ItemMaterial({
- inventoryItemType: itemTypeId,
+ inventoryItemType: material.material,
project: material.projectId,
stockBought: material.quantity,
stockAvailable: material.quantity,
@@ -73,7 +50,7 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
}],
});
const newItemMaterial = await itemMaterial.save();
- console.log(newItemMaterial);
+ res.status(201).send(newItemMaterial);
}
} catch (error) {
res.status(500).send(error);
diff --git a/src/controllers/inventoryController.js b/src/controllers/inventoryController.js
index bc0902aeb..d4c9d5261 100644
--- a/src/controllers/inventoryController.js
+++ b/src/controllers/inventoryController.js
@@ -548,10 +548,15 @@ const inventoryController = function (Item, ItemType) {
}
const itemType = new ItemType();
+ itemType.type = req.body.type;
itemType.name = req.body.name;
itemType.description = req.body.description;
+ itemType.uom = req.body.uom;
+ itemType.totalStock = req.body.totalStock;
+ itemType.totalAvailable = req.body.totalAvailable;
+ itemType.projectsUsing = [];
itemType.imageUrl = req.body.imageUrl || req.body.imageURL;
- itemType.quantifier = req.body.quantifier;
+ itemType.link = req.body.link;
itemType.save()
.then(results => res.status(201).send(results))
From 670d86fbfd149163f4ea5495e3bfc5c4ef68d27f Mon Sep 17 00:00:00 2001
From: GaryB93
Date: Thu, 12 Oct 2023 18:53:50 -0500
Subject: [PATCH 070/272] update inventory material quantities and purchase
records when adding
---
.../bmdashboard/bmMaterialsController.js | 44 +++++++++++--------
src/models/inventoryItemMaterial.js | 2 +-
2 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 708c4d884..0f1e8a38e 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -20,14 +20,33 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
};
const bmAddMaterials = async function (req, res) {
+ // add permission check...
+
const { material, requestor } = req.body;
+ const purchaseRecord = {
+ date: material.purchaseDate,
+ createdBy: requestor.requestorId,
+ poId: material.invoice,
+ sellerId: material.phone,
+ quantity: material.quantity,
+ unitPrice: material.unitPrice,
+ currency: material.currency,
+ subtotal: material.quantity,
+ tax: material.taxRate,
+ shipping: material.shippingFee,
+ };
try {
- const invMaterial = await ItemMaterial.findOne({ project: material.projectId, inventoryItemType: material.material }).exec();
- if (invMaterial) {
- console.log('found item material in project');
- // TODO: update inventoryMaterial with new purchase record
- // and updated quantities
+ const result = await ItemMaterial.findOneAndUpdate(
+ { project: material.projectId, inventoryItemType: material.material },
+ {
+ $inc: { stockBought: material.quantity, stockAvailable: material.quantity },
+ $push: { purchaseRecord: purchaseRecord },
+ },
+ { returnDocument: 'after', lean: true }).exec();
+ if (result) {
+ console.log(result);
+ res.status(201).send(result);
} else {
const itemMaterial = new ItemMaterial({
inventoryItemType: material.material,
@@ -36,18 +55,7 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
stockAvailable: material.quantity,
usageRecord: [],
updateRecord: [],
- purchaseRecord: [{
- date: material.purchaseDate,
- createdBy: requestor.requestorId,
- poId: material.invoice,
- sellerId: material.phone,
- quantity: material.quantity,
- unitPrice: material.unitPrice,
- currency: material.currency,
- subtotal: material.quantity,
- tax: material.taxRate,
- shipping: material.shippingFee,
- }],
+ purchaseRecord: [purchaseRecord],
});
const newItemMaterial = await itemMaterial.save();
res.status(201).send(newItemMaterial);
@@ -57,7 +65,7 @@ const bmMaterialsController = function (ItemMaterial, ItemType) {
}
};
- return {
+ return {
bmMaterialsList,
bmAddMaterials,
};
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index 2ffa1fba2..09c521e4d 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -23,7 +23,7 @@ const InventoryItemMaterial = new Schema({
description: { type: String, required: true, maxLength: 150 },
}],
purchaseRecord: [{
- date: { type: String, required: true },
+ date: { type: Date, required: true, default: Date.now() },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
poId: { type: String, required: true },
sellerId: { type: String, required: true },
From bc2655be2bb9b3149d13d9b34fa3a84247276e12 Mon Sep 17 00:00:00 2001
From: Chuehleo <122568562+Chuehleo@users.noreply.github.com>
Date: Fri, 13 Oct 2023 15:55:00 -0700
Subject: [PATCH 071/272] Update userProfileController.js
---
src/controllers/userProfileController.js | 159 +++++++++++------------
1 file changed, 75 insertions(+), 84 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 6036b9d0f..a388f10db 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -12,7 +12,7 @@ const Badge = require('../models/badge');
const userProfile = require('../models/userProfile');
const yearMonthDayDateValidator = require('../utilities/yearMonthDayDateValidator');
const cache = require('../utilities/nodeCache')();
-const { hasPermission, hasIndividualPermission, canRequestorUpdateUser } = require('../utilities/permissions');
+const { hasPermission, canRequestorUpdateUser } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const config = require('../config');
@@ -35,7 +35,20 @@ async function ValidatePassword(req, res) {
return;
}
// Verify request is authorized by self or adminsitrator
- if (!userId === requestor.requestorId && !await hasPermission(requestor.role, 'updatePassword')) {
+ if (userId !== requestor.requestorId && !await hasPermission(requestor.role, 'updatePassword')) {
+ console.log('User ID:', userId);
+ console.log('Requestor ID:', requestor.requestorId);
+ res.status(403).send({
+ error: "You are unauthorized to update this user's password",
+ });
+ return;
+ }
+
+
+ // Check permissions
+ if (userId === requestor.requestorId || !await hasPermission(requestor.role, 'updatePasswordForOthers')) {
+ console.log('User ID:', userId);
+ console.log('Requestor ID:', requestor.requestorId);
res.status(403).send({
error: "You are unauthorized to update this user's password",
});
@@ -52,16 +65,20 @@ async function ValidatePassword(req, res) {
const userProfileController = function (UserProfile) {
const getUserProfiles = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'getUserProfiles') &&
+ if (
+ !(await hasPermission(req.body.requestor.role, "getUserProfiles")) &&
!req.body.requestor.permissions?.frontPermissions.includes(
"putUserProfilePermissions"
)
) {
- if (!await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagement')
- && !await hasIndividualPermission(req.body.requestor.requestorId, 'seeProjectManagementTab')) {
- res.status(403).send('You are not authorized to view all users');
+ res.status(403).send("You are not authorized to view all users");
+ return;
+ }
+
+ if (cache.getCache("allusers")) {
+ const getData = JSON.parse(cache.getCache("allusers"));
+ res.status(200).send(getData);
return;
- }
}
UserProfile.find(
@@ -73,20 +90,13 @@ const userProfileController = function (UserProfile) {
})
.then((results) => {
if (!results) {
- if (cache.getCache("allusers")) {
- const getData = JSON.parse(cache.getCache("allusers"));
- res.status(200).send(getData);
- return;
- }else{
- res.status(500).send({ error: "User result was invalid" });
- return;
- }
+ res.status(500).send({ error: "User result was invalid" });
+ return;
}
cache.setCache("allusers", JSON.stringify(results));
res.status(200).send(results);
})
.catch((error) => res.status(404).send(error));
-
};
const getProjectMembers = async function (req, res) {
@@ -245,9 +255,6 @@ const userProfileController = function (UserProfile) {
"putUserProfilePermissions"
))
);
-
- const canEditTeamCode = req.body.requestor.role === "Owner" ||
- req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
if (!isRequestorAuthorized) {
res.status(403).send("You are not authorized to update this user");
@@ -309,12 +316,6 @@ const userProfileController = function (UserProfile) {
record.totalIntangibleHrs = req.body.totalIntangibleHrs;
record.bioPosted = req.body.bioPosted || "default";
record.isFirstTimelog = req.body.isFirstTimelog;
-
- if(!canEditTeamCode && record.teamCode !== req.body.teamCode){
- res.status(403).send("You are not authorized to edit team code.");
- return;
- }
-
record.teamCode = req.body.teamCode;
// find userData in cache
@@ -601,17 +602,6 @@ const userProfileController = function (UserProfile) {
const { userId } = req.params;
const { key, value } = req.body;
- if (key === "teamCode") {
- const canEditTeamCode = req.body.requestor.role === "Owner" ||
- req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
-
- if(!canEditTeamCode){
- res.status(403).send("You are not authorized to edit team code.");
- return;
- }
-
- }
-
// remove user from cache, it should be loaded next time
cache.removeCache(`user-${userId}`);
if (!key || value === undefined) return res.status(400).send({ error: 'Missing property or value' });
@@ -636,70 +626,71 @@ const userProfileController = function (UserProfile) {
const updatepassword = async function (req, res) {
const { userId } = req.params;
const { requestor } = req.body;
+
+ console.log('User ID:', userId);
+ console.log('Requestor ID:', requestor.requestorId);
+
+ // Check if userId is valid.
if (!mongoose.Types.ObjectId.isValid(userId)) {
- return res.status(400).send({
- error: 'Bad Request',
- });
+ return res.status(400).send({
+ error: 'Bad Request',
+ });
}
// Verify correct params in body
if (!req.body.currentpassword || !req.body.newpassword || !req.body.confirmnewpassword) {
- return res.status(400).send({
- error: 'One of more required fields are missing',
- });
- }
- // Verify request is authorized by self or adminsitrator
- if (!userId === requestor.requestorId && !await hasPermission(requestor.role, 'updatePassword')) {
- return res.status(403).send({
- error: "You are unauthorized to update this user's password",
- });
+ return res.status(400).send({
+ error: 'One or more required fields are missing',
+ });
}
- if (canRequestorUpdateUser(requestor.requestorId, userId)) {
- return res.status(403).send({
- error: "You are unauthorized to update this user's password",
- });
+ // Check if the requestor has the permission to update passwords.
+ const hasUpdatePasswordPermission = await hasPermission(requestor.role, 'updatePassword');
+
+ // If the requestor is updating their own password, allow them to proceed.
+ if (userId === requestor.requestorId) {
+ console.log('Requestor is updating their own password');
+ }
+ // Else if they're updating someone else's password, they need the 'updatePassword' permission.
+ else if (!hasUpdatePasswordPermission) {
+ console.log("Requestor is trying to update someone else's password but lacks the 'updatePassword' permission");
+ return res.status(403).send({
+ error: "You are unauthorized to update this user's password",
+ });
}
// Verify new and confirm new password are correct
-
if (req.body.newpassword !== req.body.confirmnewpassword) {
- res.status(400).send({
- error: 'New and confirm new passwords are not same',
- });
+ return res.status(400).send({
+ error: 'New and confirm new passwords are not the same',
+ });
}
- // Verify old and new passwords are not same
- if (req.body.currentpassword === req.body.newpassword) {
- res.status(400).send({
- error: 'Old and new passwords should not be same',
- });
- }
+ // Process the password change
+ try {
+ const user = await UserProfile.findById(userId, 'password');
+ const passwordMatch = await bcrypt.compare(req.body.currentpassword, user.password);
- return UserProfile.findById(userId, 'password')
- .then((user) => {
- bcrypt
- .compare(req.body.currentpassword, user.password)
- .then((passwordMatch) => {
- if (!passwordMatch) {
- return res.status(400).send({
+ if (!passwordMatch) {
+ return res.status(400).send({
error: 'Incorrect current password',
- });
- }
-
- user.set({
- password: req.body.newpassword,
- resetPwd: undefined,
});
- return user
- .save()
- .then(() => res.status(200).send({ message: 'updated password' }))
- .catch(error => res.status(500).send(error));
- })
- .catch(error => res.status(500).send(error));
- })
- .catch(error => res.status(500).send(error));
- };
+ }
+
+ user.set({
+ password: req.body.newpassword,
+ resetPwd: undefined,
+ });
+
+ await user.save();
+
+ return res.status(200).send({ message: 'Updated password successfully' });
+
+ } catch (error) {
+ return res.status(500).send(error);
+ }
+};
+
const getreportees = async function (req, res) {
if (!mongoose.Types.ObjectId.isValid(req.params.userId)) {
From 64a65b99fd4e07a89b7c4dd8f49db3ddc6f15e42 Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Fri, 13 Oct 2023 21:11:18 -0700
Subject: [PATCH 072/272] Add Email Sending on save and update
---
src/controllers/reasonSchedulingController.js | 68 ++++++++++++++++---
1 file changed, 58 insertions(+), 10 deletions(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 3969f2e91..39729680f 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -1,6 +1,8 @@
+
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) => {
@@ -37,6 +39,7 @@ const postReason = async (req, res) => {
});
}
+ //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({
@@ -82,8 +85,33 @@ const postReason = async (req, res) => {
date: savingDate,
userId,
});
- await newReason.save();
+
+
+ //await newReason.save();
+ console.log("Inside post sending email function.");
+ const savedData = await newReason.save();
+ if(savedData)
+ {
+ console.log("Inside if.");
+ //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 emailBody = ` Hi !
+
+ This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has set their Blue Square Reason.
+
+ Blue Square Reason : ${newReason.reason}
+ Scheduled date for the Blue Square Reason: : ${newReason.date}
+
+ Thank you,
+ One Community
`;
+ console.log("line before email sender")
+
+ emailSender('shreetesting4@gmail.com', subject, emailBody, null, null);
+ }
+
return res.sendStatus(200);
+
} catch (error) {
console.log(error);
return res.status(400).json({
@@ -226,7 +254,27 @@ const patchReason = async (req, res) => {
}
foundReason.reason = reasonData.message;
- await foundReason.save();
+ console.log("patchReason----------");
+ const savedData = await foundReason.save();
+ if(savedData)
+ {
+ console.log(" Patch - Inside if.");
+ //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 emailBody = ` Hi !
+
+ This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has updated their Blue Square Reason.
+
+ Updated Blue Square Reason : ${foundReason.reason}
+ Scheduled date for the Blue Square Reason: : ${foundReason.date}
+
+ Thank you,
+ One Community
`;
+ console.log("line before email sender")
+
+ emailSender('shreetesting4@gmail.com', subject, emailBody, null, null);
+ }
return res.status(200).json({
message: 'Reason Updated!',
@@ -243,14 +291,14 @@ const deleteReason = async (req, res) => {
const { reasonData, requestor } = req.body;
const { userId } = req.params;
- // error case 1
- // 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',
- // errorCode: 1,
- // });
- // }
+ //error case 1
+ 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',
+ errorCode: 1,
+ });
+ }
const foundUser = await UserModel.findById(userId);
From 4d98c53461d9c6150aa306d7a13fa528357181ff Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Sat, 14 Oct 2023 13:41:18 -0700
Subject: [PATCH 073/272] Fix collection name
---
src/utilities/createInitialPermissions.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/utilities/createInitialPermissions.js b/src/utilities/createInitialPermissions.js
index a5c69d87f..6e22eb6a1 100644
--- a/src/utilities/createInitialPermissions.js
+++ b/src/utilities/createInitialPermissions.js
@@ -265,9 +265,9 @@ const createInitialPermissions = async () => {
// If role exists in db and is not updated, update default
} else if (!presetDataBase.permissions.every(perm => permissions.includes(perm)) || !permissions.every(perm => presetDataBase.permissions.includes(perm))) {
- const roleId = presetDataBase._id;
+ const presetId = presetDataBase._id;
- promises.push(Role.findById(roleId, (_, record) => {
+ promises.push(RolePreset.findById(presetId, (_, record) => {
record.permissions = permissions;
record.save();
}));
From 82d29effc13a1202d8b83ed69d3c11f92a5dec7c Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Sun, 15 Oct 2023 12:06:40 -0400
Subject: [PATCH 074/272] feat: userprofiles sending totalTangibleHrs, update
user controller, all manually locations response structure
---
src/controllers/mapLocationsController.js | 85 ++++++++++++++++++++---
src/controllers/userProfileController.js | 2 +-
src/routes/mapLocationsRouter.js | 3 +-
3 files changed, 78 insertions(+), 12 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 6088de489..f01666558 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,11 +1,26 @@
-const mapLocationsController = function (mapLocation) {
+const userProfile = require('../models/userProfile');
+const cache = require('../utilities/nodeCache')();
+
+const mapLocationsController = function (MapLocation) {
const getAllLocations = function (req, res) {
+ const priorText = 'Prior to HGN Data Collection';
+ MapLocation.find({})
+ .then(results => {
+ const users = results.map(item => {
+ return ({
+ title: priorText,
+ firstName: item.firstName !== priorText ? item.firstName : '',
+ lastName: item.lastName !== priorText ? item.lastName : '',
+ jobTitle: item.jobTitle !== priorText ? item.jobTitle : '',
+ location: item.location,
+ isActive: item.isActive,
+ _id: item._id
+ })
+ })
+ res.send(users).status(200);
- mapLocation.find({})
- .then(results =>
- res.send(results).status(200)
- )
- .catch(error =>
+ })
+ .catch(error =>
res.send(error).status(404));
};
const deleteLocation = async function (req, res) {
@@ -14,6 +29,11 @@ const mapLocationsController = function (mapLocation) {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
+ const locationId = req.params.locationId
+
+ MapLocation.findOneAndDelete({ _id: locationId })
+ .then(() => res.status(200).send({ message: "The location was successfully removed!" }))
+ .catch(error => res.status(500).send({ message: error || "Couldn't remove the location" }));
};
const putUserLocation = async function (req, res) {
@@ -27,24 +47,69 @@ const mapLocationsController = function (mapLocation) {
jobTitle: req.body.jobTitle,
location: req.body.location,
}
- const location = new mapLocation(locationData);
+ const location = new MapLocation(locationData);
try {
const response = await location.save()
- if(!response) {
+ if (!response) {
throw new Error('Something went wrong during saving the location...')
}
res.status(200).send(response);
} catch (err) {
console.log(err.message)
- res.status(500).json({message: err.message || 'Something went wrong...'});
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
+ const updateUserLocation = async function (req, res) {
+ console.log(req.body)
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ res.status(403).send('You are not authorized to make changes in the teams.');
+ return;
+ }
+ const userType = req.body.type;
+ const userId= req.body._id;
+ const updateData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ _id: req.body._id
+ }
+ try {
+ let response;
+ if(userType === 'user') {
+ response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ cache.removeCache('allusers')
+ cache.removeCache(`user-${userId}`);
+ cache.setCache(`user-${userId}`, JSON.stringify(response));
+ } else {
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ }
+
+ if (!response) {
+ throw new Error('Something went wrong during saving the location...')
+ }
+ const newData = {
+ firstName: response.firstName,
+ lastName: response.lastName,
+ jobTitle: response.jobTitle,
+ location: response.location,
+ _id: response._id,
+ type: userType
+ }
+
+ res.status(200).send(newData);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
+ }
+ };
return {
getAllLocations,
deleteLocation,
- putUserLocation
+ putUserLocation,
+ updateUserLocation
};
};
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 8a866401a..9e6d83894 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -65,7 +65,7 @@ const userProfileController = function (UserProfile) {
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle totalTangibleHrs',
)
.sort({
lastName: 1,
diff --git a/src/routes/mapLocationsRouter.js b/src/routes/mapLocationsRouter.js
index e2e780dac..db004ff18 100644
--- a/src/routes/mapLocationsRouter.js
+++ b/src/routes/mapLocationsRouter.js
@@ -7,7 +7,8 @@ const router = function (mapLocations) {
mapRouter.route('/mapLocations')
.get(controller.getAllLocations)
- .put(controller.putUserLocation);
+ .put(controller.putUserLocation)
+ .patch(controller.updateUserLocation);
mapRouter.route('/mapLocations/:locationId')
.delete(controller.deleteLocation)
From 4c4db04f1e252bb6e65a6fbebed97c8280c16b0e Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Tue, 17 Oct 2023 20:29:28 -0500
Subject: [PATCH 075/272] add weeklyCommitedHours to setup user, fix updates
issues, fix weekly summaries logged hours bug
---
.../profileInitialSetupController.js | 41 +++++++++++++++++--
src/models/profileInitialSetupToken.js | 5 +++
2 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index f671e06a3..18cf7376c 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -4,6 +4,7 @@ const moment = require("moment-timezone");
const jwt = require("jsonwebtoken");
const emailSender = require("../utilities/emailSender");
const config = require("../config");
+const cache = require('../utilities/nodeCache')();
// returns the email body that includes the setup link for the recipient.
function sendLinkMessage(Link) {
@@ -25,7 +26,6 @@ function informManagerMessage(user) {
New User ${user.firstName} ${user.lastName} has completed their part of setup.
These areas need to now be completed by an Admin:
- - Weekly Committed Hours
- Admin Document
- Link to Media Files
- Assign Projects
@@ -57,6 +57,10 @@ function informManagerMessage(user) {
Job Title: |
${user.jobTitle} |
+
+ Weekly Commited Hours: |
+ ${user.weeklycommittedHours} |
+
Time Zone: |
${user.timeZone} |
@@ -87,7 +91,7 @@ const profileInitialSetupController = function (
- Generates a link using the token and emails it to the recipient.
*/
const getSetupToken = async (req, res) => {
- let { email, baseUrl } = req.body;
+ let { email, baseUrl,weeklyCommittedHours } = req.body;
email = email.toLowerCase();
const token = uuidv4();
const expiration = moment().tz("America/Los_Angeles").add(1, "week");
@@ -103,6 +107,7 @@ const profileInitialSetupController = function (
const newToken = new ProfileInitialSetupToken({
token,
email,
+ weeklyCommittedHours,
expiration: expiration.toDate(),
});
@@ -187,7 +192,13 @@ const profileInitialSetupController = function (
newUser.jobTitle = req.body.jobTitle;
newUser.phoneNumber = req.body.phoneNumber;
newUser.bio = "";
- newUser.weeklycommittedHours = req.body.weeklycommittedHours;
+ newUser.weeklycommittedHours = foundToken.weeklyCommittedHours;
+ newUser.weeklycommittedHoursHistory = [
+ {
+ hours: newUser.weeklycommittedHours,
+ dateChanged: Date.now(),
+ },
+ ];
newUser.personalLinks = [];
newUser.adminLinks = [];
newUser.teams = Array.from(new Set([]));
@@ -201,11 +212,17 @@ const profileInitialSetupController = function (
newUser.collaborationPreference = req.body.collaborationPreference;
newUser.timeZone = req.body.timeZone || "America/Los_Angeles";
newUser.location = req.body.location;
+ newUser.permissions = {
+ frontPermissions: [],
+ backPermissions: []
+ }
newUser.bioPosted = "default";
newUser.privacySettings.email = req.body.privacySettings.email;
newUser.privacySettings.phoneNumber =
req.body.privacySettings.phoneNumber;
newUser.teamCode = "";
+ newUser.isFirstTimelog = true;
+
const savedUser = await newUser.save();
emailSender(
@@ -230,6 +247,24 @@ const profileInitialSetupController = function (
const token = jwt.sign(jwtPayload, JWT_SECRET);
res.send({ token }).status(200);
+
+ const NewUserCache = {
+ permissions: savedUser.permissions,
+ isActive: true,
+ weeklycommittedHours: savedUser.weeklycommittedHours,
+ createdDate: savedUser.createdDate.toISOString(),
+ _id: savedUser._id,
+ role: savedUser.role,
+ firstName: savedUser.firstName,
+ lastName: savedUser.lastName,
+ email: savedUser.email,
+ };
+
+ const allUserCache = JSON.parse(cache.getCache("allusers"));
+ allUserCache.push(NewUserCache);
+ cache.setCache("allusers", JSON.stringify(allUserCache));
+
+
} else {
res.status(400).send("Token is expired");
}
diff --git a/src/models/profileInitialSetupToken.js b/src/models/profileInitialSetupToken.js
index fc21bcad5..48413fb77 100644
--- a/src/models/profileInitialSetupToken.js
+++ b/src/models/profileInitialSetupToken.js
@@ -10,6 +10,11 @@ const profileInitialSetupTokenSchema = new mongoose.Schema({
type: String,
required: true,
},
+ weeklyCommittedHours : {
+ type: Number,
+ required: true,
+ default: 10,
+ },
expiration: {
type: Date,
required: true,
From 5ffc3d23442fc46a71544a885b3fd42def4a849b Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Tue, 17 Oct 2023 20:53:56 -0700
Subject: [PATCH 076/272] finish new timer basic functionality
---
src/models/timer.js | 7 +-
src/routes/dashboardRouter.js | 1 -
src/websockets/TimerService/clientsHandler.js | 286 ++++++++++++++++
.../TimerService/connectionsHandler.js | 50 +++
src/websockets/TimerService/index.js | 308 ------------------
src/websockets/index.js | 153 ++++-----
6 files changed, 394 insertions(+), 411 deletions(-)
create mode 100644 src/websockets/TimerService/clientsHandler.js
create mode 100644 src/websockets/TimerService/connectionsHandler.js
delete mode 100644 src/websockets/TimerService/index.js
diff --git a/src/models/timer.js b/src/models/timer.js
index c73dfe6c2..8afbad119 100644
--- a/src/models/timer.js
+++ b/src/models/timer.js
@@ -5,13 +5,12 @@ const { Schema } = mongoose;
const timerSchema = new Schema({
userId: { type: Schema.Types.ObjectId, required: true, ref: "userProfile" },
- lastAccess: { type: Date, default: Date.now },
+ startAt: { type: Date, default: Date.now },
time: { type: Number, default: 900000 },
- countdown: { type: Boolean, default: true },
goal: { type: Number, default: 900000 },
- paused: { type: Boolean, default: true },
+ paused: { type: Boolean, default: false },
forcedPause: { type: Boolean, default: false },
- stopped: { type: Boolean, default: false },
+ started: { type: Boolean, default: false },
});
module.exports = mongoose.model("newTimer", timerSchema, "newTimers");
diff --git a/src/routes/dashboardRouter.js b/src/routes/dashboardRouter.js
index 33275597c..664c1c802 100644
--- a/src/routes/dashboardRouter.js
+++ b/src/routes/dashboardRouter.js
@@ -3,7 +3,6 @@ const express = require('express');
const route = function () {
const controller = require('../controllers/dashBoardController')();
-
const Dashboardrouter = express.Router();
Dashboardrouter.route('/dashboard/:userId')
diff --git a/src/websockets/TimerService/clientsHandler.js b/src/websockets/TimerService/clientsHandler.js
new file mode 100644
index 000000000..fdf21b8f4
--- /dev/null
+++ b/src/websockets/TimerService/clientsHandler.js
@@ -0,0 +1,286 @@
+/* eslint-disable no-multi-assign */
+/* eslint-disable radix */
+const moment = require('moment');
+const Timer = require('../../models/timer');
+const logger = require('../../startup/logger');
+
+/**
+ * Here we get the timer.
+ * If the timer already exists in memory, we return it.
+ * If it doesn't exist, we try to get it from MongoDB.
+ * If it doesn't exist in MongoDB, we create it and save it to MongoDB.
+ * Then we save it to memory and return it.
+ */
+export const getClient = async (clients, userId) => {
+ // In case of there is already a connection that is open for this user
+ // for example user open a new connection
+ if (!clients.has(userId)) {
+ try {
+ let timer = await Timer.findOne({ userId });
+ if (!timer) timer = await Timer.create({ userId });
+ clients.set(userId, timer);
+ } catch (e) {
+ logger.logException(e);
+ throw new Error(
+ 'Something happened when trying to retrieve timer from mongo',
+ );
+ }
+ }
+ return clients.get(userId);
+};
+
+/*
+ * Save client info to database
+ * Save under these conditions:
+ * connection is normally closed (paused and closed);
+ * connection is forced-paused (timer still on and connection closed)
+ * message: STOP_TIMER
+ */
+export const saveClient = async (client) => {
+ try {
+ await Timer.findOneAndUpdate({ userId: client.userId }, client);
+ } catch (e) {
+ logger.logException(e);
+ throw new Error(
+ `Something happened when trying to save user timer to mongo, Error: ${e}`,
+ );
+ }
+};
+
+/*
+ * This is the contract between client and server.
+ * The client can send one of the following messages to the server:
+ */
+export const action = {
+ START_TIMER: 'START_TIMER',
+ PAUSE_TIMER: 'PAUSE_TIMER',
+ STOP_TIMER: 'STOP_TIMER',
+ CLEAR_TIMER: 'CLEAR_TIMER',
+ SET_GOAL: 'SET_GOAL=',
+ ADD_GOAL: 'ADD_TO_GOAL=',
+ REMOVE_GOAL: 'REMOVE_FROM_GOAL=',
+ FORCED_PAUSE: 'FORCED_PAUSE',
+ ACK_FORCED: 'ACK_FORCED',
+};
+
+const updatedTimeSinceStart = (client) => {
+ if (!client.started) return client.goal;
+ const now = moment.utc();
+ const startAt = moment(client.startAt);
+ const timePassed = moment.duration(now.diff(startAt)).asMilliseconds();
+ const updatedTime = client.time - timePassed;
+ return updatedTime > 0 ? updatedTime : 0;
+};
+
+/**
+ * Here we start the timer, if it is not already started.
+ * We set the last access time to now, and set the paused and stopped flags to false.
+ * If the timer was paused, we need to check if it was paused by the user or by the server.
+ * If it was paused by the server, we need to set the forcedPause flag to true.
+ */
+const startTimer = (client) => {
+ client.startAt = moment.utc();
+ client.paused = false;
+ if (!client.started) {
+ client.started = true;
+ client.time = client.goal;
+ }
+ if (client.forcedPause) client.forcedPause = false;
+};
+
+/**
+ * Here we pause the timer, if it is not already paused.
+ * We get the total elapsed time since the last access, and set it as the new time.
+ * We set the last access time to now, and set the paused flag to true.
+ * If the timer was paused by the server, we need to set the forcedPause flag to true.
+ * It'll only be triggered when the user closes the connection sudenlly or lacks of ACKs.
+ */
+const pauseTimer = (client, forced = false) => {
+ client.time = updatedTimeSinceStart(client);
+ client.startAt = moment.invalid();
+ client.paused = true;
+ if (forced) client.forcedPause = true;
+};
+
+// Here we acknowledge the forced pause. To prevent the modal for beeing displayed again.
+const ackForcedPause = (client) => {
+ client.forcedPause = false;
+ client.paused = true;
+ client.startAt = moment.invalid();
+};
+
+/**
+ * Here we stop the timer.
+ * We pause the timer and set the stopped flag to true.
+ */
+const stopTimer = (client) => {
+ client.startAt = moment.invalid();
+ client.started = false;
+ client.pause = false;
+ client.forcedPause = false;
+};
+
+/**
+ * Here we clear the timer.
+ * We pause the timer and check it's mode to set the time to 0 or the goal.
+ * Then we set the stopped flag to false.
+ */
+const clearTimer = (client) => {
+ stopTimer(client);
+ client.time = client.goal;
+};
+
+
+// /*
+// Here we switch the timer mode.
+// We pause the timer and check it's mode to set the time to 0 or the goal.
+// */
+// const switchMode = (client) => {
+// client.countdown = !client.countdown;
+// client.time = client.countdown ? client.goal : 0;
+// client.paused = true;
+// };
+
+// Here we get the goal time from the message.
+const getGoal = msg => parseInt(msg.split('=')[1]);
+
+// Here we set the goal and time to the goal time.
+const setGoal = (client, msg) => {
+ const newGoal = getGoal(msg);
+ if (!client.started) {
+ client.goal = newGoal;
+ client.time = newGoal;
+ } else {
+ const passedTime = client.goal - client.time;
+ if (passedTime >= newGoal) {
+ client.time = 0;
+ client.goal = passedTime;
+ } else {
+ client.time = newGoal - passedTime;
+ client.goal = newGoal;
+ }
+ }
+};
+
+/**
+ * Here we add the goal time.
+ * Each addition add 15min
+ * First we get the goal time from the message.
+ * Then we add it to the current goal time and set it as the new goal time.
+ * We also add it to the current time and set it as the new time.
+ */
+const addGoal = (client, msg) => {
+ const duration = getGoal(msg);
+ const goalAfterAddition = moment
+ .duration(client.goal)
+ .add(duration, 'milliseconds')
+ .asHours();
+
+ if (goalAfterAddition > 10) return;
+
+ client.goal = moment
+ .duration(client.goal)
+ .add(duration, 'milliseconds')
+ .asMilliseconds()
+ .toFixed();
+ client.time = moment
+ .duration(client.time)
+ .add(duration, 'milliseconds')
+ .asMilliseconds()
+ .toFixed();
+};
+
+/**
+ * Here we try to remove a goal time.
+ * First we get the goal time from the message.
+ * Then we subtract it from the current goal time and set it as the new goal time.
+ * We also subtract it from the current time and set it as the new time.
+ * If the new goal time is less than 15 minutes, we don't do anything.
+ * If the new time is less than 0, we set it to 0.
+ */
+const removeGoal = (client, msg) => {
+ const duration = getGoal(msg);
+ const goalAfterRemoval = moment
+ .duration(client.goal)
+ .subtract(duration, 'milliseconds')
+ .asMinutes();
+ const timeAfterRemoval = moment
+ .duration(client.time)
+ .subtract(duration, 'milliseconds')
+ .asMinutes();
+
+ if (goalAfterRemoval < 15 || timeAfterRemoval < 0) return;
+
+ client.goal = moment
+ .duration(client.goal)
+ .subtract(duration, 'milliseconds')
+ .asMilliseconds()
+ .toFixed();
+ client.time = moment
+ .duration(client.time)
+ .subtract(duration, 'milliseconds')
+ .asMilliseconds()
+ .toFixed();
+};
+
+
+/**
+ * Here is were we handle the messages.
+ * First we check if the user is in memory, if not, we throw an error.
+ * Then we parse the request and check which action it is and call the corresponding function.
+ * If we don't have a match, we just return an error.
+ * The only operation that we write to Mongo it's the stop timer. Other operations are just in memory.
+ * So the slowest part of the app is the save to Mongo.
+ * Then we update the current client in hash map and return the response.
+ */
+export const handleMessage = async (msg, clients, userId) => {
+ if (!clients.has(userId)) {
+ throw new Error('It should have this user in memory');
+ }
+
+ const client = clients.get(userId);
+ let resp = null;
+
+ const req = msg.toString();
+ switch (req) {
+ case action.START_TIMER:
+ startTimer(client);
+ break;
+ case req.match(/SET_GOAL=/i)?.input:
+ setGoal(client, req);
+ break;
+ case req.match(/ADD_TO_GOAL=/i)?.input:
+ addGoal(client, req);
+ break;
+ case req.match(/REMOVE_FROM_GOAL=/i)?.input:
+ removeGoal(client, req);
+ break;
+ case action.PAUSE_TIMER:
+ pauseTimer(client);
+ break;
+ case action.FORCED_PAUSE:
+ pauseTimer(client, true);
+ break;
+ case action.ACK_FORCED:
+ ackForcedPause(client);
+ break;
+ case action.CLEAR_TIMER:
+ clearTimer(client);
+ break;
+ case action.STOP_TIMER:
+ stopTimer(client);
+ break;
+
+ default:
+ resp = {
+ ...client,
+ error: `Unknown operation ${req}, please use one of ${action}`,
+ };
+ break;
+ }
+
+ await saveClient(client);
+ clients.set(userId, client);
+ if (resp === null) resp = client;
+ return JSON.stringify(resp);
+};
diff --git a/src/websockets/TimerService/connectionsHandler.js b/src/websockets/TimerService/connectionsHandler.js
new file mode 100644
index 000000000..6658321bf
--- /dev/null
+++ b/src/websockets/TimerService/connectionsHandler.js
@@ -0,0 +1,50 @@
+const WebSocket = require('ws');
+
+/**
+ * Here we insert the new connection to the connections map.
+ * If the user is not in the map, we create a new entry with the user id as key and the connection as value.
+ * Else we just push the connection to the array of connections.
+ */
+export function insertNewUser(connections, userId, wsConn) {
+ const userConnetions = connections.get(userId);
+ if (!userConnetions) connections.set(userId, [wsConn]);
+ else userConnetions.push(wsConn);
+}
+
+/**
+ *Here we remove the connection from the connections map.
+ *If the user is not in the map, we do nothing.
+ *Else we remove the connection from the array of connections.
+ *If the array is empty, we delete the user from the map.
+ */
+export function removeConnection(connections, userId, connToRemove) {
+ const userConnetions = connections.get(userId);
+ if (!userConnetions) return;
+
+ const newConns = userConnetions.filter(conn => conn !== connToRemove);
+ if (newConns.length === 0) connections.delete(userId);
+ else connections.set(userId, newConns);
+}
+
+/**
+ * Here we broadcast the message to all the connections that are connected to the same user.
+ * We check if the connection is open before sending the message.
+ */
+export function broadcastToSameUser(connections, userId, data) {
+ const userConnetions = connections.get(userId);
+ if (!userConnetions) return;
+ userConnetions.forEach((conn) => {
+ if (conn.readyState === WebSocket.OPEN) conn.send(data);
+ });
+}
+
+/**
+ * Here we check if there is another connection to the same user.
+ * If there is, we return true.
+ * Else we return false.
+ */
+export function hasOtherConn(connections, userId, anotherConn) {
+ if (!connections.has(userId)) return false;
+ const userConnections = connections.get(userId);
+ return userConnections.some(con => con !== anotherConn && con.readyState === WebSocket.OPEN);
+}
diff --git a/src/websockets/TimerService/index.js b/src/websockets/TimerService/index.js
deleted file mode 100644
index 9eac199ce..000000000
--- a/src/websockets/TimerService/index.js
+++ /dev/null
@@ -1,308 +0,0 @@
-/* eslint-disable no-multi-assign */
-/* eslint-disable radix */
-const moment = require('moment');
-const Timer = require('../../models/timer');
-const logger = require('../../startup/logger');
-
-/*
-This is the contract between client and server.
-The client can send one of the following messages to the server:
-*/
-export const action = {
- START_TIMER: 'START_TIMER',
- PAUSE_TIMER: 'PAUSE_TIMER',
- STOP_TIMER: 'STOP_TIMER',
- GET_TIMER: 'GET_TIMER',
- CLEAR_TIMER: 'CLEAR_TIMER',
- SWITCH_MODE: 'SWITCH_MODE',
- SET_GOAL: 'SET_GOAL=',
- ADD_GOAL: 'ADD_GOAL=',
- REMOVE_GOAL: 'REMOVE_GOAL=',
- FORCED_PAUSE: 'FORCED_PAUSE',
- ACK_FORCED: 'ACK_FORCED',
-};
-
-/*
-Here we get the total elapsed time since the last access.
-Since we have two modes for the timer, countdown and stopwatch,
-we need to know which one is active to calculate the total elapsed time.
-If the timer is in countdown mode, we need to subtract the elapsed time from the total time.
-if this total time is less than 0, we set it to 0.
-If the timer is in stopwatch mode,
-we need to add the elapsed time since the last access to the total time.
-we then return the total
-*/
-const getTotalElapsedTime = (client) => {
- const now = moment();
- const lastAccess = moment(client.lastAccess);
- const elapSinceLastAccess = moment.duration(now.diff(lastAccess));
- const time = moment.duration(moment(client.time));
-
- let total;
- if (client.countdown) {
- total = time.subtract(elapSinceLastAccess, 'milliseconds');
- if (total.asMilliseconds() < 0) {
- total = moment.duration(0);
- }
- } else total = elapSinceLastAccess.add(client.time, 'milliseconds');
-
- return total;
-};
-
-/*
-Here we start the timer, if it is not already started.
-We set the last access time to now, and set the paused and stopped flags to false.
-If the timer was paused, we need to check if it was paused by the user or by the server.
-If it was paused by the server, we need to set the forcedPause flag to true.
-*/
-const startTimer = (client) => {
- if (!client.paused) {
- client.time = getTotalElapsedTime(client).asMilliseconds().toFixed();
- client.lastAccess = moment();
- }
-
- if (client.paused) {
- client.lastAccess = moment();
- client.stopped = false;
- client.paused = false;
- if (client.forcedPause) client.forcedPause = false;
- }
-};
-
-/*
-Here we pause the timer, if it is not already paused.
-We get the total elapsed time since the last access, and set it as the new time.
-We set the last access time to now, and set the paused flag to true.
-If the timer was paused by the server, we need to set the forcedPause flag to true.
-It'll only be triggered when the user closes the connection sudenlly or lacks of ACKs.
-*/
-const pauseTimer = (client, forced = false) => {
- if (!client.paused) {
- client.time = getTotalElapsedTime(client).asMilliseconds().toFixed();
- client.lastAccess = moment();
- client.paused = true;
- if (forced) client.forcedPause = true;
- }
-};
-
-// Here we acknowledge the forced pause. To prevent the modal for beeing displayed again.
-const ackForcedPause = (client) => {
- client.forcedPause = false;
-};
-
-/*
-Here we clear the timer.
-We pause the timer and check it's mode to set the time to 0 or the goal.
-Then we set the stopped flag to false.
-*/
-const clearTimer = (client) => {
- pauseTimer(client);
- client.time = client.countdown ? client.goal : 0;
- client.stopped = false;
-};
-
-/*
-Here we stop the timer.
-We pause the timer and set the stopped flag to true.
-*/
-const stopTimer = (client) => {
- pauseTimer(client);
- client.stopped = true;
-};
-
-/*
-Here we switch the timer mode.
-We pause the timer and check it's mode to set the time to 0 or the goal.
-*/
-const switchMode = (client) => {
- client.countdown = !client.countdown;
- client.time = client.countdown ? client.goal : 0;
- client.paused = true;
-};
-
-// Here we get the goal time from the message.
-const getGoal = msg => parseInt(msg.split('=')[1]);
-
-// Here we set the goal and time to the goal time.
-const setGoal = (client, msg) => {
- const goal = getGoal(msg);
- client.goal = client.time = goal;
-};
-
-const goalOver10Hours = (client, time) => {
- const goal = moment.duration(client.goal).add(time, 'milliseconds').asHours();
- return goal > 10;
-};
-
-/*
-Here we add the goal time.
-First we get the goal time from the message.
-Then we add it to the current goal time and set it as the new goal time.
-We also add it to the current time and set it as the new time.
-*/
-const addGoal = (client, msg) => {
- const goal = getGoal(msg);
- if (goalOver10Hours(client, goal)) return;
-
- if (!client.paused) {
- client.time = getTotalElapsedTime(client).asMilliseconds().toFixed();
- client.lastAccess = moment();
- }
-
- client.goal = moment
- .duration(client.goal)
- .add(goal, 'milliseconds')
- .asMilliseconds()
- .toFixed();
- client.time = moment
- .duration(client.time)
- .add(goal, 'milliseconds')
- .asMilliseconds()
- .toFixed();
-};
-
-/*
- * Here we check if the goal time is less than 15 minutes.
- * */
-const goalLessThan15min = (client, time) => {
- const goal = moment
- .duration(client.goal)
- .subtract(time, 'milliseconds')
- .asMinutes();
- return goal < 15;
-};
-
-/*
- * Here we try to remove a goal time.
- * First we get the goal time from the message.
- * Then we subtract it from the current goal time and set it as the new goal time.
- * We also subtract it from the current time and set it as the new time.
- * If the new goal time is less than 15 minutes, we don't do anything.
- * If the new time is less than 0, we set it to 0.
- * */
-const removeGoal = (client, msg) => {
- const goal = getGoal(msg);
- if (goalLessThan15min(client, goal)) return;
-
- if (!client.paused) {
- client.time = getTotalElapsedTime(client).asMilliseconds().toFixed();
- client.lastAccess = moment();
- }
-
- client.goal = moment
- .duration(client.goal)
- .subtract(goal, 'milliseconds')
- .asMilliseconds()
- .toFixed();
- const time = moment
- .duration(client.time)
- .subtract(goal, 'milliseconds')
- .asMilliseconds()
- .toFixed();
- client.time = time < 0 ? 0 : time;
-};
-
-/*
-Here we get the timer.
-If the timer already exists in memory, we return it.
-If it doesn't exist, we try to get it from MongoDB.
-If it doesn't exist in MongoDB, we create it and save it to MongoDB.
-Then we save it to memory and return it.
-*/
-export const getTimer = async (clientsMap, userId) => {
- if (clientsMap.has(userId)) return;
-
- try {
- let timer = await Timer.findOne({ userId });
- if (!timer) timer = await Timer.create({ userId });
- clientsMap.set(userId, timer);
- } catch (e) {
- logger.logException(e);
- throw new Error(
- 'Something happened when trying to retrieve timer from mongo',
- );
- }
-};
-
-// Here we just save the timer to MongoDB.
-const saveClient = async (client) => {
- try {
- await Timer.findOneAndUpdate({ userId: client.userId }, client);
- } catch (e) {
- logger.logException(e);
- throw new Error(
- 'Something happened when trying to save user timer to mongo',
- );
- }
-};
-
-/*
-Here is were we handle the messages.
-First we check if the user is in memory, if not, we throw an error.
-Then we parse the request and check which action it is and call the corresponding function.
-If we don't have a match, we just return an error.
-The only operation that we write to Mongo it's the stop timer. Other operations are just in memory.
-So the slowest part of the app is the save to Mongo.
-Then we update the current client in hash map and return the response.
-*/
-export const handleMessage = async (msg, clientsMap, userId) => {
- if (!clientsMap.has(userId)) {
- throw new Error('It should have this user in memory');
- }
-
- const client = clientsMap.get(userId);
- let resp = null;
-
- const req = msg.toString();
- switch (req) {
- case action.GET_TIMER:
- break;
- case action.START_TIMER:
- startTimer(client);
- break;
- case action.SWITCH_MODE:
- switchMode(client);
- break;
- case req.match(/SET_GOAL=/i)?.input:
- setGoal(client, req);
- break;
- case req.match(/ADD_GOAL=/i)?.input:
- addGoal(client, req);
- break;
- case req.match(/REMOVE_GOAL=/i)?.input:
- removeGoal(client, req);
- break;
- case action.PAUSE_TIMER:
- pauseTimer(client);
- break;
- case action.FORCED_PAUSE:
- pauseTimer(client, true);
- break;
- case action.ACK_FORCED:
- ackForcedPause(client);
- break;
- case action.CLEAR_TIMER:
- clearTimer(client);
- break;
- case action.STOP_TIMER:
- stopTimer(client);
- break;
-
- default:
- resp = {
- ...client,
- error: `Unknown operation ${req}, please use one of ${action}`,
- };
- break;
- }
-
- if (req === action.STOP_TIMER) {
- await saveClient(client).catch((err) => {
- resp = { ...client, error: err };
- });
- }
-
- clientsMap.set(userId, client);
- if (resp === null) resp = client;
- return JSON.stringify(resp);
-};
diff --git a/src/websockets/index.js b/src/websockets/index.js
index a733dff25..5da85f729 100644
--- a/src/websockets/index.js
+++ b/src/websockets/index.js
@@ -7,15 +7,25 @@ const WebSocket = require("ws");
const moment = require("moment");
const jwt = require("jsonwebtoken");
const config = require("../config");
-const { getTimer, handleMessage, action } = require("./TimerService/");
-
-/*
-Here we authenticate the user.
-We get the token from the headers and try to verify it.
-If it fails, we throw an error.
-Else we check if the token is valid and if it is, we return the user id.
+const {
+ insertNewUser,
+ removeConnection,
+ broadcastToSameUser,
+ hasOtherConn,
+} = require("./TimerService/connectionsHandler");
+const {
+ getClient,
+ handleMessage,
+ action,
+} = require("./TimerService/clientsHandler");
+
+/**
+* Here we authenticate the user.
+* We get the token from the headers and try to verify it.
+* If it fails, we throw an error.
+* Else we check if the token is valid and if it is, we return the user id.
*/
-export const authenticate = (req, res) => {
+const authenticate = (req, res) => {
const authToken = req.headers?.["sec-websocket-protocol"];
let payload = "";
try {
@@ -37,68 +47,13 @@ export const authenticate = (req, res) => {
res(null, payload.userid);
};
-/*
- * Here we insert the new connection to the connections map.
- * If the user is not in the map, we create a new entry with the user id as key and the connection as value.
- * Else we just push the connection to the array of connections.
- */
-const insertNewUser = (connections, userId, wsConn) => {
- const userConnetions = connections.get(userId);
- if (!userConnetions) connections.set(userId, [wsConn]);
- else userConnetions.push(wsConn);
-};
-
-/*
- *Here we remove the connection from the connections map.
- *If the user is not in the map, we do nothing.
- *Else we remove the connection from the array of connections.
- *If the array is empty, we delete the user from the map.
- */
-const removeConnection = (connections, userId, connToRemove) => {
- const userConnetions = connections.get(userId);
- if (!userConnetions) return;
-
- const newConns = userConnetions.filter(conn => conn !== connToRemove);
- if (newConns.length === 0) connections.delete(userId);
- else connections.set(userId, newConns);
-};
-
-/*
- * Here we broadcast the message to all the connections that are connected to the same user.
- * We check if the connection is open before sending the message.
- */
-const broadcastToSameUser = (connections, userId, data) => {
- const userConnetions = connections.get(userId);
- if (!userConnetions) return;
- userConnetions.forEach((conn) => {
- if (conn.readyState === WebSocket.OPEN) conn.send(data);
- });
-};
-
-/*
- * Here we check if there is another connection to the same user.
- * If there is, we return true.
- * Else we return false.
- */
-const checkOtherConn = (connections, anotherConn, userId) => {
- const userConnetions = connections.get(userId);
- if (!userConnetions) return false;
- for (const con of userConnetions) {
- if (con !== anotherConn && con.readyState === WebSocket.OPEN) return true;
- }
- return false;
-};
-
-/*
-Here we start the timer service.
-First we create a map to store the clients and start the Websockets Server.
-Then we set the upgrade event listener to the Express Server, authenticate the user and
-if it is valid, we add the user id to the request and handle the upgrade and emit the connection event.
+/**
+* Here we start the timer service.
+* First we create a map to store the clients and start the Websockets Server.
+* Then we set the upgrade event listener to the Express Server, authenticate the user and
+* if it is valid, we add the user id to the request and handle the upgrade and emit the connection event.
*/
export default async (expServer) => {
- const clients = new Map();
- const connections = new Map();
-
const wss = new WebSocket.Server({
noServer: true,
path: "/timer-service",
@@ -118,64 +73,66 @@ export default async (expServer) => {
});
});
- /*
- For each new connection we start a timer of 5min to check if the connection is alive.
- If it is, we then repeat the process. If it is not, we terminate the connection.
- */
+ const clients = new Map(); // { userId: timerInfo }
+ const connections = new Map(); // { userId: connections[] }
+
wss.on("connection", async (ws, req) => {
ws.isAlive = true;
+ const { userId } = req;
+
ws.on("pong", () => {
ws.isAlive = true;
});
- const { userId } = req;
-
insertNewUser(connections, userId, ws);
- /*
+ /**
* Here we get the timer from memory or from the database and send it to the client.
- * We don't broadcast it
*/
- await getTimer(clients, userId);
- ws.send(await handleMessage(action.GET_TIMER, clients, userId));
+ const clientTimer = await getClient(clients, userId);
+ ws.send(JSON.stringify(clientTimer));
- /*
- Here we handle the messages from the client.
- And we broadcast the response to all the clients that are connected to the same user.
+ /**
+ * Here we handle the messages from the client.
+ * And we broadcast the response to all the clients that are connected to the same user.
*/
ws.on("message", async (data) => {
const resp = await handleMessage(data, clients, userId);
broadcastToSameUser(connections, userId, resp);
});
- /*
- Here we handle the close event.
- If there is another connection to the same user, we don't do anything.
- Else he is the last connection and we do a forced pause if need be.
- This may happen if the user closes all the tabs or the browser or he lost connection with
- the service
- We then remove the connection from the connections map.
+ /**
+ * Here we handle the close event.
+ * If there is another connection to the same user, we don't do anything.
+ * Else he is the last connection and we do a forced pause if need be.
+ * This may happen if the user closes all the tabs or the browser or he lost connection with
+ * the service
+ * We then remove the connection from the connections map.
*/
ws.on("close", async () => {
- if (!checkOtherConn(connections, ws, userId)) {
- await handleMessage(action.FORCED_PAUSE, clients, userId);
+ if (!hasOtherConn(connections, userId, ws)) {
+ const client = clients.get(userId);
+ if (client.started && !client.paused) {
+ await handleMessage(action.FORCED_PAUSE, clients, userId);
+ }
}
removeConnection(connections, userId, ws);
});
});
- // The function to check if the connection is alive
- const interval = setInterval(async () => {
- wss.clients.forEach(async (ws) => {
- if (ws.isAlive === false) return ws.terminate();
-
+ // For each new connection we start a time interval of 1min to check if the connection is alive.
+ // change to 1min before push
+ const interval = setInterval(() => {
+ wss.clients.forEach((ws) => {
+ if (ws.isAlive === false) {
+ return ws.close();
+ }
ws.isAlive = false;
ws.ping();
});
- }, 3000000);
+ }, 10000);
- // Here we just clear the interval when the server closes
- wss.on("close", () => {
+ wss.on('close', () => {
clearInterval(interval);
});
From bc3d082a9959c527e202841f87840d836e957064 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Thu, 19 Oct 2023 06:43:15 +0800
Subject: [PATCH 077/272] test
---
src/controllers/timeEntryController.js | 3 ---
src/helpers/dashboardhelper.js | 14 ++++++++++++++
src/helpers/reporthelper.js | 3 +++
src/helpers/taskHelper.js | 6 ++++++
src/helpers/userHelper.js | 3 ++-
5 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index 0bd9bb573..094cee9ba 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -553,7 +553,6 @@ const timeEntrycontroller = function (TimeEntry) {
.then((results) => {
const data = [];
results.forEach((element) => {
- console.log(element);
const record = {};
record._id = element._id;
@@ -592,7 +591,6 @@ const timeEntrycontroller = function (TimeEntry) {
.then((results) => {
const data = [];
results.forEach((element) => {
- console.log(element);
const record = {};
record._id = element._id;
record.notes = element.notes;
@@ -627,7 +625,6 @@ const timeEntrycontroller = function (TimeEntry) {
.then((results) => {
const data = [];
results.forEach((element) => {
- console.log(element);
const record = {};
record._id = element._id;
record.notes = element.notes;
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 34d464583..1c03c2f88 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -69,6 +69,9 @@ const dashboardhelper = function () {
{
$lte: ['$$timeentry.dateOfWork', pdtend],
},
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ },
],
},
},
@@ -162,6 +165,7 @@ const dashboardhelper = function () {
.tz('America/Los_Angeles')
.endOf('week')
.format('YYYY-MM-DD');
+ const entryTypes = ['default', null];
return myTeam.aggregate([
{
$match: {
@@ -283,6 +287,9 @@ const dashboardhelper = function () {
{
$lte: ['$$timeentry.dateOfWork', pdtend],
},
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ }
],
},
},
@@ -438,6 +445,7 @@ const dashboardhelper = function () {
$gte: pdtStart,
$lte: pdtEnd,
},
+ eentryType: { $in: [ 'default', null ] },
personId: userId,
});
@@ -575,6 +583,9 @@ const dashboardhelper = function () {
{
$lte: ['$$timeentry.dateOfWork', todate],
},
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ },
],
},
},
@@ -652,6 +663,9 @@ const dashboardhelper = function () {
{
$lte: ['$$timeentry.dateOfWork', todate],
},
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ },
],
},
},
diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js
index 0c2a8104d..c812ef03c 100644
--- a/src/helpers/reporthelper.js
+++ b/src/helpers/reporthelper.js
@@ -68,6 +68,9 @@ const reporthelper = function () {
moment(pstEnd).format("YYYY-MM-DD"),
],
},
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ },
],
},
},
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index a94aaee94..30bb220e9 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -113,6 +113,9 @@ const taskHelper = function () {
{
$lte: ['$$timeentry.dateOfWork', pdtend],
},
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ },
],
},
},
@@ -357,6 +360,9 @@ const taskHelper = function () {
{
$lte: ['$$timeentry.dateOfWork', pdtend],
},
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ },
],
},
},
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index af416f1a7..e1ca1fb7f 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -565,7 +565,8 @@ const userHelper = function () {
$and: [
{ $eq: ["$isTangible", true] },
{ $gte: ["$dateOfWork", startOfLastWeek] },
- { $lte: ["$dateOfWork", endOfLastWeek] }
+ { $lte: ["$dateOfWork", endOfLastWeek] },
+ { $in: ['$entryType', 'default', null] }
]
}
}
From c417ad7711ca86d2c15a81f88f7c4cd4ca3c6348 Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Wed, 18 Oct 2023 16:35:47 -0700
Subject: [PATCH 078/272] Send email to 2 recipients - user and other(used for
onecommunity email later)
---
src/controllers/reasonSchedulingController.js | 22 +++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 39729680f..98dd152ff 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -94,7 +94,7 @@ const postReason = async (req, res) => {
{
console.log("Inside if.");
//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 !
@@ -107,7 +107,13 @@ const postReason = async (req, res) => {
One Community`;
console.log("line before email sender")
- emailSender('shreetesting4@gmail.com', subject, emailBody, null, null);
+ // 1 hardcoded email- emailSender('shreetesting4@gmail.com', 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},shreetesting4@gmail.com`, subject, emailBody, null, null);
}
return res.sendStatus(200);
@@ -260,7 +266,7 @@ const patchReason = async (req, res) => {
{
console.log(" Patch - Inside if.");
//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 !
@@ -273,7 +279,15 @@ const patchReason = async (req, res) => {
One Community`;
console.log("line before email sender")
- emailSender('shreetesting4@gmail.com', subject, emailBody, null, null);
+ // 1 hardcoded email- emailSender('shreetesting4@gmail.com', 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},shreetesting4@gmail.com`, subject, emailBody, null, null);
+
+
}
return res.status(200).json({
From 9a7bfb948da6f7b0c2beeb7cf310e3addeaa72b6 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Thu, 19 Oct 2023 10:06:48 +0800
Subject: [PATCH 079/272] add validator of regex and authorization
---
src/controllers/teamController.js | 11 ++++++++++-
src/models/team.js | 13 ++++++++++++-
src/models/userProfile.js | 17 ++++++++++++++---
3 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index 5215b024b..b204875a5 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -70,6 +70,15 @@ const teamcontroller = function (Team) {
res.status(400).send('No valid records found');
return;
}
+
+ const canEditTeamCode = req.body.requestor.role === 'Owner'
+ || req.body.requestor.permissions?.frontPermissions.includes('editTeamCode');
+
+ if (!canEditTeamCode) {
+ res.status(403).send('You are not authorized to edit team code.');
+ return;
+ }
+
record.teamName = req.body.teamName;
record.isActive = req.body.isActive;
record.teamCode = req.body.teamCode;
@@ -116,7 +125,7 @@ const teamcontroller = function (Team) {
users.forEach((element) => {
const { userId, operation } = element;
// if user's profile is stored in cache, clear it so when you visit their profile page it will be up to date
- if(cache.hasCache(`user-${userId}`)) cache.removeCache(`user-${userId}`);
+ if (cache.hasCache(`user-${userId}`)) cache.removeCache(`user-${userId}`);
if (operation === 'Assign') {
assignlist.push(userId);
diff --git a/src/models/team.js b/src/models/team.js
index a57d7bb27..97f8dc360 100644
--- a/src/models/team.js
+++ b/src/models/team.js
@@ -13,7 +13,18 @@ const team = new Schema({
addDateTime: { type: Date, default: Date.now(), ref: 'userProfile' },
},
],
- teamCode: { type: 'String', default: '' },
+ teamCode: {
+ type: 'String',
+ 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',
+ },
+ },
});
module.exports = mongoose.model('team', team, 'teams');
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index a58d1d293..4739a05e7 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -7,7 +7,7 @@ const bcrypt = require('bcryptjs');
const SALT_ROUNDS = 10;
const nextDay = new Date();
-nextDay.setDate(nextDay.getDate()+1);
+nextDay.setDate(nextDay.getDate() + 1);
const userProfileSchema = new Schema({
password: {
@@ -153,8 +153,19 @@ const userProfileSchema = new Schema({
isVisible: { type: Boolean, default: false },
weeklySummaryOption: { type: String },
bioPosted: { type: String, default: 'default' },
- isFirstTimelog: { type: Boolean, default: true},
- teamCode: { type: String, default: '' },
+ isFirstTimelog: { type: Boolean, default: true },
+ teamCode: {
+ type: String,
+ 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',
+ },
+ },
infoCollections: [
{
areaName: { type: String },
From f376fa8f049717d07eb12cdfd2eab9bcbf250da2 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Thu, 19 Oct 2023 22:37:33 +0800
Subject: [PATCH 080/272] add update task status function
---
src/controllers/taskController.js | 15 +++++++++++++--
src/routes/taskRouter.js | 3 +++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index 7a19fd853..9bcf071de 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -776,7 +776,6 @@ const taskController = function (Task) {
});
res.status(200).send(task);
-
} catch (error) {
// Generic error message, you can adjust as needed
res.status(500).send({ error: 'Internal Server Error', details: error.message });
@@ -850,6 +849,17 @@ const taskController = function (Task) {
}
};
+ const updateTaskStatus = async (req, res) => {
+ const { taskId } = req.params;
+
+ Task.findOneAndUpdate(
+ { _id: mongoose.Types.ObjectId(taskId) },
+ { ...req.body, modifiedDatetime: Date.now() },
+ )
+ .then(() => res.status(201).send())
+ .catch(error => res.status(404).send(error));
+ };
+
const getReviewReqEmailBody = function (name, taskName) {
const text = `New Task Review Request From ${name}:
The following task is available to review:
@@ -863,7 +873,7 @@ const taskController = function (Task) {
const getRecipients = async function (myUserId) {
const recipients = [];
const user = await userProfile.findById(myUserId);
- const membership = await userProfile.find({ role: ['Administrator', 'Manager', 'Mentor'] });
+ const membership = await userProfile.find({ role: { $in: ['Administrator', 'Manager', 'Mentor'] } });
membership.forEach((member) => {
if (member.teams.some(team => user.teams.includes(team))) {
recipients.push(member.email);
@@ -909,6 +919,7 @@ const taskController = function (Task) {
moveTask,
getTasksByUserList,
getTasksForTeamsByUser,
+ updateTaskStatus,
sendReviewReq,
};
};
diff --git a/src/routes/taskRouter.js b/src/routes/taskRouter.js
index ef972f2cb..46e467c9d 100644
--- a/src/routes/taskRouter.js
+++ b/src/routes/taskRouter.js
@@ -28,6 +28,9 @@ const routes = function (task, userProfile) {
wbsRouter.route('/task/update/:taskId')
.put(controller.updateTask);
+ wbsRouter.route('/task/updateStatus/:taskId')
+ .put(controller.updateTaskStatus);
+
wbsRouter.route('/task/updateAllParents/:wbsId/')
.put(controller.updateAllParents);
From 85f6e2dc0847d2644804acc9227a5fcb1b66fe5c Mon Sep 17 00:00:00 2001
From: Aaron Persaud
Date: Fri, 20 Oct 2023 10:13:56 -0400
Subject: [PATCH 081/272] update babel/traverse and mongoose to fix
vulnerabilities
---
package-lock.json | 211 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 194 insertions(+), 17 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index f9eb87ba6..3fcc98986 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -318,6 +318,11 @@
"@babel/types": "^7.16.7"
}
},
+ "@babel/helper-string-parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
+ },
"@babel/helper-validator-identifier": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
@@ -1083,20 +1088,131 @@
}
},
"@babel/traverse": {
- "version": "7.17.3",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz",
- "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==",
- "requires": {
- "@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.17.3",
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-function-name": "^7.16.7",
- "@babel/helper-hoist-variables": "^7.16.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/parser": "^7.17.3",
- "@babel/types": "^7.17.0",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+ "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/generator": "^7.23.0",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.0",
+ "@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+ "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
+ "requires": {
+ "@babel/types": "^7.23.0",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA=="
+ },
+ "@babel/helper-function-name": {
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
+ "requires": {
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
+ },
+ "@babel/highlight": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+ "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
+ },
+ "@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ }
+ },
+ "@babel/types": {
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+ "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA=="
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+ "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ }
}
},
"@babel/types": {
@@ -1194,11 +1310,49 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true
},
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "dependencies": {
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA=="
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+ "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ },
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ }
+ }
+ }
+ }
+ },
"@jridgewell/resolve-uri": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
"integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew=="
},
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="
+ },
"@jridgewell/sourcemap-codec": {
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
@@ -5382,7 +5536,7 @@
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"lodash.merge": {
"version": "4.6.2",
@@ -5666,15 +5820,15 @@
}
},
"mongoose": {
- "version": "5.13.15",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz",
- "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==",
+ "version": "5.13.21",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.21.tgz",
+ "integrity": "sha512-EvSrXrCBogenxY131qKasFcT1Pj+9Pg5AXj17vQ8S1mOEArK3CpOx965u1wTIrdnQ7DjFC+SRwPxNcqUjMAVyQ==",
"requires": {
"@types/bson": "1.x || 4.0.x",
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4",
"kareem": "2.3.2",
- "mongodb": "3.7.3",
+ "mongodb": "3.7.4",
"mongoose-legacy-pluralize": "1.0.2",
"mpath": "0.8.4",
"mquery": "3.2.5",
@@ -5686,6 +5840,29 @@
"sliced": "1.0.1"
},
"dependencies": {
+ "mongodb": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.4.tgz",
+ "integrity": "sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw==",
+ "requires": {
+ "bl": "^2.2.1",
+ "bson": "^1.1.4",
+ "denque": "^1.4.1",
+ "optional-require": "^1.1.8",
+ "safe-buffer": "^5.1.2",
+ "saslprep": "^1.0.0"
+ },
+ "dependencies": {
+ "optional-require": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
+ "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
+ "requires": {
+ "require-at": "^1.0.6"
+ }
+ }
+ }
+ },
"optional-require": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
From 63de1d12b07af4f84cc32fa5407af4e2edeaddb6 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 20 Oct 2023 09:21:52 -0700
Subject: [PATCH 082/272] add bm proj route, router, controller
---
.../bmdashboard/bmProjectsController.js | 18 ++++++++++++++++++
src/routes/bmdashboard/bmMaterialsRouter.js | 4 ++--
src/routes/bmdashboard/bmProjectsRouter.js | 14 ++++++++++++++
src/startup/routes.js | 2 ++
4 files changed, 36 insertions(+), 2 deletions(-)
create mode 100644 src/controllers/bmdashboard/bmProjectsController.js
create mode 100644 src/routes/bmdashboard/bmProjectsRouter.js
diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js
new file mode 100644
index 000000000..946869bce
--- /dev/null
+++ b/src/controllers/bmdashboard/bmProjectsController.js
@@ -0,0 +1,18 @@
+const mongoose = require('mongoose');
+
+const bmMProjectsController = function () {
+ // fetches projects with reference to BM userProfile id
+ const bmProjectsSummary = async function _projSumm(req, res) {
+ try {
+ res.json({ message: 'Hello world' });
+
+ // .then(results => res.status(200).send(results))
+ // .catch(error => res.status(500).send(error))
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return { bmProjectsSummary };
+};
+
+module.exports = bmMProjectsController;
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index ab8a67388..1188acf9d 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -8,6 +8,6 @@ materialsRouter.route('/materials')
.get(controller.bmMaterialsList);
return materialsRouter;
-}
+};
-module.exports = routes;
\ No newline at end of file
+module.exports = routes;
diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js
new file mode 100644
index 000000000..204efbfad
--- /dev/null
+++ b/src/routes/bmdashboard/bmProjectsRouter.js
@@ -0,0 +1,14 @@
+const express = require('express');
+
+const routes = function () {
+ const projectsRouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmProjectsController')();
+// const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial);
+
+projectsRouter.route('/projects')
+ .get(controller.bmProjectsSummary);
+
+ return projectsRouter;
+};
+
+module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 2fd7337a6..7208535d8 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -61,6 +61,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
+const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')();
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -96,4 +97,5 @@ module.exports = function (app) {
// bm dashboard
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
+ app.use('/api/bm', bmProjectsRouter);
};
From 36d6d23ceee94b95e1d5cc363457f7fd36922a6a Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Mon, 23 Oct 2023 20:06:25 -0700
Subject: [PATCH 083/272] make requested changes from last reviews
---
src/websockets/TimerService/clientsHandler.js | 41 +++++++++----------
1 file changed, 19 insertions(+), 22 deletions(-)
diff --git a/src/websockets/TimerService/clientsHandler.js b/src/websockets/TimerService/clientsHandler.js
index fdf21b8f4..6990ead71 100644
--- a/src/websockets/TimerService/clientsHandler.js
+++ b/src/websockets/TimerService/clientsHandler.js
@@ -29,7 +29,7 @@ export const getClient = async (clients, userId) => {
return clients.get(userId);
};
-/*
+/**
* Save client info to database
* Save under these conditions:
* connection is normally closed (paused and closed);
@@ -47,7 +47,7 @@ export const saveClient = async (client) => {
}
};
-/*
+/**
* This is the contract between client and server.
* The client can send one of the following messages to the server:
*/
@@ -63,6 +63,9 @@ export const action = {
ACK_FORCED: 'ACK_FORCED',
};
+const MAX_HOURS = 5;
+const MIN_MINS = 1;
+
const updatedTimeSinceStart = (client) => {
if (!client.started) return client.goal;
const now = moment.utc();
@@ -127,26 +130,20 @@ const stopTimer = (client) => {
*/
const clearTimer = (client) => {
stopTimer(client);
+ client.goal = moment.duration(2, 'hours').asMilliseconds();
client.time = client.goal;
};
-
-// /*
-// Here we switch the timer mode.
-// We pause the timer and check it's mode to set the time to 0 or the goal.
-// */
-// const switchMode = (client) => {
-// client.countdown = !client.countdown;
-// client.time = client.countdown ? client.goal : 0;
-// client.paused = true;
-// };
-
-// Here we get the goal time from the message.
-const getGoal = msg => parseInt(msg.split('=')[1]);
-
// Here we set the goal and time to the goal time.
+/**
+ * Here we set the goal.
+ * if timer has not started, we set both time and goal to the new goal
+ * if timer has started, we calculate the passed time and remove that from new goal
+ * and if passed time is greater than new goal, then set time to 0, but this should
+ * not be prohibited by frontend.
+ */
const setGoal = (client, msg) => {
- const newGoal = getGoal(msg);
+ const newGoal = parseInt(msg.split('=')[1]);
if (!client.started) {
client.goal = newGoal;
client.time = newGoal;
@@ -170,13 +167,13 @@ const setGoal = (client, msg) => {
* We also add it to the current time and set it as the new time.
*/
const addGoal = (client, msg) => {
- const duration = getGoal(msg);
+ const duration = parseInt(msg.split('=')[1]);
const goalAfterAddition = moment
.duration(client.goal)
.add(duration, 'milliseconds')
.asHours();
- if (goalAfterAddition > 10) return;
+ if (goalAfterAddition > MAX_HOURS) return;
client.goal = moment
.duration(client.goal)
@@ -199,7 +196,7 @@ const addGoal = (client, msg) => {
* If the new time is less than 0, we set it to 0.
*/
const removeGoal = (client, msg) => {
- const duration = getGoal(msg);
+ const duration = parseInt(msg.split('=')[1]);
const goalAfterRemoval = moment
.duration(client.goal)
.subtract(duration, 'milliseconds')
@@ -209,7 +206,7 @@ const removeGoal = (client, msg) => {
.subtract(duration, 'milliseconds')
.asMinutes();
- if (goalAfterRemoval < 15 || timeAfterRemoval < 0) return;
+ if (goalAfterRemoval < MIN_MINS || timeAfterRemoval < 0) return;
client.goal = moment
.duration(client.goal)
@@ -279,7 +276,7 @@ export const handleMessage = async (msg, clients, userId) => {
break;
}
- await saveClient(client);
+ saveClient(client);
clients.set(userId, client);
if (resp === null) resp = client;
return JSON.stringify(resp);
From 55c5e16eacd9071adfa8176e94113637e6efb791 Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Tue, 24 Oct 2023 21:12:17 -0700
Subject: [PATCH 084/272] Fix hasPermission() arguments and add catches.
---
src/controllers/rolePresetsController.js | 8 ++++----
src/utilities/permissions.js | 6 ++++--
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/controllers/rolePresetsController.js b/src/controllers/rolePresetsController.js
index 3642627f7..3a7dc18c8 100644
--- a/src/controllers/rolePresetsController.js
+++ b/src/controllers/rolePresetsController.js
@@ -2,7 +2,7 @@ const { hasPermission } = require('../utilities/permissions');
const rolePresetsController = function (Preset) {
const getPresetsByRole = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ if (!await hasPermission(req.body.requestor, 'putRole')) {
res.status(403).send('You are not authorized to make changes to roles.');
return;
}
@@ -14,7 +14,7 @@ const rolePresetsController = function (Preset) {
};
const createNewPreset = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ if (!await hasPermission(req.body.requestor, 'putRole')) {
res.status(403).send('You are not authorized to make changes to roles.');
return;
}
@@ -34,7 +34,7 @@ const rolePresetsController = function (Preset) {
};
const updatePresetById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ if (!await hasPermission(req.body.requestor, 'putRole')) {
res.status(403).send('You are not authorized to make changes to roles.');
return;
}
@@ -53,7 +53,7 @@ const rolePresetsController = function (Preset) {
};
const deletePresetById = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putRole')) {
+ if (!await hasPermission(req.body.requestor, 'putRole')) {
res.status(403).send('You are not authorized to make changes to roles.');
return;
}
diff --git a/src/utilities/permissions.js b/src/utilities/permissions.js
index 7b5d4a245..ebf35b2a1 100644
--- a/src/utilities/permissions.js
+++ b/src/utilities/permissions.js
@@ -4,12 +4,14 @@ const UserProfile = require('../models/userProfile');
const hasRolePermission = async (role, action) => Role.findOne({ roleName: role })
.exec()
- .then(({ permissions }) => permissions.includes(action));
+ .then(({ permissions }) => permissions.includes(action))
+ .catch(false);
const hasIndividualPermission = async (userId, action) => UserProfile.findById(userId)
.select('permissions')
.exec()
- .then(({ permissions }) => permissions.frontPermissions.includes(action));
+ .then(({ permissions }) => permissions.frontPermissions.includes(action))
+ .catch(false);
const hasPermission = async (requestor, action) => await hasRolePermission(requestor.role, action) || hasIndividualPermission(requestor.requestorId, action);
From 701be2501cf6f82da6eb90723c1d4fc55f5a6eed Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Wed, 25 Oct 2023 17:19:35 -0700
Subject: [PATCH 085/272] cleanup old timer related code and files
---
src/controllers/REAL_TIME_timerController.js | 155 -------------------
src/models/REAL_TIME_timer.js | 13 --
src/models/oldTimer.js | 14 --
src/routes/timerRouter.js | 15 --
src/startup/routes.js | 3 -
5 files changed, 200 deletions(-)
delete mode 100644 src/controllers/REAL_TIME_timerController.js
delete mode 100644 src/models/REAL_TIME_timer.js
delete mode 100644 src/models/oldTimer.js
delete mode 100644 src/routes/timerRouter.js
diff --git a/src/controllers/REAL_TIME_timerController.js b/src/controllers/REAL_TIME_timerController.js
deleted file mode 100644
index 699dcddef..000000000
--- a/src/controllers/REAL_TIME_timerController.js
+++ /dev/null
@@ -1,155 +0,0 @@
-
-const logger = require('../startup/logger');
-const OldTimer = require('../models/oldTimer');
-
-const timerController = function (Timer) {
- const getTimerFromDatabase = async ({ userId }) => {
- try {
- const timerObject = await Timer.findOne({ userId }).exec();
- if (!timerObject) {
- const newRecord = {
- userId,
- totalSeconds: 0,
- isRunning: false,
- isApplicationPaused: false,
- isUserPaused: false,
- };
- const newTimer = await Timer.create(newRecord);
- return newTimer;
- }
- return timerObject;
- } catch (e) {
- logger.logException(e);
- throw new Error('Issue trying to retrieve timer data from MongoDB');
- }
- };
-
- const setTimerToDatabase = async ({
- userId,
- timerObject: {
- totalSeconds,
- isRunning,
- isUserPaused,
- isApplicationPaused,
- } = {},
- } = {}) => {
- try {
- const update = {
- $set: {
- totalSeconds,
- isRunning,
- isUserPaused,
- isApplicationPaused,
- },
- };
-
- const options = {
- upsert: true,
- new: true,
- setDefaultsOnInsert: true,
- rawResult: true,
- };
-
- return await Timer.findOneAndUpdate({ userId }, update, options).exec();
- } catch (e) {
- logger.logException(e);
- throw new Error('Issue trying to set timer data from MongoDB');
- }
- };
-
- const putTimer = function (req, res) {
- const { userId } = req.params;
-
- const query = { userId };
- const update = {
- $set: {
- pausedAt: req.body.pausedAt,
- isWorking: req.body.isWorking,
- started: req.body.isWorking ? Date.now() : null,
- lastAccess: Date.now(),
- },
- };
- const options = {
- upsert: true, new: true, setDefaultsOnInsert: true, rawResult: true,
- };
-
- OldTimer.findOneAndUpdate(query, update, options, (error, rawResult) => {
- if (error) {
- return res.status(500).send({ error });
- }
-
- if (rawResult === null || rawResult.value === undefined || rawResult.value === null
- || rawResult.lastErrorObject === null || rawResult.lastErrorObject === undefined
- || rawResult.value.length === 0) {
- return res.status(500).send('Update/Upsert timer date failed');
- }
-
- if (rawResult.lastErrorObject.updatedExisting === true) {
- return res.status(200).send({ message: 'updated timer data' });
- }
- if (rawResult.lastErrorObject.updatedExisting === false
- && rawResult.lastErrorObject.upserted !== undefined && rawResult.lastErrorObject.upserted !== null) {
- return res.status(201).send({ _id: rawResult.lastErrorObject.upserted });
- }
- return res.status(500).send('Update/Upsert timer date failed');
- });
- };
-
- const timePassed = (timer) => {
- if (!timer.started) { return 0; }
- const now = timer.timedOut ? timer.lastAccess : Date.now();
- return Math.floor((now - timer.started) / 1000);
- };
-
- const adjust = (timer, cb) => {
- const oneMin = 60 * 1000;
- const fiveMin = 5 * oneMin;
- const timeSinceLastAccess = timer.lastAccess ? (Date.now() - timer.lastAccess) : 0;
- const setLastAccess = !timer.lastAccess || (timeSinceLastAccess > oneMin);
-
- timer.timedOut = timer.isWorking && (timeSinceLastAccess > fiveMin);
- timer.seconds = timer.pausedAt + timePassed(timer);
-
- if (timer.timedOut) {
- return OldTimer.findOneAndUpdate({ userId: timer.userId }, {
- isWorking: false,
- pauseAt: timer.seconds,
- started: null,
- lastAccess: Date.now(),
- }).then(() => cb(timer));
- }
- if (setLastAccess) {
- return OldTimer.findOneAndUpdate({ userId: timer.userId }, { lastAccess: Date.now() }).then(() => cb(timer));
- }
-
- return cb(timer);
- };
-
- const getTimer = function (req, res) {
- const { userId } = req.params;
-
- OldTimer.findOne({ userId }).lean().exec((error, record) => {
- if (error) {
- return res.status(500).send(error);
- }
- if (record === null) {
- if (req.body.requestor.requestorId === userId) {
- const newRecord = {
- userId,
- pausedAt: 0,
- isWorking: false,
- };
- return OldTimer.create(newRecord).then(result => res.status(200).send(result)).catch(() => res.status(400).send('Timer record not found for the given user ID'));
- }
- return res.status(400).send('Timer record not found for the given user ID');
- }
- return adjust(record, (timer) => { res.status(200).send(timer); });
- });
- };
-
- return {
- putTimer, getTimer, getTimerFromDatabase, setTimerToDatabase,
- };
-};
-
-module.exports = timerController;
diff --git a/src/models/REAL_TIME_timer.js b/src/models/REAL_TIME_timer.js
deleted file mode 100644
index 4e143aeaa..000000000
--- a/src/models/REAL_TIME_timer.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const mongoose = require('mongoose');
-
-const { Schema } = mongoose;
-
-const timerSchema = new Schema({
- userId: { type: Schema.Types.ObjectId, required: true, ref: 'userProfile' },
- totalSeconds: { type: Number, default: 0 },
- isRunning: { type: Boolean, default: false },
- isUserPaused: { type: Boolean, default: false },
- isApplicationPaused: { type: Boolean, default: false },
-});
-
-module.exports = mongoose.model('newTimer', timerSchema, 'newTimers');
diff --git a/src/models/oldTimer.js b/src/models/oldTimer.js
deleted file mode 100644
index dca0ade1a..000000000
--- a/src/models/oldTimer.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const mongoose = require('mongoose');
-
-const { Schema } = mongoose;
-
-const timerSchema = new Schema({
- userId: { type: Schema.Types.ObjectId, required: true, ref: 'userProfile' },
- pausedAt: { type: Number, default: 0 },
- isWorking: { type: Boolean, default: false },
- started: { type: Date },
- lastAccess: { type: Date },
- });
-
-
-module.exports = mongoose.model('timer', timerSchema, 'timers');
diff --git a/src/routes/timerRouter.js b/src/routes/timerRouter.js
deleted file mode 100644
index 094b2ba81..000000000
--- a/src/routes/timerRouter.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const express = require('express');
-
-const routes = function (Timer) {
- const TimerRouter = express.Router();
-
- const controller = require('../controllers/REAL_TIME_timerController')(Timer);
-
- TimerRouter.route('/timer/:userId')
- .put(controller.putTimer)
- .get(controller.getTimer);
-
- return TimerRouter;
-};
-
-module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 2fd7337a6..eae746e24 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -7,7 +7,6 @@ const actionItem = require('../models/actionItem');
const notification = require('../models/notification');
const wbs = require('../models/wbs');
const task = require('../models/task');
-const timer = require('../models/timer');
const popup = require('../models/popupEditor');
const popupBackup = require('../models/popupEditorBackup');
const taskNotification = require('../models/taskNotification');
@@ -38,7 +37,6 @@ const forcePwdRouter = require('../routes/forcePwdRouter')(userProfile);
const reportsRouter = require('../routes/reportsRouter')();
const wbsRouter = require('../routes/wbsRouter')(wbs);
const taskRouter = require('../routes/taskRouter')(task);
-const timerRouter = require('../routes/timerRouter')(timer);
const popupRouter = require('../routes/popupEditorRouter')(popup);
const popupBackupRouter = require('../routes/popupEditorBackupRouter')(popupBackup);
const taskNotificationRouter = require('../routes/taskNotificationRouter')(taskNotification);
@@ -76,7 +74,6 @@ module.exports = function (app) {
app.use('/api', reportsRouter);
app.use('/api', wbsRouter);
app.use('/api', taskRouter);
- app.use('/api', timerRouter);
app.use('/api', popupRouter);
app.use('/api', popupBackupRouter);
app.use('/api', taskNotificationRouter);
From 467cbb84140103fcdd0ad97c728584d1d6156229 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Wed, 25 Oct 2023 18:31:29 -0700
Subject: [PATCH 086/272] remove 2h default time when clear timer
---
src/websockets/TimerService/clientsHandler.js | 77 +------------------
1 file changed, 1 insertion(+), 76 deletions(-)
diff --git a/src/websockets/TimerService/clientsHandler.js b/src/websockets/TimerService/clientsHandler.js
index 6990ead71..e9e932fd7 100644
--- a/src/websockets/TimerService/clientsHandler.js
+++ b/src/websockets/TimerService/clientsHandler.js
@@ -4,13 +4,6 @@ const moment = require('moment');
const Timer = require('../../models/timer');
const logger = require('../../startup/logger');
-/**
- * Here we get the timer.
- * If the timer already exists in memory, we return it.
- * If it doesn't exist, we try to get it from MongoDB.
- * If it doesn't exist in MongoDB, we create it and save it to MongoDB.
- * Then we save it to memory and return it.
- */
export const getClient = async (clients, userId) => {
// In case of there is already a connection that is open for this user
// for example user open a new connection
@@ -29,13 +22,6 @@ export const getClient = async (clients, userId) => {
return clients.get(userId);
};
-/**
- * Save client info to database
- * Save under these conditions:
- * connection is normally closed (paused and closed);
- * connection is forced-paused (timer still on and connection closed)
- * message: STOP_TIMER
- */
export const saveClient = async (client) => {
try {
await Timer.findOneAndUpdate({ userId: client.userId }, client);
@@ -47,10 +33,6 @@ export const saveClient = async (client) => {
}
};
-/**
- * This is the contract between client and server.
- * The client can send one of the following messages to the server:
- */
export const action = {
START_TIMER: 'START_TIMER',
PAUSE_TIMER: 'PAUSE_TIMER',
@@ -75,12 +57,6 @@ const updatedTimeSinceStart = (client) => {
return updatedTime > 0 ? updatedTime : 0;
};
-/**
- * Here we start the timer, if it is not already started.
- * We set the last access time to now, and set the paused and stopped flags to false.
- * If the timer was paused, we need to check if it was paused by the user or by the server.
- * If it was paused by the server, we need to set the forcedPause flag to true.
- */
const startTimer = (client) => {
client.startAt = moment.utc();
client.paused = false;
@@ -91,31 +67,19 @@ const startTimer = (client) => {
if (client.forcedPause) client.forcedPause = false;
};
-/**
- * Here we pause the timer, if it is not already paused.
- * We get the total elapsed time since the last access, and set it as the new time.
- * We set the last access time to now, and set the paused flag to true.
- * If the timer was paused by the server, we need to set the forcedPause flag to true.
- * It'll only be triggered when the user closes the connection sudenlly or lacks of ACKs.
- */
const pauseTimer = (client, forced = false) => {
client.time = updatedTimeSinceStart(client);
- client.startAt = moment.invalid();
+ client.startAt = moment.invalid(); // invalid can not be saved in database
client.paused = true;
if (forced) client.forcedPause = true;
};
-// Here we acknowledge the forced pause. To prevent the modal for beeing displayed again.
const ackForcedPause = (client) => {
client.forcedPause = false;
client.paused = true;
client.startAt = moment.invalid();
};
-/**
- * Here we stop the timer.
- * We pause the timer and set the stopped flag to true.
- */
const stopTimer = (client) => {
client.startAt = moment.invalid();
client.started = false;
@@ -123,25 +87,11 @@ const stopTimer = (client) => {
client.forcedPause = false;
};
-/**
- * Here we clear the timer.
- * We pause the timer and check it's mode to set the time to 0 or the goal.
- * Then we set the stopped flag to false.
- */
const clearTimer = (client) => {
stopTimer(client);
- client.goal = moment.duration(2, 'hours').asMilliseconds();
client.time = client.goal;
};
-// Here we set the goal and time to the goal time.
-/**
- * Here we set the goal.
- * if timer has not started, we set both time and goal to the new goal
- * if timer has started, we calculate the passed time and remove that from new goal
- * and if passed time is greater than new goal, then set time to 0, but this should
- * not be prohibited by frontend.
- */
const setGoal = (client, msg) => {
const newGoal = parseInt(msg.split('=')[1]);
if (!client.started) {
@@ -159,13 +109,6 @@ const setGoal = (client, msg) => {
}
};
-/**
- * Here we add the goal time.
- * Each addition add 15min
- * First we get the goal time from the message.
- * Then we add it to the current goal time and set it as the new goal time.
- * We also add it to the current time and set it as the new time.
- */
const addGoal = (client, msg) => {
const duration = parseInt(msg.split('=')[1]);
const goalAfterAddition = moment
@@ -187,14 +130,6 @@ const addGoal = (client, msg) => {
.toFixed();
};
-/**
- * Here we try to remove a goal time.
- * First we get the goal time from the message.
- * Then we subtract it from the current goal time and set it as the new goal time.
- * We also subtract it from the current time and set it as the new time.
- * If the new goal time is less than 15 minutes, we don't do anything.
- * If the new time is less than 0, we set it to 0.
- */
const removeGoal = (client, msg) => {
const duration = parseInt(msg.split('=')[1]);
const goalAfterRemoval = moment
@@ -220,16 +155,6 @@ const removeGoal = (client, msg) => {
.toFixed();
};
-
-/**
- * Here is were we handle the messages.
- * First we check if the user is in memory, if not, we throw an error.
- * Then we parse the request and check which action it is and call the corresponding function.
- * If we don't have a match, we just return an error.
- * The only operation that we write to Mongo it's the stop timer. Other operations are just in memory.
- * So the slowest part of the app is the save to Mongo.
- * Then we update the current client in hash map and return the response.
- */
export const handleMessage = async (msg, clients, userId) => {
if (!clients.has(userId)) {
throw new Error('It should have this user in memory');
From 29e9bb2c3fddcf4d1a47607691c0ba2e0a4d0d12 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Wed, 25 Oct 2023 23:36:47 -0700
Subject: [PATCH 087/272] make timer keep remaining time as goal after log
time, and add initial goal in timer modal
---
src/models/timer.js | 1 +
src/websockets/TimerService/clientsHandler.js | 24 +++++++++----------
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/src/models/timer.js b/src/models/timer.js
index 8afbad119..09c2f89da 100644
--- a/src/models/timer.js
+++ b/src/models/timer.js
@@ -8,6 +8,7 @@ const timerSchema = new Schema({
startAt: { type: Date, default: Date.now },
time: { type: Number, default: 900000 },
goal: { type: Number, default: 900000 },
+ initialGoal: { type: Number, default: 900000 },
paused: { type: Boolean, default: false },
forcedPause: { type: Boolean, default: false },
started: { type: Boolean, default: false },
diff --git a/src/websockets/TimerService/clientsHandler.js b/src/websockets/TimerService/clientsHandler.js
index e9e932fd7..3bb2c358d 100644
--- a/src/websockets/TimerService/clientsHandler.js
+++ b/src/websockets/TimerService/clientsHandler.js
@@ -81,32 +81,30 @@ const ackForcedPause = (client) => {
};
const stopTimer = (client) => {
+ if (client.started) pauseTimer(client);
client.startAt = moment.invalid();
client.started = false;
client.pause = false;
client.forcedPause = false;
+ if (client.time === 0) {
+ client.goal = client.initialGoal;
+ client.time = client.goal;
+ } else {
+ client.goal = client.time;
+ }
};
const clearTimer = (client) => {
stopTimer(client);
+ client.goal = client.initialGoal;
client.time = client.goal;
};
const setGoal = (client, msg) => {
const newGoal = parseInt(msg.split('=')[1]);
- if (!client.started) {
- client.goal = newGoal;
- client.time = newGoal;
- } else {
- const passedTime = client.goal - client.time;
- if (passedTime >= newGoal) {
- client.time = 0;
- client.goal = passedTime;
- } else {
- client.time = newGoal - passedTime;
- client.goal = newGoal;
- }
- }
+ client.goal = newGoal;
+ client.time = newGoal;
+ client.initialGoal = newGoal;
};
const addGoal = (client, msg) => {
From 8d37664a8b3ca4603ee5e9cd9f8f55d5c98c50a0 Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Thu, 26 Oct 2023 16:56:16 +0000
Subject: [PATCH 088/272] included replyTo field to the emailOptions
---
src/utilities/emailSender.js | 34 ++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/src/utilities/emailSender.js b/src/utilities/emailSender.js
index 4841d1410..98ca3e337 100644
--- a/src/utilities/emailSender.js
+++ b/src/utilities/emailSender.js
@@ -1,7 +1,6 @@
-const nodemailer = require('nodemailer');
-const { google } = require('googleapis');
-const logger = require('../startup/logger');
-
+const nodemailer = require("nodemailer");
+const { google } = require("googleapis");
+const logger = require("../startup/logger");
const closure = () => {
const queue = [];
@@ -13,9 +12,9 @@ const closure = () => {
const REFRESH_TOKEN = process.env.REACT_APP_EMAIL_REFRESH_TOKEN;
// Create the email envelope (transport)
const transporter = nodemailer.createTransport({
- service: 'gmail',
+ service: "gmail",
auth: {
- type: 'OAuth2',
+ type: "OAuth2",
user: CLIENT_EMAIL,
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
@@ -25,7 +24,7 @@ const closure = () => {
const OAuth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
- REDIRECT_URI,
+ REDIRECT_URI
);
OAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
@@ -35,9 +34,7 @@ const closure = () => {
if (!nextItem) return;
- const {
- recipient, subject, message, cc, bcc,
- } = nextItem;
+ const { recipient, subject, message, cc, bcc, replyTo } = nextItem;
try {
// Generate the accessToken on the fly
@@ -51,6 +48,7 @@ const closure = () => {
bcc,
subject,
html: message,
+ replyTo,
auth: {
user: CLIENT_EMAIL,
refreshToken: REFRESH_TOKEN,
@@ -65,10 +63,22 @@ const closure = () => {
}
}, process.env.MAIL_QUEUE_INTERVAL || 1000);
- const emailSender = function (recipient, subject, message, cc = null, bcc = null) {
+ const emailSender = function (
+ recipient,
+ subject,
+ message,
+ cc = null,
+ bcc = null,
+ replyTo = null
+ ) {
if (process.env.sendEmail) {
queue.push({
- recipient, subject, message, cc, bcc,
+ recipient,
+ subject,
+ message,
+ cc,
+ bcc,
+ replyTo,
});
}
};
From 326f7fece0a63501551c69ff5e1a7c87cc19a28e Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Thu, 26 Oct 2023 16:57:01 +0000
Subject: [PATCH 089/272] improved the message received by one community when a
user makes a suggestion
---
src/controllers/dashBoardController.js | 120 ++++++++++++++-----------
1 file changed, 66 insertions(+), 54 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index c9cdbd588..aacc915dd 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -1,8 +1,8 @@
-const mongoose = require("mongoose");
-const path = require("path");
-const fs = require("fs/promises");
-const dashboardhelper = require("../helpers/dashboardhelper")();
-const emailSender = require("../utilities/emailSender");
+const path = require('path');
+const fs = require('fs/promises');
+const mongoose = require('mongoose');
+const dashboardhelper = require('../helpers/dashboardhelper')();
+const emailSender = require('../utilities/emailSender');
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -20,13 +20,13 @@ const dashboardcontroller = function () {
const laborthismonth = dashboardhelper.laborthismonth(
userId,
req.params.fromDate,
- req.params.toDate
+ req.params.toDate,
);
laborthismonth.then((results) => {
if (!results || results.length === 0) {
const emptyresult = [
{
- projectName: "",
+ projectName: '',
timeSpent_hrs: 0,
},
];
@@ -42,7 +42,7 @@ const dashboardcontroller = function () {
const laborthisweek = dashboardhelper.laborthisweek(
userId,
req.params.fromDate,
- req.params.toDate
+ req.params.toDate,
);
laborthisweek.then((results) => {
res.send(results).status(200);
@@ -63,7 +63,7 @@ const dashboardcontroller = function () {
});
}
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
};
const orgData = function (req, res) {
@@ -73,7 +73,7 @@ const dashboardcontroller = function () {
.then((results) => {
res.status(200).send(results[0]);
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
};
const getBugReportEmailBody = function (
@@ -85,7 +85,7 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity
+ severity,
) {
const text = `New Bug Report From ${firstName} ${lastName}:
[Feature Name] Bug Title:
@@ -130,32 +130,32 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity
+ severity,
);
try {
emailSender(
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
`Bug Rport from ${firstName} ${lastName}`,
emailBody,
- email
+ email,
);
- res.status(200).send("Success");
+ res.status(200).send('Success');
} catch {
- res.status(500).send("Failed");
+ res.status(500).send('Failed');
}
};
const suggestionData = {
suggestion: [
- "Identify and remedy poor client and/or user service experiences",
- "Identify bright spots and enhance positive service experiences",
- "Make fundamental changes to our programs and/or operations",
- "Inform the development of new programs/projects",
- "Identify where we are less inclusive or equitable across demographic groups",
- "Strengthen relationships with the people we serve",
+ 'Identify and remedy poor client and/or user service experiences',
+ 'Identify bright spots and enhance positive service experiences',
+ 'Make fundamental changes to our programs and/or operations',
+ 'Inform the development of new programs/projects',
+ 'Identify where we are less inclusive or equitable across demographic groups',
+ 'Strengthen relationships with the people we serve',
"Understand people's needs and how we can help them achieve their goals",
- "Other",
+ 'Other',
],
field: [],
};
@@ -164,42 +164,54 @@ const dashboardcontroller = function () {
let fieldaaray = [];
if (suggestionData.field.length) {
fieldaaray = suggestionData.field.map(
- (item) => `${item}
- ${args[3][item]}
`
+ item => `${item}
+ ${args[3][item]}
`,
);
}
- const text = `New Suggestion:
- Suggestion Category:
- ${args[0]}
- Suggestion:
- ${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ""}
- Wants Feedback:
- ${args[2]}
- Thank you,
- One Community
`;
+ const text = `New Suggestion From ${args[3].firstName} ${
+ args[3].lastName
+ }:
+ Suggestion Category:
+ ${args[0]}
+ Suggestion:
+ ${args[1]}
+ ${fieldaaray.length > 0 ? fieldaaray : ''}
+ Name of Suggester:
+ ${args[3].firstName} ${args[3].lastName}
+ Email of Suggester:
+ ${args[4]}
+ Wants Feedback:
+ ${args[2]}
+ Thank you,
+ One Community
`;
return text;
};
// send suggestion email
const sendMakeSuggestion = async (req, res) => {
- const { suggestioncate, suggestion, confirm, ...rest } = req.body;
+ const {
+ suggestioncate, suggestion, confirm, email, ...rest
+} = req.body;
const emailBody = await getsuggestionEmailBody(
suggestioncate,
suggestion,
confirm,
- rest
+ rest,
+ email,
);
try {
emailSender(
- "onecommunityglobal@gmail.com",
- "A new suggestion",
- emailBody
+ 'beblicarl.cb@gmail.com',
+ 'A new suggestion',
+ emailBody,
+ null,
+ null,
+ email,
);
- res.status(200).send("Success");
+ res.status(200).send('Success');
} catch {
- res.status(500).send("Failed");
+ res.status(500).send('Failed');
}
};
@@ -208,40 +220,40 @@ const dashboardcontroller = function () {
if (suggestionData) {
res.status(200).send(suggestionData);
} else {
- res.status(404).send("Suggestion data not found.");
+ res.status(404).send('Suggestion data not found.');
}
} catch (error) {
- console.error("Error getting suggestion data:", error);
- res.status(500).send("Internal Server Error");
+ console.error('Error getting suggestion data:', error);
+ res.status(500).send('Internal Server Error');
}
};
const editSuggestionOption = async (req, res) => {
try {
if (req.body.suggestion) {
- if (req.body.action === "add") {
+ if (req.body.action === 'add') {
suggestionData.suggestion.unshift(req.body.newField);
}
- if (req.body.action === "delete") {
+ if (req.body.action === 'delete') {
suggestionData.suggestion = suggestionData.suggestion.filter(
- (item, index) => index + 1 !== +req.body.newField
+ (item, index) => index + 1 !== +req.body.newField,
);
}
} else {
- if (req.body.action === "add") {
+ if (req.body.action === 'add') {
suggestionData.field.unshift(req.body.newField);
}
- if (req.body.action === "delete") {
+ if (req.body.action === 'delete') {
suggestionData.field = suggestionData.field.filter(
- (item) => item !== req.body.newField
+ item => item !== req.body.newField,
);
}
}
- res.status(200).send("success");
+ res.status(200).send('success');
} catch (error) {
- console.error("Error editing suggestion option:", error);
- res.status(500).send("Internal Server Error");
+ console.error('Error editing suggestion option:', error);
+ res.status(500).send('Internal Server Error');
}
};
From 815b0f5ae588efb855fbde13fa65f301280b7686 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 26 Oct 2023 13:23:24 -0700
Subject: [PATCH 090/272] update projects controller to return basic proj info
---
.../bmdashboard/bmMaterialsController.js | 24 +++++++++----------
.../bmdashboard/bmProjectsController.js | 23 ++++++++++++++----
src/routes/bmdashboard/bmProjectsRouter.js | 7 +++---
src/startup/routes.js | 2 +-
4 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index a31ed460e..fb6003e90 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,4 +1,4 @@
-const mongoose = require('mongoose')
+const mongoose = require('mongoose');
const bmMaterialsController = function (ItemMaterial) {
const bmMaterialsList = async function _matsList(req, res) {
@@ -7,37 +7,37 @@ const bmMaterialsController = function (ItemMaterial) {
.populate([
{
path: 'project',
- select: '_id projectName'
+ select: '_id projectName',
},
{
path: 'inventoryItemType',
- select: '_id name uom totalStock totalAvailable'
+ select: '_id name uom totalStock totalAvailable',
},
{
path: 'usageRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
+ select: '_id firstName lastName',
+ },
},
{
path: 'updateRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
+ select: '_id firstName lastName',
+ },
},
{
path: 'purchaseRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
- }
+ select: '_id firstName lastName',
+ },
+ },
])
.exec()
.then(results => res.status(200).send(results))
- .catch(error => res.status(500).send(error))
+ .catch(error => res.status(500).send(error));
} catch (err) {
res.json(err);
}
@@ -45,4 +45,4 @@ const bmMaterialsController = function (ItemMaterial) {
return { bmMaterialsList };
};
-module.exports = bmMaterialsController;
\ No newline at end of file
+module.exports = bmMaterialsController;
diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js
index 946869bce..f80eea6c0 100644
--- a/src/controllers/bmdashboard/bmProjectsController.js
+++ b/src/controllers/bmdashboard/bmProjectsController.js
@@ -1,13 +1,26 @@
const mongoose = require('mongoose');
-const bmMProjectsController = function () {
- // fetches projects with reference to BM userProfile id
+const bmMProjectsController = function (UserProfile) {
const bmProjectsSummary = async function _projSumm(req, res) {
+ const { userId } = req.params;
try {
- res.json({ message: 'Hello world' });
+ const projectData = await UserProfile
+ // fetch user profile, return only projects array
+ .findOne({ _id: userId }, { projects: 1 })
+ // populate data with projects documents using the ObjectId in the projects array
+ .populate({
+ path: 'projects',
+ // limit to projects with category value 'Housing'
+ match: { category: 'Housing' },
+ // returns only these fields
+ select: '_id projectName isActive createdDatetime',
+ })
+ .exec()
+ .then(result => result.projects)
+ .catch(error => res.status(500).send(error));
- // .then(results => res.status(200).send(results))
- // .catch(error => res.status(500).send(error))
+ // for each project, find all materials in the project
+ res.status(200).send(projectData);
} catch (err) {
res.json(err);
}
diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js
index 204efbfad..05adfa59d 100644
--- a/src/routes/bmdashboard/bmProjectsRouter.js
+++ b/src/routes/bmdashboard/bmProjectsRouter.js
@@ -1,11 +1,10 @@
const express = require('express');
-const routes = function () {
+const routes = function (userProfile) {
const projectsRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmProjectsController')();
-// const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial);
+ const controller = require('../../controllers/bmdashboard/bmProjectsController')(userProfile);
-projectsRouter.route('/projects')
+projectsRouter.route('/projects/:userId')
.get(controller.bmProjectsSummary);
return projectsRouter;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 7208535d8..aa786dbbd 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -61,7 +61,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
-const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')();
+const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')(userProfile);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
From c58cdd3401d8364653dca9d039dd06e5c36f679e Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Thu, 26 Oct 2023 16:04:14 -0700
Subject: [PATCH 091/272] update record api for material , get bm active
projects api
---
.../bmdashboard/bmMaterialsController.js | 24 ++++++++++++-
.../bmdashboard/bmProjectsController.js | 35 +++++++++++++++++++
src/routes/bmdashboard/bmMaterialsRouter.js | 3 ++
src/routes/bmdashboard/bmProjectsRouter.js | 13 +++++++
src/startup/routes.js | 2 ++
5 files changed, 76 insertions(+), 1 deletion(-)
create mode 100644 src/controllers/bmdashboard/bmProjectsController.js
create mode 100644 src/routes/bmdashboard/bmProjectsRouter.js
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index a31ed460e..1fb1fc792 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -42,7 +42,29 @@ const bmMaterialsController = function (ItemMaterial) {
res.json(err);
}
};
- return { bmMaterialsList };
+
+ const bmPostMaterialUpdateRecord = function (req, res) {
+ console.log(req.body);
+ ItemMaterial.update(
+ { "_id": req.body.material._id },
+ {
+ $push: {
+ updateRecord: {
+ date : req.body.date,
+ createdBy : req.body.requestor.requestorId,
+ action : req.body.action,
+ cause : req.body.cause,
+ quantity : req.body.quantity,
+ description : req.body.description
+ }
+ }
+ }
+ )
+ .then(results => res.status(200).send(results))
+ .catch(error => res.status(500).send(error))
+ };
+ return { bmMaterialsList,
+ bmPostMaterialUpdateRecord };
};
module.exports = bmMaterialsController;
\ No newline at end of file
diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js
new file mode 100644
index 000000000..42ee507eb
--- /dev/null
+++ b/src/controllers/bmdashboard/bmProjectsController.js
@@ -0,0 +1,35 @@
+const mongoose = require('mongoose');
+const UserProfile = require('../../models/userProfile')
+
+const bmProjectsController = function () {
+
+ //Get current user's Housing/Building projects
+ const getUserActiveBMProjects = function (req, res) {
+ try {
+ const userId = req.body.requestor.requestorId;
+ UserProfile.findById(userId)
+ .populate([
+ {
+ path: 'projects',
+ select: '_id projectName category isActive',
+ match: { category: 'Housing' },
+ }
+ ])
+ .select({
+ projects: 1
+ })
+ .then((results) => {
+ res.status(200).send(results);
+ })
+ .catch(error => res.status(500).send(error));
+ }
+
+ catch (err) {
+ res.json(err);
+ }
+
+ };
+ return { getUserActiveBMProjects };
+}
+
+module.exports = bmProjectsController;
\ No newline at end of file
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index ab8a67388..0be779cd7 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -7,6 +7,9 @@ const controller = require('../../controllers/bmdashboard/bmMaterialsController'
materialsRouter.route('/materials')
.get(controller.bmMaterialsList);
+materialsRouter.route('/addUpdateMaterialRecord')
+ .post(controller.bmPostMaterialUpdateRecord);
+
return materialsRouter;
}
diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js
new file mode 100644
index 000000000..cec4b16e9
--- /dev/null
+++ b/src/routes/bmdashboard/bmProjectsRouter.js
@@ -0,0 +1,13 @@
+const express = require('express');
+
+const routes = function () {
+const materialsRouter = express.Router();
+const controller = require('../../controllers/bmdashboard/bmProjectsController')();
+
+materialsRouter.route('/getUserActiveBMProjects')
+ .get(controller.getUserActiveBMProjects);
+
+ return materialsRouter;
+}
+
+module.exports = routes;
\ No newline at end of file
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 2fd7337a6..00d8a3fec 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -61,6 +61,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
+const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')()
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -96,4 +97,5 @@ module.exports = function (app) {
// bm dashboard
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
+ app.use('/api/bm', bmProjectsRouter);
};
From edcdbba50d80d6334f0ae02466185588802d2fd7 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Thu, 26 Oct 2023 16:04:40 -0700
Subject: [PATCH 092/272] update record api for material , get bm active
projects api
---
.../bmdashboard/bmMaterialsController.js | 52 +-
.../bmdashboard/bmProjectsController.js | 18 +-
src/controllers/dashBoardController.js | 92 +--
src/controllers/isEmailExistsController.js | 22 +-
.../profileInitialSetupController.js | 89 ++-
src/controllers/teamController.js | 2 +-
src/controllers/userProfileController.js | 106 ++-
src/helpers/dashboardhelper.js | 4 +-
src/helpers/reporthelper.js | 94 +--
src/helpers/taskHelper.js | 4 +-
src/helpers/userHelper.js | 603 +++++++++---------
src/models/badge.js | 2 +-
src/models/inventoryItemMaterial.js | 6 +-
src/models/inventoryItemType.js | 6 +-
src/models/profileInitialSetupToken.js | 4 +-
src/models/userProfile.js | 4 +-
src/routes/bmdashboard/bmMaterialsRouter.js | 4 +-
src/routes/bmdashboard/bmProjectsRouter.js | 4 +-
src/routes/isEmailExistsRouter.js | 14 +-
src/routes/profileInitialSetupRouter.js | 6 +-
src/startup/routes.js | 2 +-
21 files changed, 548 insertions(+), 590 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 1fb1fc792..09fa91ab8 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,4 +1,4 @@
-const mongoose = require('mongoose')
+const mongoose = require('mongoose');
const bmMaterialsController = function (ItemMaterial) {
const bmMaterialsList = async function _matsList(req, res) {
@@ -7,37 +7,37 @@ const bmMaterialsController = function (ItemMaterial) {
.populate([
{
path: 'project',
- select: '_id projectName'
+ select: '_id projectName',
},
{
path: 'inventoryItemType',
- select: '_id name uom totalStock totalAvailable'
+ select: '_id name uom totalStock totalAvailable',
},
{
path: 'usageRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
+ select: '_id firstName lastName',
+ },
},
{
path: 'updateRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
+ select: '_id firstName lastName',
+ },
},
{
path: 'purchaseRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
- }
+ select: '_id firstName lastName',
+ },
+ },
])
.exec()
.then(results => res.status(200).send(results))
- .catch(error => res.status(500).send(error))
+ .catch(error => res.status(500).send(error));
} catch (err) {
res.json(err);
}
@@ -46,25 +46,27 @@ const bmMaterialsController = function (ItemMaterial) {
const bmPostMaterialUpdateRecord = function (req, res) {
console.log(req.body);
ItemMaterial.update(
- { "_id": req.body.material._id },
+ { _id: req.body.material._id },
{
$push: {
updateRecord: {
- date : req.body.date,
- createdBy : req.body.requestor.requestorId,
- action : req.body.action,
- cause : req.body.cause,
- quantity : req.body.quantity,
- description : req.body.description
- }
- }
- }
+ date: req.body.date,
+ createdBy: req.body.requestor.requestorId,
+ action: req.body.action,
+ cause: req.body.cause,
+ quantity: req.body.quantity,
+ description: req.body.description,
+ },
+ },
+ },
)
.then(results => res.status(200).send(results))
- .catch(error => res.status(500).send(error))
+ .catch(error => res.status(500).send(error));
};
- return { bmMaterialsList,
- bmPostMaterialUpdateRecord };
+ return {
+ bmMaterialsList,
+ bmPostMaterialUpdateRecord,
+};
};
-module.exports = bmMaterialsController;
\ No newline at end of file
+module.exports = bmMaterialsController;
diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js
index 42ee507eb..3ff0f851a 100644
--- a/src/controllers/bmdashboard/bmProjectsController.js
+++ b/src/controllers/bmdashboard/bmProjectsController.js
@@ -1,9 +1,8 @@
const mongoose = require('mongoose');
-const UserProfile = require('../../models/userProfile')
+const UserProfile = require('../../models/userProfile');
const bmProjectsController = function () {
-
- //Get current user's Housing/Building projects
+ // Get current user's Housing/Building projects
const getUserActiveBMProjects = function (req, res) {
try {
const userId = req.body.requestor.requestorId;
@@ -13,23 +12,20 @@ const bmProjectsController = function () {
path: 'projects',
select: '_id projectName category isActive',
match: { category: 'Housing' },
- }
+ },
])
.select({
- projects: 1
+ projects: 1,
})
.then((results) => {
res.status(200).send(results);
})
.catch(error => res.status(500).send(error));
- }
-
- catch (err) {
+ } catch (err) {
res.json(err);
}
-
};
return { getUserActiveBMProjects };
-}
+};
-module.exports = bmProjectsController;
\ No newline at end of file
+module.exports = bmProjectsController;
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index c9cdbd588..c7f9c3973 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -1,8 +1,8 @@
-const mongoose = require("mongoose");
-const path = require("path");
-const fs = require("fs/promises");
-const dashboardhelper = require("../helpers/dashboardhelper")();
-const emailSender = require("../utilities/emailSender");
+const path = require('path');
+const fs = require('fs/promises');
+const mongoose = require('mongoose');
+const dashboardhelper = require('../helpers/dashboardhelper')();
+const emailSender = require('../utilities/emailSender');
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -20,13 +20,13 @@ const dashboardcontroller = function () {
const laborthismonth = dashboardhelper.laborthismonth(
userId,
req.params.fromDate,
- req.params.toDate
+ req.params.toDate,
);
laborthismonth.then((results) => {
if (!results || results.length === 0) {
const emptyresult = [
{
- projectName: "",
+ projectName: '',
timeSpent_hrs: 0,
},
];
@@ -42,7 +42,7 @@ const dashboardcontroller = function () {
const laborthisweek = dashboardhelper.laborthisweek(
userId,
req.params.fromDate,
- req.params.toDate
+ req.params.toDate,
);
laborthisweek.then((results) => {
res.send(results).status(200);
@@ -63,7 +63,7 @@ const dashboardcontroller = function () {
});
}
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
};
const orgData = function (req, res) {
@@ -73,7 +73,7 @@ const dashboardcontroller = function () {
.then((results) => {
res.status(200).send(results[0]);
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
};
const getBugReportEmailBody = function (
@@ -85,7 +85,7 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity
+ severity,
) {
const text = `New Bug Report From ${firstName} ${lastName}:
[Feature Name] Bug Title:
@@ -130,32 +130,32 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity
+ severity,
);
try {
emailSender(
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
`Bug Rport from ${firstName} ${lastName}`,
emailBody,
- email
+ email,
);
- res.status(200).send("Success");
+ res.status(200).send('Success');
} catch {
- res.status(500).send("Failed");
+ res.status(500).send('Failed');
}
};
const suggestionData = {
suggestion: [
- "Identify and remedy poor client and/or user service experiences",
- "Identify bright spots and enhance positive service experiences",
- "Make fundamental changes to our programs and/or operations",
- "Inform the development of new programs/projects",
- "Identify where we are less inclusive or equitable across demographic groups",
- "Strengthen relationships with the people we serve",
+ 'Identify and remedy poor client and/or user service experiences',
+ 'Identify bright spots and enhance positive service experiences',
+ 'Make fundamental changes to our programs and/or operations',
+ 'Inform the development of new programs/projects',
+ 'Identify where we are less inclusive or equitable across demographic groups',
+ 'Strengthen relationships with the people we serve',
"Understand people's needs and how we can help them achieve their goals",
- "Other",
+ 'Other',
],
field: [],
};
@@ -164,8 +164,8 @@ const dashboardcontroller = function () {
let fieldaaray = [];
if (suggestionData.field.length) {
fieldaaray = suggestionData.field.map(
- (item) => `${item}
- ${args[3][item]}
`
+ item => `${item}
+ ${args[3][item]}
`,
);
}
const text = `New Suggestion:
@@ -173,7 +173,7 @@ const dashboardcontroller = function () {
${args[0]}
Suggestion:
${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ""}
+ ${fieldaaray.length > 0 ? fieldaaray : ''}
Wants Feedback:
${args[2]}
Thank you,
@@ -184,22 +184,24 @@ const dashboardcontroller = function () {
// send suggestion email
const sendMakeSuggestion = async (req, res) => {
- const { suggestioncate, suggestion, confirm, ...rest } = req.body;
+ const {
+ suggestioncate, suggestion, confirm, ...rest
+} = req.body;
const emailBody = await getsuggestionEmailBody(
suggestioncate,
suggestion,
confirm,
- rest
+ rest,
);
try {
emailSender(
- "onecommunityglobal@gmail.com",
- "A new suggestion",
- emailBody
+ 'onecommunityglobal@gmail.com',
+ 'A new suggestion',
+ emailBody,
);
- res.status(200).send("Success");
+ res.status(200).send('Success');
} catch {
- res.status(500).send("Failed");
+ res.status(500).send('Failed');
}
};
@@ -208,40 +210,40 @@ const dashboardcontroller = function () {
if (suggestionData) {
res.status(200).send(suggestionData);
} else {
- res.status(404).send("Suggestion data not found.");
+ res.status(404).send('Suggestion data not found.');
}
} catch (error) {
- console.error("Error getting suggestion data:", error);
- res.status(500).send("Internal Server Error");
+ console.error('Error getting suggestion data:', error);
+ res.status(500).send('Internal Server Error');
}
};
const editSuggestionOption = async (req, res) => {
try {
if (req.body.suggestion) {
- if (req.body.action === "add") {
+ if (req.body.action === 'add') {
suggestionData.suggestion.unshift(req.body.newField);
}
- if (req.body.action === "delete") {
+ if (req.body.action === 'delete') {
suggestionData.suggestion = suggestionData.suggestion.filter(
- (item, index) => index + 1 !== +req.body.newField
+ (item, index) => index + 1 !== +req.body.newField,
);
}
} else {
- if (req.body.action === "add") {
+ if (req.body.action === 'add') {
suggestionData.field.unshift(req.body.newField);
}
- if (req.body.action === "delete") {
+ if (req.body.action === 'delete') {
suggestionData.field = suggestionData.field.filter(
- (item) => item !== req.body.newField
+ item => item !== req.body.newField,
);
}
}
- res.status(200).send("success");
+ res.status(200).send('success');
} catch (error) {
- console.error("Error editing suggestion option:", error);
- res.status(500).send("Internal Server Error");
+ console.error('Error editing suggestion option:', error);
+ res.status(500).send('Internal Server Error');
}
};
diff --git a/src/controllers/isEmailExistsController.js b/src/controllers/isEmailExistsController.js
index 2c41efc33..f6009a3c5 100644
--- a/src/controllers/isEmailExistsController.js
+++ b/src/controllers/isEmailExistsController.js
@@ -1,25 +1,23 @@
const UserProfile = require('../models/userProfile');
const isEmailExistsController = function () {
-
const isEmailExists = async function (req, res) {
-
- try {
- const userProfile = await UserProfile.findOne({ email: req.params.email }).lean().exec()
+ try {
+ const userProfile = await UserProfile.findOne({ email: req.params.email }).lean().exec();
if (userProfile) {
- res.status(200).send(`Email, ${userProfile.email}, found.`)
+ res.status(200).send(`Email, ${userProfile.email}, found.`);
} else {
- res.status(403).send(`Email, ${req.params.email}, not found.`)
+ res.status(403).send(`Email, ${req.params.email}, not found.`);
}
} catch (err) {
- console.log(err)
+ console.log(err);
}
- }
+ };
return {
- isEmailExists
- }
-}
+ isEmailExists,
+ };
+};
-module.exports = isEmailExistsController
+module.exports = isEmailExistsController;
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 18cf7376c..6914cf48a 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -1,9 +1,9 @@
-const mongoose = require("mongoose");
-const { v4: uuidv4 } = require("uuid");
-const moment = require("moment-timezone");
-const jwt = require("jsonwebtoken");
-const emailSender = require("../utilities/emailSender");
-const config = require("../config");
+const mongoose = require('mongoose');
+const { v4: uuidv4 } = require('uuid');
+const moment = require('moment-timezone');
+const jwt = require('jsonwebtoken');
+const emailSender = require('../utilities/emailSender');
+const config = require('../config');
const cache = require('../utilities/nodeCache')();
// returns the email body that includes the setup link for the recipient.
@@ -79,7 +79,7 @@ function informManagerMessage(user) {
const profileInitialSetupController = function (
ProfileInitialSetupToken,
userProfile,
- Project
+ Project,
) {
const { JWT_SECRET } = config;
@@ -91,16 +91,16 @@ const profileInitialSetupController = function (
- Generates a link using the token and emails it to the recipient.
*/
const getSetupToken = async (req, res) => {
- let { email, baseUrl,weeklyCommittedHours } = req.body;
+ let { email, baseUrl, weeklyCommittedHours } = req.body;
email = email.toLowerCase();
const token = uuidv4();
- const expiration = moment().tz("America/Los_Angeles").add(1, "week");
+ const expiration = moment().tz('America/Los_Angeles').add(1, 'week');
try {
const existingEmail = await userProfile.findOne({
- email: email,
+ email,
});
if (existingEmail) {
- res.status(400).send("email already in use");
+ res.status(400).send('email already in use');
} else {
await ProfileInitialSetupToken.findOneAndDelete({ email });
@@ -116,10 +116,10 @@ const profileInitialSetupController = function (
emailSender(
email,
- "NEEDED: Complete your One Community profile setup",
+ 'NEEDED: Complete your One Community profile setup',
sendLinkMessage(link),
null,
- null
+ null,
);
res.status(200).send(link);
@@ -136,7 +136,7 @@ const profileInitialSetupController = function (
*/
const validateSetupToken = async (req, res) => {
const { token } = req.body;
- const currentMoment = moment.tz("America/Los_Angeles");
+ const currentMoment = moment.tz('America/Los_Angeles');
try {
const foundToken = await ProfileInitialSetupToken.findOne({ token });
@@ -146,10 +146,10 @@ const profileInitialSetupController = function (
if (expirationMoment.isAfter(currentMoment)) {
res.status(200).send(foundToken);
} else {
- res.status(400).send("Invalid token");
+ res.status(400).send('Invalid token');
}
} else {
- res.status(404).send("Token not found");
+ res.status(404).send('Token not found');
}
} catch (error) {
res.status(500).send(`Error finding token: ${error}`);
@@ -167,31 +167,30 @@ const profileInitialSetupController = function (
*/
const setUpNewUser = async (req, res) => {
const { token } = req.body;
- const currentMoment = moment.tz("America/Los_Angeles");
+ const currentMoment = moment.tz('America/Los_Angeles');
try {
const foundToken = await ProfileInitialSetupToken.findOne({ token });
const existingEmail = await userProfile.findOne({
email: foundToken.email,
});
if (existingEmail) {
- res.status(400).send("email already in use");
- } else {
- if (foundToken) {
+ res.status(400).send('email already in use');
+ } else if (foundToken) {
const expirationMoment = moment(foundToken.expiration);
if (expirationMoment.isAfter(currentMoment)) {
const defaultProject = await Project.findOne({
- projectName: "Orientation and Initial Setup",
+ projectName: 'Orientation and Initial Setup',
});
const newUser = new userProfile();
newUser.password = req.body.password;
- newUser.role = "Volunteer";
+ newUser.role = 'Volunteer';
newUser.firstName = req.body.firstName;
newUser.lastName = req.body.lastName;
newUser.jobTitle = req.body.jobTitle;
newUser.phoneNumber = req.body.phoneNumber;
- newUser.bio = "";
+ newUser.bio = '';
newUser.weeklycommittedHours = foundToken.weeklyCommittedHours;
newUser.weeklycommittedHoursHistory = [
{
@@ -205,32 +204,31 @@ const profileInitialSetupController = function (
newUser.projects = Array.from(new Set([defaultProject]));
newUser.createdDate = Date.now();
newUser.email = req.body.email;
- newUser.weeklySummaries = [{ summary: "" }];
+ newUser.weeklySummaries = [{ summary: '' }];
newUser.weeklySummariesCount = 0;
- newUser.weeklySummaryOption = "Required";
- newUser.mediaUrl = "";
+ newUser.weeklySummaryOption = 'Required';
+ newUser.mediaUrl = '';
newUser.collaborationPreference = req.body.collaborationPreference;
- newUser.timeZone = req.body.timeZone || "America/Los_Angeles";
+ newUser.timeZone = req.body.timeZone || 'America/Los_Angeles';
newUser.location = req.body.location;
newUser.permissions = {
frontPermissions: [],
- backPermissions: []
- }
- newUser.bioPosted = "default";
+ backPermissions: [],
+ };
+ newUser.bioPosted = 'default';
newUser.privacySettings.email = req.body.privacySettings.email;
- newUser.privacySettings.phoneNumber =
- req.body.privacySettings.phoneNumber;
- newUser.teamCode = "";
+ newUser.privacySettings.phoneNumber = req.body.privacySettings.phoneNumber;
+ newUser.teamCode = '';
newUser.isFirstTimelog = true;
const savedUser = await newUser.save();
emailSender(
- process.env.MANAGER_EMAIL || "jae@onecommunityglobal.org", // "jae@onecommunityglobal.org"
+ process.env.MANAGER_EMAIL || 'jae@onecommunityglobal.org', // "jae@onecommunityglobal.org"
`NEW USER REGISTERED: ${savedUser.firstName} ${savedUser.lastName}`,
informManagerMessage(savedUser),
null,
- null
+ null,
);
await ProfileInitialSetupToken.findByIdAndDelete(foundToken._id);
@@ -240,14 +238,14 @@ const profileInitialSetupController = function (
permissions: savedUser.permissions,
expiryTimestamp: moment().add(
config.TOKEN.Lifetime,
- config.TOKEN.Units
+ config.TOKEN.Units,
),
};
const token = jwt.sign(jwtPayload, JWT_SECRET);
res.send({ token }).status(200);
-
+
const NewUserCache = {
permissions: savedUser.permissions,
isActive: true,
@@ -260,18 +258,15 @@ const profileInitialSetupController = function (
email: savedUser.email,
};
- const allUserCache = JSON.parse(cache.getCache("allusers"));
+ const allUserCache = JSON.parse(cache.getCache('allusers'));
allUserCache.push(NewUserCache);
- cache.setCache("allusers", JSON.stringify(allUserCache));
-
-
+ cache.setCache('allusers', JSON.stringify(allUserCache));
} else {
- res.status(400).send("Token is expired");
+ res.status(400).send('Token is expired');
}
} else {
- res.status(400).send("Invalid token");
+ res.status(400).send('Invalid token');
}
- }
} catch (error) {
res.status(500).send(`Error: ${error}`);
}
@@ -283,17 +278,15 @@ const profileInitialSetupController = function (
- sends the API Key as response
*/
const getTimeZoneAPIKeyByToken = async (req, res) => {
- const token = req.body.token;
+ const { token } = req.body;
const premiumKey = process.env.TIMEZONE_PREMIUM_KEY;
const foundToken = await ProfileInitialSetupToken.findOne({ token });
if (foundToken) {
res.status(200).send({ userAPIKey: premiumKey });
- return;
} else {
- res.status(403).send("Unauthorized Request");
- return;
+ res.status(403).send('Unauthorized Request');
}
};
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index c82b9e5ce..756f386d5 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -115,7 +115,7 @@ const teamcontroller = function (Team) {
users.forEach((element) => {
const { userId, operation } = element;
// if user's profile is stored in cache, clear it so when you visit their profile page it will be up to date
- if(cache.hasCache(`user-${userId}`)) cache.removeCache(`user-${userId}`);
+ if (cache.hasCache(`user-${userId}`)) cache.removeCache(`user-${userId}`);
if (operation === 'Assign') {
assignlist.push(userId);
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 6dc571b39..aed8f1788 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -59,27 +59,25 @@ const userProfileController = function (UserProfile) {
UserProfile.find(
{},
- "_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate"
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate',
)
.sort({
lastName: 1,
})
.then((results) => {
if (!results) {
- if (cache.getCache("allusers")) {
- const getData = JSON.parse(cache.getCache("allusers"));
+ if (cache.getCache('allusers')) {
+ const getData = JSON.parse(cache.getCache('allusers'));
res.status(200).send(getData);
return;
- }else{
- res.status(500).send({ error: "User result was invalid" });
- return;
}
+ res.status(500).send({ error: 'User result was invalid' });
+ return;
}
- cache.setCache("allusers", JSON.stringify(results));
+ cache.setCache('allusers', JSON.stringify(results));
res.status(200).send(results);
})
- .catch((error) => res.status(404).send(error));
-
+ .catch(error => res.status(404).send(error));
};
const getProjectMembers = async function (req, res) {
@@ -93,14 +91,14 @@ const userProfileController = function (UserProfile) {
$in: [req.params.projectId],
},
},
- "_id firstName email",
+ '_id firstName email',
(err, profiles) => {
if (err) {
- res.status(404).send("Error finding user profiles");
+ res.status(404).send('Error finding user profiles');
return;
}
res.json(profiles);
- }
+ },
);
};
@@ -118,15 +116,15 @@ const userProfileController = function (UserProfile) {
const userByEmail = await UserProfile.findOne({
email: {
$regex: escapeRegex(req.body.email),
- $options: "i",
+ $options: 'i',
},
});
if (userByEmail) {
res.status(400).send({
error:
- "That email address is already in use. Please choose another email address.",
- type: "email",
+ 'That email address is already in use. Please choose another email address.',
+ type: 'email',
});
return;
}
@@ -145,8 +143,8 @@ const userProfileController = function (UserProfile) {
if (userByPhoneNumber) {
res.status(400).send({
error:
- "That phone number is already in use. Please choose another number.",
- type: "phoneNumber",
+ 'That phone number is already in use. Please choose another number.',
+ type: 'phoneNumber',
});
return;
}
@@ -160,8 +158,8 @@ const userProfileController = function (UserProfile) {
if (userDuplicateName && !req.body.allowsDuplicateName) {
res.status(400).send({
error:
- "That name is already in use. Please confirm if you want to use this name.",
- type: "name",
+ 'That name is already in use. Please confirm if you want to use this name.',
+ type: 'name',
});
return;
}
@@ -188,15 +186,15 @@ const userProfileController = function (UserProfile) {
up.projects = Array.from(new Set(req.body.projects));
up.createdDate = req.body.createdDate;
up.email = req.body.email;
- up.weeklySummaries = req.body.weeklySummaries || [{ summary: "" }];
+ up.weeklySummaries = req.body.weeklySummaries || [{ summary: '' }];
up.weeklySummariesCount = req.body.weeklySummariesCount || 0;
up.weeklySummaryOption = req.body.weeklySummaryOption;
- up.mediaUrl = req.body.mediaUrl || "";
- up.collaborationPreference = req.body.collaborationPreference || "";
- up.timeZone = req.body.timeZone || "America/Los_Angeles";
+ up.mediaUrl = req.body.mediaUrl || '';
+ up.collaborationPreference = req.body.collaborationPreference || '';
+ up.timeZone = req.body.timeZone || 'America/Los_Angeles';
up.location = req.body.location;
up.permissions = req.body.permissions;
- up.bioPosted = req.body.bioPosted || "default";
+ up.bioPosted = req.body.bioPosted || 'default';
up.isFirstTimelog = true;
up.save()
@@ -218,11 +216,11 @@ const userProfileController = function (UserProfile) {
lastName: up.lastName,
email: up.email,
};
- const allUserCache = JSON.parse(cache.getCache("allusers"));
+ const allUserCache = JSON.parse(cache.getCache('allusers'));
allUserCache.push(userCache);
- cache.setCache("allusers", JSON.stringify(allUserCache));
+ cache.setCache('allusers', JSON.stringify(allUserCache));
})
- .catch((error) => res.status(501).send(error));
+ .catch(error => res.status(501).send(error));
};
const putUserProfile = async function (req, res) {
@@ -233,12 +231,12 @@ const userProfileController = function (UserProfile) {
|| req.body.requestor.requestorId === userid
)
);
-
- const canEditTeamCode = req.body.requestor.role === "Owner" ||
- req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
+
+ const canEditTeamCode = req.body.requestor.role === 'Owner'
+ || req.body.requestor.permissions?.frontPermissions.includes('editTeamCode');
if (!isRequestorAuthorized) {
- res.status(403).send("You are not authorized to update this user");
+ res.status(403).send('You are not authorized to update this user');
return;
}
@@ -250,7 +248,7 @@ const userProfileController = function (UserProfile) {
cache.removeCache(`user-${userid}`);
UserProfile.findById(userid, async (err, record) => {
if (err || !record) {
- res.status(404).send("No valid records found");
+ res.status(404).send('No valid records found');
return;
}
// validate userprofile pic
@@ -269,8 +267,7 @@ const userProfileController = function (UserProfile) {
: [];
record.jobTitle = req.body.jobTitle;
record.emailPubliclyAccessible = req.body.emailPubliclyAccessible;
- record.phoneNumberPubliclyAccessible =
- req.body.phoneNumberPubliclyAccessible;
+ record.phoneNumberPubliclyAccessible = req.body.phoneNumberPubliclyAccessible;
record.profilePic = req.body.profilePic;
record.firstName = req.body.firstName;
@@ -292,24 +289,24 @@ const userProfileController = function (UserProfile) {
record.isVisible = req.body.isVisible || false;
record.isRehireable = req.body.isRehireable || false;
record.totalIntangibleHrs = req.body.totalIntangibleHrs;
- record.bioPosted = req.body.bioPosted || "default";
+ record.bioPosted = req.body.bioPosted || 'default';
record.isFirstTimelog = req.body.isFirstTimelog;
- if(!canEditTeamCode && record.teamCode !== req.body.teamCode){
- res.status(403).send("You are not authorized to edit team code.");
+ if (!canEditTeamCode && record.teamCode !== req.body.teamCode) {
+ res.status(403).send('You are not authorized to edit team code.');
return;
}
record.teamCode = req.body.teamCode;
// find userData in cache
- const isUserInCache = cache.hasCache("allusers");
+ const isUserInCache = cache.hasCache('allusers');
let allUserData;
let userData;
let userIdx;
if (isUserInCache) {
- allUserData = JSON.parse(cache.getCache("allusers"));
- userIdx = allUserData.findIndex((users) => users._id === userid);
+ allUserData = JSON.parse(cache.getCache('allusers'));
+ userIdx = allUserData.findIndex(users => users._id === userid);
userData = allUserData[userIdx];
}
if (await hasPermission(req.body.requestor, 'putUserProfileImportantInfo')) {
@@ -324,11 +321,11 @@ const userProfileController = function (UserProfile) {
// If their last update was made today, remove that
const lasti = record.weeklycommittedHoursHistory.length - 1;
const lastChangeDate = moment(
- record.weeklycommittedHoursHistory[lasti].dateChanged
+ record.weeklycommittedHoursHistory[lasti].dateChanged,
);
const now = moment();
- if (lastChangeDate.isSame(now, "day")) {
+ if (lastChangeDate.isSame(now, 'day')) {
record.weeklycommittedHoursHistory.pop();
}
@@ -341,8 +338,7 @@ const userProfileController = function (UserProfile) {
record.weeklycommittedHoursHistory.push(newEntry);
}
- record.missedHours =
- req.body.role === "Core Team" ? req.body?.missedHours ?? 0 : 0;
+ record.missedHours = req.body.role === 'Core Team' ? req.body?.missedHours ?? 0 : 0;
record.adminLinks = req.body.adminLinks;
record.teams = Array.from(new Set(req.body.teams));
record.projects = Array.from(new Set(req.body.projects));
@@ -374,8 +370,7 @@ const userProfileController = function (UserProfile) {
record.weeklycommittedHoursHistory.push(newEntry);
}
// then also change the first committed history (index 0)
- record.weeklycommittedHoursHistory[0].dateChanged =
- record.createdDate;
+ record.weeklycommittedHoursHistory[0].dateChanged = record.createdDate;
}
record.bioPosted = req.body.bioPosted || 'default';
@@ -390,7 +385,7 @@ const userProfileController = function (UserProfile) {
userData.endDate = record.endDate.toISOString();
}
} else {
- record.set("endDate", undefined, { strict: false });
+ record.set('endDate', undefined, { strict: false });
}
if (isUserInCache) {
userData.role = record.role;
@@ -412,7 +407,7 @@ const userProfileController = function (UserProfile) {
results.infringements,
results.firstName,
results.lastName,
- results.email
+ results.email,
);
res.status(200).json({
_id: record._id,
@@ -421,10 +416,10 @@ const userProfileController = function (UserProfile) {
// update alluser cache if we have cache
if (isUserInCache) {
allUserData.splice(userIdx, 1, userData);
- cache.setCache("allusers", JSON.stringify(allUserData));
+ cache.setCache('allusers', JSON.stringify(allUserData));
}
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
});
};
@@ -569,15 +564,14 @@ const userProfileController = function (UserProfile) {
const { userId } = req.params;
const { key, value } = req.body;
- if (key === "teamCode") {
- const canEditTeamCode = req.body.requestor.role === "Owner" ||
- req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
+ if (key === 'teamCode') {
+ const canEditTeamCode = req.body.requestor.role === 'Owner'
+ || req.body.requestor.permissions?.frontPermissions.includes('editTeamCode');
- if(!canEditTeamCode){
- res.status(403).send("You are not authorized to edit team code.");
+ if (!canEditTeamCode) {
+ res.status(403).send('You are not authorized to edit team code.');
return;
}
-
}
// remove user from cache, it should be loaded next time
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 34d464583..fe2007281 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -192,7 +192,7 @@ const dashboardhelper = function () {
// leaderboard user roles hierarchy
$or: [
{
- role: { $in: ['Owner', 'Core Team'] },
+ role: { $in: ['Owner', 'Core Team'] },
},
{
$and: [
@@ -200,7 +200,7 @@ const dashboardhelper = function () {
role: 'Administrator',
},
{ 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ]
+ ],
},
{
$and: [
diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js
index 0c2a8104d..3826aa8ed 100644
--- a/src/helpers/reporthelper.js
+++ b/src/helpers/reporthelper.js
@@ -1,5 +1,5 @@
-const moment = require("moment-timezone");
-const userProfile = require("../models/userProfile");
+const moment = require('moment-timezone');
+const userProfile = require('../models/userProfile');
/**
*
@@ -8,9 +8,9 @@ const userProfile = require("../models/userProfile");
* @returns The absolute value of the difference in weeks between the two input dates.
*/
const absoluteDifferenceInWeeks = (dateOfWork, pstEnd) => {
- dateOfWork = moment(dateOfWork).endOf("week");
- pstEnd = moment(pstEnd).tz("America/Los_Angeles").endOf("week");
- return Math.abs(dateOfWork.diff(pstEnd, "weeks"));
+ dateOfWork = moment(dateOfWork).endOf('week');
+ pstEnd = moment(pstEnd).tz('America/Los_Angeles').endOf('week');
+ return Math.abs(dateOfWork.diff(pstEnd, 'weeks'));
};
const reporthelper = function () {
@@ -23,14 +23,14 @@ const reporthelper = function () {
*/
const weeklySummaries = async (startWeekIndex, endWeekIndex) => {
const pstStart = moment()
- .tz("America/Los_Angeles")
- .startOf("week")
- .subtract(startWeekIndex, "week")
+ .tz('America/Los_Angeles')
+ .startOf('week')
+ .subtract(startWeekIndex, 'week')
.toDate();
const pstEnd = moment()
- .tz("America/Los_Angeles")
- .endOf("week")
- .subtract(endWeekIndex, "week")
+ .tz('America/Los_Angeles')
+ .endOf('week')
+ .subtract(endWeekIndex, 'week')
.toDate();
const results = await userProfile.aggregate([
@@ -39,33 +39,33 @@ const reporthelper = function () {
},
{
$lookup: {
- from: "timeEntries",
- localField: "_id",
- foreignField: "personId",
- as: "timeEntries",
+ from: 'timeEntries',
+ localField: '_id',
+ foreignField: 'personId',
+ as: 'timeEntries',
},
},
{
- $set: { totalTangibleHrs: { $objectToArray: "$hoursByCategory" } },
+ $set: { totalTangibleHrs: { $objectToArray: '$hoursByCategory' } },
},
{
$project: {
timeEntries: {
$filter: {
- input: "$timeEntries",
- as: "timeEntry",
+ input: '$timeEntries',
+ as: 'timeEntry',
cond: {
$and: [
{
$gte: [
- "$$timeEntry.dateOfWork",
- moment(pstStart).format("YYYY-MM-DD"),
+ '$$timeEntry.dateOfWork',
+ moment(pstStart).format('YYYY-MM-DD'),
],
},
{
$lte: [
- "$$timeEntry.dateOfWork",
- moment(pstEnd).format("YYYY-MM-DD"),
+ '$$timeEntry.dateOfWork',
+ moment(pstEnd).format('YYYY-MM-DD'),
],
},
],
@@ -86,22 +86,22 @@ const reporthelper = function () {
bioPosted: 1,
badgeCollection: {
$filter: {
- input: "$badgeCollection",
- as: "badge",
+ input: '$badgeCollection',
+ as: 'badge',
cond: {
$or: [
{
$and: [
{
$gte: [
- "$$badge.earnedDate",
- moment(pstStart).format("YYYY-MM-DD"),
+ '$$badge.earnedDate',
+ moment(pstStart).format('YYYY-MM-DD'),
],
},
{
$lte: [
- "$$badge.earnedDate",
- moment(pstEnd).format("YYYY-MM-DD"),
+ '$$badge.earnedDate',
+ moment(pstEnd).format('YYYY-MM-DD'),
],
},
],
@@ -109,10 +109,10 @@ const reporthelper = function () {
{
$and: [
{
- $gte: ["$$badge.lastModified", pstStart],
+ $gte: ['$$badge.lastModified', pstStart],
},
{
- $lte: ["$$badge.lastModified", pstEnd],
+ $lte: ['$$badge.lastModified', pstEnd],
},
],
},
@@ -126,15 +126,15 @@ const reporthelper = function () {
role: 1,
weeklySummaries: {
$filter: {
- input: "$weeklySummaries",
- as: "ws",
+ input: '$weeklySummaries',
+ as: 'ws',
cond: {
$and: [
{
- $gte: ["$$ws.dueDate", pstStart],
+ $gte: ['$$ws.dueDate', pstStart],
},
{
- $lte: ["$$ws.dueDate", pstEnd],
+ $lte: ['$$ws.dueDate', pstEnd],
},
],
},
@@ -142,13 +142,13 @@ const reporthelper = function () {
},
weeklySummariesCount: 1,
isTangible: 1,
- totalTangibleHrs: { $sum: "$totalTangibleHrs.v" },
+ totalTangibleHrs: { $sum: '$totalTangibleHrs.v' },
daysInTeam: {
$dateDiff: {
- startDate: "$createdDate",
+ startDate: '$createdDate',
endDate: new Date(),
- unit: "day",
- timezone: "America/Los_Angeles",
+ unit: 'day',
+ timezone: 'America/Los_Angeles',
},
},
},
@@ -162,8 +162,8 @@ const reporthelper = function () {
result.timeEntries.forEach((entry) => {
const index = absoluteDifferenceInWeeks(entry.dateOfWork, pstEnd);
if (
- result.totalSeconds[index] === undefined ||
- result.totalSeconds[index] === null
+ result.totalSeconds[index] === undefined
+ || result.totalSeconds[index] === null
) {
result.totalSeconds[index] = 0;
}
@@ -189,16 +189,16 @@ const reporthelper = function () {
*/
const doesDateBelongToWeek = function (dueDate, weekIndex) {
const pstStartOfWeek = moment()
- .tz("America/Los_Angeles")
- .startOf("week")
- .subtract(weekIndex, "week");
+ .tz('America/Los_Angeles')
+ .startOf('week')
+ .subtract(weekIndex, 'week');
const pstEndOfWeek = moment()
- .tz("America/Los_Angeles")
- .endOf("week")
- .subtract(weekIndex, "week");
+ .tz('America/Los_Angeles')
+ .endOf('week')
+ .subtract(weekIndex, 'week');
const fromDate = moment(pstStartOfWeek).toDate();
const toDate = moment(pstEndOfWeek).toDate();
- return moment(dueDate).isBetween(fromDate, toDate, undefined, "[]");
+ return moment(dueDate).isBetween(fromDate, toDate, undefined, '[]');
};
/**
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index a94aaee94..f59dedcbc 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -43,7 +43,7 @@ const taskHelper = function () {
// dashboard tasks user roles hierarchy
$or: [
{
- role: { $in: ['Owner', 'Core Team'] },
+ role: { $in: ['Owner', 'Core Team'] },
},
{
$and: [
@@ -51,7 +51,7 @@ const taskHelper = function () {
role: 'Administrator',
},
{ 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ]
+ ],
},
{
$and: [
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index af416f1a7..a1fd6265a 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -1,28 +1,28 @@
/* eslint-disable no-continue */
/* eslint-disable no-await-in-loop */
-const mongoose = require("mongoose");
-const moment = require("moment-timezone");
-const _ = require("lodash");
-const userProfile = require("../models/userProfile");
-const timeEntries = require("../models/timeentry");
-const badge = require("../models/badge");
-const myTeam = require("./helperModels/myTeam");
-const dashboardHelper = require("./dashboardhelper")();
-const reportHelper = require("./reporthelper")();
-const emailSender = require("../utilities/emailSender");
-const logger = require("../startup/logger");
-const hasPermission = require("../utilities/permissions");
-const Reason = require("../models/reason");
-const token = require("../models/profileInitialSetupToken")
+const mongoose = require('mongoose');
+const moment = require('moment-timezone');
+const _ = require('lodash');
+const userProfile = require('../models/userProfile');
+const timeEntries = require('../models/timeentry');
+const badge = require('../models/badge');
+const myTeam = require('./helperModels/myTeam');
+const dashboardHelper = require('./dashboardhelper')();
+const reportHelper = require('./reporthelper')();
+const emailSender = require('../utilities/emailSender');
+const logger = require('../startup/logger');
+const hasPermission = require('../utilities/permissions');
+const Reason = require('../models/reason');
+const token = require('../models/profileInitialSetupToken');
const userHelper = function () {
const getTeamMembers = function (user) {
const userId = mongoose.Types.ObjectId(user._id);
// var teamid = userdetails.teamId;
return myTeam.findById(userId).select({
- "myTeam._id": 0,
- "myTeam.role": 0,
- "myTeam.fullName": 0,
+ 'myTeam._id': 0,
+ 'myTeam.role': 0,
+ 'myTeam.fullName': 0,
_id: 0,
});
};
@@ -46,40 +46,39 @@ const userHelper = function () {
const getUserName = async function (userId) {
const userid = mongoose.Types.ObjectId(userId);
- return userProfile.findById(userid, "firstName lastName");
+ return userProfile.findById(userid, 'firstName lastName');
};
const validateProfilePic = function (profilePic) {
- const picParts = profilePic.split("base64");
+ const picParts = profilePic.split('base64');
let result = true;
const errors = [];
if (picParts.length < 2) {
return {
result: false,
- errors: "Invalid image"
+ errors: 'Invalid image',
};
}
// validate size
const imageSize = picParts[1].length;
- const sizeInBytes =
- (4 * Math.ceil(imageSize / 3) * 0.5624896334383812) / 1024;
+ const sizeInBytes = (4 * Math.ceil(imageSize / 3) * 0.5624896334383812) / 1024;
if (sizeInBytes > 50) {
- errors.push("Image size should not exceed 50KB");
+ errors.push('Image size should not exceed 50KB');
result = false;
}
- const imageType = picParts[0].split("/")[1];
- if (imageType !== "jpeg;" && imageType !== "png;") {
- errors.push("Image type shoud be either jpeg or png.");
+ const imageType = picParts[0].split('/')[1];
+ if (imageType !== 'jpeg;' && imageType !== 'png;') {
+ errors.push('Image type shoud be either jpeg or png.');
result = false;
}
return {
result,
- errors
+ errors,
};
};
@@ -87,7 +86,7 @@ const userHelper = function () {
firstName,
lastName,
infringement,
- totalInfringements
+ totalInfringements,
) {
const text = `Dear ${firstName} ${lastName},
Oops, it looks like something happened and you’ve managed to get a blue square.
@@ -114,11 +113,11 @@ const userHelper = function () {
*/
const emailWeeklySummariesForAllUsers = async (weekIndex = 1) => {
const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
+ .tz('America/Los_Angeles')
.format();
logger.logInfo(
- `Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`
+ `Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`,
);
const emails = [];
@@ -126,13 +125,11 @@ const userHelper = function () {
try {
const results = await reportHelper.weeklySummaries(weekIndex, weekIndex);
- let emailBody = "Weekly Summaries for all active users:
";
+ let emailBody = 'Weekly Summaries for all active users:
';
- const weeklySummaryNotProvidedMessage =
- 'Weekly Summary: Not provided!
';
+ const weeklySummaryNotProvidedMessage = 'Weekly Summary: Not provided!
';
- const weeklySummaryNotRequiredMessage =
- 'Weekly Summary: Not required for this user
';
+ const weeklySummaryNotRequiredMessage = 'Weekly Summary: Not required for this user
';
results.sort((a, b) => `${a.firstName} ${a.lastName}`.localeCompare(`${b.firstName} ${b.lastname}`));
@@ -146,7 +143,7 @@ const userHelper = function () {
mediaUrl,
weeklySummariesCount,
weeklycommittedHours,
- weeklySummaryOption
+ weeklySummaryOption,
} = result;
if (email !== undefined && email !== null) {
@@ -163,14 +160,14 @@ const userHelper = function () {
let weeklySummaryMessage = weeklySummaryNotProvidedMessage;
const colorStyle = (() => {
switch (weeklySummaryOption) {
- case "Team":
+ case 'Team':
return 'style="color: magenta;"';
- case "Not Required":
+ case 'Not Required':
return 'style="color: green"';
- case "Required":
- return "";
+ case 'Required':
+ return '';
default:
- return result.weeklySummaryNotReq ? 'style="color: green"' : "";
+ return result.weeklySummaryNotReq ? 'style="color: green"' : '';
}
})();
// weeklySummaries array should only have one item if any, hence weeklySummaries[0] needs be used to access it.
@@ -181,8 +178,8 @@ const userHelper = function () {
Weekly Summary
(for the week ending on ${moment(dueDate)
- .tz("America/Los_Angeles")
- .format("YYYY-MMM-DD")}):
+ .tz('America/Los_Angeles')
+ .format('YYYY-MMM-DD')}):
${summary}
@@ -207,15 +204,15 @@ const userHelper = function () {
${weeklySummariesCount === 8
? `
Total Valid Weekly Summaries: ${weeklySummariesCount}
`
- : `
Total Valid Weekly Summaries: ${weeklySummariesCount ||
- "No valid submissions yet!"}
`
+ : `
Total Valid Weekly Summaries: ${weeklySummariesCount
+ || 'No valid submissions yet!'}
`
}
${hoursLogged >= weeklycommittedHours
? `
Hours logged: ${hoursLogged.toFixed(2)} / ${weeklycommittedHours}
`
: `
Hours logged: ${hoursLogged.toFixed(
- 2
+ 2,
)} / ${weeklycommittedHours}
`
}
${weeklySummaryMessage}
@@ -225,10 +222,8 @@ const userHelper = function () {
// Necessary because our version of node is outdated
// and doesn't have String.prototype.replaceAll
let emailString = [...new Set(emails)].toString();
- while (emailString.includes(","))
- emailString = emailString.replace(",", "\n");
- while (emailString.includes("\n"))
- emailString = emailString.replace("\n", ", ");
+ while (emailString.includes(',')) emailString = emailString.replace(',', '\n');
+ while (emailString.includes('\n')) emailString = emailString.replace('\n', ', ');
emailBody += `\n
@@ -240,10 +235,10 @@ const userHelper = function () {
`;
emailSender(
- "onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com",
- "Weekly Summaries for all active users...",
+ 'onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com',
+ 'Weekly Summaries for all active users...',
emailBody,
- null
+ null,
);
} catch (err) {
logger.logException(err);
@@ -265,15 +260,15 @@ const userHelper = function () {
$each: [
{
dueDate: moment()
- .tz("America/Los_Angeles")
- .endOf("week"),
- summary: ""
- }
+ .tz('America/Los_Angeles')
+ .endOf('week'),
+ summary: '',
+ },
],
$position: 0,
- $slice: 4
- }
- }
+ $slice: 4,
+ },
+ },
})
.catch(error => logger.logException(error));
};
@@ -287,11 +282,11 @@ const userHelper = function () {
const assignBlueSquareForTimeNotMet = async () => {
try {
const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
+ .tz('America/Los_Angeles')
.format();
const currentUTCDate = moment
- .tz("America/Los_Angeles")
- .startOf("day")
+ .tz('America/Los_Angeles')
+ .startOf('day')
.toISOString();
logger.logInfo(
@@ -301,24 +296,24 @@ const userHelper = function () {
);
const pdtStartOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .startOf("week")
- .subtract(1, "week");
+ .tz('America/Los_Angeles')
+ .startOf('week')
+ .subtract(1, 'week');
const pdtEndOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .endOf("week")
- .subtract(1, "week");
+ .tz('America/Los_Angeles')
+ .endOf('week')
+ .subtract(1, 'week');
const users = await userProfile.find(
{ isActive: true },
- "_id weeklycommittedHours weeklySummaries missedHours"
+ '_id weeklycommittedHours weeklySummaries missedHours',
);
- //this part is supposed to be a for, so it'll be slower when sending emails, so the emails will not be
- //targeted as spam
- //There's no need to put Promise.all here
+ // this part is supposed to be a for, so it'll be slower when sending emails, so the emails will not be
+ // targeted as spam
+ // There's no need to put Promise.all here
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -345,13 +340,12 @@ const userHelper = function () {
const results = await dashboardHelper.laborthisweek(
personId,
pdtStartOfLastWeek,
- pdtEndOfLastWeek
+ pdtEndOfLastWeek,
);
const { timeSpent_hrs: timeSpent } = results[0];
- const weeklycommittedHours =
- user.weeklycommittedHours + (user.missedHours ?? 0);
+ const weeklycommittedHours = user.weeklycommittedHours + (user.missedHours ?? 0);
const timeNotMet = timeSpent < weeklycommittedHours;
let description;
@@ -360,19 +354,19 @@ const userHelper = function () {
personId,
{
$inc: {
- totalTangibleHrs: timeSpent || 0
+ totalTangibleHrs: timeSpent || 0,
},
$max: {
- personalBestMaxHrs: timeSpent || 0
+ personalBestMaxHrs: timeSpent || 0,
},
$push: {
- savedTangibleHrs: { $each: [timeSpent || 0], $slice: -200 }
+ savedTangibleHrs: { $each: [timeSpent || 0], $slice: -200 },
},
$set: {
- lastWeekTangibleHrs: timeSpent || 0
- }
+ lastWeekTangibleHrs: timeSpent || 0,
+ },
},
- { new: true }
+ { new: true },
);
if (
@@ -384,13 +378,13 @@ const userHelper = function () {
hasWeeklySummary = true;
}
- const cutOffDate = moment().subtract(1, "year");
+ const cutOffDate = moment().subtract(1, 'year');
const oldInfringements = [];
for (let k = 0; k < updateResult?.infringements.length; k += 1) {
if (
- updateResult?.infringements &&
- moment(updateResult?.infringements[k].date).diff(cutOffDate) >= 0
+ updateResult?.infringements
+ && moment(updateResult?.infringements[k].date).diff(cutOffDate) >= 0
) {
oldInfringements.push(updateResult.infringements[k]);
} else {
@@ -403,72 +397,70 @@ const userHelper = function () {
personId,
{
$push: {
- oldInfringements: { $each: oldInfringements, $slice: -10 }
- }
+ oldInfringements: { $each: oldInfringements, $slice: -10 },
+ },
},
- { new: true }
+ { new: true },
);
}
if (timeNotMet || !hasWeeklySummary) {
if (foundReason) {
description = foundReason.reason;
- } else {
- if (timeNotMet && !hasWeeklySummary) {
+ } else if (timeNotMet && !hasWeeklySummary) {
description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${timeSpent.toFixed(2)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
- "dddd YYYY-MM-DD"
- )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
+ 'dddd YYYY-MM-DD',
+ )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
} else if (timeNotMet) {
description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${timeSpent.toFixed(2)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
- "dddd YYYY-MM-DD"
- )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
+ 'dddd YYYY-MM-DD',
+ )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
} else {
description = `System auto-assigned infringement for not submitting a weekly summary for the week starting ${pdtStartOfLastWeek.format(
- "dddd YYYY-MM-DD"
- )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
+ 'dddd YYYY-MM-DD',
+ )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
}
- }
const infringement = {
date: moment()
.utc()
- .format("YYYY-MM-DD"),
- description
+ .format('YYYY-MM-DD'),
+ description,
};
const status = await userProfile.findByIdAndUpdate(
personId,
{
$push: {
- infringements: infringement
- }
+ infringements: infringement,
+ },
},
- { new: true }
+ { new: true },
);
emailSender(
status.email,
- "New Infringement Assigned",
+ 'New Infringement Assigned',
getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
- status.infringements.length
+ status.infringements.length,
),
null,
- "onecommunityglobal@gmail.com"
+ 'onecommunityglobal@gmail.com',
);
const categories = await dashboardHelper.laborThisWeekByCategory(
personId,
pdtStartOfLastWeek,
- pdtEndOfLastWeek
+ pdtEndOfLastWeek,
);
if (Array.isArray(categories) && categories.length > 0) {
await userProfile.findOneAndUpdate(
{ _id: personId, categoryTangibleHrs: { $exists: false } },
- { $set: { categoryTangibleHrs: [] } }
+ { $set: { categoryTangibleHrs: [] } },
);
} else {
continue;
@@ -478,29 +470,29 @@ const userHelper = function () {
const elem = categories[j];
if (elem._id == null) {
- elem._id = "Other";
+ elem._id = 'Other';
}
const updateResult2 = await userProfile.findOneAndUpdate(
- { _id: personId, "categoryTangibleHrs.category": elem._id },
- { $inc: { "categoryTangibleHrs.$.hrs": elem.timeSpent_hrs } },
- { new: true }
+ { _id: personId, 'categoryTangibleHrs.category': elem._id },
+ { $inc: { 'categoryTangibleHrs.$.hrs': elem.timeSpent_hrs } },
+ { new: true },
);
if (!updateResult2) {
await userProfile.findOneAndUpdate(
{
_id: personId,
- "categoryTangibleHrs.category": { $ne: elem._id }
+ 'categoryTangibleHrs.category': { $ne: elem._id },
},
{
$addToSet: {
categoryTangibleHrs: {
category: elem._id,
- hrs: elem.timeSpent_hrs
- }
- }
- }
+ hrs: elem.timeSpent_hrs,
+ },
+ },
+ },
);
}
}
@@ -512,12 +504,11 @@ const userHelper = function () {
// processWeeklySummaries for nonActive users
try {
- const inactiveUsers = await userProfile.find({ isActive: false }, "_id");
+ const inactiveUsers = await userProfile.find({ isActive: false }, '_id');
for (let i = 0; i < inactiveUsers.length; i += 1) {
const user = inactiveUsers[i];
await processWeeklySummariesByUserId(mongoose.Types.ObjectId(user._id), false);
-
}
} catch (err) {
logger.logException(err);
@@ -527,52 +518,52 @@ const userHelper = function () {
const applyMissedHourForCoreTeam = async () => {
try {
const currentDate = moment()
- .tz("America/Los_Angeles")
+ .tz('America/Los_Angeles')
.format();
logger.logInfo(
- `Job for applying missed hours for Core Team members starting at ${currentDate}`
+ `Job for applying missed hours for Core Team members starting at ${currentDate}`,
);
const startOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .startOf("week")
- .subtract(1, "week")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .startOf('week')
+ .subtract(1, 'week')
+ .format('YYYY-MM-DD');
const endOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .endOf("week")
- .subtract(1, "week")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .endOf('week')
+ .subtract(1, 'week')
+ .format('YYYY-MM-DD');
const missedHours = await userProfile.aggregate([
{
$match: {
- role: "Core Team",
- isActive: true
- }
+ role: 'Core Team',
+ isActive: true,
+ },
},
{
$lookup: {
- from: "timeEntries",
- localField: "_id",
- foreignField: "personId",
+ from: 'timeEntries',
+ localField: '_id',
+ foreignField: 'personId',
pipeline: [
{
$match: {
$expr: {
$and: [
- { $eq: ["$isTangible", true] },
- { $gte: ["$dateOfWork", startOfLastWeek] },
- { $lte: ["$dateOfWork", endOfLastWeek] }
- ]
- }
- }
- }
+ { $eq: ['$isTangible', true] },
+ { $gte: ['$dateOfWork', startOfLastWeek] },
+ { $lte: ['$dateOfWork', endOfLastWeek] },
+ ],
+ },
+ },
+ },
],
- as: "timeEntries"
- }
+ as: 'timeEntries',
+ },
},
{
$project: {
@@ -591,31 +582,31 @@ const userHelper = function () {
{
$sum: {
$map: {
- input: "$timeEntries",
- in: "$$this.totalSeconds"
- }
- }
+ input: '$timeEntries',
+ in: '$$this.totalSeconds',
+ },
+ },
},
- 3600
- ]
- }
- ]
+ 3600,
+ ],
+ },
+ ],
},
- 0
- ]
- }
- }
- }
+ 0,
+ ],
+ },
+ },
+ },
]);
const bulkOps = [];
- missedHours.forEach(obj => {
+ missedHours.forEach((obj) => {
bulkOps.push({
updateOne: {
filter: { _id: obj._id },
- update: { missedHours: obj.missedHours }
- }
+ update: { missedHours: obj.missedHours },
+ },
});
});
@@ -627,16 +618,16 @@ const userHelper = function () {
const deleteBlueSquareAfterYear = async () => {
const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
+ .tz('America/Los_Angeles')
.format();
logger.logInfo(
- `Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`
+ `Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`,
);
const cutOffDate = moment()
- .subtract(1, "year")
- .format("YYYY-MM-DD");
+ .subtract(1, 'year')
+ .format('YYYY-MM-DD');
try {
const results = await userProfile.updateMany(
@@ -645,11 +636,11 @@ const userHelper = function () {
$pull: {
infringements: {
date: {
- $lte: cutOffDate
- }
- }
- }
- }
+ $lte: cutOffDate,
+ },
+ },
+ },
+ },
);
logger.logInfo(results);
@@ -660,17 +651,17 @@ const userHelper = function () {
const reActivateUser = async () => {
const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
+ .tz('America/Los_Angeles')
.format();
logger.logInfo(
- `Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`
+ `Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`,
);
try {
const users = await userProfile.find(
{ isActive: false, reactivationDate: { $exists: true } },
- "_id isActive reactivationDate"
+ '_id isActive reactivationDate',
);
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -679,18 +670,18 @@ const userHelper = function () {
user._id,
{
$set: {
- isActive: true
+ isActive: true,
},
$unset: {
- endDate: user.endDate
- }
+ endDate: user.endDate,
+ },
},
- { new: true }
+ { new: true },
);
logger.logInfo(
`User with id: ${user._id} was re-acticated at ${moment()
- .tz("America/Los_Angeles")
- .format()}.`
+ .tz('America/Los_Angeles')
+ .format()}.`,
);
const id = user._id;
const person = await userProfile.findById(id);
@@ -712,7 +703,6 @@ const userHelper = function () {
emailSender('onecommunityglobal@gmail.com', subject, emailBody, null, null);
-
}
}
} catch (err) {
@@ -722,7 +712,6 @@ const userHelper = function () {
const notifyInfringements = function (original, current, firstName, lastName, emailAddress) {
-
if (!current) return;
const newOriginal = original.toObject();
const newCurrent = current.toObject();
@@ -737,43 +726,43 @@ const userHelper = function () {
getInfringementEmailBody(firstName, lastName, element, totalInfringements),
null,
- "onecommunityglobal@gmail.com"
+ 'onecommunityglobal@gmail.com',
);
});
};
const replaceBadge = async function (personId, oldBadgeId, newBadgeId) {
userProfile.updateOne(
- { _id: personId, "badgeCollection.badge": oldBadgeId },
+ { _id: personId, 'badgeCollection.badge': oldBadgeId },
{
$set: {
- "badgeCollection.$.badge": newBadgeId,
- "badgeCollection.$.lastModified": Date.now().toString(),
- "badgeCollection.$.count": 1
- }
+ 'badgeCollection.$.badge': newBadgeId,
+ 'badgeCollection.$.lastModified': Date.now().toString(),
+ 'badgeCollection.$.count': 1,
+ },
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
- }
+ },
);
};
const increaseBadgeCount = async function (personId, badgeId) {
- console.log("Increase Badge Count", personId, badgeId);
+ console.log('Increase Badge Count', personId, badgeId);
userProfile.updateOne(
- { _id: personId, "badgeCollection.badge": badgeId },
+ { _id: personId, 'badgeCollection.badge': badgeId },
{
- $inc: { "badgeCollection.$.count": 1 },
- $set: { "badgeCollection.$.lastModified": Date.now().toString() },
- $push: { "badgeCollection.$.earnedDate": earnedDateBadge() }
+ $inc: { 'badgeCollection.$.count': 1 },
+ $set: { 'badgeCollection.$.lastModified': Date.now().toString() },
+ $push: { 'badgeCollection.$.earnedDate': earnedDateBadge() },
},
- err => {
+ (err) => {
if (err) {
console.log(err);
}
- }
+ },
);
};
@@ -781,7 +770,7 @@ const userHelper = function () {
personId,
badgeId,
count = 1,
- featured = false
+ featured = false,
) {
console.log('Adding Badge');
userProfile.findByIdAndUpdate(
@@ -793,11 +782,11 @@ const userHelper = function () {
},
},
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
- }
+ },
);
};
@@ -806,14 +795,14 @@ const userHelper = function () {
personId,
{
$pull: {
- badgeCollection: { badge: badgeId }
- }
+ badgeCollection: { badge: badgeId },
+ },
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
- }
+ },
);
};
@@ -822,18 +811,18 @@ const userHelper = function () {
removeDupBadge(personId, badgeId);
} else if (count) {
userProfile.updateOne(
- { _id: personId, "badgeCollection.badge": badgeId },
+ { _id: personId, 'badgeCollection.badge': badgeId },
{
$set: {
- "badgeCollection.$.count": count,
- "badgeCollection.$.lastModified": Date.now().toString()
- }
+ 'badgeCollection.$.count': count,
+ 'badgeCollection.$.lastModified': Date.now().toString(),
+ },
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
- }
+ },
);
}
};
@@ -841,7 +830,6 @@ const userHelper = function () {
// remove the last badge you earned on this streak(not including 1)
const removePrevHrBadge = async function (personId, user, badgeCollection, hrs, weeks) {
-
// Check each Streak Greater than One to check if it works
if (weeks < 3) {
return;
@@ -851,24 +839,24 @@ const userHelper = function () {
.aggregate([
{
$match: {
- type: "X Hours for X Week Streak",
+ type: 'X Hours for X Week Streak',
weeks: { $gt: 1, $lt: weeks },
- totalHrs: hrs
- }
+ totalHrs: hrs,
+ },
},
{ $sort: { weeks: -1, totalHrs: -1 } },
{
$group: {
- _id: "$weeks",
+ _id: '$weeks',
badges: {
- $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" }
- }
- }
- }
+ $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' },
+ },
+ },
+ },
])
- .then(results => {
- results.forEach(streak => {
- streak.badges.every(bdge => {
+ .then((results) => {
+ results.forEach((streak) => {
+ streak.badges.every((bdge) => {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
@@ -881,7 +869,7 @@ const userHelper = function () {
changeBadgeCount(
personId,
badgeCollection[i].badge._id,
- badgeCollection[i].badge.count - 1
+ badgeCollection[i].badge.count - 1,
);
removed = true;
return false;
@@ -903,7 +891,6 @@ const userHelper = function () {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (badgeOfType && badgeOfType.months > badgeCollection[i].badge.months) {
-
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
badgeOfType = badgeCollection[i].badge;
@@ -911,23 +898,21 @@ const userHelper = function () {
}
}
await badge
- .find({ type: "No Infringement Streak" })
+ .find({ type: 'No Infringement Streak' })
.sort({ months: -1 })
- .then(results => {
+ .then((results) => {
if (!Array.isArray(results) || !results.length) {
return;
}
- results.every(elem => {
+ results.every((elem) => {
// Cannot account for time paused yet
if (elem.months <= 12) {
-
if (moment().diff(moment(user.createdDate), 'months', true) >= elem.months) {
-
if (
- user.infringements.length === 0 ||
- Math.abs(
+ user.infringements.length === 0
+ || Math.abs(
moment().diff(
moment(user.infringements[user.infringements?.length - 1].date),
@@ -942,7 +927,7 @@ const userHelper = function () {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id)
+ mongoose.Types.ObjectId(elem._id),
);
}
return false;
@@ -952,12 +937,10 @@ const userHelper = function () {
}
}
} else if (user?.infringements?.length === 0) {
-
if (moment().diff(moment(user.createdDate), 'months', true) >= elem.months) {
-
if (
- user.oldInfringements.length === 0 ||
- Math.abs(
+ user.oldInfringements.length === 0
+ || Math.abs(
moment().diff(
moment(user.oldInfringements[user.oldInfringements?.length - 1].date),
@@ -973,7 +956,7 @@ const userHelper = function () {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id)
+ mongoose.Types.ObjectId(elem._id),
);
}
return false;
@@ -992,11 +975,11 @@ const userHelper = function () {
const checkMinHoursMultiple = async function (
personId,
user,
- badgeCollection
+ badgeCollection,
) {
const badgesOfType = badgeCollection
.map(obj => obj.badge)
- .filter(badge => badge.type === 'Minimum Hours Multiple')
+ .filter(badge => badge.type === 'Minimum Hours Multiple');
await badge
.find({ type: 'Minimum Hours Multiple' })
.sort({ multiple: -1 })
@@ -1009,49 +992,47 @@ const userHelper = function () {
const elem = results[i]; // making variable elem accessible for below code
if (
- user.lastWeekTangibleHrs / user.weeklycommittedHours >=
- elem.multiple
+ user.lastWeekTangibleHrs / user.weeklycommittedHours
+ >= elem.multiple
) {
const theBadge = badgesOfType.find(
- (badge) => badge._id.toString() === elem._id.toString()
+ badge => badge._id.toString() === elem._id.toString(),
);
return theBadge
? increaseBadgeCount(
personId,
- mongoose.Types.ObjectId(theBadge._id)
+ mongoose.Types.ObjectId(theBadge._id),
)
: addBadge(personId, mongoose.Types.ObjectId(elem._id));
}
}
- })
+ });
};
// 'Personal Max',
const checkPersonalMax = async function (personId, user, badgeCollection) {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === "Personal Max") {
+ if (badgeCollection[i].badge?.type === 'Personal Max') {
if (badgeOfType) {
removeDupBadge(personId, badgeOfType._id);
}
}
}
- await badge.findOne({ type: "Personal Max" }).then(results => {
+ await badge.findOne({ type: 'Personal Max' }).then((results) => {
if (
- user.lastWeekTangibleHrs &&
- user.lastWeekTangibleHrs >= 1 &&
- user.lastWeekTangibleHrs === user.personalBestMaxHrs
+ user.lastWeekTangibleHrs
+ && user.lastWeekTangibleHrs >= 1
+ && user.lastWeekTangibleHrs === user.personalBestMaxHrs
) {
if (badgeOfType) {
changeBadgeCount(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- user.personalBestMaxHrs
+ user.personalBestMaxHrs,
);
} else {
-
addBadge(personId, mongoose.Types.ObjectId(results._id), user.personalBestMaxHrs);
-
}
}
});
@@ -1071,22 +1052,21 @@ const userHelper = function () {
userProfile
.aggregate([
{ $match: { isActive: true } },
- { $group: { _id: 1, maxHours: { $max: "$lastWeekTangibleHrs" } } },
+ { $group: { _id: 1, maxHours: { $max: '$lastWeekTangibleHrs' } } },
])
.then((userResults) => {
if (badgeOfType.length > 1) {
removeDupBadge(user._id, badgeOfType[0]._id);
-
}
if (
- user.lastWeekTangibleHrs &&
- user.lastWeekTangibleHrs >= userResults[0].maxHours
+ user.lastWeekTangibleHrs
+ && user.lastWeekTangibleHrs >= userResults[0].maxHours
) {
if (badgeOfType.length) {
increaseBadgeCount(
personId,
- mongoose.Types.ObjectId(badgeOfType[0]._id)
+ mongoose.Types.ObjectId(badgeOfType[0]._id),
);
} else {
addBadge(personId, mongoose.Types.ObjectId(results._id));
@@ -1102,15 +1082,15 @@ const userHelper = function () {
// Handle Increasing the 1 week streak badges
const badgesOfType = [];
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === "X Hours for X Week Streak") {
+ if (badgeCollection[i].badge?.type === 'X Hours for X Week Streak') {
badgesOfType.push(badgeCollection[i].badge);
}
}
await badge
- .find({ type: "X Hours for X Week Streak", weeks: 1 })
+ .find({ type: 'X Hours for X Week Streak', weeks: 1 })
.sort({ totalHrs: -1 })
- .then(results => {
- results.every(elem => {
+ .then((results) => {
+ results.every((elem) => {
if (elem.totalHrs <= user.lastWeekTangibleHrs) {
let theBadge;
for (let i = 0; i < badgesOfType.length; i += 1) {
@@ -1132,21 +1112,21 @@ const userHelper = function () {
// Check each Streak Greater than One to check if it works
await badge
.aggregate([
- { $match: { type: "X Hours for X Week Streak", weeks: { $gt: 1 } } },
+ { $match: { type: 'X Hours for X Week Streak', weeks: { $gt: 1 } } },
{ $sort: { weeks: -1, totalHrs: -1 } },
{
$group: {
- _id: "$weeks",
+ _id: '$weeks',
badges: {
- $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" }
- }
- }
- }
+ $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' },
+ },
+ },
+ },
])
- .then(results => {
+ .then((results) => {
let lastHr = -1;
- results.forEach(streak => {
- streak.badges.every(bdge => {
+ results.forEach((streak) => {
+ streak.badges.every((bdge) => {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
@@ -1155,12 +1135,11 @@ const userHelper = function () {
&& badgeCollection[i].badge?.weeks === bdge.weeks
) {
if (badgeOfType && badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs) {
-
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType &&
- badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
+ badgeOfType
+ && badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -1185,7 +1164,7 @@ const userHelper = function () {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(bdge._id)
+ mongoose.Types.ObjectId(bdge._id),
);
removePrevHrBadge(personId, user, badgeCollection, bdge.hrs, bdge.weeks);
@@ -1196,12 +1175,11 @@ const userHelper = function () {
user,
badgeCollection,
bdge.hrs,
- bdge.weeks
+ bdge.weeks,
);
} else if (badgeOfType && badgeOfType.totalHrs === bdge.hrs) {
increaseBadgeCount(personId, mongoose.Types.ObjectId(badgeOfType._id));
removePrevHrBadge(personId, user, badgeCollection, bdge.hrs, bdge.weeks);
-
}
return false;
}
@@ -1222,8 +1200,8 @@ const userHelper = function () {
let teamMembers;
await getTeamMembers({
- _id: personId
- }).then(results => {
+ _id: personId,
+ }).then((results) => {
if (results) {
teamMembers = results.myteam;
} else {
@@ -1242,13 +1220,11 @@ const userHelper = function () {
});
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
-
if (badgeCollection[i].badge?.type === 'Lead a team of X+') {
if (badgeOfType && badgeOfType.people <= badgeCollection[i].badge.people) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (badgeOfType && badgeOfType.people > badgeCollection[i].badge.people) {
-
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
badgeOfType = badgeCollection[i].badge;
@@ -1256,9 +1232,9 @@ const userHelper = function () {
}
}
await badge
- .find({ type: "Lead a team of X+" })
+ .find({ type: 'Lead a team of X+' })
.sort({ people: -1 })
- .then(results => {
+ .then((results) => {
if (!Array.isArray(results) || !results.length) {
return;
}
@@ -1292,40 +1268,40 @@ const userHelper = function () {
const checkTotalHrsInCat = async function (personId, user, badgeCollection) {
const hoursByCategory = user.hoursByCategory || {};
const categories = [
- "food",
- "energy",
- "housing",
- "education",
- "society",
- "economics",
- "stewardship"
+ 'food',
+ 'energy',
+ 'housing',
+ 'education',
+ 'society',
+ 'economics',
+ 'stewardship',
];
const badgesOfType = badgeCollection
- .filter(object => object.badge.type === "Total Hrs in Category")
+ .filter(object => object.badge.type === 'Total Hrs in Category')
.map(object => object.badge);
- categories.forEach(async category => {
+ categories.forEach(async (category) => {
const categoryHrs = Object.keys(hoursByCategory).find(
- elem => elem === category
+ elem => elem === category,
);
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
- badgeCollection[i].badge?.type === "Total Hrs in Category" &&
- badgeCollection[i].badge?.category === category
+ badgeCollection[i].badge?.type === 'Total Hrs in Category'
+ && badgeCollection[i].badge?.category === category
) {
if (
- badgeOfType &&
- badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
+ badgeOfType
+ && badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType &&
- badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
+ badgeOfType
+ && badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -1340,15 +1316,15 @@ const userHelper = function () {
await badge.find({ type: 'Total Hrs in Category', category: newCatg })
.sort({ totalHrs: -1 })
- .then(results => {
+ .then((results) => {
if (!Array.isArray(results) || !results.length || !categoryHrs) {
return;
}
- results.every(elem => {
+ results.every((elem) => {
if (
- hoursByCategory[categoryHrs] >= 100 &&
- hoursByCategory[categoryHrs] >= elem.totalHrs
+ hoursByCategory[categoryHrs] >= 100
+ && hoursByCategory[categoryHrs] >= elem.totalHrs
) {
let theBadge;
for (let i = 0; i < badgesOfType.length; i += 1) {
@@ -1363,13 +1339,13 @@ const userHelper = function () {
}
if (badgeOfType) {
if (
- badgeOfType._id.toString() !== elem._id.toString() &&
- badgeOfType.totalHrs < elem.totalHrs
+ badgeOfType._id.toString() !== elem._id.toString()
+ && badgeOfType.totalHrs < elem.totalHrs
) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id)
+ mongoose.Types.ObjectId(elem._id),
);
}
return false;
@@ -1384,9 +1360,8 @@ const userHelper = function () {
};
const awardNewBadges = async () => {
- console.log("Awarding");
+ console.log('Awarding');
try {
-
const users = await userProfile.find({ isActive: true }).populate('badgeCollection.badge');
@@ -1419,14 +1394,14 @@ const userHelper = function () {
{
personId: userId,
dateOfWork: { $gte: pdtstart, $lte: pdtend },
- isTangible: true
+ isTangible: true,
},
- "totalSeconds"
+ 'totalSeconds',
)
- .then(results => {
+ .then((results) => {
const totalTangibleWeeklySeconds = results.reduce(
(acc, { totalSeconds }) => acc + totalSeconds,
- 0
+ 0,
);
return (totalTangibleWeeklySeconds / 3600).toFixed(2);
});
@@ -1436,19 +1411,19 @@ const userHelper = function () {
try {
const users = await userProfile.find(
{ isActive: true, endDate: { $exists: true } },
- "_id isActive endDate"
+ '_id isActive endDate',
);
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
const { endDate } = user;
endDate.setHours(endDate.getHours() + 7);
- if (moment().isAfter(moment(endDate).add(1, "days"))) {
+ if (moment().isAfter(moment(endDate).add(1, 'days'))) {
await userProfile.findByIdAndUpdate(
user._id,
user.set({
- isActive: false
+ isActive: false,
}),
- { new: true }
+ { new: true },
);
const id = user._id;
const person = await userProfile.findById(id);
@@ -1485,7 +1460,7 @@ const userHelper = function () {
} catch (error) {
logger.logException(err);
}
- }
+ };
return {
@@ -1502,7 +1477,7 @@ const userHelper = function () {
emailWeeklySummariesForAllUsers,
awardNewBadges,
getTangibleHoursReportedThisWeekByUserId,
- deleteExpiredTokens
+ deleteExpiredTokens,
};
};
diff --git a/src/models/badge.js b/src/models/badge.js
index 8b2c754e7..e3e93eaaf 100644
--- a/src/models/badge.js
+++ b/src/models/badge.js
@@ -19,7 +19,7 @@ const Badge = new Schema({
imageUrl: { type: String },
ranking: { type: Number },
description: { type: String },
- showReport: {type: Boolean},
+ showReport: { type: Boolean },
});
module.exports = mongoose.model('badge', Badge, 'badges');
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index e6153af45..8460ecd6e 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -29,12 +29,12 @@ const InventoryItemMaterial = new Schema({
poId: { type: String, required: true },
sellerId: { type: String, required: true },
quantity: { type: Number, required: true }, // adds to stockBought
- unitPrice: {type: Number, required: true},
+ unitPrice: { type: Number, required: true },
currency: { type: String, required: true },
subtotal: { type: Number, required: true },
tax: { type: Number, required: true },
shipping: { type: Number, required: true },
- }]
-})
+ }],
+});
module.exports = mongoose.model('inventoryItemMaterial', InventoryItemMaterial, 'inventoryMaterial');
diff --git a/src/models/inventoryItemType.js b/src/models/inventoryItemType.js
index 321038a84..b7b3ec46f 100644
--- a/src/models/inventoryItemType.js
+++ b/src/models/inventoryItemType.js
@@ -9,11 +9,9 @@ const InventoryItemType = new Schema({ // creates an item, tracks total amount i
uom: { type: String, required: true }, // unit of measurement
totalStock: { type: Number, required: true }, // total amount of all stock acquired
totalAvailable: { type: Number, required: true },
- projectsUsing: [ {type: mongoose.SchemaTypes.ObjectId, ref: 'project'} ],
+ projectsUsing: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'project' }],
imageUrl: { type: String },
- link: { type: String}
+ link: { type: String },
});
module.exports = mongoose.model('inventoryItemType', InventoryItemType, 'inventoryItemType');
-
-
diff --git a/src/models/profileInitialSetupToken.js b/src/models/profileInitialSetupToken.js
index 48413fb77..77b830229 100644
--- a/src/models/profileInitialSetupToken.js
+++ b/src/models/profileInitialSetupToken.js
@@ -10,7 +10,7 @@ const profileInitialSetupTokenSchema = new mongoose.Schema({
type: String,
required: true,
},
- weeklyCommittedHours : {
+ weeklyCommittedHours: {
type: Number,
required: true,
default: 10,
@@ -21,4 +21,4 @@ const profileInitialSetupTokenSchema = new mongoose.Schema({
},
});
-module.exports = mongoose.model('profileInitialSetupToken', profileInitialSetupTokenSchema, 'profileInitialSetupToken');
\ No newline at end of file
+module.exports = mongoose.model('profileInitialSetupToken', profileInitialSetupTokenSchema, 'profileInitialSetupToken');
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index a58d1d293..1a29ec3e0 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -7,7 +7,7 @@ const bcrypt = require('bcryptjs');
const SALT_ROUNDS = 10;
const nextDay = new Date();
-nextDay.setDate(nextDay.getDate()+1);
+nextDay.setDate(nextDay.getDate() + 1);
const userProfileSchema = new Schema({
password: {
@@ -153,7 +153,7 @@ const userProfileSchema = new Schema({
isVisible: { type: Boolean, default: false },
weeklySummaryOption: { type: String },
bioPosted: { type: String, default: 'default' },
- isFirstTimelog: { type: Boolean, default: true},
+ isFirstTimelog: { type: Boolean, default: true },
teamCode: { type: String, default: '' },
infoCollections: [
{
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index 0be779cd7..a0f8dfea6 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -11,6 +11,6 @@ materialsRouter.route('/addUpdateMaterialRecord')
.post(controller.bmPostMaterialUpdateRecord);
return materialsRouter;
-}
+};
-module.exports = routes;
\ No newline at end of file
+module.exports = routes;
diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js
index cec4b16e9..a171fc4cd 100644
--- a/src/routes/bmdashboard/bmProjectsRouter.js
+++ b/src/routes/bmdashboard/bmProjectsRouter.js
@@ -8,6 +8,6 @@ materialsRouter.route('/getUserActiveBMProjects')
.get(controller.getUserActiveBMProjects);
return materialsRouter;
-}
+};
-module.exports = routes;
\ No newline at end of file
+module.exports = routes;
diff --git a/src/routes/isEmailExistsRouter.js b/src/routes/isEmailExistsRouter.js
index cfb4e6033..d19b14fe2 100644
--- a/src/routes/isEmailExistsRouter.js
+++ b/src/routes/isEmailExistsRouter.js
@@ -2,14 +2,14 @@
const express = require('express');
const routes = function () {
- const controller = require('../controllers/isEmailExistsController')()
+ const controller = require('../controllers/isEmailExistsController')();
- const isEmailExistsRouter = express.Router()
+ const isEmailExistsRouter = express.Router();
- isEmailExistsRouter.route("/is-email-exists/:email")
- .get(controller.isEmailExists)
+ isEmailExistsRouter.route('/is-email-exists/:email')
+ .get(controller.isEmailExists);
- return isEmailExistsRouter
-}
+ return isEmailExistsRouter;
+};
-module.exports = routes
+module.exports = routes;
diff --git a/src/routes/profileInitialSetupRouter.js b/src/routes/profileInitialSetupRouter.js
index a23c6a868..2091afcad 100644
--- a/src/routes/profileInitialSetupRouter.js
+++ b/src/routes/profileInitialSetupRouter.js
@@ -5,9 +5,9 @@ const routes = function (ProfileInitialSetupToken, userProfile, Project) {
const controller = require('../controllers/profileInitialSetupController')(ProfileInitialSetupToken, userProfile, Project);
ProfileInitialSetup.route('/getInitialSetuptoken')
.post(controller.getSetupToken);
- ProfileInitialSetup.route('/ProfileInitialSetup').post(controller.setUpNewUser)
- ProfileInitialSetup.route('/validateToken').post(controller.validateSetupToken)
- ProfileInitialSetup.route('/getTimeZoneAPIKeyByToken').post(controller.getTimeZoneAPIKeyByToken)
+ ProfileInitialSetup.route('/ProfileInitialSetup').post(controller.setUpNewUser);
+ ProfileInitialSetup.route('/validateToken').post(controller.validateSetupToken);
+ ProfileInitialSetup.route('/getTimeZoneAPIKeyByToken').post(controller.getTimeZoneAPIKeyByToken);
return ProfileInitialSetup;
};
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 00d8a3fec..7208535d8 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -61,7 +61,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
-const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')()
+const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')();
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
From bd8f4de8a7ff455500408c608a32f81ddb4c79a3 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sun, 29 Oct 2023 14:49:00 -0700
Subject: [PATCH 093/272] make timer chime consistent over all tabs
---
src/models/timer.js | 1 +
src/websockets/TimerService/clientsHandler.js | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/src/models/timer.js b/src/models/timer.js
index 09c2f89da..f50921fb3 100644
--- a/src/models/timer.js
+++ b/src/models/timer.js
@@ -9,6 +9,7 @@ const timerSchema = new Schema({
time: { type: Number, default: 900000 },
goal: { type: Number, default: 900000 },
initialGoal: { type: Number, default: 900000 },
+ chiming: { type: Boolean, default: false },
paused: { type: Boolean, default: false },
forcedPause: { type: Boolean, default: false },
started: { type: Boolean, default: false },
diff --git a/src/websockets/TimerService/clientsHandler.js b/src/websockets/TimerService/clientsHandler.js
index 3bb2c358d..60eb33fa4 100644
--- a/src/websockets/TimerService/clientsHandler.js
+++ b/src/websockets/TimerService/clientsHandler.js
@@ -43,6 +43,7 @@ export const action = {
REMOVE_GOAL: 'REMOVE_FROM_GOAL=',
FORCED_PAUSE: 'FORCED_PAUSE',
ACK_FORCED: 'ACK_FORCED',
+ START_CHIME: 'START_CHIME',
};
const MAX_HOURS = 5;
@@ -69,11 +70,17 @@ const startTimer = (client) => {
const pauseTimer = (client, forced = false) => {
client.time = updatedTimeSinceStart(client);
+ if (client.time === 0) client.chiming = true;
client.startAt = moment.invalid(); // invalid can not be saved in database
client.paused = true;
if (forced) client.forcedPause = true;
};
+const startChime = (client, msg) => {
+ const state = msg.split('=')[1];
+ client.chiming = state === 'true';
+};
+
const ackForcedPause = (client) => {
client.forcedPause = false;
client.paused = true;
@@ -86,6 +93,7 @@ const stopTimer = (client) => {
client.started = false;
client.pause = false;
client.forcedPause = false;
+ if (client.chiming) client.chiming = false;
if (client.time === 0) {
client.goal = client.initialGoal;
client.time = client.goal;
@@ -97,6 +105,7 @@ const stopTimer = (client) => {
const clearTimer = (client) => {
stopTimer(client);
client.goal = client.initialGoal;
+ client.chiming = false;
client.time = client.goal;
};
@@ -175,6 +184,9 @@ export const handleMessage = async (msg, clients, userId) => {
case req.match(/REMOVE_FROM_GOAL=/i)?.input:
removeGoal(client, req);
break;
+ case req.match(/START_CHIME=/i)?.input:
+ startChime(client, req);
+ break;
case action.PAUSE_TIMER:
pauseTimer(client);
break;
From 64f6c4121012e4e10d01568e847a6172562a2512 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Tue, 31 Oct 2023 16:04:22 +0800
Subject: [PATCH 094/272] set default value for createdDatetime
---
src/models/team.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/models/team.js b/src/models/team.js
index 97f8dc360..00fbaf8e3 100644
--- a/src/models/team.js
+++ b/src/models/team.js
@@ -5,7 +5,7 @@ const { Schema } = mongoose;
const team = new Schema({
teamName: { type: 'String', required: true },
isActive: { type: 'Boolean', required: true, default: true },
- createdDatetime: { type: Date },
+ createdDatetime: { type: Date, default: Date.now() },
modifiedDatetime: { type: Date, default: Date.now() },
members: [
{
From 8036f37181e6f41b064d702357d542d0b90aac45 Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Tue, 31 Oct 2023 20:07:56 -0500
Subject: [PATCH 095/272] Tried to fix old approach
---
src/controllers/dashBoardController.js | 20 ++++++++++++++++++++
src/models/dashBoardData.js | 10 ++++++++++
src/routes/dashboardRouter.js | 4 ++++
src/startup/routes.js | 3 ++-
4 files changed, 36 insertions(+), 1 deletion(-)
create mode 100644 src/models/dashBoardData.js
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index c9cdbd588..3a203481f 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -3,6 +3,7 @@ const path = require("path");
const fs = require("fs/promises");
const dashboardhelper = require("../helpers/dashboardhelper")();
const emailSender = require("../utilities/emailSender");
+const DashboardData = require('../models/dashBoardData');
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -15,6 +16,23 @@ const dashboardcontroller = function () {
});
};
+ const updateDashboardData = function (req, res) {
+ if (req.body.requestor.role === 'Owner') {
+ DashboardData.findOneAndUpdate({ _id: 'ai-prompt' }, { ...req.body, aIPromptText: req.body.aIPromptText })
+ .then(() => {
+ res.status(200).send('Successfully saved AI prompt.');
+ }).catch(error => res.status(500).send(error));
+ }
+ };
+
+ const getDashBoardData = function (req, res) {
+ DashboardData.findById({ _id: 'ai-prompt' })
+ .then((results) => {
+ res.status(200).send(results);
+ })
+ .catch(error => res.status(500).send(error));
+ };
+
const monthlydata = function (req, res) {
const userId = mongoose.Types.ObjectId(req.params.userId);
const laborthismonth = dashboardhelper.laborthismonth(
@@ -247,6 +265,8 @@ const dashboardcontroller = function () {
return {
dashboarddata,
+ getDashBoardData,
+ updateDashboardData,
monthlydata,
weeklydata,
leaderboarddata,
diff --git a/src/models/dashBoardData.js b/src/models/dashBoardData.js
new file mode 100644
index 000000000..2ae3a5482
--- /dev/null
+++ b/src/models/dashBoardData.js
@@ -0,0 +1,10 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const DashboardData = new Schema({
+ _id: { type: mongoose.Schema.Types.String },
+ aIPromptText: { type: String },
+});
+
+module.exports = mongoose.model('dashboardData', DashboardData, 'dashboard');
diff --git a/src/routes/dashboardRouter.js b/src/routes/dashboardRouter.js
index 664c1c802..7b55fcb89 100644
--- a/src/routes/dashboardRouter.js
+++ b/src/routes/dashboardRouter.js
@@ -5,6 +5,10 @@ const route = function () {
const Dashboardrouter = express.Router();
+ Dashboardrouter.route('/dashboard/aiPrompt')
+ .get(controller.getDashBoardData)
+ .put(controller.updateDashboardData);
+
Dashboardrouter.route('/dashboard/:userId')
.get(controller.dashboarddata);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 2fd7337a6..41b63a5ec 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -18,6 +18,7 @@ const role = require('../models/role');
const rolePreset = require('../models/rolePreset');
const ownerMessage = require('../models/ownerMessage');
const ownerStandardMessage = require('../models/ownerStandardMessage');
+const dashboardData = require('../models/dashBoardData');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
@@ -25,7 +26,7 @@ const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
-const dashboardRouter = require('../routes/dashboardRouter')();
+const dashboardRouter = require('../routes/dashboardRouter')(dashboardData);
const timeEntryRouter = require('../routes/timeentryRouter')(timeEntry);
const projectRouter = require('../routes/projectRouter')(project);
const informationRouter = require('../routes/informationRouter')(information);
From 66c6c3c8d8d1f637efc7cb850b03f269149f428c Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 1 Nov 2023 09:22:24 -0700
Subject: [PATCH 096/272] add building project schema. update project summary
controller.
---
.../bmdashboard/bmProjectController.js | 27 ++++++++++++++++
.../bmdashboard/bmProjectsController.js | 31 -------------------
src/models/bmdashboard/buildingProject.js | 15 +++++++++
src/models/inventoryItemMaterial.js | 6 ++--
src/routes/bmdashboard/bmProjectRouter.js | 13 ++++++++
src/routes/bmdashboard/bmProjectsRouter.js | 13 --------
src/startup/routes.js | 6 ++--
7 files changed, 62 insertions(+), 49 deletions(-)
create mode 100644 src/controllers/bmdashboard/bmProjectController.js
delete mode 100644 src/controllers/bmdashboard/bmProjectsController.js
create mode 100644 src/models/bmdashboard/buildingProject.js
create mode 100644 src/routes/bmdashboard/bmProjectRouter.js
delete mode 100644 src/routes/bmdashboard/bmProjectsRouter.js
diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js
new file mode 100644
index 000000000..96f19ab60
--- /dev/null
+++ b/src/controllers/bmdashboard/bmProjectController.js
@@ -0,0 +1,27 @@
+const bmMProjectController = function (BuildingProject) {
+ const bmProjectSummary = async function _projSumm(req, res) {
+ try {
+ const projectData = await BuildingProject
+ .find()
+ .populate([
+ {
+ path: 'buildingManager',
+ select: '_id firstName lastName email',
+ },
+ {
+ path: 'team',
+ select: '_id firstName lastName email',
+ },
+ ])
+ .exec()
+ .then(result => result)
+ .catch(error => res.status(500).send(error));
+ res.status(200).send(projectData);
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return { bmProjectSummary };
+};
+
+module.exports = bmMProjectController;
diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js
deleted file mode 100644
index f80eea6c0..000000000
--- a/src/controllers/bmdashboard/bmProjectsController.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const mongoose = require('mongoose');
-
-const bmMProjectsController = function (UserProfile) {
- const bmProjectsSummary = async function _projSumm(req, res) {
- const { userId } = req.params;
- try {
- const projectData = await UserProfile
- // fetch user profile, return only projects array
- .findOne({ _id: userId }, { projects: 1 })
- // populate data with projects documents using the ObjectId in the projects array
- .populate({
- path: 'projects',
- // limit to projects with category value 'Housing'
- match: { category: 'Housing' },
- // returns only these fields
- select: '_id projectName isActive createdDatetime',
- })
- .exec()
- .then(result => result.projects)
- .catch(error => res.status(500).send(error));
-
- // for each project, find all materials in the project
- res.status(200).send(projectData);
- } catch (err) {
- res.json(err);
- }
- };
- return { bmProjectsSummary };
-};
-
-module.exports = bmMProjectsController;
diff --git a/src/models/bmdashboard/buildingProject.js b/src/models/bmdashboard/buildingProject.js
new file mode 100644
index 000000000..566bc124e
--- /dev/null
+++ b/src/models/bmdashboard/buildingProject.js
@@ -0,0 +1,15 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const buildingProject = new Schema({
+ isActive: Boolean,
+ name: String,
+ template: String, // construction template (ie Earthbag Village)
+ location: String, // use lat/lng instead?
+ dateCreated: { type: Date, default: Date.now },
+ buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }, // BM's id
+ team: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }],
+});
+
+module.exports = mongoose.model('buildingProject', buildingProject, 'buildingProjects');
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index e6153af45..8460ecd6e 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -29,12 +29,12 @@ const InventoryItemMaterial = new Schema({
poId: { type: String, required: true },
sellerId: { type: String, required: true },
quantity: { type: Number, required: true }, // adds to stockBought
- unitPrice: {type: Number, required: true},
+ unitPrice: { type: Number, required: true },
currency: { type: String, required: true },
subtotal: { type: Number, required: true },
tax: { type: Number, required: true },
shipping: { type: Number, required: true },
- }]
-})
+ }],
+});
module.exports = mongoose.model('inventoryItemMaterial', InventoryItemMaterial, 'inventoryMaterial');
diff --git a/src/routes/bmdashboard/bmProjectRouter.js b/src/routes/bmdashboard/bmProjectRouter.js
new file mode 100644
index 000000000..6bd535ae1
--- /dev/null
+++ b/src/routes/bmdashboard/bmProjectRouter.js
@@ -0,0 +1,13 @@
+const express = require('express');
+
+const routes = function (buildingProject) {
+ const projectRouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmProjectController')(buildingProject);
+
+projectRouter.route('/projects')
+ .get(controller.bmProjectSummary);
+
+ return projectRouter;
+};
+
+module.exports = routes;
diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js
deleted file mode 100644
index 05adfa59d..000000000
--- a/src/routes/bmdashboard/bmProjectsRouter.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const express = require('express');
-
-const routes = function (userProfile) {
- const projectsRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmProjectsController')(userProfile);
-
-projectsRouter.route('/projects/:userId')
- .get(controller.bmProjectsSummary);
-
- return projectsRouter;
-};
-
-module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index aa786dbbd..7f9446315 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -22,6 +22,8 @@ const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
+const buildingProject = require('../models/bmdashboard/buildingProject');
+
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -61,7 +63,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
-const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')(userProfile);
+const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -97,5 +99,5 @@ module.exports = function (app) {
// bm dashboard
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
- app.use('/api/bm', bmProjectsRouter);
+ app.use('/api/bm', bmProjectRouter);
};
From cf9d773e07f5d671e1b147af9a56c80ebaef15a2 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Wed, 1 Nov 2023 12:58:36 -0400
Subject: [PATCH 097/272] fix: moving part of logic from the frontend, bug
fixes feat: updating timezone
---
src/controllers/mapLocationsController.js | 88 ++++++++++++++---------
src/models/mapLocation.js | 15 ++--
2 files changed, 58 insertions(+), 45 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index f01666558..9fa214080 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,27 +1,32 @@
-const userProfile = require('../models/userProfile');
+const UserProfile = require('../models/userProfile');
const cache = require('../utilities/nodeCache')();
+
const mapLocationsController = function (MapLocation) {
- const getAllLocations = function (req, res) {
- const priorText = 'Prior to HGN Data Collection';
- MapLocation.find({})
- .then(results => {
- const users = results.map(item => {
- return ({
- title: priorText,
- firstName: item.firstName !== priorText ? item.firstName : '',
- lastName: item.lastName !== priorText ? item.lastName : '',
- jobTitle: item.jobTitle !== priorText ? item.jobTitle : '',
- location: item.location,
- isActive: item.isActive,
- _id: item._id
- })
- })
- res.send(users).status(200);
-
- })
- .catch(error =>
- res.send(error).status(404));
+ const getAllLocations = async function (req, res) {
+
+ try {
+ const users = [];
+ const results = await UserProfile.find({},
+ '_id firstName lastName isActive location jobTitle totalTangibleHrs hoursByCategory'
+ );
+
+ results.forEach((item) => {
+ if (
+ (item.location?.coords.lat && item.location?.coords.lng && item.totalTangibleHrs >= 10) ||
+ (item.location?.coords.lat && item.location?.coords.lng && calculateTotalHours(item.hoursByCategory) >= 10)
+ ) {
+ users.push(item);
+ }
+ });
+
+ const m_users = await MapLocation.find({});
+
+ res.status(200).send({ users, m_users });
+ } catch (err) {
+ res.status(404).send(err);
+ }
+
};
const deleteLocation = async function (req, res) {
@@ -37,7 +42,7 @@ const mapLocationsController = function (MapLocation) {
};
const putUserLocation = async function (req, res) {
- if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ if (!req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
@@ -61,32 +66,36 @@ const mapLocationsController = function (MapLocation) {
}
};
const updateUserLocation = async function (req, res) {
- console.log(req.body)
- if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ if (!req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
const userType = req.body.type;
- const userId= req.body._id;
+ const userId = req.body._id;
const updateData = {
- firstName: req.body.firstName,
- lastName: req.body.lastName,
- jobTitle: req.body.jobTitle,
- location: req.body.location,
- _id: req.body._id
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ }
+
+ if (req.body.timeZone) {
+ updateData.timeZone = req.body.timeZone
}
try {
let response;
- if(userType === 'user') {
- response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ if (userType === 'user') {
+ console.log('updateData----', updateData);
+ response = await UserProfile.findOneAndUpdate({ _id: userId }, { $set: { ...updateData, jobTitle: [updateData.jobTitle] } }, { new: true });
cache.removeCache('allusers')
cache.removeCache(`user-${userId}`);
+
cache.setCache(`user-${userId}`, JSON.stringify(response));
} else {
- response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, { $set: updateData }, { new: true })
}
-
+
if (!response) {
throw new Error('Something went wrong during saving the location...')
}
@@ -98,13 +107,22 @@ const mapLocationsController = function (MapLocation) {
_id: response._id,
type: userType
}
-
+
res.status(200).send(newData);
} catch (err) {
console.log(err.message)
res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
+
+ function calculateTotalHours(hoursByCategory) {
+ let hours = 0;
+ Object.keys(hoursByCategory).forEach((x) => {
+ hours += hoursByCategory[x];
+ });
+ return hours;
+ }
+
return {
getAllLocations,
deleteLocation,
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
index 65415239f..851587dc3 100644
--- a/src/models/mapLocation.js
+++ b/src/models/mapLocation.js
@@ -3,18 +3,13 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
const mapLocation = new Schema({
- firstName: {
+ title: {
type: String,
- default: 'Prior to HGN Data Collection',
- },
- lastName: {
- type: String,
- default: 'Prior to HGN Data Collection',
- },
- jobTitle: {
- type: String,
- default: 'Prior to HGN Data Collection',
+ default: 'Prior to HGN Data Collection'
},
+ firstName: String,
+ lastName: String,
+ jobTitle: String,
isActive: {
type: Boolean,
default: false,
From 37942f92fa5b215e3d6cead862b455cfc2384087 Mon Sep 17 00:00:00 2001
From: leonzh2k
Date: Thu, 6 Jul 2023 17:55:26 -0400
Subject: [PATCH 098/272] add new fields to send in UserProfileController
Add jobTitle and location fields to the userProfile objects
that are sent back to the client when requesting all userProfiles.
These two bits of info are displayed on the interactive map.
---
src/controllers/userProfileController.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 6dc571b39..b9b3bb8a0 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -57,9 +57,15 @@ const userProfileController = function (UserProfile) {
return;
}
+ if (cache.getCache('allusers')) {
+ const getData = JSON.parse(cache.getCache('allusers'));
+ res.status(200).send(getData);
+ return;
+ }
+
UserProfile.find(
{},
- "_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate"
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate',
)
.sort({
lastName: 1,
From f63e1e8c19ebef62acfd09d63510911fe32eec4e Mon Sep 17 00:00:00 2001
From: xaanders
Date: Thu, 14 Sep 2023 16:40:41 -0400
Subject: [PATCH 099/272] feat: adding location object to user profile schema
---
src/models/userProfile.js | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index a58d1d293..fc0787e57 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -7,7 +7,7 @@ const bcrypt = require('bcryptjs');
const SALT_ROUNDS = 10;
const nextDay = new Date();
-nextDay.setDate(nextDay.getDate()+1);
+nextDay.setDate(nextDay.getDate() + 1);
const userProfileSchema = new Schema({
password: {
@@ -81,7 +81,16 @@ const userProfileSchema = new Schema({
infringements: [
{ date: { type: String, required: true }, description: { type: String, required: true } },
],
- location: { type: String, default: '' },
+ location: {
+ userProvided: { type: String, default: '' },
+ coords: {
+ lat: { type: Number, default: '' },
+ lng: { type: Number, default: '' },
+ },
+ country: { type: String, default: '' },
+ city: { type: String, default: '' }
+
+ },
oldInfringements: [
{ date: { type: String, required: true }, description: { type: String, required: true } },
],
@@ -157,9 +166,9 @@ const userProfileSchema = new Schema({
teamCode: { type: String, default: '' },
infoCollections: [
{
- areaName: { type: String },
+ areaName: { type: String },
areaContent: { type: String },
- }],
+ }],
});
userProfileSchema.pre('save', function (next) {
From 61a4357cc1704455f26e8d4db1a475c06fb240a1 Mon Sep 17 00:00:00 2001
From: xaanders
Date: Sat, 16 Sep 2023 12:02:02 -0400
Subject: [PATCH 100/272] fix: editing email message after new user creating
---
src/controllers/profileInitialSetupController.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 18cf7376c..b4230f1a4 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -67,7 +67,7 @@ function informManagerMessage(user) {
Location: |
- ${user.location} |
+ ${user.location.userProvided}, ${user.location.country} |
From 2e4a2afe95deb0a8cc75dc731baf45836a1a9a3d Mon Sep 17 00:00:00 2001
From: xaanders
Date: Fri, 22 Sep 2023 19:58:43 -0400
Subject: [PATCH 101/272] feat: adding a initial functionality for adding new
people to the map(maplocation controller, maplocation router, maplocation
model)
---
src/controllers/mapLocationsController.js | 69 +++++++++++++++++++++++
src/models/mapLocation.js | 42 ++++++++++++++
src/routes/mapLocationsRouter.js | 18 ++++++
src/startup/routes.js | 4 ++
4 files changed, 133 insertions(+)
create mode 100644 src/controllers/mapLocationsController.js
create mode 100644 src/models/mapLocation.js
create mode 100644 src/routes/mapLocationsRouter.js
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
new file mode 100644
index 000000000..83526998d
--- /dev/null
+++ b/src/controllers/mapLocationsController.js
@@ -0,0 +1,69 @@
+const mongoose = require('mongoose');
+const mapLocation = require('../models/mapLocation');
+const { hasPermission } = require('../utilities/permissions');
+
+const mapLocationsController = function () {
+ const getAllLocations = function (req, res) {
+ console.log('controller:')
+ console.log(req.body)
+
+ mapLocation.find({})
+ .then(results => res.send(results).status(200))
+ .catch(error => res.send(error).status(404));
+ };
+ const deleteLocation = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'deleteTeam')) {
+ res.status(403).send({ error: 'You are not authorized to delete teams.' });
+ return;
+ }
+ const { teamId } = req.params;
+ Team.findById(teamId, (error, record) => {
+ if (error || record === null) {
+ res.status(400).send({ error: 'No valid records found' });
+ return;
+ }
+ const removeteamfromprofile = userProfile.updateMany({}, { $pull: { teams: record._id } }).exec();
+ const deleteteam = record.remove();
+
+ Promise.all([removeteamfromprofile, deleteteam])
+ .then(res.status(200).send({ message: ' Team successfully deleted and user profiles updated' }))
+ .catch((errors) => {
+ res.status(400).send(errors);
+ });
+ }).catch((error) => {
+ res.status(400).send(error);
+ });
+ };
+ const putUserLocation = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'putTeam')) {
+ res.status(403).send('You are not authorized to make changes in the teams.');
+ return;
+ }
+
+ const { teamId } = req.params;
+
+ Team.findById(teamId, (error, record) => {
+ if (error || record === null) {
+ res.status(400).send('No valid records found');
+ return;
+ }
+ record.teamName = req.body.teamName;
+ record.isActive = req.body.isActive;
+ record.createdDatetime = Date.now();
+ record.modifiedDatetime = Date.now();
+
+ record
+ .save()
+ .then(results => res.status(201).send(results._id))
+ .catch(errors => res.status(400).send(errors));
+ });
+ };
+
+ return {
+ getAllLocations,
+ deleteLocation,
+ putUserLocation
+ };
+};
+
+module.exports = mapLocationsController;
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
new file mode 100644
index 000000000..d7b9d82b5
--- /dev/null
+++ b/src/models/mapLocation.js
@@ -0,0 +1,42 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const mapLocation = new Schema({
+ firstName: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ lastName: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ title: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ userProvided: {
+ type: String,
+ required: true,
+ },
+ coords: {
+ lat: {
+ type: String,
+ required: true,
+ },
+ lng: {
+ type: String,
+ required: true,
+ }
+ },
+ country: {
+ type: String,
+ required: true,
+ },
+ city: {
+ type: String,
+ default: '',
+ }
+});
+
+module.exports = mongoose.model('MapLocation', mapLocation, 'maplocations');
diff --git a/src/routes/mapLocationsRouter.js b/src/routes/mapLocationsRouter.js
new file mode 100644
index 000000000..e2e780dac
--- /dev/null
+++ b/src/routes/mapLocationsRouter.js
@@ -0,0 +1,18 @@
+const express = require('express');
+
+const router = function (mapLocations) {
+ const controller = require('../controllers/mapLocationsController')(mapLocations);
+
+ const mapRouter = express.Router();
+
+ mapRouter.route('/mapLocations')
+ .get(controller.getAllLocations)
+ .put(controller.putUserLocation);
+
+ mapRouter.route('/mapLocations/:locationId')
+ .delete(controller.deleteLocation)
+
+ return mapRouter;
+};
+
+module.exports = router;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index eae746e24..0f4c7308c 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -21,6 +21,7 @@ const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
+const mapLocations = require('../models/mapLocation');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -56,6 +57,8 @@ const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter
const reasonRouter = require('../routes/reasonRouter')(reason, userProfile);
const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverText);
+const mapLocationRouter = require('../routes/mapLocationsRouter')(mapLocations);
+
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
@@ -90,6 +93,7 @@ module.exports = function (app) {
app.use('/api', informationRouter);
app.use('/api', mouseoverTextRouter);
app.use('/api', isEmailExistsRouter);
+ app.use('/api', mapLocationRouter);
// bm dashboard
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
From fb1841d56ccc85322ba724465a7e3ab4f889d315 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Mon, 2 Oct 2023 16:13:42 -0400
Subject: [PATCH 102/272] fix: jobTitle model key, feat: adding isActive
status, getting all locations, put new location to a collection
---
src/controllers/mapLocationsController.js | 72 +++++++++--------------
src/models/mapLocation.js | 38 +++++++-----
2 files changed, 49 insertions(+), 61 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 83526998d..6088de489 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,62 +1,44 @@
-const mongoose = require('mongoose');
-const mapLocation = require('../models/mapLocation');
-const { hasPermission } = require('../utilities/permissions');
-
-const mapLocationsController = function () {
+const mapLocationsController = function (mapLocation) {
const getAllLocations = function (req, res) {
- console.log('controller:')
- console.log(req.body)
mapLocation.find({})
- .then(results => res.send(results).status(200))
- .catch(error => res.send(error).status(404));
+ .then(results =>
+ res.send(results).status(200)
+ )
+ .catch(error =>
+ res.send(error).status(404));
};
const deleteLocation = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteTeam')) {
- res.status(403).send({ error: 'You are not authorized to delete teams.' });
+
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
- const { teamId } = req.params;
- Team.findById(teamId, (error, record) => {
- if (error || record === null) {
- res.status(400).send({ error: 'No valid records found' });
- return;
- }
- const removeteamfromprofile = userProfile.updateMany({}, { $pull: { teams: record._id } }).exec();
- const deleteteam = record.remove();
-
- Promise.all([removeteamfromprofile, deleteteam])
- .then(res.status(200).send({ message: ' Team successfully deleted and user profiles updated' }))
- .catch((errors) => {
- res.status(400).send(errors);
- });
- }).catch((error) => {
- res.status(400).send(error);
- });
};
const putUserLocation = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putTeam')) {
+
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
+ const locationData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ }
+ const location = new mapLocation(locationData);
- const { teamId } = req.params;
-
- Team.findById(teamId, (error, record) => {
- if (error || record === null) {
- res.status(400).send('No valid records found');
- return;
+ try {
+ const response = await location.save()
+ if(!response) {
+ throw new Error('Something went wrong during saving the location...')
}
- record.teamName = req.body.teamName;
- record.isActive = req.body.isActive;
- record.createdDatetime = Date.now();
- record.modifiedDatetime = Date.now();
-
- record
- .save()
- .then(results => res.status(201).send(results._id))
- .catch(errors => res.status(400).send(errors));
- });
+ res.status(200).send(response);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({message: err.message || 'Something went wrong...'});
+ }
};
return {
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
index d7b9d82b5..65415239f 100644
--- a/src/models/mapLocation.js
+++ b/src/models/mapLocation.js
@@ -11,32 +11,38 @@ const mapLocation = new Schema({
type: String,
default: 'Prior to HGN Data Collection',
},
- title: {
+ jobTitle: {
type: String,
default: 'Prior to HGN Data Collection',
},
- userProvided: {
- type: String,
- required: true,
+ isActive: {
+ type: Boolean,
+ default: false,
},
- coords: {
- lat: {
+ location: {
+ userProvided: {
type: String,
required: true,
},
- lng: {
+ coords: {
+ lat: {
+ type: String,
+ required: true,
+ },
+ lng: {
+ type: String,
+ required: true,
+ }
+ },
+ country: {
type: String,
required: true,
- }
- },
- country: {
- type: String,
- required: true,
+ },
+ city: {
+ type: String,
+ default: '',
+ },
},
- city: {
- type: String,
- default: '',
- }
});
module.exports = mongoose.model('MapLocation', mapLocation, 'maplocations');
From f2a6e41f321eb7e16aa9e75fc1d2f51039ab9adc Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Sun, 15 Oct 2023 12:06:40 -0400
Subject: [PATCH 103/272] feat: userprofiles sending totalTangibleHrs, update
user controller, all manually locations response structure
---
src/controllers/mapLocationsController.js | 85 ++++++++++++++++++++---
src/routes/mapLocationsRouter.js | 3 +-
2 files changed, 77 insertions(+), 11 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 6088de489..f01666558 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,11 +1,26 @@
-const mapLocationsController = function (mapLocation) {
+const userProfile = require('../models/userProfile');
+const cache = require('../utilities/nodeCache')();
+
+const mapLocationsController = function (MapLocation) {
const getAllLocations = function (req, res) {
+ const priorText = 'Prior to HGN Data Collection';
+ MapLocation.find({})
+ .then(results => {
+ const users = results.map(item => {
+ return ({
+ title: priorText,
+ firstName: item.firstName !== priorText ? item.firstName : '',
+ lastName: item.lastName !== priorText ? item.lastName : '',
+ jobTitle: item.jobTitle !== priorText ? item.jobTitle : '',
+ location: item.location,
+ isActive: item.isActive,
+ _id: item._id
+ })
+ })
+ res.send(users).status(200);
- mapLocation.find({})
- .then(results =>
- res.send(results).status(200)
- )
- .catch(error =>
+ })
+ .catch(error =>
res.send(error).status(404));
};
const deleteLocation = async function (req, res) {
@@ -14,6 +29,11 @@ const mapLocationsController = function (mapLocation) {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
+ const locationId = req.params.locationId
+
+ MapLocation.findOneAndDelete({ _id: locationId })
+ .then(() => res.status(200).send({ message: "The location was successfully removed!" }))
+ .catch(error => res.status(500).send({ message: error || "Couldn't remove the location" }));
};
const putUserLocation = async function (req, res) {
@@ -27,24 +47,69 @@ const mapLocationsController = function (mapLocation) {
jobTitle: req.body.jobTitle,
location: req.body.location,
}
- const location = new mapLocation(locationData);
+ const location = new MapLocation(locationData);
try {
const response = await location.save()
- if(!response) {
+ if (!response) {
throw new Error('Something went wrong during saving the location...')
}
res.status(200).send(response);
} catch (err) {
console.log(err.message)
- res.status(500).json({message: err.message || 'Something went wrong...'});
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
+ const updateUserLocation = async function (req, res) {
+ console.log(req.body)
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ res.status(403).send('You are not authorized to make changes in the teams.');
+ return;
+ }
+ const userType = req.body.type;
+ const userId= req.body._id;
+ const updateData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ _id: req.body._id
+ }
+ try {
+ let response;
+ if(userType === 'user') {
+ response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ cache.removeCache('allusers')
+ cache.removeCache(`user-${userId}`);
+ cache.setCache(`user-${userId}`, JSON.stringify(response));
+ } else {
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ }
+
+ if (!response) {
+ throw new Error('Something went wrong during saving the location...')
+ }
+ const newData = {
+ firstName: response.firstName,
+ lastName: response.lastName,
+ jobTitle: response.jobTitle,
+ location: response.location,
+ _id: response._id,
+ type: userType
+ }
+
+ res.status(200).send(newData);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
+ }
+ };
return {
getAllLocations,
deleteLocation,
- putUserLocation
+ putUserLocation,
+ updateUserLocation
};
};
diff --git a/src/routes/mapLocationsRouter.js b/src/routes/mapLocationsRouter.js
index e2e780dac..db004ff18 100644
--- a/src/routes/mapLocationsRouter.js
+++ b/src/routes/mapLocationsRouter.js
@@ -7,7 +7,8 @@ const router = function (mapLocations) {
mapRouter.route('/mapLocations')
.get(controller.getAllLocations)
- .put(controller.putUserLocation);
+ .put(controller.putUserLocation)
+ .patch(controller.updateUserLocation);
mapRouter.route('/mapLocations/:locationId')
.delete(controller.deleteLocation)
From f556211d1ed6d46711eda0b89ef1d603d0ee0731 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Wed, 1 Nov 2023 12:58:36 -0400
Subject: [PATCH 104/272] fix: moving part of logic from the frontend, bug
fixes feat: updating timezone
---
src/controllers/mapLocationsController.js | 88 ++++++++++++++---------
src/models/mapLocation.js | 15 ++--
2 files changed, 58 insertions(+), 45 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index f01666558..9fa214080 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,27 +1,32 @@
-const userProfile = require('../models/userProfile');
+const UserProfile = require('../models/userProfile');
const cache = require('../utilities/nodeCache')();
+
const mapLocationsController = function (MapLocation) {
- const getAllLocations = function (req, res) {
- const priorText = 'Prior to HGN Data Collection';
- MapLocation.find({})
- .then(results => {
- const users = results.map(item => {
- return ({
- title: priorText,
- firstName: item.firstName !== priorText ? item.firstName : '',
- lastName: item.lastName !== priorText ? item.lastName : '',
- jobTitle: item.jobTitle !== priorText ? item.jobTitle : '',
- location: item.location,
- isActive: item.isActive,
- _id: item._id
- })
- })
- res.send(users).status(200);
-
- })
- .catch(error =>
- res.send(error).status(404));
+ const getAllLocations = async function (req, res) {
+
+ try {
+ const users = [];
+ const results = await UserProfile.find({},
+ '_id firstName lastName isActive location jobTitle totalTangibleHrs hoursByCategory'
+ );
+
+ results.forEach((item) => {
+ if (
+ (item.location?.coords.lat && item.location?.coords.lng && item.totalTangibleHrs >= 10) ||
+ (item.location?.coords.lat && item.location?.coords.lng && calculateTotalHours(item.hoursByCategory) >= 10)
+ ) {
+ users.push(item);
+ }
+ });
+
+ const m_users = await MapLocation.find({});
+
+ res.status(200).send({ users, m_users });
+ } catch (err) {
+ res.status(404).send(err);
+ }
+
};
const deleteLocation = async function (req, res) {
@@ -37,7 +42,7 @@ const mapLocationsController = function (MapLocation) {
};
const putUserLocation = async function (req, res) {
- if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ if (!req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
@@ -61,32 +66,36 @@ const mapLocationsController = function (MapLocation) {
}
};
const updateUserLocation = async function (req, res) {
- console.log(req.body)
- if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ if (!req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
const userType = req.body.type;
- const userId= req.body._id;
+ const userId = req.body._id;
const updateData = {
- firstName: req.body.firstName,
- lastName: req.body.lastName,
- jobTitle: req.body.jobTitle,
- location: req.body.location,
- _id: req.body._id
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ }
+
+ if (req.body.timeZone) {
+ updateData.timeZone = req.body.timeZone
}
try {
let response;
- if(userType === 'user') {
- response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ if (userType === 'user') {
+ console.log('updateData----', updateData);
+ response = await UserProfile.findOneAndUpdate({ _id: userId }, { $set: { ...updateData, jobTitle: [updateData.jobTitle] } }, { new: true });
cache.removeCache('allusers')
cache.removeCache(`user-${userId}`);
+
cache.setCache(`user-${userId}`, JSON.stringify(response));
} else {
- response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, { $set: updateData }, { new: true })
}
-
+
if (!response) {
throw new Error('Something went wrong during saving the location...')
}
@@ -98,13 +107,22 @@ const mapLocationsController = function (MapLocation) {
_id: response._id,
type: userType
}
-
+
res.status(200).send(newData);
} catch (err) {
console.log(err.message)
res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
+
+ function calculateTotalHours(hoursByCategory) {
+ let hours = 0;
+ Object.keys(hoursByCategory).forEach((x) => {
+ hours += hoursByCategory[x];
+ });
+ return hours;
+ }
+
return {
getAllLocations,
deleteLocation,
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
index 65415239f..851587dc3 100644
--- a/src/models/mapLocation.js
+++ b/src/models/mapLocation.js
@@ -3,18 +3,13 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
const mapLocation = new Schema({
- firstName: {
+ title: {
type: String,
- default: 'Prior to HGN Data Collection',
- },
- lastName: {
- type: String,
- default: 'Prior to HGN Data Collection',
- },
- jobTitle: {
- type: String,
- default: 'Prior to HGN Data Collection',
+ default: 'Prior to HGN Data Collection'
},
+ firstName: String,
+ lastName: String,
+ jobTitle: String,
isActive: {
type: Boolean,
default: false,
From 883a00b2107ccf81441b78b6122f54f6dd61c3b0 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Thu, 2 Nov 2023 10:21:10 -0400
Subject: [PATCH 105/272] fix: modifying users before sent
---
src/controllers/mapLocationsController.js | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 9fa214080..c9edd53b8 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -19,10 +19,17 @@ const mapLocationsController = function (MapLocation) {
users.push(item);
}
});
-
- const m_users = await MapLocation.find({});
-
- res.status(200).send({ users, m_users });
+ const modifiedUsers = users.map(item => ({
+ location: item.location,
+ isActive: item.isActive,
+ jobTitle: item.jobTitle[0],
+ _id: item._id,
+ firstName: item.firstName,
+ lastName: item.lastName
+ }));
+
+ const mUsers = await MapLocation.find({});
+ res.status(200).send({ users: modifiedUsers, mUsers });
} catch (err) {
res.status(404).send(err);
}
@@ -86,7 +93,6 @@ const mapLocationsController = function (MapLocation) {
try {
let response;
if (userType === 'user') {
- console.log('updateData----', updateData);
response = await UserProfile.findOneAndUpdate({ _id: userId }, { $set: { ...updateData, jobTitle: [updateData.jobTitle] } }, { new: true });
cache.removeCache('allusers')
cache.removeCache(`user-${userId}`);
From e5380d28843c933ce203902b30da1bde6f8d53a9 Mon Sep 17 00:00:00 2001
From: leonzh2k
Date: Thu, 6 Jul 2023 17:55:26 -0400
Subject: [PATCH 106/272] add new fields to send in UserProfileController
Add jobTitle and location fields to the userProfile objects
that are sent back to the client when requesting all userProfiles.
These two bits of info are displayed on the interactive map.
---
src/controllers/userProfileController.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index b9b3bb8a0..b0ff9eeee 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -65,7 +65,7 @@ const userProfileController = function (UserProfile) {
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate',
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
)
.sort({
lastName: 1,
From 632ef2007b53650b57d3ff6e06e694d6be8a7879 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Sun, 15 Oct 2023 12:06:40 -0400
Subject: [PATCH 107/272] feat: userprofiles sending totalTangibleHrs, update
user controller, all manually locations response structure
---
src/controllers/mapLocationsController.js | 29 +++++++++++++++++++++++
src/controllers/userProfileController.js | 2 +-
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index c9edd53b8..97ae88b09 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -129,6 +129,35 @@ const mapLocationsController = function (MapLocation) {
return hours;
}
+ try {
+ let response;
+ if(userType === 'user') {
+ response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ cache.removeCache('allusers')
+ cache.removeCache(`user-${userId}`);
+ cache.setCache(`user-${userId}`, JSON.stringify(response));
+ } else {
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ }
+
+ if (!response) {
+ throw new Error('Something went wrong during saving the location...')
+ }
+ const newData = {
+ firstName: response.firstName,
+ lastName: response.lastName,
+ jobTitle: response.jobTitle,
+ location: response.location,
+ _id: response._id,
+ type: userType
+ }
+
+ res.status(200).send(newData);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
+ }
+ };
return {
getAllLocations,
deleteLocation,
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index b0ff9eeee..d91b08739 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -65,7 +65,7 @@ const userProfileController = function (UserProfile) {
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle totalTangibleHrs',
)
.sort({
lastName: 1,
From f7b7d125361fe3e910b3cf6e45aea1c3a315f558 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Wed, 1 Nov 2023 12:58:36 -0400
Subject: [PATCH 108/272] fix: moving part of logic from the frontend, bug
fixes feat: updating timezone
---
src/controllers/mapLocationsController.js | 31 +----------------------
1 file changed, 1 insertion(+), 30 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 97ae88b09..29af9e3d6 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -128,36 +128,7 @@ const mapLocationsController = function (MapLocation) {
});
return hours;
}
-
- try {
- let response;
- if(userType === 'user') {
- response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
- cache.removeCache('allusers')
- cache.removeCache(`user-${userId}`);
- cache.setCache(`user-${userId}`, JSON.stringify(response));
- } else {
- response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
- }
-
- if (!response) {
- throw new Error('Something went wrong during saving the location...')
- }
- const newData = {
- firstName: response.firstName,
- lastName: response.lastName,
- jobTitle: response.jobTitle,
- location: response.location,
- _id: response._id,
- type: userType
- }
-
- res.status(200).send(newData);
- } catch (err) {
- console.log(err.message)
- res.status(500).json({ message: err.message || 'Something went wrong...' });
- }
- };
+
return {
getAllLocations,
deleteLocation,
From e7f23406597cc7ef13df73ea490d32f31d8d0e4b Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Thu, 2 Nov 2023 13:10:56 -0400
Subject: [PATCH 109/272] rebasing and resolving conflicts
---
src/controllers/userProfileController.js | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index d91b08739..6dc571b39 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -57,15 +57,9 @@ const userProfileController = function (UserProfile) {
return;
}
- if (cache.getCache('allusers')) {
- const getData = JSON.parse(cache.getCache('allusers'));
- res.status(200).send(getData);
- return;
- }
-
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle totalTangibleHrs',
+ "_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate"
)
.sort({
lastName: 1,
From 26e5f806ddc67af1d8dafdbe684fe6c4ee080ecf Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Thu, 2 Nov 2023 11:30:39 -0700
Subject: [PATCH 110/272] update material 1 api
---
.../bmdashboard/bmMaterialsController.js | 35 +++++++++++--------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 09fa91ab8..54ec65967 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -44,23 +44,30 @@ const bmMaterialsController = function (ItemMaterial) {
};
const bmPostMaterialUpdateRecord = function (req, res) {
- console.log(req.body);
- ItemMaterial.update(
+
+ let quantityUsed = +req.body.quantityUsed;
+ let quantityWasted = +req.body.quantityWasted;
+ let material = req.body.material;
+ if(req.body.QtyUsedLogUnit=='percent' && quantityWasted>=0)
+ {
+ quantityUsed = (+quantityUsed / 100) * material.stockAvailable;
+ }
+ if(req.body.QtyWastedLogUnit=='percent' && quantityUsed>=0)
+ {
+ quantityWasted = (+quantityWasted / 100) * material.stockAvailable;
+ }
+
+ ItemMaterial.updateOne(
{ _id: req.body.material._id },
{
- $push: {
- updateRecord: {
- date: req.body.date,
- createdBy: req.body.requestor.requestorId,
- action: req.body.action,
- cause: req.body.cause,
- quantity: req.body.quantity,
- description: req.body.description,
- },
- },
- },
+ $inc: {
+ 'stockUsed': quantityUsed,
+ 'stockWasted': quantityWasted,
+ 'stockAvailable': -(quantityUsed+quantityWasted)
+ }
+ }
)
- .then(results => res.status(200).send(results))
+ .then(results => {res.status(200).send(results)})
.catch(error => res.status(500).send(error));
};
return {
From b9e28592e96eb5378ff5e071783f0926e4e46e7d Mon Sep 17 00:00:00 2001
From: leonzh2k
Date: Thu, 6 Jul 2023 17:55:26 -0400
Subject: [PATCH 111/272] add new fields to send in UserProfileController
Add jobTitle and location fields to the userProfile objects
that are sent back to the client when requesting all userProfiles.
These two bits of info are displayed on the interactive map.
---
src/controllers/userProfileController.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 737b1bc6a..70d774042 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -57,9 +57,15 @@ const userProfileController = function (UserProfile) {
return;
}
+ if (cache.getCache('allusers')) {
+ const getData = JSON.parse(cache.getCache('allusers'));
+ res.status(200).send(getData);
+ return;
+ }
+
UserProfile.find(
{},
- "_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate"
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate',
)
.sort({
lastName: 1,
From c2d332fd937967793017f315f6363ab89fcc89ef Mon Sep 17 00:00:00 2001
From: xaanders
Date: Thu, 14 Sep 2023 16:40:41 -0400
Subject: [PATCH 112/272] feat: adding location object to user profile schema
---
src/models/userProfile.js | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index 4739a05e7..a5bb3bfa3 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -81,7 +81,16 @@ const userProfileSchema = new Schema({
infringements: [
{ date: { type: String, required: true }, description: { type: String, required: true } },
],
- location: { type: String, default: '' },
+ location: {
+ userProvided: { type: String, default: '' },
+ coords: {
+ lat: { type: Number, default: '' },
+ lng: { type: Number, default: '' },
+ },
+ country: { type: String, default: '' },
+ city: { type: String, default: '' }
+
+ },
oldInfringements: [
{ date: { type: String, required: true }, description: { type: String, required: true } },
],
@@ -168,9 +177,9 @@ const userProfileSchema = new Schema({
},
infoCollections: [
{
- areaName: { type: String },
+ areaName: { type: String },
areaContent: { type: String },
- }],
+ }],
});
userProfileSchema.pre('save', function (next) {
From 3d5e4546ce199508f2ab7f1989d25ddd8c4bcaf2 Mon Sep 17 00:00:00 2001
From: xaanders
Date: Sat, 16 Sep 2023 12:02:02 -0400
Subject: [PATCH 113/272] fix: editing email message after new user creating
---
src/controllers/profileInitialSetupController.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 18cf7376c..b4230f1a4 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -67,7 +67,7 @@ function informManagerMessage(user) {
Location: |
- ${user.location} |
+ ${user.location.userProvided}, ${user.location.country} |
From 35662d57c7f729203b6b2ecfa17ce35af4e11a58 Mon Sep 17 00:00:00 2001
From: xaanders
Date: Fri, 22 Sep 2023 19:58:43 -0400
Subject: [PATCH 114/272] feat: adding a initial functionality for adding new
people to the map(maplocation controller, maplocation router, maplocation
model)
---
src/controllers/mapLocationsController.js | 69 +++++++++++++++++++++++
src/models/mapLocation.js | 42 ++++++++++++++
src/routes/mapLocationsRouter.js | 18 ++++++
src/startup/routes.js | 4 ++
4 files changed, 133 insertions(+)
create mode 100644 src/controllers/mapLocationsController.js
create mode 100644 src/models/mapLocation.js
create mode 100644 src/routes/mapLocationsRouter.js
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
new file mode 100644
index 000000000..83526998d
--- /dev/null
+++ b/src/controllers/mapLocationsController.js
@@ -0,0 +1,69 @@
+const mongoose = require('mongoose');
+const mapLocation = require('../models/mapLocation');
+const { hasPermission } = require('../utilities/permissions');
+
+const mapLocationsController = function () {
+ const getAllLocations = function (req, res) {
+ console.log('controller:')
+ console.log(req.body)
+
+ mapLocation.find({})
+ .then(results => res.send(results).status(200))
+ .catch(error => res.send(error).status(404));
+ };
+ const deleteLocation = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'deleteTeam')) {
+ res.status(403).send({ error: 'You are not authorized to delete teams.' });
+ return;
+ }
+ const { teamId } = req.params;
+ Team.findById(teamId, (error, record) => {
+ if (error || record === null) {
+ res.status(400).send({ error: 'No valid records found' });
+ return;
+ }
+ const removeteamfromprofile = userProfile.updateMany({}, { $pull: { teams: record._id } }).exec();
+ const deleteteam = record.remove();
+
+ Promise.all([removeteamfromprofile, deleteteam])
+ .then(res.status(200).send({ message: ' Team successfully deleted and user profiles updated' }))
+ .catch((errors) => {
+ res.status(400).send(errors);
+ });
+ }).catch((error) => {
+ res.status(400).send(error);
+ });
+ };
+ const putUserLocation = async function (req, res) {
+ if (!await hasPermission(req.body.requestor.role, 'putTeam')) {
+ res.status(403).send('You are not authorized to make changes in the teams.');
+ return;
+ }
+
+ const { teamId } = req.params;
+
+ Team.findById(teamId, (error, record) => {
+ if (error || record === null) {
+ res.status(400).send('No valid records found');
+ return;
+ }
+ record.teamName = req.body.teamName;
+ record.isActive = req.body.isActive;
+ record.createdDatetime = Date.now();
+ record.modifiedDatetime = Date.now();
+
+ record
+ .save()
+ .then(results => res.status(201).send(results._id))
+ .catch(errors => res.status(400).send(errors));
+ });
+ };
+
+ return {
+ getAllLocations,
+ deleteLocation,
+ putUserLocation
+ };
+};
+
+module.exports = mapLocationsController;
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
new file mode 100644
index 000000000..d7b9d82b5
--- /dev/null
+++ b/src/models/mapLocation.js
@@ -0,0 +1,42 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const mapLocation = new Schema({
+ firstName: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ lastName: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ title: {
+ type: String,
+ default: 'Prior to HGN Data Collection',
+ },
+ userProvided: {
+ type: String,
+ required: true,
+ },
+ coords: {
+ lat: {
+ type: String,
+ required: true,
+ },
+ lng: {
+ type: String,
+ required: true,
+ }
+ },
+ country: {
+ type: String,
+ required: true,
+ },
+ city: {
+ type: String,
+ default: '',
+ }
+});
+
+module.exports = mongoose.model('MapLocation', mapLocation, 'maplocations');
diff --git a/src/routes/mapLocationsRouter.js b/src/routes/mapLocationsRouter.js
new file mode 100644
index 000000000..e2e780dac
--- /dev/null
+++ b/src/routes/mapLocationsRouter.js
@@ -0,0 +1,18 @@
+const express = require('express');
+
+const router = function (mapLocations) {
+ const controller = require('../controllers/mapLocationsController')(mapLocations);
+
+ const mapRouter = express.Router();
+
+ mapRouter.route('/mapLocations')
+ .get(controller.getAllLocations)
+ .put(controller.putUserLocation);
+
+ mapRouter.route('/mapLocations/:locationId')
+ .delete(controller.deleteLocation)
+
+ return mapRouter;
+};
+
+module.exports = router;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index eae746e24..0f4c7308c 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -21,6 +21,7 @@ const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
+const mapLocations = require('../models/mapLocation');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -56,6 +57,8 @@ const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter
const reasonRouter = require('../routes/reasonRouter')(reason, userProfile);
const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverText);
+const mapLocationRouter = require('../routes/mapLocationsRouter')(mapLocations);
+
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
@@ -90,6 +93,7 @@ module.exports = function (app) {
app.use('/api', informationRouter);
app.use('/api', mouseoverTextRouter);
app.use('/api', isEmailExistsRouter);
+ app.use('/api', mapLocationRouter);
// bm dashboard
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
From 3e76b43ab0737f4e51d6dd34d8f465c28a02c692 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Mon, 2 Oct 2023 16:13:42 -0400
Subject: [PATCH 115/272] fix: jobTitle model key, feat: adding isActive
status, getting all locations, put new location to a collection
---
src/controllers/mapLocationsController.js | 72 +++++++++--------------
src/models/mapLocation.js | 38 +++++++-----
2 files changed, 49 insertions(+), 61 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 83526998d..6088de489 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,62 +1,44 @@
-const mongoose = require('mongoose');
-const mapLocation = require('../models/mapLocation');
-const { hasPermission } = require('../utilities/permissions');
-
-const mapLocationsController = function () {
+const mapLocationsController = function (mapLocation) {
const getAllLocations = function (req, res) {
- console.log('controller:')
- console.log(req.body)
mapLocation.find({})
- .then(results => res.send(results).status(200))
- .catch(error => res.send(error).status(404));
+ .then(results =>
+ res.send(results).status(200)
+ )
+ .catch(error =>
+ res.send(error).status(404));
};
const deleteLocation = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'deleteTeam')) {
- res.status(403).send({ error: 'You are not authorized to delete teams.' });
+
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
- const { teamId } = req.params;
- Team.findById(teamId, (error, record) => {
- if (error || record === null) {
- res.status(400).send({ error: 'No valid records found' });
- return;
- }
- const removeteamfromprofile = userProfile.updateMany({}, { $pull: { teams: record._id } }).exec();
- const deleteteam = record.remove();
-
- Promise.all([removeteamfromprofile, deleteteam])
- .then(res.status(200).send({ message: ' Team successfully deleted and user profiles updated' }))
- .catch((errors) => {
- res.status(400).send(errors);
- });
- }).catch((error) => {
- res.status(400).send(error);
- });
};
const putUserLocation = async function (req, res) {
- if (!await hasPermission(req.body.requestor.role, 'putTeam')) {
+
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
+ const locationData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ }
+ const location = new mapLocation(locationData);
- const { teamId } = req.params;
-
- Team.findById(teamId, (error, record) => {
- if (error || record === null) {
- res.status(400).send('No valid records found');
- return;
+ try {
+ const response = await location.save()
+ if(!response) {
+ throw new Error('Something went wrong during saving the location...')
}
- record.teamName = req.body.teamName;
- record.isActive = req.body.isActive;
- record.createdDatetime = Date.now();
- record.modifiedDatetime = Date.now();
-
- record
- .save()
- .then(results => res.status(201).send(results._id))
- .catch(errors => res.status(400).send(errors));
- });
+ res.status(200).send(response);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({message: err.message || 'Something went wrong...'});
+ }
};
return {
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
index d7b9d82b5..65415239f 100644
--- a/src/models/mapLocation.js
+++ b/src/models/mapLocation.js
@@ -11,32 +11,38 @@ const mapLocation = new Schema({
type: String,
default: 'Prior to HGN Data Collection',
},
- title: {
+ jobTitle: {
type: String,
default: 'Prior to HGN Data Collection',
},
- userProvided: {
- type: String,
- required: true,
+ isActive: {
+ type: Boolean,
+ default: false,
},
- coords: {
- lat: {
+ location: {
+ userProvided: {
type: String,
required: true,
},
- lng: {
+ coords: {
+ lat: {
+ type: String,
+ required: true,
+ },
+ lng: {
+ type: String,
+ required: true,
+ }
+ },
+ country: {
type: String,
required: true,
- }
- },
- country: {
- type: String,
- required: true,
+ },
+ city: {
+ type: String,
+ default: '',
+ },
},
- city: {
- type: String,
- default: '',
- }
});
module.exports = mongoose.model('MapLocation', mapLocation, 'maplocations');
From f3832a31ce438bb39542cc30f0d2a4f28a5868d4 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Sun, 15 Oct 2023 12:06:40 -0400
Subject: [PATCH 116/272] feat: userprofiles sending totalTangibleHrs, update
user controller, all manually locations response structure
---
src/controllers/mapLocationsController.js | 85 ++++++++++++++++++++---
src/routes/mapLocationsRouter.js | 3 +-
2 files changed, 77 insertions(+), 11 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 6088de489..f01666558 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,11 +1,26 @@
-const mapLocationsController = function (mapLocation) {
+const userProfile = require('../models/userProfile');
+const cache = require('../utilities/nodeCache')();
+
+const mapLocationsController = function (MapLocation) {
const getAllLocations = function (req, res) {
+ const priorText = 'Prior to HGN Data Collection';
+ MapLocation.find({})
+ .then(results => {
+ const users = results.map(item => {
+ return ({
+ title: priorText,
+ firstName: item.firstName !== priorText ? item.firstName : '',
+ lastName: item.lastName !== priorText ? item.lastName : '',
+ jobTitle: item.jobTitle !== priorText ? item.jobTitle : '',
+ location: item.location,
+ isActive: item.isActive,
+ _id: item._id
+ })
+ })
+ res.send(users).status(200);
- mapLocation.find({})
- .then(results =>
- res.send(results).status(200)
- )
- .catch(error =>
+ })
+ .catch(error =>
res.send(error).status(404));
};
const deleteLocation = async function (req, res) {
@@ -14,6 +29,11 @@ const mapLocationsController = function (mapLocation) {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
+ const locationId = req.params.locationId
+
+ MapLocation.findOneAndDelete({ _id: locationId })
+ .then(() => res.status(200).send({ message: "The location was successfully removed!" }))
+ .catch(error => res.status(500).send({ message: error || "Couldn't remove the location" }));
};
const putUserLocation = async function (req, res) {
@@ -27,24 +47,69 @@ const mapLocationsController = function (mapLocation) {
jobTitle: req.body.jobTitle,
location: req.body.location,
}
- const location = new mapLocation(locationData);
+ const location = new MapLocation(locationData);
try {
const response = await location.save()
- if(!response) {
+ if (!response) {
throw new Error('Something went wrong during saving the location...')
}
res.status(200).send(response);
} catch (err) {
console.log(err.message)
- res.status(500).json({message: err.message || 'Something went wrong...'});
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
+ const updateUserLocation = async function (req, res) {
+ console.log(req.body)
+ if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ res.status(403).send('You are not authorized to make changes in the teams.');
+ return;
+ }
+ const userType = req.body.type;
+ const userId= req.body._id;
+ const updateData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ _id: req.body._id
+ }
+ try {
+ let response;
+ if(userType === 'user') {
+ response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ cache.removeCache('allusers')
+ cache.removeCache(`user-${userId}`);
+ cache.setCache(`user-${userId}`, JSON.stringify(response));
+ } else {
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ }
+
+ if (!response) {
+ throw new Error('Something went wrong during saving the location...')
+ }
+ const newData = {
+ firstName: response.firstName,
+ lastName: response.lastName,
+ jobTitle: response.jobTitle,
+ location: response.location,
+ _id: response._id,
+ type: userType
+ }
+
+ res.status(200).send(newData);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
+ }
+ };
return {
getAllLocations,
deleteLocation,
- putUserLocation
+ putUserLocation,
+ updateUserLocation
};
};
diff --git a/src/routes/mapLocationsRouter.js b/src/routes/mapLocationsRouter.js
index e2e780dac..db004ff18 100644
--- a/src/routes/mapLocationsRouter.js
+++ b/src/routes/mapLocationsRouter.js
@@ -7,7 +7,8 @@ const router = function (mapLocations) {
mapRouter.route('/mapLocations')
.get(controller.getAllLocations)
- .put(controller.putUserLocation);
+ .put(controller.putUserLocation)
+ .patch(controller.updateUserLocation);
mapRouter.route('/mapLocations/:locationId')
.delete(controller.deleteLocation)
From ac823a55717273c4675f55d21529c26f948093f5 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Wed, 1 Nov 2023 12:58:36 -0400
Subject: [PATCH 117/272] fix: moving part of logic from the frontend, bug
fixes feat: updating timezone
---
src/controllers/mapLocationsController.js | 88 ++++++++++++++---------
src/models/mapLocation.js | 15 ++--
2 files changed, 58 insertions(+), 45 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index f01666558..9fa214080 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -1,27 +1,32 @@
-const userProfile = require('../models/userProfile');
+const UserProfile = require('../models/userProfile');
const cache = require('../utilities/nodeCache')();
+
const mapLocationsController = function (MapLocation) {
- const getAllLocations = function (req, res) {
- const priorText = 'Prior to HGN Data Collection';
- MapLocation.find({})
- .then(results => {
- const users = results.map(item => {
- return ({
- title: priorText,
- firstName: item.firstName !== priorText ? item.firstName : '',
- lastName: item.lastName !== priorText ? item.lastName : '',
- jobTitle: item.jobTitle !== priorText ? item.jobTitle : '',
- location: item.location,
- isActive: item.isActive,
- _id: item._id
- })
- })
- res.send(users).status(200);
-
- })
- .catch(error =>
- res.send(error).status(404));
+ const getAllLocations = async function (req, res) {
+
+ try {
+ const users = [];
+ const results = await UserProfile.find({},
+ '_id firstName lastName isActive location jobTitle totalTangibleHrs hoursByCategory'
+ );
+
+ results.forEach((item) => {
+ if (
+ (item.location?.coords.lat && item.location?.coords.lng && item.totalTangibleHrs >= 10) ||
+ (item.location?.coords.lat && item.location?.coords.lng && calculateTotalHours(item.hoursByCategory) >= 10)
+ ) {
+ users.push(item);
+ }
+ });
+
+ const m_users = await MapLocation.find({});
+
+ res.status(200).send({ users, m_users });
+ } catch (err) {
+ res.status(404).send(err);
+ }
+
};
const deleteLocation = async function (req, res) {
@@ -37,7 +42,7 @@ const mapLocationsController = function (MapLocation) {
};
const putUserLocation = async function (req, res) {
- if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ if (!req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
@@ -61,32 +66,36 @@ const mapLocationsController = function (MapLocation) {
}
};
const updateUserLocation = async function (req, res) {
- console.log(req.body)
- if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
+ if (!req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
const userType = req.body.type;
- const userId= req.body._id;
+ const userId = req.body._id;
const updateData = {
- firstName: req.body.firstName,
- lastName: req.body.lastName,
- jobTitle: req.body.jobTitle,
- location: req.body.location,
- _id: req.body._id
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ }
+
+ if (req.body.timeZone) {
+ updateData.timeZone = req.body.timeZone
}
try {
let response;
- if(userType === 'user') {
- response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ if (userType === 'user') {
+ console.log('updateData----', updateData);
+ response = await UserProfile.findOneAndUpdate({ _id: userId }, { $set: { ...updateData, jobTitle: [updateData.jobTitle] } }, { new: true });
cache.removeCache('allusers')
cache.removeCache(`user-${userId}`);
+
cache.setCache(`user-${userId}`, JSON.stringify(response));
} else {
- response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, { $set: updateData }, { new: true })
}
-
+
if (!response) {
throw new Error('Something went wrong during saving the location...')
}
@@ -98,13 +107,22 @@ const mapLocationsController = function (MapLocation) {
_id: response._id,
type: userType
}
-
+
res.status(200).send(newData);
} catch (err) {
console.log(err.message)
res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
+
+ function calculateTotalHours(hoursByCategory) {
+ let hours = 0;
+ Object.keys(hoursByCategory).forEach((x) => {
+ hours += hoursByCategory[x];
+ });
+ return hours;
+ }
+
return {
getAllLocations,
deleteLocation,
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
index 65415239f..851587dc3 100644
--- a/src/models/mapLocation.js
+++ b/src/models/mapLocation.js
@@ -3,18 +3,13 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
const mapLocation = new Schema({
- firstName: {
+ title: {
type: String,
- default: 'Prior to HGN Data Collection',
- },
- lastName: {
- type: String,
- default: 'Prior to HGN Data Collection',
- },
- jobTitle: {
- type: String,
- default: 'Prior to HGN Data Collection',
+ default: 'Prior to HGN Data Collection'
},
+ firstName: String,
+ lastName: String,
+ jobTitle: String,
isActive: {
type: Boolean,
default: false,
From ac4aa7ba8a289b6d54b839ec606e49fe5797e09c Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Thu, 2 Nov 2023 10:21:10 -0400
Subject: [PATCH 118/272] fix: modifying users before sent
---
src/controllers/mapLocationsController.js | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 9fa214080..c9edd53b8 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -19,10 +19,17 @@ const mapLocationsController = function (MapLocation) {
users.push(item);
}
});
-
- const m_users = await MapLocation.find({});
-
- res.status(200).send({ users, m_users });
+ const modifiedUsers = users.map(item => ({
+ location: item.location,
+ isActive: item.isActive,
+ jobTitle: item.jobTitle[0],
+ _id: item._id,
+ firstName: item.firstName,
+ lastName: item.lastName
+ }));
+
+ const mUsers = await MapLocation.find({});
+ res.status(200).send({ users: modifiedUsers, mUsers });
} catch (err) {
res.status(404).send(err);
}
@@ -86,7 +93,6 @@ const mapLocationsController = function (MapLocation) {
try {
let response;
if (userType === 'user') {
- console.log('updateData----', updateData);
response = await UserProfile.findOneAndUpdate({ _id: userId }, { $set: { ...updateData, jobTitle: [updateData.jobTitle] } }, { new: true });
cache.removeCache('allusers')
cache.removeCache(`user-${userId}`);
From 23bb45dfab1a7440cbc540c2ebc736e86f426b51 Mon Sep 17 00:00:00 2001
From: leonzh2k
Date: Thu, 6 Jul 2023 17:55:26 -0400
Subject: [PATCH 119/272] add new fields to send in UserProfileController
Add jobTitle and location fields to the userProfile objects
that are sent back to the client when requesting all userProfiles.
These two bits of info are displayed on the interactive map.
---
src/controllers/userProfileController.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 70d774042..ae41bec5f 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -65,7 +65,7 @@ const userProfileController = function (UserProfile) {
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate',
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
)
.sort({
lastName: 1,
From 082fd3f132db23f175bcf501b08ad67d1f5efce7 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Sun, 15 Oct 2023 12:06:40 -0400
Subject: [PATCH 120/272] feat: userprofiles sending totalTangibleHrs, update
user controller, all manually locations response structure
---
src/controllers/mapLocationsController.js | 29 +++++++++++++++++++++++
src/controllers/userProfileController.js | 2 +-
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index c9edd53b8..97ae88b09 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -129,6 +129,35 @@ const mapLocationsController = function (MapLocation) {
return hours;
}
+ try {
+ let response;
+ if(userType === 'user') {
+ response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
+ cache.removeCache('allusers')
+ cache.removeCache(`user-${userId}`);
+ cache.setCache(`user-${userId}`, JSON.stringify(response));
+ } else {
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
+ }
+
+ if (!response) {
+ throw new Error('Something went wrong during saving the location...')
+ }
+ const newData = {
+ firstName: response.firstName,
+ lastName: response.lastName,
+ jobTitle: response.jobTitle,
+ location: response.location,
+ _id: response._id,
+ type: userType
+ }
+
+ res.status(200).send(newData);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
+ }
+ };
return {
getAllLocations,
deleteLocation,
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index ae41bec5f..1cc7f133c 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -65,7 +65,7 @@ const userProfileController = function (UserProfile) {
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle totalTangibleHrs',
)
.sort({
lastName: 1,
From d6122b319d12231c057404b5458fe0eba1cba16b Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Wed, 1 Nov 2023 12:58:36 -0400
Subject: [PATCH 121/272] fix: moving part of logic from the frontend, bug
fixes feat: updating timezone
---
src/controllers/mapLocationsController.js | 31 +----------------------
1 file changed, 1 insertion(+), 30 deletions(-)
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 97ae88b09..29af9e3d6 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -128,36 +128,7 @@ const mapLocationsController = function (MapLocation) {
});
return hours;
}
-
- try {
- let response;
- if(userType === 'user') {
- response = await userProfile.findOneAndUpdate({ _id: userId }, {$set: {...updateData, jobTitle: [updateData.jobTitle]}}, { new: true });
- cache.removeCache('allusers')
- cache.removeCache(`user-${userId}`);
- cache.setCache(`user-${userId}`, JSON.stringify(response));
- } else {
- response = await MapLocation.findOneAndUpdate({ _id: userId }, {$set: updateData}, { new: true })
- }
-
- if (!response) {
- throw new Error('Something went wrong during saving the location...')
- }
- const newData = {
- firstName: response.firstName,
- lastName: response.lastName,
- jobTitle: response.jobTitle,
- location: response.location,
- _id: response._id,
- type: userType
- }
-
- res.status(200).send(newData);
- } catch (err) {
- console.log(err.message)
- res.status(500).json({ message: err.message || 'Something went wrong...' });
- }
- };
+
return {
getAllLocations,
deleteLocation,
From 1effe936b57d19eb32a02015314dd4a25fe20116 Mon Sep 17 00:00:00 2001
From: leonzh2k
Date: Thu, 6 Jul 2023 17:55:26 -0400
Subject: [PATCH 122/272] add new fields to send in UserProfileController
Add jobTitle and location fields to the userProfile objects
that are sent back to the client when requesting all userProfiles.
These two bits of info are displayed on the interactive map.
---
src/controllers/userProfileController.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 1cc7f133c..ae41bec5f 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -65,7 +65,7 @@ const userProfileController = function (UserProfile) {
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle totalTangibleHrs',
+ '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
)
.sort({
lastName: 1,
From b2b2cb0810a2a4cc2358b5c04d99bf523181fd23 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Thu, 2 Nov 2023 13:10:56 -0400
Subject: [PATCH 123/272] rebasing and resolving conflicts
---
src/controllers/userProfileController.js | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index ae41bec5f..737b1bc6a 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -57,15 +57,9 @@ const userProfileController = function (UserProfile) {
return;
}
- if (cache.getCache('allusers')) {
- const getData = JSON.parse(cache.getCache('allusers'));
- res.status(200).send(getData);
- return;
- }
-
UserProfile.find(
{},
- '_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate location jobTitle',
+ "_id firstName lastName role weeklycommittedHours email permissions isActive reactivationDate createdDate endDate"
)
.sort({
lastName: 1,
From 34a6f5594c82243eb974b7943b2d45c3ee855a39 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Sat, 4 Nov 2023 14:41:07 -0700
Subject: [PATCH 124/272] update material
---
.../bmdashboard/bmMaterialsController.js | 89 +++++++++++++++++--
src/routes/bmdashboard/bmMaterialsRouter.js | 5 ++
2 files changed, 85 insertions(+), 9 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 54ec65967..0e96b5bbb 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -57,22 +57,93 @@ const bmMaterialsController = function (ItemMaterial) {
quantityWasted = (+quantityWasted / 100) * material.stockAvailable;
}
- ItemMaterial.updateOne(
- { _id: req.body.material._id },
+ if(quantityUsed>material.stockAvailable || quantityWasted>material.stockAvailable || (quantityUsed+quantityWasted)>material.stockAvailable)
+ {
+ res.status(500).send('Please check the used and wasted stock values. Either individual values or their sum exceeds the total stock available.')
+ }
+ else
+ {
+ quantityUsed = Number.parseFloat(quantityUsed.toFixed(2));
+ quantityWasted = Number.parseFloat(quantityWasted.toFixed(2));
+ let newAvailable = Number.parseFloat(quantityUsed+quantityWasted);
+
+ ItemMaterial.updateOne(
+ { _id: req.body.material._id },
+ {
+ $inc: {
+ 'stockUsed': quantityUsed,
+ 'stockWasted': quantityWasted,
+ 'stockAvailable': -(newAvailable)
+ },
+ $push: {
+ updateRecord: {
+ date: req.body.date,
+ createdBy: req.body.requestor.requestorId,
+ quantity: -(quantityUsed+quantityWasted),
+ },
+ }
+ }
+ )
+ .then(results => {res.status(200).send(results)})
+ .catch(error => res.status(500).send({'message':error}));
+ }
+ };
+
+ const bmPostMaterialUpdateBulk = function (req, res) {
+ const materialUpdates= req.body;
+ const updateRecordsToBeAdded = materialUpdates.map(payload => {
+ let quantityUsed = +payload.quantityUsed;
+ let quantityWasted = +payload.quantityWasted;
+ let material = payload.material;
+ if(payload.QtyUsedLogUnit=='percent' && quantityWasted>=0)
{
- $inc: {
+ quantityUsed = (+quantityUsed / 100) * material.stockAvailable;
+ }
+ if(payload.QtyWastedLogUnit=='percent' && quantityUsed>=0)
+ {
+ quantityWasted = (+quantityWasted / 100) * material.stockAvailable;
+ }
+
+ quantityUsed = Number.parseFloat(quantityUsed.toFixed(2));
+ quantityWasted = Number.parseFloat(quantityWasted.toFixed(2));
+ let newAvailable = Number.parseFloat(quantityUsed+quantityWasted);
+
+ return ({
+ updateId: material._id,
+ increment: {
'stockUsed': quantityUsed,
'stockWasted': quantityWasted,
- 'stockAvailable': -(quantityUsed+quantityWasted)
- }
- }
- )
- .then(results => {res.status(200).send(results)})
- .catch(error => res.status(500).send(error));
+ 'stockAvailable': -(newAvailable)
+ },
+ updateValue: {
+ createdBy: req.body.requestor.requestorId,
+ quantity: -(quantityUsed+quantityWasted),
+ date: payload.date,
+ }});
+
+ });
+ console.log(updateRecordsToBeAdded);
+
+ try {
+ const updatePromises = updateRecordsToBeAdded.map(updateItem => ItemMaterial.updateOne(
+ { _id: updateItem.updateId },
+ {
+ $inc: updateItem.increment ,
+ $push: { usageRecord: updateItem.updateValue } },
+ ).exec());
+ Promise.all(updatePromises)
+ .then((results) => {
+ res.status(200).send({ result: `Successfully posted log for ${results.length} Material records.` });
+ })
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
+ }
};
return {
bmMaterialsList,
bmPostMaterialUpdateRecord,
+ bmPostMaterialUpdateBulk
};
};
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index a0f8dfea6..35a887b9b 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -10,6 +10,11 @@ materialsRouter.route('/materials')
materialsRouter.route('/addUpdateMaterialRecord')
.post(controller.bmPostMaterialUpdateRecord);
+ materialsRouter.route('/UpdateMaterialRecordBulk')
+ .post(controller.bmPostMaterialUpdateBulk);
+
+
+
return materialsRouter;
};
From 4e318bc4046fb42324a9b12b0adc5c1522208f5c Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sat, 4 Nov 2023 17:01:10 -0700
Subject: [PATCH 125/272] add empty string in teamCode validator for creating
new user
---
src/models/userProfile.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index 4739a05e7..3219fec18 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -159,7 +159,7 @@ const userProfileSchema = new Schema({
default: '',
validate: {
validator(v) {
- const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$/;
+ const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$|^$/;
return teamCoderegex.test(v);
},
message:
From b568f900b655b8a2654eee9d3ed0ca3f3ea4e137 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Mon, 6 Nov 2023 14:40:30 +0800
Subject: [PATCH 126/272] implemented edit and delete functions
---
src/controllers/timeEntryController.js | 164 ++++++++++++++---------
src/controllers/userProfileController.js | 11 +-
src/routes/timeentryRouter.js | 2 +-
3 files changed, 106 insertions(+), 71 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index d2a4b3df4..aa7eff6ae 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -90,13 +90,16 @@ const timeEntrycontroller = function (TimeEntry) {
const session = await mongoose.startSession();
session.startTransaction();
+ const type = req.body.entryType;
+
try {
if (!req.params.timeEntryId) {
return res.status(400).send({ error: 'ObjectId in request param is not in correct format' });
}
- if (!mongoose.Types.ObjectId.isValid(req.params.timeEntryId) || !mongoose.Types.ObjectId.isValid(req.body.projectId)) {
- return res.status(400).send({ error: 'ObjectIds are not correctly formed' });
+ if (!mongoose.Types.ObjectId.isValid(req.params.timeEntryId)
+ || ((type === 'default' || type === 'project') && !mongoose.Types.ObjectId.isValid(req.body.projectId))) {
+ return res.status(400).send({ error: 'ObjectIds are not correctly formed' });
}
// Get initial timeEntry by timeEntryId
@@ -106,7 +109,8 @@ const timeEntrycontroller = function (TimeEntry) {
return res.status(400).send({ error: `No valid records found for ${req.params.timeEntryId}` });
}
- if (!(await hasPermission(req.body.requestor, 'editTimeEntry') || timeEntry.personId.toString() === req.body.requestor.requestorId.toString())) {
+ if (!(await hasPermission(req.body.requestor, 'editTimeEntry')
+ || ((type === 'default' || type === 'person') && timeEntry.personId.toString() === req.body.requestor.requestorId.toString()))) {
return res.status(403).send({ error: 'Unauthorized request' });
}
@@ -115,7 +119,7 @@ const timeEntrycontroller = function (TimeEntry) {
const totalSeconds = moment.duration(`${hours}:${minutes}`).asSeconds();
- if (timeEntry.isTangible === true && totalSeconds !== timeEntry.totalSeconds) {
+ if (type === 'default' && timeEntry.isTangible === true && totalSeconds !== timeEntry.totalSeconds) {
notifyEditByEmail(timeEntry.personId.toString(), timeEntry, totalSeconds, req.body);
}
@@ -134,24 +138,27 @@ const timeEntrycontroller = function (TimeEntry) {
// Update the hoursLogged field of related tasks based on before and after timeEntries
// initialIsTangible is a bealoon value, req.body.isTangible is a string
// initialProjectId may be a task id or project id, so do not throw error.
- try {
- if (initialIsTangible === true) {
- const initialTask = await task.findById(initialProjectId);
- initialTask.hoursLogged -= (initialSeconds / 3600);
- await initialTask.save();
- }
+ if (type === 'default') {
+ try {
+ if (initialIsTangible === true) {
+ const initialTask = await task.findById(initialProjectId);
+ initialTask.hoursLogged -= (initialSeconds / 3600);
+ await initialTask.save();
+ }
- if (req.body.isTangible === true) {
- const editedTask = await task.findById(req.body.projectId);
- editedTask.hoursLogged += (totalSeconds / 3600);
- await editedTask.save();
+ if (req.body.isTangible === true) {
+ const editedTask = await task.findById(req.body.projectId);
+ editedTask.hoursLogged += (totalSeconds / 3600);
+ await editedTask.save();
+ }
+ } catch (error) {
+ console.log('Failed to find task by id');
}
- } catch (error) {
- console.log('Failed to find task by id');
}
// Update edit history
- if (initialSeconds !== totalSeconds
+ if ((type === 'default' || type === 'person')
+ && initialSeconds !== totalSeconds
&& timeEntry.isTangible
&& req.body.requestor.requestorId === timeEntry.personId.toString()
&& !await hasPermission(req.body.requestor, 'editTimeEntry')
@@ -163,37 +170,39 @@ const timeEntrycontroller = function (TimeEntry) {
newSeconds: totalSeconds,
});
- // Issue infraction if edit history contains more than 5 edits in the last year
- let totalRecentEdits = 0;
+ if (type === 'default') {
+ // Issue infraction if edit history contains more than 5 edits in the last year
+ let totalRecentEdits = 0;
- requestor.timeEntryEditHistory.forEach((edit) => {
- if (moment().tz('America/Los_Angeles').diff(edit.date, 'days') <= 365) {
- totalRecentEdits += 1;
- }
- });
-
- if (totalRecentEdits >= 5) {
- requestor.infringements.push({
- date: moment().tz('America/Los_Angeles'),
- description: `${totalRecentEdits} time entry edits in the last calendar year`,
+ requestor.timeEntryEditHistory.forEach((edit) => {
+ if (moment().tz('America/Los_Angeles').diff(edit.date, 'days') <= 365) {
+ totalRecentEdits += 1;
+ }
});
- emailSender('onecommunityglobal@gmail.com', `${requestor.firstName} ${requestor.lastName} was issued a blue square for for editing a time entry ${totalRecentEdits} times`, `
-
- ${requestor.firstName} ${requestor.lastName} (${requestor.email}) was issued a blue square for editing their time entries ${totalRecentEdits} times
- within the last calendar year.
-
-
- This is the ${totalRecentEdits}th edit within the past 365 days.
-
+ if (totalRecentEdits >= 5) {
+ requestor.infringements.push({
+ date: moment().tz('America/Los_Angeles'),
+ description: `${totalRecentEdits} time entry edits in the last calendar year`,
+ });
+
+ emailSender('onecommunityglobal@gmail.com', `${requestor.firstName} ${requestor.lastName} was issued a blue square for for editing a time entry ${totalRecentEdits} times`, `
+
+ ${requestor.firstName} ${requestor.lastName} (${requestor.email}) was issued a blue square for editing their time entries ${totalRecentEdits} times
+ within the last calendar year.
+
+
+ This is the ${totalRecentEdits}th edit within the past 365 days.
+
`);
- const emailInfringement = {
- date: moment().tz('America/Los_Angeles').format('MMMM-DD-YY'),
- description: `You edited your time entries ${totalRecentEdits} times within the last 365 days, exceeding the limit of 4 times per year you can edit them without penalty.`,
- };
+ const emailInfringement = {
+ date: moment().tz('America/Los_Angeles').format('MMMM-DD-YY'),
+ description: `You edited your time entries ${totalRecentEdits} times within the last 365 days, exceeding the limit of 4 times per year you can edit them without penalty.`,
+ };
- emailSender(requestor.email, 'You\'ve been issued a blue square for editing your time entry', getInfringementEmailBody(requestor.firstName, requestor.lastName, emailInfringement, requestor.infringements.length));
+ emailSender(requestor.email, 'You\'ve been issued a blue square for editing your time entry', getInfringementEmailBody(requestor.firstName, requestor.lastName, emailInfringement, requestor.infringements.length));
+ }
}
await requestor.save();
@@ -204,10 +213,12 @@ const timeEntrycontroller = function (TimeEntry) {
res.status(200).send({ message: 'Successfully updated time entry' });
- // checking if logged in hours exceed estimated time after timeentry edit for a task
- const record = await userProfile.findById(timeEntry.personId.toString());
- const currentTask = await task.findById(req.body.projectId);
- checkTaskOvertime(timeEntry, record, currentTask);
+ if (type === 'default') {
+ // checking if logged in hours exceed estimated time after timeentry edit for a task
+ const record = await userProfile.findById(timeEntry.personId.toString());
+ const currentTask = await task.findById(req.body.projectId);
+ checkTaskOvertime(timeEntry, record, currentTask);
+ }
} catch (err) {
await session.abortTransaction();
return res.status(400).send({ error: err.toString() });
@@ -249,9 +260,8 @@ const timeEntrycontroller = function (TimeEntry) {
|| !req.body.timeSpent
|| !req.body.isTangible;
- const returnErr = (res) => {
- res.status(400).send({ error: 'Bad request' });
- return;
+ const returnErr = (result) => {
+ result.status(400).send({ error: 'Bad request' });
};
switch (req.body.entryType) {
@@ -307,10 +317,12 @@ const timeEntrycontroller = function (TimeEntry) {
.status(200)
.send({ message: `Time Entry saved with id as ${results._id}` });
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => {
+ res.status(400).send(error);
+ });
// Add this tangbile time entry to related task's hoursLogged
- if ((timeentry.entryType == 'default') && timeentry.isTangible === true) {
+ if ((timeentry.entryType === 'default') && timeentry.isTangible === true) {
try {
const currentTask = await task.findById(req.body.projectId);
currentTask.hoursLogged += (timeentry.totalSeconds / 3600);
@@ -320,7 +332,7 @@ const timeEntrycontroller = function (TimeEntry) {
}
}
// checking if logged in hours exceed estimated time after timeentry for a task
- if (timeentry.entryType == 'default') {
+ if (timeentry.entryType === 'default') {
const record = await userProfile.findById(timeentry.personId.toString());
const currentTask = await task.findById(req.body.projectId);
checkTaskOvertime(timeentry, record, currentTask);
@@ -347,7 +359,7 @@ const timeEntrycontroller = function (TimeEntry) {
TimeEntry.aggregate([
{
$match: {
- entryType: { $in: [ 'default', null ] },
+ entryType: { $in: ['default', null] },
personId: mongoose.Types.ObjectId(userId),
dateOfWork: { $gte: fromdate, $lte: todate },
},
@@ -423,7 +435,9 @@ const timeEntrycontroller = function (TimeEntry) {
},
]).then((results) => {
res.status(200).send(results);
- }).catch(error => res.status(400).send(error));
+ }).catch((error) => {
+ res.status(400).send(error);
+ });
};
const getTimeEntriesForUsersList = function (req, res) {
@@ -431,7 +445,7 @@ const timeEntrycontroller = function (TimeEntry) {
TimeEntry.find(
{
- entryType: { $in: [ 'default', null, 'person' ] },
+ entryType: { $in: ['default', null, 'person'] },
personId: { $in: users },
dateOfWork: { $gte: fromDate, $lte: toDate },
},
@@ -458,7 +472,9 @@ const timeEntrycontroller = function (TimeEntry) {
});
res.status(200).send(data);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => {
+ res.status(400).send(error);
+ });
};
const getTimeEntriesForSpecifiedProject = function (req, res) {
@@ -476,7 +492,7 @@ const timeEntrycontroller = function (TimeEntry) {
const { projectId } = req.params;
TimeEntry.find(
{
- entryType: [ 'default', null ],
+ entryType: ['default', null],
projectId,
dateOfWork: { $gte: fromDate, $lte: todate },
},
@@ -487,7 +503,9 @@ const timeEntrycontroller = function (TimeEntry) {
.then((results) => {
res.status(200).send(results);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => {
+ res.status(400).send(error);
+ });
};
const deleteTimeEntry = async function (req, res) {
@@ -503,6 +521,18 @@ const timeEntrycontroller = function (TimeEntry) {
return;
}
+ if (record.entryType === 'project' || record.entryType === 'person' || record.entryType === 'team') {
+ record
+ .remove()
+ .then(() => {
+ res.status(200).send({ message: 'Successfully deleted' });
+ })
+ .catch((error) => {
+ res.status(500).send(error);
+ });
+ return;
+ }
+
if (
record.personId.toString()
=== req.body.requestor.requestorId.toString()
@@ -572,7 +602,9 @@ const timeEntrycontroller = function (TimeEntry) {
});
res.status(200).send(data);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => {
+ res.status(400).send(error);
+ });
};
const getLostTimeEntriesForProjectList = function (req, res) {
@@ -580,7 +612,7 @@ const timeEntrycontroller = function (TimeEntry) {
TimeEntry.find(
{
- entryType: "project",
+ entryType: 'project',
projectId: { $in: projects },
dateOfWork: { $gte: fromDate, $lte: toDate },
},
@@ -606,7 +638,9 @@ const timeEntrycontroller = function (TimeEntry) {
});
res.status(200).send(data);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => {
+ res.status(400).send(error);
+ });
};
const getLostTimeEntriesForTeamList = function (req, res) {
@@ -614,7 +648,7 @@ const timeEntrycontroller = function (TimeEntry) {
TimeEntry.find(
{
- entryType: "team",
+ entryType: 'team',
teamId: { $in: teams },
dateOfWork: { $gte: fromDate, $lte: toDate },
},
@@ -629,7 +663,7 @@ const timeEntrycontroller = function (TimeEntry) {
record._id = element._id;
record.notes = element.notes;
record.isTangible = element.isTangible;
- record.teamId = element.teamId;
+ record.teamId = element.teamId ? element.teamId._id : '';
record.teamName = element.teamId
? element.teamId.teamName
: '';
@@ -640,7 +674,9 @@ const timeEntrycontroller = function (TimeEntry) {
});
res.status(200).send(data);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => {
+ res.status(400).send(error);
+ });
};
return {
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index 6dc571b39..440ce765e 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -569,15 +569,14 @@ const userProfileController = function (UserProfile) {
const { userId } = req.params;
const { key, value } = req.body;
- if (key === "teamCode") {
- const canEditTeamCode = req.body.requestor.role === "Owner" ||
- req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
+ if (key === 'teamCode') {
+ const canEditTeamCode = req.body.requestor.role === 'Owner'
+ || req.body.requestor.permissions?.frontPermissions.includes('editTeamCode');
- if(!canEditTeamCode){
- res.status(403).send("You are not authorized to edit team code.");
+ if (!canEditTeamCode) {
+ res.status(403).send('You are not authorized to edit team code.');
return;
}
-
}
// remove user from cache, it should be loaded next time
diff --git a/src/routes/timeentryRouter.js b/src/routes/timeentryRouter.js
index 7e0a41797..0562f49ed 100644
--- a/src/routes/timeentryRouter.js
+++ b/src/routes/timeentryRouter.js
@@ -21,7 +21,7 @@ const routes = function (TimeEntry) {
TimeEntryRouter.route('/TimeEntry/lostUsers')
.post(controller.getLostTimeEntriesForUserList);
-
+
TimeEntryRouter.route('/TimeEntry/lostProjects')
.post(controller.getLostTimeEntriesForProjectList);
From 0058b42a8bd1b7ad00cd4e9aeec2007ec40c6c2d Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Mon, 6 Nov 2023 13:02:46 -0800
Subject: [PATCH 127/272] add fetch single project api. update fetch all
projects query.
---
.../bmdashboard/bmProjectController.js | 43 +++++++++++++++++--
src/routes/bmdashboard/bmProjectRouter.js | 7 ++-
2 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js
index 96f19ab60..3e88ea08a 100644
--- a/src/controllers/bmdashboard/bmProjectController.js
+++ b/src/controllers/bmdashboard/bmProjectController.js
@@ -1,8 +1,10 @@
const bmMProjectController = function (BuildingProject) {
- const bmProjectSummary = async function _projSumm(req, res) {
- try {
+ // fetches all projects by building manager id
+ const fetchAllProjects = async (req, res) => {
+ const { userId } = req.params;
+ try {
const projectData = await BuildingProject
- .find()
+ .find({ buildingManager: userId })
.populate([
{
path: 'buildingManager',
@@ -21,7 +23,40 @@ const bmMProjectController = function (BuildingProject) {
res.json(err);
}
};
- return { bmProjectSummary };
+
+ // fetches single project by project id
+ const fetchSingleProject = async (req, res) => {
+ const { userId, projectId } = req.params;
+ try {
+ BuildingProject
+ .findById(projectId)
+ .populate([
+ {
+ path: 'buildingManager',
+ select: '_id firstName lastName email',
+ },
+ {
+ path: 'team',
+ select: '_id firstName lastName email',
+ },
+ ])
+ .exec()
+ .then((project) => {
+ // authenticate request by comparing userId param with buildingManager id field
+ // ObjectId must be converted to string
+ if (userId !== project.buildingManager._id.toString()) {
+ return res.status(403).send({
+ message: 'You are not authorized to view this record.',
+ });
+ }
+ return res.status(200).send(project);
+ })
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return { fetchAllProjects, fetchSingleProject };
};
module.exports = bmMProjectController;
diff --git a/src/routes/bmdashboard/bmProjectRouter.js b/src/routes/bmdashboard/bmProjectRouter.js
index 6bd535ae1..7069950dc 100644
--- a/src/routes/bmdashboard/bmProjectRouter.js
+++ b/src/routes/bmdashboard/bmProjectRouter.js
@@ -4,8 +4,11 @@ const routes = function (buildingProject) {
const projectRouter = express.Router();
const controller = require('../../controllers/bmdashboard/bmProjectController')(buildingProject);
-projectRouter.route('/projects')
- .get(controller.bmProjectSummary);
+projectRouter.route('/projects/:userId')
+ .get(controller.fetchAllProjects);
+
+projectRouter.route('/projects/:userId/:projectId')
+ .get(controller.fetchSingleProject);
return projectRouter;
};
From ec5d40584a18cd5de8d8b6f255dc54acc68a2f20 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 7 Nov 2023 12:41:53 -0800
Subject: [PATCH 128/272] update project routes. add auth checks to
controllers.
---
.../bmdashboard/bmProjectController.js | 47 +++++++++++++------
src/routes/bmdashboard/bmProjectRouter.js | 4 +-
2 files changed, 34 insertions(+), 17 deletions(-)
diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js
index 3e88ea08a..929aba4ba 100644
--- a/src/controllers/bmdashboard/bmProjectController.js
+++ b/src/controllers/bmdashboard/bmProjectController.js
@@ -1,10 +1,21 @@
+// TODO: uncomment when executing auth checks
+// const jwt = require('jsonwebtoken');
+// const config = require('../../config');
+
const bmMProjectController = function (BuildingProject) {
- // fetches all projects by building manager id
+ // TODO: uncomment when executing auth checks
+ // const { JWT_SECRET } = config;
+
const fetchAllProjects = async (req, res) => {
- const { userId } = req.params;
- try {
+ //! Note: for easier testing this route currently returns all projects from the db
+ // TODO: uncomment the lines below to return only projects where field buildingManager === userid
+ // const token = req.headers.authorization;
+ // const { userid } = jwt.verify(token, JWT_SECRET);
+ try {
const projectData = await BuildingProject
- .find({ buildingManager: userId })
+ // TODO: uncomment this line to filter by buildingManager field
+ // .find({ buildingManager: userid })
+ .find()
.populate([
{
path: 'buildingManager',
@@ -26,7 +37,11 @@ const bmMProjectController = function (BuildingProject) {
// fetches single project by project id
const fetchSingleProject = async (req, res) => {
- const { userId, projectId } = req.params;
+ //! Note: for easier testing this route currently returns the project without an auth check
+ // TODO: uncomment the lines below to check the user's ability to view the current project
+ // const token = req.headers.authorization;
+ // const { userid } = jwt.verify(token, JWT_SECRET);
+ const { projectId } = req.params;
try {
BuildingProject
.findById(projectId)
@@ -41,16 +56,18 @@ const bmMProjectController = function (BuildingProject) {
},
])
.exec()
- .then((project) => {
- // authenticate request by comparing userId param with buildingManager id field
- // ObjectId must be converted to string
- if (userId !== project.buildingManager._id.toString()) {
- return res.status(403).send({
- message: 'You are not authorized to view this record.',
- });
- }
- return res.status(200).send(project);
- })
+ .then(project => res.status(200).send(project))
+ // TODO: uncomment this block to execute the auth check
+ // authenticate request by comparing userId param with buildingManager id field
+ // Note: _id has type object and must be converted to string
+ // .then((project) => {
+ // if (userid !== project.buildingManager._id.toString()) {
+ // return res.status(403).send({
+ // message: 'You are not authorized to view this record.',
+ // });
+ // }
+ // return res.status(200).send(project);
+ // })
.catch(error => res.status(500).send(error));
} catch (err) {
res.json(err);
diff --git a/src/routes/bmdashboard/bmProjectRouter.js b/src/routes/bmdashboard/bmProjectRouter.js
index 7069950dc..d60ea9b2b 100644
--- a/src/routes/bmdashboard/bmProjectRouter.js
+++ b/src/routes/bmdashboard/bmProjectRouter.js
@@ -4,10 +4,10 @@ const routes = function (buildingProject) {
const projectRouter = express.Router();
const controller = require('../../controllers/bmdashboard/bmProjectController')(buildingProject);
-projectRouter.route('/projects/:userId')
+projectRouter.route('/projects')
.get(controller.fetchAllProjects);
-projectRouter.route('/projects/:userId/:projectId')
+projectRouter.route('/project/:projectId')
.get(controller.fetchSingleProject);
return projectRouter;
From dbfc6bef60dbf37e0f9f8da70b55ee947fec4a73 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Tue, 7 Nov 2023 23:05:08 -0800
Subject: [PATCH 129/272] make sure escapeRegex check entire string for
existing info name
---
src/utilities/escapeRegex.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/utilities/escapeRegex.js b/src/utilities/escapeRegex.js
index 10fa2e61e..01a65ea50 100644
--- a/src/utilities/escapeRegex.js
+++ b/src/utilities/escapeRegex.js
@@ -1,6 +1,6 @@
const escapeRegex = function (text) {
- return text.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&');
+ return `^${text.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&')}&`;
};
module.exports = escapeRegex;
From a7ebfdd40fd5fbedcbcf21e423ab0cb353228d97 Mon Sep 17 00:00:00 2001
From: Chuehleo <122568562+Chuehleo@users.noreply.github.com>
Date: Thu, 9 Nov 2023 01:33:16 -0700
Subject: [PATCH 130/272] Update userProfileController.js
---
src/controllers/userProfileController.js | 107 ++++++++++++++---------
1 file changed, 68 insertions(+), 39 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index a39b3c9ff..a388f10db 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -34,7 +34,6 @@ async function ValidatePassword(req, res) {
});
return;
}
-
// Verify request is authorized by self or adminsitrator
if (userId !== requestor.requestorId && !await hasPermission(requestor.role, 'updatePassword')) {
console.log('User ID:', userId);
@@ -50,6 +49,11 @@ async function ValidatePassword(req, res) {
if (userId === requestor.requestorId || !await hasPermission(requestor.role, 'updatePasswordForOthers')) {
console.log('User ID:', userId);
console.log('Requestor ID:', requestor.requestorId);
+ res.status(403).send({
+ error: "You are unauthorized to update this user's password",
+ });
+ return;
+ }
// Verify new and confirm new password are correct
if (req.body.newpassword !== req.body.confirmnewpassword) {
@@ -61,8 +65,19 @@ async function ValidatePassword(req, res) {
const userProfileController = function (UserProfile) {
const getUserProfiles = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'getUserProfiles')) {
- res.status(403).send('You are not authorized to view all users');
+ if (
+ !(await hasPermission(req.body.requestor.role, "getUserProfiles")) &&
+ !req.body.requestor.permissions?.frontPermissions.includes(
+ "putUserProfilePermissions"
+ )
+ ) {
+ res.status(403).send("You are not authorized to view all users");
+ return;
+ }
+
+ if (cache.getCache("allusers")) {
+ const getData = JSON.parse(cache.getCache("allusers"));
+ res.status(200).send(getData);
return;
}
@@ -85,8 +100,8 @@ const userProfileController = function (UserProfile) {
};
const getProjectMembers = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'getProjectMembers')) {
- res.status(403).send('You are not authorized to view all users');
+ if (!(await hasPermission(req.body.requestor.role, "getProjectMembers"))) {
+ res.status(403).send("You are not authorized to view all users");
return;
}
UserProfile.find(
@@ -107,13 +122,16 @@ const userProfileController = function (UserProfile) {
};
const postUserProfile = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'postUserProfile')) {
- res.status(403).send('You are not authorized to create new users');
+ if (!(await hasPermission(req.body.requestor.role, "postUserProfile"))) {
+ res.status(403).send("You are not authorized to create new users");
return;
}
- if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
- res.status(403).send('You are not authorized to create new owners');
+ if (
+ req.body.role === "Owner" &&
+ !(await hasPermission(req.body.requestor.role, "addDeleteEditOwners"))
+ ) {
+ res.status(403).send("You are not authorized to create new owners");
return;
}
@@ -230,10 +248,12 @@ const userProfileController = function (UserProfile) {
const putUserProfile = async function (req, res) {
const userid = req.params.userId;
const isRequestorAuthorized = !!(
- canRequestorUpdateUser(req.body.requestor.requestorId, userid) && (
- await hasPermission(req.body.requestor, 'putUserProfile')
- || req.body.requestor.requestorId === userid
- )
+ canRequestorUpdateUser(req.body.requestor.requestorId, userid) &&
+ ((await hasPermission(req.body.requestor.role, "putUserProfile")) ||
+ req.body.requestor.requestorId === userid ||
+ req.body.requestor.permissions?.frontPermissions.includes(
+ "putUserProfilePermissions"
+ ))
);
if (!isRequestorAuthorized) {
@@ -241,8 +261,11 @@ const userProfileController = function (UserProfile) {
return;
}
- if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
- res.status(403).send('You are not authorized to update this user');
+ if (
+ req.body.role === "Owner" &&
+ !(await hasPermission(req.body.requestor.role, "addDeleteEditOwners"))
+ ) {
+ res.status(403).send("You are not authorized to update this user");
return;
}
@@ -295,12 +318,6 @@ const userProfileController = function (UserProfile) {
record.isFirstTimelog = req.body.isFirstTimelog;
record.teamCode = req.body.teamCode;
- if(!canEditTeamCode && record.teamCode !== req.body.teamCode){
- res.status(403).send("You are not authorized to edit team code.");
- return;
- }
- record.teamCode = req.body.teamCode;
-
// find userData in cache
const isUserInCache = cache.hasCache("allusers");
let allUserData;
@@ -311,7 +328,15 @@ const userProfileController = function (UserProfile) {
userIdx = allUserData.findIndex((users) => users._id === userid);
userData = allUserData[userIdx];
}
- if (await hasPermission(req.body.requestor, 'putUserProfileImportantInfo')) {
+ if (
+ (await hasPermission(
+ req.body.requestor.role,
+ "putUserProfileImportantInfo"
+ )) ||
+ req.body.requestor.permissions?.frontPermissions.includes(
+ "putUserProfilePermissions"
+ )
+ ) {
record.role = req.body.role;
record.isRehireable = req.body.isRehireable;
record.isActive = req.body.isActive;
@@ -377,9 +402,16 @@ const userProfileController = function (UserProfile) {
record.createdDate;
}
- record.bioPosted = req.body.bioPosted || 'default';
-
- if (await hasPermission(req.body.requestor, 'putUserProfilePermissions')) {
+ record.bioPosted = req.body.bioPosted || "default";
+ if (
+ (await hasPermission(
+ req.body.requestor.role,
+ "putUserProfilePermissions"
+ )) ||
+ req.body.requestor.permissions?.frontPermissions.includes(
+ "putUserProfilePermissions"
+ )
+ ) {
record.permissions = req.body.permissions;
}
@@ -399,7 +431,9 @@ const userProfileController = function (UserProfile) {
userData.createdDate = record.createdDate.toISOString();
}
}
- if (await hasPermission(req.body.requestor, 'infringementAuthorizer')) {
+ if (
+ await hasPermission(req.body.requestor.role, "infringementAuthorizer")
+ ) {
record.infringements = req.body.infringements;
}
@@ -429,12 +463,12 @@ const userProfileController = function (UserProfile) {
const deleteUserProfile = async function (req, res) {
const { option, userId } = req.body;
- if (!await hasPermission(req.body.requestor, 'deleteUserProfile')) {
+ if (!await hasPermission(req.body.requestor.role, 'deleteUserProfile')) {
res.status(403).send('You are not authorized to delete users');
return;
}
- if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
+ if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor.role, 'addDeleteEditOwners')) {
res.status(403).send('You are not authorized to delete this user');
return;
}
@@ -605,15 +639,9 @@ const userProfileController = function (UserProfile) {
// Verify correct params in body
if (!req.body.currentpassword || !req.body.newpassword || !req.body.confirmnewpassword) {
- return res.status(400).send({
- error: 'One of more required fields are missing',
- });
- }
- // Verify request is authorized by self or adminsitrator
- if (userId !== requestor.requestorId && !await hasPermission(req.body.requestor, 'updatePassword')) {
- return res.status(403).send({
- error: "You are unauthorized to update this user's password",
- });
+ return res.status(400).send({
+ error: 'One or more required fields are missing',
+ });
}
// Check if the requestor has the permission to update passwords.
@@ -673,10 +701,11 @@ const userProfileController = function (UserProfile) {
}
const userid = mongoose.Types.ObjectId(req.params.userId);
+ const { role } = req.body.requestor;
let validroles = ['Volunteer', 'Manager', 'Administrator', 'Core Team', 'Owner', 'Mentor'];
- if (await hasPermission(req.body.requestor, 'getReporteesLimitRoles')) {
+ if (await hasPermission(role, 'getReporteesLimitRoles')) {
validroles = ['Volunteer', 'Manager'];
}
@@ -747,7 +776,7 @@ const userProfileController = function (UserProfile) {
});
return;
}
- if (!await hasPermission(req.body.requestor, 'changeUserStatus')) {
+ if (!await hasPermission(req.body.requestor.role, 'changeUserStatus')) {
res.status(403).send('You are not authorized to change user status');
return;
}
From 92bf9a85e5594ec943c1f5446817f7c070f52d06 Mon Sep 17 00:00:00 2001
From: Chuehleo <122568562+Chuehleo@users.noreply.github.com>
Date: Thu, 9 Nov 2023 02:07:31 -0700
Subject: [PATCH 131/272] Update userProfileController.js
---
src/controllers/userProfileController.js | 194 +++++++++++------------
1 file changed, 90 insertions(+), 104 deletions(-)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index a388f10db..5968e3dd6 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -35,20 +35,15 @@ async function ValidatePassword(req, res) {
return;
}
// Verify request is authorized by self or adminsitrator
- if (userId !== requestor.requestorId && !await hasPermission(requestor.role, 'updatePassword')) {
- console.log('User ID:', userId);
- console.log('Requestor ID:', requestor.requestorId);
+ if (userId !== requestor.requestorId && !await hasPermission(req.body.requestor, 'updatePassword')) {
res.status(403).send({
error: "You are unauthorized to update this user's password",
});
return;
}
-
- // Check permissions
- if (userId === requestor.requestorId || !await hasPermission(requestor.role, 'updatePasswordForOthers')) {
- console.log('User ID:', userId);
- console.log('Requestor ID:', requestor.requestorId);
+ // Verify request is authorized by self or adminsitrator
+ if (userId === requestor.requestorId || !await hasPermission(req.body.requestor, 'updatePassword')) {
res.status(403).send({
error: "You are unauthorized to update this user's password",
});
@@ -65,19 +60,8 @@ async function ValidatePassword(req, res) {
const userProfileController = function (UserProfile) {
const getUserProfiles = async function (req, res) {
- if (
- !(await hasPermission(req.body.requestor.role, "getUserProfiles")) &&
- !req.body.requestor.permissions?.frontPermissions.includes(
- "putUserProfilePermissions"
- )
- ) {
- res.status(403).send("You are not authorized to view all users");
- return;
- }
-
- if (cache.getCache("allusers")) {
- const getData = JSON.parse(cache.getCache("allusers"));
- res.status(200).send(getData);
+ if (!await hasPermission(req.body.requestor, 'getUserProfiles')) {
+ res.status(403).send('You are not authorized to view all users');
return;
}
@@ -90,18 +74,25 @@ const userProfileController = function (UserProfile) {
})
.then((results) => {
if (!results) {
- res.status(500).send({ error: "User result was invalid" });
- return;
+ if (cache.getCache("allusers")) {
+ const getData = JSON.parse(cache.getCache("allusers"));
+ res.status(200).send(getData);
+ return;
+ }else{
+ res.status(500).send({ error: "User result was invalid" });
+ return;
+ }
}
cache.setCache("allusers", JSON.stringify(results));
res.status(200).send(results);
})
.catch((error) => res.status(404).send(error));
+
};
const getProjectMembers = async function (req, res) {
- if (!(await hasPermission(req.body.requestor.role, "getProjectMembers"))) {
- res.status(403).send("You are not authorized to view all users");
+ if (!await hasPermission(req.body.requestor, 'getProjectMembers')) {
+ res.status(403).send('You are not authorized to view all users');
return;
}
UserProfile.find(
@@ -122,16 +113,13 @@ const userProfileController = function (UserProfile) {
};
const postUserProfile = async function (req, res) {
- if (!(await hasPermission(req.body.requestor.role, "postUserProfile"))) {
- res.status(403).send("You are not authorized to create new users");
+ if (!await hasPermission(req.body.requestor, 'postUserProfile')) {
+ res.status(403).send('You are not authorized to create new users');
return;
}
- if (
- req.body.role === "Owner" &&
- !(await hasPermission(req.body.requestor.role, "addDeleteEditOwners"))
- ) {
- res.status(403).send("You are not authorized to create new owners");
+ if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
+ res.status(403).send('You are not authorized to create new owners');
return;
}
@@ -248,24 +236,22 @@ const userProfileController = function (UserProfile) {
const putUserProfile = async function (req, res) {
const userid = req.params.userId;
const isRequestorAuthorized = !!(
- canRequestorUpdateUser(req.body.requestor.requestorId, userid) &&
- ((await hasPermission(req.body.requestor.role, "putUserProfile")) ||
- req.body.requestor.requestorId === userid ||
- req.body.requestor.permissions?.frontPermissions.includes(
- "putUserProfilePermissions"
- ))
+ canRequestorUpdateUser(req.body.requestor.requestorId, userid) && (
+ await hasPermission(req.body.requestor, 'putUserProfile')
+ || req.body.requestor.requestorId === userid
+ )
);
+
+ const canEditTeamCode = req.body.requestor.role === "Owner" ||
+ req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
if (!isRequestorAuthorized) {
res.status(403).send("You are not authorized to update this user");
return;
}
- if (
- req.body.role === "Owner" &&
- !(await hasPermission(req.body.requestor.role, "addDeleteEditOwners"))
- ) {
- res.status(403).send("You are not authorized to update this user");
+ if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
+ res.status(403).send('You are not authorized to update this user');
return;
}
@@ -318,6 +304,13 @@ const userProfileController = function (UserProfile) {
record.isFirstTimelog = req.body.isFirstTimelog;
record.teamCode = req.body.teamCode;
+ if(!canEditTeamCode && record.teamCode !== req.body.teamCode){
+ res.status(403).send("You are not authorized to edit team code.");
+ return;
+ }
+
+ record.teamCode = req.body.teamCode;
+
// find userData in cache
const isUserInCache = cache.hasCache("allusers");
let allUserData;
@@ -328,15 +321,7 @@ const userProfileController = function (UserProfile) {
userIdx = allUserData.findIndex((users) => users._id === userid);
userData = allUserData[userIdx];
}
- if (
- (await hasPermission(
- req.body.requestor.role,
- "putUserProfileImportantInfo"
- )) ||
- req.body.requestor.permissions?.frontPermissions.includes(
- "putUserProfilePermissions"
- )
- ) {
+ if (await hasPermission(req.body.requestor, 'putUserProfileImportantInfo')) {
record.role = req.body.role;
record.isRehireable = req.body.isRehireable;
record.isActive = req.body.isActive;
@@ -402,16 +387,9 @@ const userProfileController = function (UserProfile) {
record.createdDate;
}
- record.bioPosted = req.body.bioPosted || "default";
- if (
- (await hasPermission(
- req.body.requestor.role,
- "putUserProfilePermissions"
- )) ||
- req.body.requestor.permissions?.frontPermissions.includes(
- "putUserProfilePermissions"
- )
- ) {
+ record.bioPosted = req.body.bioPosted || 'default';
+
+ if (await hasPermission(req.body.requestor, 'putUserProfilePermissions')) {
record.permissions = req.body.permissions;
}
@@ -431,9 +409,7 @@ const userProfileController = function (UserProfile) {
userData.createdDate = record.createdDate.toISOString();
}
}
- if (
- await hasPermission(req.body.requestor.role, "infringementAuthorizer")
- ) {
+ if (await hasPermission(req.body.requestor, 'infringementAuthorizer')) {
record.infringements = req.body.infringements;
}
@@ -463,12 +439,12 @@ const userProfileController = function (UserProfile) {
const deleteUserProfile = async function (req, res) {
const { option, userId } = req.body;
- if (!await hasPermission(req.body.requestor.role, 'deleteUserProfile')) {
+ if (!await hasPermission(req.body.requestor, 'deleteUserProfile')) {
res.status(403).send('You are not authorized to delete users');
return;
}
- if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor.role, 'addDeleteEditOwners')) {
+ if (req.body.role === 'Owner' && !await hasPermission(req.body.requestor, 'addDeleteEditOwners')) {
res.status(403).send('You are not authorized to delete this user');
return;
}
@@ -602,6 +578,17 @@ const userProfileController = function (UserProfile) {
const { userId } = req.params;
const { key, value } = req.body;
+ if (key === "teamCode") {
+ const canEditTeamCode = req.body.requestor.role === "Owner" ||
+ req.body.requestor.permissions?.frontPermissions.includes("editTeamCode");
+
+ if(!canEditTeamCode){
+ res.status(403).send("You are not authorized to edit team code.");
+ return;
+ }
+
+ }
+
// remove user from cache, it should be loaded next time
cache.removeCache(`user-${userId}`);
if (!key || value === undefined) return res.status(400).send({ error: 'Missing property or value' });
@@ -626,24 +613,18 @@ const userProfileController = function (UserProfile) {
const updatepassword = async function (req, res) {
const { userId } = req.params;
const { requestor } = req.body;
-
- console.log('User ID:', userId);
- console.log('Requestor ID:', requestor.requestorId);
-
- // Check if userId is valid.
if (!mongoose.Types.ObjectId.isValid(userId)) {
- return res.status(400).send({
- error: 'Bad Request',
- });
+ return res.status(400).send({
+ error: 'Bad Request',
+ });
}
// Verify correct params in body
if (!req.body.currentpassword || !req.body.newpassword || !req.body.confirmnewpassword) {
- return res.status(400).send({
- error: 'One or more required fields are missing',
- });
+ return res.status(400).send({
+ error: 'One of more required fields are missing',
+ });
}
-
// Check if the requestor has the permission to update passwords.
const hasUpdatePasswordPermission = await hasPermission(requestor.role, 'updatePassword');
@@ -666,31 +647,37 @@ const userProfileController = function (UserProfile) {
});
}
- // Process the password change
- try {
- const user = await UserProfile.findById(userId, 'password');
- const passwordMatch = await bcrypt.compare(req.body.currentpassword, user.password);
+ // Verify old and new passwords are not same
+ if (req.body.currentpassword === req.body.newpassword) {
+ res.status(400).send({
+ error: 'Old and new passwords should not be same',
+ });
+ }
- if (!passwordMatch) {
- return res.status(400).send({
+ return UserProfile.findById(userId, 'password')
+ .then((user) => {
+ bcrypt
+ .compare(req.body.currentpassword, user.password)
+ .then((passwordMatch) => {
+ if (!passwordMatch) {
+ return res.status(400).send({
error: 'Incorrect current password',
- });
- }
-
- user.set({
- password: req.body.newpassword,
- resetPwd: undefined,
- });
-
- await user.save();
-
- return res.status(200).send({ message: 'Updated password successfully' });
-
- } catch (error) {
- return res.status(500).send(error);
- }
-};
+ });
+ }
+ user.set({
+ password: req.body.newpassword,
+ resetPwd: undefined,
+ });
+ return user
+ .save()
+ .then(() => res.status(200).send({ message: 'updated password' }))
+ .catch(error => res.status(500).send(error));
+ })
+ .catch(error => res.status(500).send(error));
+ })
+ .catch(error => res.status(500).send(error));
+ };
const getreportees = async function (req, res) {
if (!mongoose.Types.ObjectId.isValid(req.params.userId)) {
@@ -701,11 +688,10 @@ const userProfileController = function (UserProfile) {
}
const userid = mongoose.Types.ObjectId(req.params.userId);
- const { role } = req.body.requestor;
let validroles = ['Volunteer', 'Manager', 'Administrator', 'Core Team', 'Owner', 'Mentor'];
- if (await hasPermission(role, 'getReporteesLimitRoles')) {
+ if (await hasPermission(req.body.requestor, 'getReporteesLimitRoles')) {
validroles = ['Volunteer', 'Manager'];
}
@@ -776,7 +762,7 @@ const userProfileController = function (UserProfile) {
});
return;
}
- if (!await hasPermission(req.body.requestor.role, 'changeUserStatus')) {
+ if (!await hasPermission(req.body.requestor, 'changeUserStatus')) {
res.status(403).send('You are not authorized to change user status');
return;
}
From fa3b768b0642e87cc273b8a4cb2f90071cf9af27 Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Thu, 9 Nov 2023 10:05:04 -0600
Subject: [PATCH 132/272] Create default prompt when there is no prompt
---
src/controllers/dashBoardController.js | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 3a203481f..40037297a 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -27,10 +27,26 @@ const dashboardcontroller = function () {
const getDashBoardData = function (req, res) {
DashboardData.findById({ _id: 'ai-prompt' })
- .then((results) => {
- res.status(200).send(results);
- })
- .catch(error => res.status(500).send(error));
+ .then((result) => {
+ if (result) {
+ // If the GPT prompt exists, send it back.
+ res.status(200).send(result);
+ } else {
+ // If the GPT prompt does not exist, create it.
+ const defaultPrompt = {
+ _id: 'ai-prompt',
+ aIPromptText: "Please edit the following summary of my week's work. Make sure it is professionally written in 3rd person format.\nWrite it as only one paragraph. It must be only one paragraph. Keep it less than 500 words. Start the paragraph with 'This week'.\nMake sure the paragraph contains no links or URLs and write it in a tone that is matter-of-fact and without embellishment.\nDo not add flowery language, keep it simple and factual. Do not add a final summary sentence. Apply all this to the following:"
+ };
+ DashboardData.create(defaultPrompt)
+ .then((newResult) => {
+ res.status(200).send(newResult);
+ })
+ .catch((creationError) => {
+ res.status(500).send(creationError);
+ });
+ }
+ })
+ .catch(error => res.status(500).send(error));
};
const monthlydata = function (req, res) {
From 4eb13e71cbc4271f6e4296ca94faf1bcae844e96 Mon Sep 17 00:00:00 2001
From: robertoooc
Date: Thu, 9 Nov 2023 18:12:53 -0800
Subject: [PATCH 133/272] adds logic to prevent server from throwing errors
when a time entry is edited and not related to task
---
src/controllers/timeEntryController.js | 66 ++++++++++++++++----------
1 file changed, 41 insertions(+), 25 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index bea25d0a6..962f30170 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -122,6 +122,8 @@ const timeEntrycontroller = function (TimeEntry) {
const initialSeconds = timeEntry.totalSeconds;
const initialProjectId = timeEntry.projectId;
const initialIsTangible = timeEntry.isTangible;
+ // Get the task related to this time entry, if not found, then it's a project and will be null
+ const findTask = await task.findById(initialProjectId);
timeEntry.notes = req.body.notes;
timeEntry.totalSeconds = totalSeconds;
@@ -134,19 +136,19 @@ const timeEntrycontroller = function (TimeEntry) {
// initialIsTangible is a bealoon value, req.body.isTangible is a string
// initialProjectId may be a task id or project id, so do not throw error.
try {
- if (initialIsTangible === true) {
- const initialTask = await task.findById(initialProjectId);
- initialTask.hoursLogged -= (initialSeconds / 3600);
- await initialTask.save();
- }
+ if (findTask) {
+ if (initialIsTangible === true) {
+ findTask.hoursLogged -= (initialSeconds / 3600);
+ }
+
+ if (req.body.isTangible === true) {
+ findTask.hoursLogged += (totalSeconds / 3600);
+ }
- if (req.body.isTangible === true) {
- const editedTask = await task.findById(req.body.projectId);
- editedTask.hoursLogged += (totalSeconds / 3600);
- await editedTask.save();
+ await findTask.save();
}
} catch (error) {
- console.log('Failed to find task by id');
+ throw new Error(error);
}
// Update edit history
@@ -203,10 +205,13 @@ const timeEntrycontroller = function (TimeEntry) {
res.status(200).send({ message: 'Successfully updated time entry' });
- // checking if logged in hours exceed estimated time after timeentry edit for a task
- const record = await userProfile.findById(timeEntry.personId.toString());
- const currentTask = await task.findById(req.body.projectId);
- checkTaskOvertime(timeEntry, record, currentTask);
+ // If the time entry isn't related to a task (i.e. it's a project), then don't check for overtime (Most likely pr team)
+ if (findTask) {
+ // checking if logged in hours exceed estimated time after timeentry edit for a task
+ const record = await userProfile.findById(timeEntry.personId.toString());
+ const currentTask = await task.findById(req.body.projectId);
+ checkTaskOvertime(timeEntry, record, currentTask);
+ }
} catch (err) {
await session.abortTransaction();
return res.status(400).send({ error: err.toString() });
@@ -271,20 +276,28 @@ const timeEntrycontroller = function (TimeEntry) {
})
.catch(error => res.status(400).send(error));
- // Add this tangbile time entry to related task's hoursLogged
- if (timeentry.isTangible === true) {
+ // Get the task related to this time entry, if not found, then it's a project sets to null
+ const currentTask = await task.findById(req.body.projectId).catch(() => null);
+
+ // Add this tangbile time entry to related task's hoursLogged and checks if timeEntry is related to a task
+ if (timeentry.isTangible === true && currentTask) {
try {
- const currentTask = await task.findById(req.body.projectId);
- currentTask.hoursLogged += (timeentry.totalSeconds / 3600);
+ currentTask.hoursLogged += timeentry.totalSeconds / 3600;
await currentTask.save();
} catch (error) {
- throw new Error('Failed to find the task by id');
+ throw new Error(error);
+ }
+ }
+
+ // checking if logged in hours exceed estimated time after timeentry for a task, only if the time entry is related to a task (It might not be, if it's a project)
+ if (currentTask) {
+ try {
+ const record = await userProfile.findById(timeentry.personId.toString());
+ checkTaskOvertime(timeentry, record, currentTask);
+ } catch (error) {
+ throw new Error(error);
}
}
- // checking if logged in hours exceed estimated time after timeentry for a task
- const record = await userProfile.findById(timeentry.personId.toString());
- const currentTask = await task.findById(req.body.projectId);
- checkTaskOvertime(timeentry, record, currentTask);
};
const getTimeEntriesForSpecifiedPeriod = function (req, res) {
@@ -469,8 +482,11 @@ const timeEntrycontroller = function (TimeEntry) {
if (record.isTangible === true) {
task.findById(record.projectId)
.then((currentTask) => {
- currentTask.hoursLogged -= (record.totalSeconds / 3600);
- currentTask.save();
+ // If the time entry isn't related to a task (i.e. it's a project), then don't revert hours (Most likely pr team)
+ if (currentTask) {
+ currentTask.hoursLogged -= (record.totalSeconds / 3600);
+ currentTask.save();
+ }
})
.catch((error) => {
throw new Error(error);
From 8a634b4dfdd9339a89d8dae939925a5ac10abb74 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 10 Nov 2023 09:31:52 -0800
Subject: [PATCH 134/272] add new inventory models, invtype router and
controller
---
.../bmdashboard/bmInventoryTypeController.js | 19 +++++++++++++
.../bmdashboard/buildingInventoryType.js | 13 +++++++++
src/models/bmdashboard/buildingMaterial.js | 28 +++++++++++++++++++
.../bmdashboard/bmInventoryTypeRouter.js | 13 +++++++++
4 files changed, 73 insertions(+)
create mode 100644 src/controllers/bmdashboard/bmInventoryTypeController.js
create mode 100644 src/models/bmdashboard/buildingInventoryType.js
create mode 100644 src/models/bmdashboard/buildingMaterial.js
create mode 100644 src/routes/bmdashboard/bmInventoryTypeRouter.js
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
new file mode 100644
index 000000000..b9ced243e
--- /dev/null
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -0,0 +1,19 @@
+const bmInventoryTypeController = function (InvType) {
+ const fetchMaterialTypes = async (req, res) => {
+ try {
+ InvType
+ .find()
+ .exec()
+ .then(result => res.status(200).send(result))
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
+ }
+ };
+
+ return {
+ fetchMaterialTypes,
+ };
+};
+
+module.exports = bmInventoryTypeController;
diff --git a/src/models/bmdashboard/buildingInventoryType.js b/src/models/bmdashboard/buildingInventoryType.js
new file mode 100644
index 000000000..71285fa24
--- /dev/null
+++ b/src/models/bmdashboard/buildingInventoryType.js
@@ -0,0 +1,13 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const buildingInventoryType = new Schema({
+ category: String, // Consumable, Material, Tool, Equipment
+ name: String,
+ description: String,
+ unit: String, // unit of measurement
+ imageUrl: String,
+});
+
+module.exports = mongoose.model('buildingInventoryType', buildingInventoryType, 'buildingInventoryTypes');
diff --git a/src/models/bmdashboard/buildingMaterial.js b/src/models/bmdashboard/buildingMaterial.js
new file mode 100644
index 000000000..714ba4ae7
--- /dev/null
+++ b/src/models/bmdashboard/buildingMaterial.js
@@ -0,0 +1,28 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const buildingMaterial = new Schema({
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+ stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+ stockUsed: { type: Number, default: 0 }, // total amount of item used successfully in the project
+ stockWasted: { type: Number, default: 0 }, // total amount of item wasted/ruined/lost in the project
+ stockAvailable: { type: Number, default: 0 }, // bought - (used + wasted)
+ purchaseRecord: [{
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantity: Number,
+ status: { type: String, default: 'Pending' }, // Pending, Rejected, Approved
+ }],
+ updateRecord: [{
+ _id: false,
+ date: Date,
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantityUsed: String, // '10 cubic yards'
+ quantityWasted: Number,
+ }],
+});
+
+module.exports = mongoose.model('buildingMaterial', buildingMaterial, 'buildingMaterials');
diff --git a/src/routes/bmdashboard/bmInventoryTypeRouter.js b/src/routes/bmdashboard/bmInventoryTypeRouter.js
new file mode 100644
index 000000000..ceae439dc
--- /dev/null
+++ b/src/routes/bmdashboard/bmInventoryTypeRouter.js
@@ -0,0 +1,13 @@
+const express = require('express');
+
+const routes = function (invType) {
+ const inventoryTypeRouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmInventoryTypeController')(invType);
+
+ inventoryTypeRouter.route('/invtypes/materials')
+ .get(controller.fetchMaterialTypes);
+
+ return inventoryTypeRouter;
+};
+
+module.exports = routes;
From cff986158da264ab65cc78e960d86b7bb4f3f58f Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Fri, 10 Nov 2023 17:17:54 -0800
Subject: [PATCH 135/272] building inventory
---
package-lock.json | 7 +-
package.json | 1 +
.../bmdashboard/bmMaterialsController.js | 68 +++++++++----------
src/models/buildingInventoryType.js | 10 +++
src/models/buildingMaterial.js | 23 +++++++
src/models/buildingProject.js | 12 ++++
src/models/inventoryItemMaterial.js | 4 +-
src/routes/bmdashboard/bmMaterialsRouter.js | 4 +-
src/startup/routes.js | 6 +-
9 files changed, 94 insertions(+), 41 deletions(-)
create mode 100644 src/models/buildingInventoryType.js
create mode 100644 src/models/buildingMaterial.js
create mode 100644 src/models/buildingProject.js
diff --git a/package-lock.json b/package-lock.json
index 3fcc98986..d26330d5e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5536,7 +5536,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",
@@ -5806,6 +5806,11 @@
"moment": ">= 2.9.0"
}
},
+ "mongo-round": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mongo-round/-/mongo-round-1.0.0.tgz",
+ "integrity": "sha512-lwvLJv827Uks+3HnTOt1I/Qr78Avke3du1oMaFqFpTwtRKtOposNOKkfpGXQN4ZGpRN3XAS8fEppIJ4TUj0xQw=="
+ },
"mongodb": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
diff --git a/package.json b/package.json
index 1c6b8a5d4..32d23ee6a 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"lodash": "^4.17.21",
"moment": "^2.29.4",
"moment-timezone": "^0.5.35",
+ "mongo-round": "^1.0.0",
"mongodb": "^3.7.3",
"mongoose": "^5.13.15",
"mongoose-validator": "^2.1.0",
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 0e96b5bbb..4529546da 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -7,18 +7,11 @@ const bmMaterialsController = function (ItemMaterial) {
.populate([
{
path: 'project',
- select: '_id projectName',
+ select: '_id name',
},
{
- path: 'inventoryItemType',
- select: '_id name uom totalStock totalAvailable',
- },
- {
- path: 'usageRecord',
- populate: {
- path: 'createdBy',
- select: '_id firstName lastName',
- },
+ path: 'itemType',
+ select: '_id name unit',
},
{
path: 'updateRecord',
@@ -30,14 +23,17 @@ const bmMaterialsController = function (ItemMaterial) {
{
path: 'purchaseRecord',
populate: {
- path: 'createdBy',
+ path: 'requestedBy',
select: '_id firstName lastName',
},
},
])
.exec()
.then(results => res.status(200).send(results))
- .catch(error => res.status(500).send(error));
+ .catch(error => {
+ console.log(error)
+ res.status(500).send(error)
+ });
} catch (err) {
res.json(err);
}
@@ -63,26 +59,28 @@ const bmMaterialsController = function (ItemMaterial) {
}
else
{
- quantityUsed = Number.parseFloat(quantityUsed.toFixed(2));
- quantityWasted = Number.parseFloat(quantityWasted.toFixed(2));
- let newAvailable = Number.parseFloat(quantityUsed+quantityWasted);
+ quantityUsed = +material.stockUsed + parseFloat(quantityUsed.toFixed(4));
+ quantityWasted = +material.stockWasted + parseFloat(quantityWasted.toFixed(4));
+ let newAvailable = +material.stockAvailable - parseFloat(quantityUsed+quantityWasted);
ItemMaterial.updateOne(
{ _id: req.body.material._id },
- {
- $inc: {
+
+ {
+ $set: {
'stockUsed': quantityUsed,
'stockWasted': quantityWasted,
'stockAvailable': -(newAvailable)
},
- $push: {
- updateRecord: {
- date: req.body.date,
- createdBy: req.body.requestor.requestorId,
- quantity: -(quantityUsed+quantityWasted),
- },
+ $push: {
+ updateRecord: {
+ date: req.body.date,
+ createdBy: req.body.requestor.requestorId,
+ quantity: -(quantityUsed+quantityWasted),
+ },
+ }
}
- }
+
)
.then(results => {res.status(200).send(results)})
.catch(error => res.status(500).send({'message':error}));
@@ -104,20 +102,21 @@ const bmMaterialsController = function (ItemMaterial) {
quantityWasted = (+quantityWasted / 100) * material.stockAvailable;
}
- quantityUsed = Number.parseFloat(quantityUsed.toFixed(2));
- quantityWasted = Number.parseFloat(quantityWasted.toFixed(2));
- let newAvailable = Number.parseFloat(quantityUsed+quantityWasted);
-
+ quantityUsed = +material.stockUsed + parseFloat(quantityUsed.toFixed(4));
+ quantityWasted = +material.stockWasted + parseFloat(quantityWasted.toFixed(4));
+ let newAvailable = +material.stockAvailable - parseFloat(quantityUsed+quantityWasted);
+ newAvailable = parseFloat(newAvailable.toFixed(4));
+ console.log(quantityUsed,quantityWasted,newAvailable);
return ({
updateId: material._id,
- increment: {
+ set: {
'stockUsed': quantityUsed,
'stockWasted': quantityWasted,
- 'stockAvailable': -(newAvailable)
+ 'stockAvailable': -newAvailable
},
updateValue: {
createdBy: req.body.requestor.requestorId,
- quantity: -(quantityUsed+quantityWasted),
+ quantity: -(newAvailable),
date: payload.date,
}});
@@ -127,9 +126,10 @@ const bmMaterialsController = function (ItemMaterial) {
try {
const updatePromises = updateRecordsToBeAdded.map(updateItem => ItemMaterial.updateOne(
{ _id: updateItem.updateId },
- {
- $inc: updateItem.increment ,
- $push: { usageRecord: updateItem.updateValue } },
+ {
+ $set : updateItem.set,
+ $push: { updateRecord: updateItem.updateValue }
+ },
).exec());
Promise.all(updatePromises)
.then((results) => {
diff --git a/src/models/buildingInventoryType.js b/src/models/buildingInventoryType.js
new file mode 100644
index 000000000..3981b3f5a
--- /dev/null
+++ b/src/models/buildingInventoryType.js
@@ -0,0 +1,10 @@
+const mongoose = require('mongoose');
+const { Schema } = mongoose;
+const buildingInventoryType = new Schema({
+ category: String, // Consumable, Material, Tool, Equipment
+ name: String,
+ description: String,
+ unit: String, // unit of measurement
+ imageUrl: String,
+});
+module.exports = mongoose.model('buildingInventoryType', buildingInventoryType, 'buildingInventoryTypes');
\ No newline at end of file
diff --git a/src/models/buildingMaterial.js b/src/models/buildingMaterial.js
new file mode 100644
index 000000000..c1d74b879
--- /dev/null
+++ b/src/models/buildingMaterial.js
@@ -0,0 +1,23 @@
+const mongoose = require('mongoose');
+const { Schema } = mongoose;
+const buildingMaterial = new Schema({
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+ stockBought: Number, // total amount of item bought for use in the project
+ stockUsed: Number, // total amount of item used successfully in the project
+ stockWasted: Number, // total amount of item wasted/ruined/lost in the project
+ stockAvailable: Number, // bought - (used + wasted)
+ purchaseRecord: [{
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantity: Number,
+ status: { type: String, default: 'Pending' }, // Pending, Rejected, Approved
+ }],
+ updateRecord: [{
+ date: Date,
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantityUsed: String, // '10 cubic yards'
+ quantityWasted: Number,
+ }],
+});
+module.exports = mongoose.model('buildingMaterial', buildingMaterial, 'buildingMaterials');
diff --git a/src/models/buildingProject.js b/src/models/buildingProject.js
new file mode 100644
index 000000000..20d26fc41
--- /dev/null
+++ b/src/models/buildingProject.js
@@ -0,0 +1,12 @@
+const mongoose = require('mongoose');
+const { Schema } = mongoose;
+const buildingProject = new Schema({
+ isActive: Boolean,
+ name: String,
+ template: String, // construction template (ie Earthbag Village)
+ location: String, // use lat/lng instead?
+ dateCreated: { type: Date, default: Date.now },
+ buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }, // BM's id
+ team: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }],
+});
+module.exports = mongoose.model('buildingProject', buildingProject, 'buildingProjects');
\ No newline at end of file
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index 8460ecd6e..3cc7a9966 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -7,9 +7,9 @@ const InventoryItemMaterial = new Schema({
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'project', required: true },
stockBought: { type: Number, required: true }, // amount bought for project, affects total stock
stockUsed: { type: Number, required: true },
- stockAvailable: { type: Number, required: true },
+ stockAvailable: { type: Number, required: true},
stockHeld: { type: Number, required: true },
- stockWasted: { type: Number, required: true },
+ stockWasted: { type: Number, required: true },
usageRecord: [{ // daily log of amount inventory item used at job site
date: { type: Date, required: true, default: Date.now() },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile', required: true },
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index 35a887b9b..d56c682bd 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -1,8 +1,8 @@
const express = require('express');
-const routes = function (itemMaterial) {
+const routes = function (buildingMaterial) {
const materialsRouter = express.Router();
-const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial);
+const controller = require('../../controllers/bmdashboard/bmMaterialsController')(buildingMaterial);
materialsRouter.route('/materials')
.get(controller.bmMaterialsList);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 7208535d8..798ae969e 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -21,7 +21,9 @@ const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
-const inventoryItemMaterial = require('../models/inventoryItemMaterial');
+const buildingMaterial = require('../models/buildingMaterial');
+const buildingProject = require('../models/buildingProject');
+const buildingInventoryType = require('../models/buildingInventoryType');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -60,7 +62,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(buildingMaterial);
const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')();
module.exports = function (app) {
From 36dd97298dcf2ec8e34801c1ba7b2f7de074f028 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Fri, 10 Nov 2023 19:17:11 -0800
Subject: [PATCH 136/272] building material update
---
.../bmdashboard/bmMaterialsController.js | 60 ++++++++++---------
.../bmdashboard/bmProjectsController.js | 31 ----------
.../buildingInventoryType.js | 0
.../{ => bmdashboard}/buildingMaterial.js | 0
src/models/buildingProject.js | 12 ----
src/routes/bmdashboard/bmMaterialsRouter.js | 4 +-
src/routes/bmdashboard/bmProjectsRouter.js | 13 ----
src/startup/routes.js | 9 ++-
8 files changed, 38 insertions(+), 91 deletions(-)
delete mode 100644 src/controllers/bmdashboard/bmProjectsController.js
rename src/models/{ => bmdashboard}/buildingInventoryType.js (100%)
rename src/models/{ => bmdashboard}/buildingMaterial.js (100%)
delete mode 100644 src/models/buildingProject.js
delete mode 100644 src/routes/bmdashboard/bmProjectsRouter.js
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index ebf5798fa..c5403de21 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -37,18 +37,18 @@ const bmMaterialsController = function (ItemMaterial) {
};
const bmPostMaterialUpdateRecord = function (req, res) {
-
+ let payload = req.body;
let quantityUsed = +req.body.quantityUsed;
let quantityWasted = +req.body.quantityWasted;
let material = req.body.material;
- if(req.body.QtyUsedLogUnit=='percent' && quantityWasted>=0)
- {
- quantityUsed = (+quantityUsed / 100) * material.stockAvailable;
- }
- if(req.body.QtyWastedLogUnit=='percent' && quantityUsed>=0)
- {
- quantityWasted = (+quantityWasted / 100) * material.stockAvailable;
- }
+ if(payload.QtyUsedLogUnit=='percent' && quantityWasted>=0)
+ {
+ quantityUsed = +((+quantityUsed / 100) * material.stockAvailable).toFixed(4);
+ }
+ if(payload.QtyWastedLogUnit=='percent' && quantityUsed>=0)
+ {
+ quantityWasted = +((+quantityWasted / 100) * material.stockAvailable).toFixed(4);
+ }
if(quantityUsed>material.stockAvailable || quantityWasted>material.stockAvailable || (quantityUsed+quantityWasted)>material.stockAvailable)
{
@@ -56,24 +56,27 @@ const bmMaterialsController = function (ItemMaterial) {
}
else
{
- quantityUsed = +material.stockUsed + parseFloat(quantityUsed.toFixed(4));
- quantityWasted = +material.stockWasted + parseFloat(quantityWasted.toFixed(4));
- let newAvailable = +material.stockAvailable - parseFloat(quantityUsed+quantityWasted);
-
+ let newStockUsed = +material.stockUsed + parseFloat(quantityUsed);
+ let newStockWasted = +material.stockWasted + parseFloat(quantityWasted);
+ let newAvailable = +material.stockAvailable - parseFloat(quantityUsed) - parseFloat(quantityWasted);
+ newStockUsed = parseFloat(newStockUsed.toFixed(4));
+ newStockWasted = parseFloat(newStockWasted.toFixed(4));
+ newAvailable = parseFloat(newAvailable.toFixed(4));
ItemMaterial.updateOne(
{ _id: req.body.material._id },
{
$set: {
- 'stockUsed': quantityUsed,
- 'stockWasted': quantityWasted,
- 'stockAvailable': -(newAvailable)
+ 'stockUsed': newStockUsed,
+ 'stockWasted': newStockWasted,
+ 'stockAvailable': newAvailable
},
$push: {
updateRecord: {
date: req.body.date,
createdBy: req.body.requestor.requestorId,
- quantity: -(quantityUsed+quantityWasted),
+ quantityUsed: quantityUsed + ' ' + material.itemType.unit,
+ quantityWasted: quantityWasted
},
}
}
@@ -92,33 +95,34 @@ const bmMaterialsController = function (ItemMaterial) {
let material = payload.material;
if(payload.QtyUsedLogUnit=='percent' && quantityWasted>=0)
{
- quantityUsed = (+quantityUsed / 100) * material.stockAvailable;
+ quantityUsed = +((+quantityUsed / 100) * material.stockAvailable).toFixed(4);
}
if(payload.QtyWastedLogUnit=='percent' && quantityUsed>=0)
{
- quantityWasted = (+quantityWasted / 100) * material.stockAvailable;
+ quantityWasted = +((+quantityWasted / 100) * material.stockAvailable).toFixed(4);
}
- quantityUsed = +material.stockUsed + parseFloat(quantityUsed.toFixed(4));
- quantityWasted = +material.stockWasted + parseFloat(quantityWasted.toFixed(4));
- let newAvailable = +material.stockAvailable - parseFloat(quantityUsed+quantityWasted);
+ let newStockUsed = +material.stockUsed + parseFloat(quantityUsed);
+ let newStockWasted = +material.stockWasted + parseFloat(quantityWasted);
+ let newAvailable = +material.stockAvailable - parseFloat(quantityUsed) - parseFloat(quantityWasted);
+ newStockUsed = parseFloat(newStockUsed.toFixed(4));
+ newStockWasted = parseFloat(newStockWasted.toFixed(4));
newAvailable = parseFloat(newAvailable.toFixed(4));
- console.log(quantityUsed,quantityWasted,newAvailable);
return ({
updateId: material._id,
set: {
- 'stockUsed': quantityUsed,
- 'stockWasted': quantityWasted,
- 'stockAvailable': -newAvailable
+ 'stockUsed': newStockUsed,
+ 'stockWasted': newStockWasted,
+ 'stockAvailable': newAvailable
},
updateValue: {
createdBy: req.body.requestor.requestorId,
- quantity: -(newAvailable),
+ quantityUsed: quantityUsed + ' ' + material.itemType.unit,
+ quantityWasted: quantityWasted,
date: payload.date,
}});
});
- console.log(updateRecordsToBeAdded);
try {
const updatePromises = updateRecordsToBeAdded.map(updateItem => ItemMaterial.updateOne(
diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js
deleted file mode 100644
index 3ff0f851a..000000000
--- a/src/controllers/bmdashboard/bmProjectsController.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const mongoose = require('mongoose');
-const UserProfile = require('../../models/userProfile');
-
-const bmProjectsController = function () {
- // Get current user's Housing/Building projects
- const getUserActiveBMProjects = function (req, res) {
- try {
- const userId = req.body.requestor.requestorId;
- UserProfile.findById(userId)
- .populate([
- {
- path: 'projects',
- select: '_id projectName category isActive',
- match: { category: 'Housing' },
- },
- ])
- .select({
- projects: 1,
- })
- .then((results) => {
- res.status(200).send(results);
- })
- .catch(error => res.status(500).send(error));
- } catch (err) {
- res.json(err);
- }
- };
- return { getUserActiveBMProjects };
-};
-
-module.exports = bmProjectsController;
diff --git a/src/models/buildingInventoryType.js b/src/models/bmdashboard/buildingInventoryType.js
similarity index 100%
rename from src/models/buildingInventoryType.js
rename to src/models/bmdashboard/buildingInventoryType.js
diff --git a/src/models/buildingMaterial.js b/src/models/bmdashboard/buildingMaterial.js
similarity index 100%
rename from src/models/buildingMaterial.js
rename to src/models/bmdashboard/buildingMaterial.js
diff --git a/src/models/buildingProject.js b/src/models/buildingProject.js
deleted file mode 100644
index 20d26fc41..000000000
--- a/src/models/buildingProject.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const mongoose = require('mongoose');
-const { Schema } = mongoose;
-const buildingProject = new Schema({
- isActive: Boolean,
- name: String,
- template: String, // construction template (ie Earthbag Village)
- location: String, // use lat/lng instead?
- dateCreated: { type: Date, default: Date.now },
- buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }, // BM's id
- team: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }],
-});
-module.exports = mongoose.model('buildingProject', buildingProject, 'buildingProjects');
\ No newline at end of file
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index d56c682bd..a07d82b5c 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -7,10 +7,10 @@ const controller = require('../../controllers/bmdashboard/bmMaterialsController'
materialsRouter.route('/materials')
.get(controller.bmMaterialsList);
-materialsRouter.route('/addUpdateMaterialRecord')
+materialsRouter.route('/updateMaterialRecord')
.post(controller.bmPostMaterialUpdateRecord);
- materialsRouter.route('/UpdateMaterialRecordBulk')
+ materialsRouter.route('/updateMaterialRecordBulk')
.post(controller.bmPostMaterialUpdateBulk);
diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js
deleted file mode 100644
index a171fc4cd..000000000
--- a/src/routes/bmdashboard/bmProjectsRouter.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const express = require('express');
-
-const routes = function () {
-const materialsRouter = express.Router();
-const controller = require('../../controllers/bmdashboard/bmProjectsController')();
-
-materialsRouter.route('/getUserActiveBMProjects')
- .get(controller.getUserActiveBMProjects);
-
- return materialsRouter;
-};
-
-module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 201c777b9..1713d6a67 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -20,9 +20,9 @@ const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
-const buildingMaterial = require('../models/buildingMaterial');
-const buildingProject = require('../models/buildingProject');
-const buildingInventoryType = require('../models/buildingInventoryType');
+const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
+const buildingProject = require('../models/bmdashboard/buildingProject');
+const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -61,7 +61,6 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(buildingMaterial);
-const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')();
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
module.exports = function (app) {
@@ -96,6 +95,6 @@ module.exports = function (app) {
app.use('/api', isEmailExistsRouter);
// bm dashboard
app.use('/api/bm', bmLoginRouter);
- app.use('/api/bm', bmProjectsRouter);
app.use('/api/bm', bmProjectRouter);
+ app.use('/api/bm', bmMaterialsRouter);
};
From 55dd2e67cdf3b9fb91081ccb175003129c2b91d7 Mon Sep 17 00:00:00 2001
From: Aishwaryak01
Date: Sat, 11 Nov 2023 12:04:05 -0500
Subject: [PATCH 137/272] Create buildingTools.js
Created model file for buildingTools.js which consists of schema to hold various attribute information related to tools.
---
src/models/bmdashboard/buildingTools.js | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 src/models/bmdashboard/buildingTools.js
diff --git a/src/models/bmdashboard/buildingTools.js b/src/models/bmdashboard/buildingTools.js
new file mode 100644
index 000000000..94468de42
--- /dev/null
+++ b/src/models/bmdashboard/buildingTools.js
@@ -0,0 +1,19 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const buildingTools = new Schema({
+ inventoryItemId: { type: mongoose.SchemaTypes.ObjectId, ref: 'INVENTORY' }, // later ,INVENTORY needs to be changed as per inventory model
+ title: { type: String, required: true },
+ image: { type: String, required: true },
+ rentedOnDate: { type: Date, required: true },
+ rentDuration: { type: Number, required: true }, // This value should be taken in number of days
+ total: {type: Number, required: true},
+ availableCount:{type: Number, required: true},
+ logInStatus:{Boolean},
+ condition:{type: String, enum: ['Good', 'Needs Repair', 'Out of Order','Unused'], default: 'Condition'},
+ userResponsible:{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ purchaseStatus:{type: String, enum: ['Rented', 'Purchased'], default: 'Status'},
+});
+
+module.exports = mongoose.model('buildingTools', buildingTools, 'buildingTools');
\ No newline at end of file
From bd537f79f38c980eea9ba1660e6b89aff577ece8 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Mon, 13 Nov 2023 10:52:54 +0800
Subject: [PATCH 138/272] solve weekly summaries report page issue
---
src/helpers/reporthelper.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js
index c812ef03c..0c2a8104d 100644
--- a/src/helpers/reporthelper.js
+++ b/src/helpers/reporthelper.js
@@ -68,9 +68,6 @@ const reporthelper = function () {
moment(pstEnd).format("YYYY-MM-DD"),
],
},
- {
- $in: ['$$timeentry.entryType', ['default', null]],
- },
],
},
},
From 9512ea0b5241968f5721c8db526c207807f860b0 Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Mon, 13 Nov 2023 11:56:18 +0000
Subject: [PATCH 139/272] added new fields to the email options and edited the
email body
---
src/controllers/dashBoardController.js | 109 ++++++++++++-------------
1 file changed, 54 insertions(+), 55 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index aacc915dd..68e88ae58 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -1,8 +1,8 @@
-const path = require('path');
-const fs = require('fs/promises');
-const mongoose = require('mongoose');
-const dashboardhelper = require('../helpers/dashboardhelper')();
-const emailSender = require('../utilities/emailSender');
+const path = require("path");
+const fs = require("fs/promises");
+const mongoose = require("mongoose");
+const dashboardhelper = require("../helpers/dashboardhelper")();
+const emailSender = require("../utilities/emailSender");
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -20,13 +20,13 @@ const dashboardcontroller = function () {
const laborthismonth = dashboardhelper.laborthismonth(
userId,
req.params.fromDate,
- req.params.toDate,
+ req.params.toDate
);
laborthismonth.then((results) => {
if (!results || results.length === 0) {
const emptyresult = [
{
- projectName: '',
+ projectName: "",
timeSpent_hrs: 0,
},
];
@@ -42,7 +42,7 @@ const dashboardcontroller = function () {
const laborthisweek = dashboardhelper.laborthisweek(
userId,
req.params.fromDate,
- req.params.toDate,
+ req.params.toDate
);
laborthisweek.then((results) => {
res.send(results).status(200);
@@ -63,7 +63,7 @@ const dashboardcontroller = function () {
});
}
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => res.status(400).send(error));
};
const orgData = function (req, res) {
@@ -73,7 +73,7 @@ const dashboardcontroller = function () {
.then((results) => {
res.status(200).send(results[0]);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => res.status(400).send(error));
};
const getBugReportEmailBody = function (
@@ -85,7 +85,7 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity,
+ severity
) {
const text = `New Bug Report From ${firstName} ${lastName}:
[Feature Name] Bug Title:
@@ -130,32 +130,32 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity,
+ severity
);
try {
emailSender(
- 'onecommunityglobal@gmail.com',
+ "onecommunityglobal@gmail.com",
`Bug Rport from ${firstName} ${lastName}`,
emailBody,
- email,
+ email
);
- res.status(200).send('Success');
+ res.status(200).send("Success");
} catch {
- res.status(500).send('Failed');
+ res.status(500).send("Failed");
}
};
const suggestionData = {
suggestion: [
- 'Identify and remedy poor client and/or user service experiences',
- 'Identify bright spots and enhance positive service experiences',
- 'Make fundamental changes to our programs and/or operations',
- 'Inform the development of new programs/projects',
- 'Identify where we are less inclusive or equitable across demographic groups',
- 'Strengthen relationships with the people we serve',
+ "Identify and remedy poor client and/or user service experiences",
+ "Identify bright spots and enhance positive service experiences",
+ "Make fundamental changes to our programs and/or operations",
+ "Inform the development of new programs/projects",
+ "Identify where we are less inclusive or equitable across demographic groups",
+ "Strengthen relationships with the people we serve",
"Understand people's needs and how we can help them achieve their goals",
- 'Other',
+ "Other",
],
field: [],
};
@@ -164,54 +164,53 @@ const dashboardcontroller = function () {
let fieldaaray = [];
if (suggestionData.field.length) {
fieldaaray = suggestionData.field.map(
- item => `${item}
- ${args[3][item]}
`,
+ (item) => `${item}
+ ${args[3][item]}
`
);
}
const text = `New Suggestion From ${args[3].firstName} ${
args[3].lastName
- }:
- Suggestion Category:
+ }
+ :
+ ⚹ Suggestion Category:
${args[0]}
- Suggestion:
+ ⚹ Suggestion:
${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ''}
- Name of Suggester:
+ ${fieldaaray.length > 0 ? fieldaaray : ""}
+ ⚹ Name of Suggester:
${args[3].firstName} ${args[3].lastName}
- Email of Suggester:
+ ⚹ Email of Suggester:
${args[4]}
- Wants Feedback:
+ ⚹ Wants Feedback:
${args[2]}
- Thank you,
- One Community
`;
+ Thank you,
+ One Community`;
return text;
};
// send suggestion email
const sendMakeSuggestion = async (req, res) => {
- const {
- suggestioncate, suggestion, confirm, email, ...rest
-} = req.body;
+ const { suggestioncate, suggestion, confirm, email, ...rest } = req.body;
const emailBody = await getsuggestionEmailBody(
suggestioncate,
suggestion,
confirm,
rest,
- email,
+ email
);
try {
emailSender(
- 'beblicarl.cb@gmail.com',
- 'A new suggestion',
+ "onecommunityglobal@gmail.com",
+ "A new suggestion",
emailBody,
null,
null,
- email,
+ email
);
- res.status(200).send('Success');
+ res.status(200).send("Success");
} catch {
- res.status(500).send('Failed');
+ res.status(500).send("Failed");
}
};
@@ -220,40 +219,40 @@ const dashboardcontroller = function () {
if (suggestionData) {
res.status(200).send(suggestionData);
} else {
- res.status(404).send('Suggestion data not found.');
+ res.status(404).send("Suggestion data not found.");
}
} catch (error) {
- console.error('Error getting suggestion data:', error);
- res.status(500).send('Internal Server Error');
+ console.error("Error getting suggestion data:", error);
+ res.status(500).send("Internal Server Error");
}
};
const editSuggestionOption = async (req, res) => {
try {
if (req.body.suggestion) {
- if (req.body.action === 'add') {
+ if (req.body.action === "add") {
suggestionData.suggestion.unshift(req.body.newField);
}
- if (req.body.action === 'delete') {
+ if (req.body.action === "delete") {
suggestionData.suggestion = suggestionData.suggestion.filter(
- (item, index) => index + 1 !== +req.body.newField,
+ (item, index) => index + 1 !== +req.body.newField
);
}
} else {
- if (req.body.action === 'add') {
+ if (req.body.action === "add") {
suggestionData.field.unshift(req.body.newField);
}
- if (req.body.action === 'delete') {
+ if (req.body.action === "delete") {
suggestionData.field = suggestionData.field.filter(
- item => item !== req.body.newField,
+ (item) => item !== req.body.newField
);
}
}
- res.status(200).send('success');
+ res.status(200).send("success");
} catch (error) {
- console.error('Error editing suggestion option:', error);
- res.status(500).send('Internal Server Error');
+ console.error("Error editing suggestion option:", error);
+ res.status(500).send("Internal Server Error");
}
};
From db3a8703a27fce2f9b3d926f725d0c889bb7ee2b Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Mon, 13 Nov 2023 11:58:25 +0000
Subject: [PATCH 140/272] added new fields in the email options
---
src/utilities/emailSender.js | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/utilities/emailSender.js b/src/utilities/emailSender.js
index 98ca3e337..b4864add6 100644
--- a/src/utilities/emailSender.js
+++ b/src/utilities/emailSender.js
@@ -1,6 +1,6 @@
-const nodemailer = require("nodemailer");
-const { google } = require("googleapis");
-const logger = require("../startup/logger");
+const nodemailer = require('nodemailer');
+const { google } = require('googleapis');
+const logger = require('../startup/logger');
const closure = () => {
const queue = [];
@@ -12,9 +12,9 @@ const closure = () => {
const REFRESH_TOKEN = process.env.REACT_APP_EMAIL_REFRESH_TOKEN;
// Create the email envelope (transport)
const transporter = nodemailer.createTransport({
- service: "gmail",
+ service: 'gmail',
auth: {
- type: "OAuth2",
+ type: 'OAuth2',
user: CLIENT_EMAIL,
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
@@ -24,7 +24,7 @@ const closure = () => {
const OAuth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
- REDIRECT_URI
+ REDIRECT_URI,
);
OAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
@@ -34,7 +34,9 @@ const closure = () => {
if (!nextItem) return;
- const { recipient, subject, message, cc, bcc, replyTo } = nextItem;
+ const {
+ recipient, subject, message, cc, bcc, replyTo,
+} = nextItem;
try {
// Generate the accessToken on the fly
@@ -69,7 +71,7 @@ const closure = () => {
message,
cc = null,
bcc = null,
- replyTo = null
+ replyTo = null,
) {
if (process.env.sendEmail) {
queue.push({
From 54aeac506b0cba57b56fe7999742e135de4642ec Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Mon, 13 Nov 2023 14:36:42 -0500
Subject: [PATCH 141/272] merging development
---
src/controllers/badgeController.js | 3 +
.../bmdashboard/bmMaterialsController.js | 24 +++---
.../bmdashboard/bmProjectController.js | 79 +++++++++++++++++++
src/helpers/userHelper.js | 45 +++++++++--
src/models/bmdashboard/buildingProject.js | 15 ++++
src/models/inventoryItemMaterial.js | 6 +-
src/routes/bmdashboard/bmMaterialsRouter.js | 4 +-
src/routes/bmdashboard/bmProjectRouter.js | 16 ++++
src/startup/routes.js | 4 +
src/utilities/escapeRegex.js | 2 +-
10 files changed, 172 insertions(+), 26 deletions(-)
create mode 100644 src/controllers/bmdashboard/bmProjectController.js
create mode 100644 src/models/bmdashboard/buildingProject.js
create mode 100644 src/routes/bmdashboard/bmProjectRouter.js
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 62bad6399..366c9323e 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -2,6 +2,7 @@ const mongoose = require('mongoose');
const UserProfile = require('../models/userProfile');
const { hasPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
+const cache = require('../utilities/nodeCache')();
const badgeController = function (Badge) {
const getAllBadges = async function (req, res) {
@@ -47,6 +48,8 @@ const badgeController = function (Badge) {
if (result) {
record.badgeCollection = req.body.badgeCollection;
+ if (cache.hasCache(`user-${userToBeAssigned}`)) cache.removeCache(`user-${userToBeAssigned}`);
+
record.save()
.then(results => res.status(201).send(results._id))
.catch(errors => res.status(500).send(errors));
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index a31ed460e..fb6003e90 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,4 +1,4 @@
-const mongoose = require('mongoose')
+const mongoose = require('mongoose');
const bmMaterialsController = function (ItemMaterial) {
const bmMaterialsList = async function _matsList(req, res) {
@@ -7,37 +7,37 @@ const bmMaterialsController = function (ItemMaterial) {
.populate([
{
path: 'project',
- select: '_id projectName'
+ select: '_id projectName',
},
{
path: 'inventoryItemType',
- select: '_id name uom totalStock totalAvailable'
+ select: '_id name uom totalStock totalAvailable',
},
{
path: 'usageRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
+ select: '_id firstName lastName',
+ },
},
{
path: 'updateRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
+ select: '_id firstName lastName',
+ },
},
{
path: 'purchaseRecord',
populate: {
path: 'createdBy',
- select: '_id firstName lastName'
- }
- }
+ select: '_id firstName lastName',
+ },
+ },
])
.exec()
.then(results => res.status(200).send(results))
- .catch(error => res.status(500).send(error))
+ .catch(error => res.status(500).send(error));
} catch (err) {
res.json(err);
}
@@ -45,4 +45,4 @@ const bmMaterialsController = function (ItemMaterial) {
return { bmMaterialsList };
};
-module.exports = bmMaterialsController;
\ No newline at end of file
+module.exports = bmMaterialsController;
diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js
new file mode 100644
index 000000000..929aba4ba
--- /dev/null
+++ b/src/controllers/bmdashboard/bmProjectController.js
@@ -0,0 +1,79 @@
+// TODO: uncomment when executing auth checks
+// const jwt = require('jsonwebtoken');
+// const config = require('../../config');
+
+const bmMProjectController = function (BuildingProject) {
+ // TODO: uncomment when executing auth checks
+ // const { JWT_SECRET } = config;
+
+ const fetchAllProjects = async (req, res) => {
+ //! Note: for easier testing this route currently returns all projects from the db
+ // TODO: uncomment the lines below to return only projects where field buildingManager === userid
+ // const token = req.headers.authorization;
+ // const { userid } = jwt.verify(token, JWT_SECRET);
+ try {
+ const projectData = await BuildingProject
+ // TODO: uncomment this line to filter by buildingManager field
+ // .find({ buildingManager: userid })
+ .find()
+ .populate([
+ {
+ path: 'buildingManager',
+ select: '_id firstName lastName email',
+ },
+ {
+ path: 'team',
+ select: '_id firstName lastName email',
+ },
+ ])
+ .exec()
+ .then(result => result)
+ .catch(error => res.status(500).send(error));
+ res.status(200).send(projectData);
+ } catch (err) {
+ res.json(err);
+ }
+ };
+
+ // fetches single project by project id
+ const fetchSingleProject = async (req, res) => {
+ //! Note: for easier testing this route currently returns the project without an auth check
+ // TODO: uncomment the lines below to check the user's ability to view the current project
+ // const token = req.headers.authorization;
+ // const { userid } = jwt.verify(token, JWT_SECRET);
+ const { projectId } = req.params;
+ try {
+ BuildingProject
+ .findById(projectId)
+ .populate([
+ {
+ path: 'buildingManager',
+ select: '_id firstName lastName email',
+ },
+ {
+ path: 'team',
+ select: '_id firstName lastName email',
+ },
+ ])
+ .exec()
+ .then(project => res.status(200).send(project))
+ // TODO: uncomment this block to execute the auth check
+ // authenticate request by comparing userId param with buildingManager id field
+ // Note: _id has type object and must be converted to string
+ // .then((project) => {
+ // if (userid !== project.buildingManager._id.toString()) {
+ // return res.status(403).send({
+ // message: 'You are not authorized to view this record.',
+ // });
+ // }
+ // return res.status(200).send(project);
+ // })
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return { fetchAllProjects, fetchSingleProject };
+};
+
+module.exports = bmMProjectController;
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index af416f1a7..c75dd7b45 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -87,8 +87,18 @@ const userHelper = function () {
firstName,
lastName,
infringement,
- totalInfringements
+ totalInfringements,
+ timeRemaining
) {
+ let final_paragraph = '';
+
+ if (timeRemaining == undefined) {
+ final_paragraph = 'Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
';
+ } else {
+ final_paragraph = `Life happens and we understand that. Please make up the missed hours this following week though to avoid getting another blue square. So you know what’s needed, the missing/incomplete hours (${timeRemaining} hours) have been added to your current week and this new weekly total can be seen at the top of your dashboard.
+ Reminder also that each blue square is removed from your profile 1 year after it was issued.
`;
+ }
+
const text = `Dear ${firstName} ${lastName},
Oops, it looks like something happened and you’ve managed to get a blue square.
Date Assigned: ${infringement.date}
@@ -96,9 +106,10 @@ const userHelper = function () {
Total Infringements: This is your ${moment
.localeData()
.ordinal(totalInfringements)} blue square of 5.
- Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
+ ${final_paragraph}
Thank you,
One Community
`;
+
return text;
};
@@ -322,6 +333,8 @@ const userHelper = function () {
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
+ const person = await userProfile.findById(user._id);
+
const foundReason = await Reason.findOne({
date: currentUTCDate,
userId: user._id,
@@ -356,6 +369,9 @@ const userHelper = function () {
const timeNotMet = timeSpent < weeklycommittedHours;
let description;
+ const timeRemaining = weeklycommittedHours - timeSpent;
+
+
const updateResult = await userProfile.findByIdAndUpdate(
personId,
{
@@ -446,15 +462,28 @@ const userHelper = function () {
{ new: true }
);
- emailSender(
- status.email,
- "New Infringement Assigned",
- getInfringementEmailBody(
+ let emailBody = '';
+ if (person.role == 'Core Team' && timeRemaining > 0) {
+ emailBody = getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
- status.infringements.length
- ),
+ status.infringements.length,
+ timeRemaining,
+ );
+ } else {
+ emailBody = getInfringementEmailBody(
+ status.firstName,
+ status.lastName,
+ infringement,
+ status.infringements.length,
+ );
+ }
+
+ emailSender(
+ status.email,
+ 'New Infringement Assigned',
+ emailBody,
null,
"onecommunityglobal@gmail.com"
);
diff --git a/src/models/bmdashboard/buildingProject.js b/src/models/bmdashboard/buildingProject.js
new file mode 100644
index 000000000..566bc124e
--- /dev/null
+++ b/src/models/bmdashboard/buildingProject.js
@@ -0,0 +1,15 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const buildingProject = new Schema({
+ isActive: Boolean,
+ name: String,
+ template: String, // construction template (ie Earthbag Village)
+ location: String, // use lat/lng instead?
+ dateCreated: { type: Date, default: Date.now },
+ buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }, // BM's id
+ team: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }],
+});
+
+module.exports = mongoose.model('buildingProject', buildingProject, 'buildingProjects');
diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js
index e6153af45..8460ecd6e 100644
--- a/src/models/inventoryItemMaterial.js
+++ b/src/models/inventoryItemMaterial.js
@@ -29,12 +29,12 @@ const InventoryItemMaterial = new Schema({
poId: { type: String, required: true },
sellerId: { type: String, required: true },
quantity: { type: Number, required: true }, // adds to stockBought
- unitPrice: {type: Number, required: true},
+ unitPrice: { type: Number, required: true },
currency: { type: String, required: true },
subtotal: { type: Number, required: true },
tax: { type: Number, required: true },
shipping: { type: Number, required: true },
- }]
-})
+ }],
+});
module.exports = mongoose.model('inventoryItemMaterial', InventoryItemMaterial, 'inventoryMaterial');
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index ab8a67388..1188acf9d 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -8,6 +8,6 @@ materialsRouter.route('/materials')
.get(controller.bmMaterialsList);
return materialsRouter;
-}
+};
-module.exports = routes;
\ No newline at end of file
+module.exports = routes;
diff --git a/src/routes/bmdashboard/bmProjectRouter.js b/src/routes/bmdashboard/bmProjectRouter.js
new file mode 100644
index 000000000..d60ea9b2b
--- /dev/null
+++ b/src/routes/bmdashboard/bmProjectRouter.js
@@ -0,0 +1,16 @@
+const express = require('express');
+
+const routes = function (buildingProject) {
+ const projectRouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmProjectController')(buildingProject);
+
+projectRouter.route('/projects')
+ .get(controller.fetchAllProjects);
+
+projectRouter.route('/project/:projectId')
+ .get(controller.fetchSingleProject);
+
+ return projectRouter;
+};
+
+module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 0f4c7308c..c7a7393c9 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -22,6 +22,8 @@ const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const mapLocations = require('../models/mapLocation');
+const buildingProject = require('../models/bmdashboard/buildingProject');
+
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -62,6 +64,7 @@ const mapLocationRouter = require('../routes/mapLocationsRouter')(mapLocations);
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
+const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -97,4 +100,5 @@ module.exports = function (app) {
// bm dashboard
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
+ app.use('/api/bm', bmProjectRouter);
};
diff --git a/src/utilities/escapeRegex.js b/src/utilities/escapeRegex.js
index 10fa2e61e..01a65ea50 100644
--- a/src/utilities/escapeRegex.js
+++ b/src/utilities/escapeRegex.js
@@ -1,6 +1,6 @@
const escapeRegex = function (text) {
- return text.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&');
+ return `^${text.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&')}&`;
};
module.exports = escapeRegex;
From 8009191ffa3dd7333bd0d84b8162e3d231bd8440 Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Tue, 14 Nov 2023 15:28:08 +0800
Subject: [PATCH 142/272] reduce redundant code
---
src/controllers/projectController.js | 2 +-
src/controllers/timeEntryController.js | 27 ++++++++++---------
src/helpers/dashboardhelper.js | 7 +++--
src/helpers/taskHelper.js | 2 +-
src/helpers/userHelper.js | 36 +++++++++++++-------------
5 files changed, 36 insertions(+), 38 deletions(-)
diff --git a/src/controllers/projectController.js b/src/controllers/projectController.js
index dc92af354..a88378985 100644
--- a/src/controllers/projectController.js
+++ b/src/controllers/projectController.js
@@ -28,7 +28,7 @@ const projectController = function (Project) {
// find if project has any time entries associated with it
- timeentry.find({ projectId: record._id, entryType: [ 'default', 'project', null ] }, '_id')
+ timeentry.find({ projectId: record._id }, '_id')
.then((timeentries) => {
if (timeentries.length > 0) {
res.status(400).send({ error: 'This project has associated time entries and cannot be deleted. Consider inactivaing it instead.' });
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index aa7eff6ae..8adc6693d 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -236,7 +236,7 @@ const timeEntrycontroller = function (TimeEntry) {
}
const items = [];
records.forEach((element) => {
- if (element.entryType == 'default' || element.entryType == undefined) {
+ if (element.entryType === 'default' || element.entryType === undefined) {
const timeentry = new TimeEntry();
timeentry.personId = element.personId;
timeentry.projectId = element.projectId;
@@ -265,7 +265,7 @@ const timeEntrycontroller = function (TimeEntry) {
};
switch (req.body.entryType) {
- case 'default':
+ default:
if (
!mongoose.Types.ObjectId.isValid(req.body.personId)
|| !mongoose.Types.ObjectId.isValid(req.body.projectId)
@@ -321,18 +321,18 @@ const timeEntrycontroller = function (TimeEntry) {
res.status(400).send(error);
});
- // Add this tangbile time entry to related task's hoursLogged
- if ((timeentry.entryType === 'default') && timeentry.isTangible === true) {
- try {
- const currentTask = await task.findById(req.body.projectId);
- currentTask.hoursLogged += (timeentry.totalSeconds / 3600);
- await currentTask.save();
- } catch (error) {
- throw new Error('Failed to find the task by id');
- }
- }
- // checking if logged in hours exceed estimated time after timeentry for a task
if (timeentry.entryType === 'default') {
+ // Add this tangbile time entry to related task's hoursLogged
+ if (timeentry.isTangible === true) {
+ try {
+ const currentTask = await task.findById(req.body.projectId);
+ currentTask.hoursLogged += (timeentry.totalSeconds / 3600);
+ await currentTask.save();
+ } catch (error) {
+ throw new Error('Failed to find the task by id');
+ }
+ }
+ // checking if logged in hours exceed estimated time after timeentry for a task
const record = await userProfile.findById(timeentry.personId.toString());
const currentTask = await task.findById(req.body.projectId);
checkTaskOvertime(timeentry, record, currentTask);
@@ -492,7 +492,6 @@ const timeEntrycontroller = function (TimeEntry) {
const { projectId } = req.params;
TimeEntry.find(
{
- entryType: ['default', null],
projectId,
dateOfWork: { $gte: fromDate, $lte: todate },
},
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 1c03c2f88..041b4e948 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -165,7 +165,6 @@ const dashboardhelper = function () {
.tz('America/Los_Angeles')
.endOf('week')
.format('YYYY-MM-DD');
- const entryTypes = ['default', null];
return myTeam.aggregate([
{
$match: {
@@ -196,7 +195,7 @@ const dashboardhelper = function () {
// leaderboard user roles hierarchy
$or: [
{
- role: { $in: ['Owner', 'Core Team'] },
+ role: { $in: ['Owner', 'Core Team'] },
},
{
$and: [
@@ -289,7 +288,7 @@ const dashboardhelper = function () {
},
{
$in: ['$$timeentry.entryType', ['default', null]],
- }
+ },
],
},
},
@@ -445,7 +444,7 @@ const dashboardhelper = function () {
$gte: pdtStart,
$lte: pdtEnd,
},
- eentryType: { $in: [ 'default', null ] },
+ entryType: { $in: ['default', null] },
personId: userId,
});
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 30bb220e9..b91020039 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -43,7 +43,7 @@ const taskHelper = function () {
// dashboard tasks user roles hierarchy
$or: [
{
- role: { $in: ['Owner', 'Core Team'] },
+ role: { $in: ['Owner', 'Core Team'] },
},
{
$and: [
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 5824d5d73..be9e40bbc 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -578,31 +578,31 @@ const userHelper = function () {
const missedHours = await userProfile.aggregate([
{
$match: {
- role: "Core Team",
- isActive: true
- }
+ role: 'Core Team',
+ isActive: true,
+ },
},
{
$lookup: {
- from: "timeEntries",
- localField: "_id",
- foreignField: "personId",
+ from: 'timeEntries',
+ localField: '_id',
+ foreignField: 'personId',
pipeline: [
{
$match: {
$expr: {
$and: [
- { $eq: ["$isTangible", true] },
- { $gte: ["$dateOfWork", startOfLastWeek] },
- { $lte: ["$dateOfWork", endOfLastWeek] },
- { $in: ['$entryType', 'default', null] }
- ]
- }
- }
- }
+ { $eq: ['$isTangible', true] },
+ { $gte: ['$dateOfWork', startOfLastWeek] },
+ { $lte: ['$dateOfWork', endOfLastWeek] },
+ { $in: ['$entryType', 'default', null] },
+ ],
+ },
+ },
+ },
],
- as: "timeEntries"
- }
+ as: 'timeEntries',
+ },
},
{
$project: {
@@ -621,8 +621,8 @@ const userHelper = function () {
{
$sum: {
$map: {
- input: "$timeEntries",
- in: "$$this.totalSeconds"
+ input: '$timeEntries',
+ in: '$$this.totalSeconds',
}
}
},
From 9036fb629a2a816651ed988d61c7bc6626735c89 Mon Sep 17 00:00:00 2001
From: Eduardo Horta
Date: Tue, 14 Nov 2023 13:48:59 -0300
Subject: [PATCH 143/272] Added .nvmrc file. Node v14.
---
.nvmrc | 1 +
1 file changed, 1 insertion(+)
create mode 100644 .nvmrc
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 000000000..518633e16
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+lts/fermium
From 0fbbe6183f908f873b7c170747997954a42e4504 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 14 Nov 2023 15:22:25 -0800
Subject: [PATCH 144/272] update to routes, router, controller
---
.../bmdashboard/bmMaterialsController.js | 92 ++++++++++---------
src/routes/bmdashboard/bmMaterialsRouter.js | 8 +-
src/startup/routes.js | 7 +-
3 files changed, 56 insertions(+), 51 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index d8bcfe7df..a2e87eec2 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,6 +1,9 @@
-// const mongoose = require('mongoose')
+const mongoose = require('mongoose');
-const bmMaterialsController = function (ItemMaterial) {
+// use in bmPurchaseMaterials auth check (see below)
+// const buildingProject = require('../../models/bmdashboard/buildingProject');
+
+const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
const bmMaterialsList = async function _matsList(req, res) {
try {
ItemMaterial.find()
@@ -43,57 +46,58 @@ const bmMaterialsController = function (ItemMaterial) {
}
};
- const bmAddMaterials = async function (req, res) {
- // add permission check...
-
- const { material, requestor } = req.body;
- const purchaseRecord = {
- date: material.purchaseDate,
- createdBy: requestor.requestorId,
- poId: material.invoice,
- sellerId: material.phone,
- quantity: material.quantity,
- unitPrice: material.unitPrice,
- currency: material.currency,
- subtotal: material.quantity,
- tax: material.taxRate,
- shipping: material.shippingFee,
+ const bmPurchaseMaterials = async function (req, res) {
+ const {
+ projectId,
+ matTypeId,
+ quantity,
+ requestor: { requestorId },
+ } = req.body;
+ const newPurchaseRecord = {
+ quantity,
+ requestedBy: requestorId,
};
-
try {
- const result = await ItemMaterial.findOneAndUpdate(
- { project: material.projectId, inventoryItemType: material.material },
- {
- $inc: { stockBought: material.quantity, stockAvailable: material.quantity },
- $push: { purchaseRecord },
- },
- { returnDocument: 'after', lean: true },
- )
- .exec();
- if (result) {
- console.log(result);
- res.status(201).send(result);
- } else {
- const itemMaterial = new ItemMaterial({
- inventoryItemType: material.material,
- project: material.projectId,
- stockBought: material.quantity,
- stockAvailable: material.quantity,
- usageRecord: [],
- updateRecord: [],
- purchaseRecord: [purchaseRecord],
- });
- const newItemMaterial = await itemMaterial.save();
- res.status(201).send(newItemMaterial);
+ // check if requestor has permission to make purchase request
+ //! Note: this code is disabled until permissions are added
+ // TODO: uncomment this code to execute auth check
+ // const { buildingManager: bmId } = await buildingProject.findById(projectId, 'buildingManager').exec();
+ // if (bmId !== requestorId) {
+ // res.status(403).send({ message: 'You are not authorized to edit this record.' });
+ // return;
+ // }
+
+ // check if the material is already being used in the project
+ // if no, add a new document to the collection
+ // if yes, update the existing document
+ const doc = await BuildingMaterial.findOne({ project: projectId, itemType: matTypeId });
+ if (!doc) {
+ const newDoc = {
+ itemType: matTypeId,
+ project: projectId,
+ purchaseRecord: [newPurchaseRecord],
+ };
+ BuildingMaterial
+ .create(newDoc)
+ .then(() => res.status(201).send())
+ .catch(error => res.status(500).send(error));
+ return;
}
+ BuildingMaterial
+ .findOneAndUpdate(
+ { _id: mongoose.Types.ObjectId(doc._id) },
+ { $push: { purchaseRecord: newPurchaseRecord } },
+ )
+ .exec()
+ .then(() => res.status(201).send())
+ .catch(error => res.status(500).send(error));
} catch (error) {
res.status(500).send(error);
}
};
-
return {
bmMaterialsList,
- bmAddMaterials,
+ bmPurchaseMaterials,
};
};
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index 66dc6c985..da29c35d7 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -1,13 +1,11 @@
const express = require('express');
-const routes = function (itemMaterial, itemType) {
+const routes = function (itemMaterial, buildingMaterial) {
const materialsRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial, itemType);
-
+ const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial, buildingMaterial);
materialsRouter.route('/materials')
.get(controller.bmMaterialsList)
- .post(controller.bmAddMaterials);
-
+ .post(controller.bmPurchaseMaterials);
return materialsRouter;
};
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 2c8aced29..b1989698a 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -22,7 +22,8 @@ const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const buildingProject = require('../models/bmdashboard/buildingProject');
-
+const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
+const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -60,8 +61,9 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, inventoryItemType);
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, buildingMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
+const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(buildingInventoryType);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -97,4 +99,5 @@ module.exports = function (app) {
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
app.use('/api/bm', bmProjectRouter);
+ app.use('/api/bm', bmInventoryTypeRouter);
};
From 9c0d47bbd82e22dc97d4463ad2f01bc7d58f0a19 Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Tue, 14 Nov 2023 16:21:36 -0800
Subject: [PATCH 145/272] Remove console.log
---
src/controllers/reasonSchedulingController.js | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 98dd152ff..050b9a42b 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -88,11 +88,10 @@ const postReason = async (req, res) => {
//await newReason.save();
- console.log("Inside post sending email function.");
- const savedData = await newReason.save();
+ const savedData = await newReason.save();
if(savedData)
{
- console.log("Inside if.");
+
//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`;
@@ -105,15 +104,15 @@ const postReason = async (req, res) => {
Thank you,
One Community
`;
- console.log("line before email sender")
+
- // 1 hardcoded email- emailSender('shreetesting4@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);
//3 - user email and hardcoded email ( After PR approval hardcode Jae's email)
- // emailSender(`${foundUser.email},shreetesting4@gmail.com`, subject, emailBody, null, null);
+ // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null);
}
return res.sendStatus(200);
@@ -260,11 +259,11 @@ const patchReason = async (req, res) => {
}
foundReason.reason = reasonData.message;
- console.log("patchReason----------");
+
const savedData = await foundReason.save();
if(savedData)
{
- console.log(" Patch - Inside if.");
+
//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`;
@@ -277,15 +276,15 @@ const patchReason = async (req, res) => {
Thank you,
One Community
`;
- console.log("line before email sender")
- // 1 hardcoded email- emailSender('shreetesting4@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);
//3 - user email and hardcoded email ( After PR approval hardcode Jae's email)
- // emailSender(`${foundUser.email},shreetesting4@gmail.com`, subject, emailBody, null, null);
+ // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null);
}
From cec78db63afed949828395476c4d73f914e6133b Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 15 Nov 2023 17:04:41 -0800
Subject: [PATCH 146/272] add priority, brand fields to controller. update
material schema.
---
src/controllers/bmdashboard/bmMaterialsController.js | 4 ++++
src/models/bmdashboard/buildingMaterial.js | 12 +++++++-----
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index a2e87eec2..a8090ebd9 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -51,10 +51,14 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
projectId,
matTypeId,
quantity,
+ priority,
+ brand,
requestor: { requestorId },
} = req.body;
const newPurchaseRecord = {
quantity,
+ priority,
+ brand,
requestedBy: requestorId,
};
try {
diff --git a/src/models/bmdashboard/buildingMaterial.js b/src/models/bmdashboard/buildingMaterial.js
index 714ba4ae7..4170443e0 100644
--- a/src/models/bmdashboard/buildingMaterial.js
+++ b/src/models/bmdashboard/buildingMaterial.js
@@ -13,15 +13,17 @@ const buildingMaterial = new Schema({
_id: false, // do not add _id field to subdocument
date: { type: Date, default: Date.now() },
requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantity: Number,
- status: { type: String, default: 'Pending' }, // Pending, Rejected, Approved
+ quantity: { type: Number, required: true },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ brand: String,
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
}],
updateRecord: [{
_id: false,
- date: Date,
+ date: { type: Date, required: true },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantityUsed: String, // '10 cubic yards'
- quantityWasted: Number,
+ quantityUsed: { type: Number, required: true },
+ quantityWasted: { type: Number, required: true },
}],
});
From aec7cb8db3697737dbaa971ad65d3c45406ed78c Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 15 Nov 2023 17:21:32 -0800
Subject: [PATCH 147/272] update materials completed
---
src/controllers/bmdashboard/bmMaterialsController.js | 4 ++--
src/models/bmdashboard/buildingMaterial.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index c5403de21..502a2014a 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -75,7 +75,7 @@ const bmMaterialsController = function (ItemMaterial) {
updateRecord: {
date: req.body.date,
createdBy: req.body.requestor.requestorId,
- quantityUsed: quantityUsed + ' ' + material.itemType.unit,
+ quantityUsed: quantityUsed,
quantityWasted: quantityWasted
},
}
@@ -117,7 +117,7 @@ const bmMaterialsController = function (ItemMaterial) {
},
updateValue: {
createdBy: req.body.requestor.requestorId,
- quantityUsed: quantityUsed + ' ' + material.itemType.unit,
+ quantityUsed: quantityUsed,
quantityWasted: quantityWasted,
date: payload.date,
}});
diff --git a/src/models/bmdashboard/buildingMaterial.js b/src/models/bmdashboard/buildingMaterial.js
index c1d74b879..8e49219f2 100644
--- a/src/models/bmdashboard/buildingMaterial.js
+++ b/src/models/bmdashboard/buildingMaterial.js
@@ -16,7 +16,7 @@ const buildingMaterial = new Schema({
updateRecord: [{
date: Date,
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantityUsed: String, // '10 cubic yards'
+ quantityUsed: Number,
quantityWasted: Number,
}],
});
From 89233e9869ff9273613e61a8fea8f6331002618f Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Wed, 15 Nov 2023 21:01:48 -0600
Subject: [PATCH 148/272] add setMapLocation
---
.../profileInitialSetupController.js | 27 ++++++++++++++++++-
src/routes/profileInitialSetupRouter.js | 6 +++--
src/startup/middleware.js | 2 +-
src/startup/routes.js | 2 +-
4 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index b4230f1a4..21113c0fd 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -79,7 +79,8 @@ function informManagerMessage(user) {
const profileInitialSetupController = function (
ProfileInitialSetupToken,
userProfile,
- Project
+ Project,
+ MapLocation
) {
const { JWT_SECRET } = config;
@@ -297,11 +298,35 @@ const profileInitialSetupController = function (
}
};
+
+ const setMapLocation = async (req,res) => {
+
+ const locationData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.location,
+ }
+ const location = new MapLocation(locationData);
+
+ try {
+ const response = await location.save()
+ if (!response) {
+ throw new Error('Something went wrong during saving the location...')
+ }
+ res.status(200).send(response);
+ } catch (err) {
+ console.log(err.message)
+ res.status(500).json({ message: err.message || 'Something went wrong...' });
+ }
+ }
+
return {
getSetupToken,
setUpNewUser,
validateSetupToken,
getTimeZoneAPIKeyByToken,
+ setMapLocation
};
};
diff --git a/src/routes/profileInitialSetupRouter.js b/src/routes/profileInitialSetupRouter.js
index a23c6a868..0e5b050c7 100644
--- a/src/routes/profileInitialSetupRouter.js
+++ b/src/routes/profileInitialSetupRouter.js
@@ -1,13 +1,15 @@
const express = require('express');
-const routes = function (ProfileInitialSetupToken, userProfile, Project) {
+const routes = function (ProfileInitialSetupToken, userProfile, Project , mapLocations) {
const ProfileInitialSetup = express.Router();
- const controller = require('../controllers/profileInitialSetupController')(ProfileInitialSetupToken, userProfile, Project);
+ const controller = require('../controllers/profileInitialSetupController')(ProfileInitialSetupToken, userProfile, Project , mapLocations);
ProfileInitialSetup.route('/getInitialSetuptoken')
.post(controller.getSetupToken);
ProfileInitialSetup.route('/ProfileInitialSetup').post(controller.setUpNewUser)
ProfileInitialSetup.route('/validateToken').post(controller.validateSetupToken)
ProfileInitialSetup.route('/getTimeZoneAPIKeyByToken').post(controller.getTimeZoneAPIKeyByToken)
+ ProfileInitialSetup.route('/mapLocationsToken').post(controller.setMapLocation)
+
return ProfileInitialSetup;
};
diff --git a/src/startup/middleware.js b/src/startup/middleware.js
index 23ce1d4a6..16916c9f3 100644
--- a/src/startup/middleware.js
+++ b/src/startup/middleware.js
@@ -22,7 +22,7 @@ module.exports = function (app) {
next();
return;
}
- if (req.originalUrl === '/api/ProfileInitialSetup' || req.originalUrl === '/api/validateToken' || req.originalUrl === '/api/getTimeZoneAPIKeyByToken' && req.method === 'POST'
+ if (req.originalUrl === '/api/ProfileInitialSetup' || req.originalUrl === '/api/validateToken' || req.originalUrl === '/api/getTimeZoneAPIKeyByToken' && req.method === 'POST' || req.originalUrl === '/api/mapLocationsToken' && req.method === 'POST'
) {
next();
return;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 99e761f75..d4dcb3685 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -45,7 +45,7 @@ const popupBackupRouter = require('../routes/popupEditorBackupRouter')(popupBack
const taskNotificationRouter = require('../routes/taskNotificationRouter')(taskNotification);
const inventoryRouter = require('../routes/inventoryRouter')(inventoryItem, inventoryItemType);
const timeZoneAPIRouter = require('../routes/timeZoneAPIRoutes')();
-const profileInitialSetupRouter = require('../routes/profileInitialSetupRouter')(profileInitialSetuptoken, userProfile, project);
+const profileInitialSetupRouter = require('../routes/profileInitialSetupRouter')(profileInitialSetuptoken, userProfile, project , mapLocations);
const isEmailExistsRouter = require('../routes/isEmailExistsRouter')();
From 7542d5c29e6f8657e59e77af12b7b4ee15391477 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 15 Nov 2023 20:25:45 -0800
Subject: [PATCH 149/272] update inv type schema
---
src/models/bmdashboard/buildingInventoryType.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/models/bmdashboard/buildingInventoryType.js b/src/models/bmdashboard/buildingInventoryType.js
index 71285fa24..8d2364c64 100644
--- a/src/models/bmdashboard/buildingInventoryType.js
+++ b/src/models/bmdashboard/buildingInventoryType.js
@@ -3,10 +3,10 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
const buildingInventoryType = new Schema({
- category: String, // Consumable, Material, Tool, Equipment
- name: String,
- description: String,
- unit: String, // unit of measurement
+ category: { type: String, enum: ['Consumable', 'Material', 'Tool', 'Equipment'], required: true },
+ name: { type: String, required: true },
+ description: { type: String, required: true },
+ unit: { type: String, required: true }, // unit of measurement
imageUrl: String,
});
From 337fe08ef46f76e074b61bc67a9333ea52ef7b5b Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Thu, 16 Nov 2023 09:41:23 -0800
Subject: [PATCH 150/272] update dependencies
---
package-lock.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package-lock.json b/package-lock.json
index 3fcc98986..97de1f352 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5536,7 +5536,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",
From b9c52f0f75bbe6ce0b4291bf66eb765a8e69ed82 Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Thu, 16 Nov 2023 11:59:44 -0800
Subject: [PATCH 151/272] Text Change
---
src/controllers/reasonSchedulingController.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 050b9a42b..e310049c2 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -20,7 +20,7 @@ const postReason = async (req, res) => {
if (moment.tz(reasonData.date, 'America/Los_Angeles').day() !== 0) {
return res.status(400).json({
message:
- 'The selected day must be a sunday so the code can work properly',
+ "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.",
errorCode: 0,
});
}
From 903da0c7f447ae8961ce879eb5cdf2bc067f1c64 Mon Sep 17 00:00:00 2001
From: Aishwaryak01
Date: Thu, 16 Nov 2023 15:09:48 -0500
Subject: [PATCH 152/272] Updated file buildingTool.js
Updated file buildingTool.js for changes requested in PR
---
.../bmdashboard/{buildingTools.js => buildingTool.js} | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
rename src/models/bmdashboard/{buildingTools.js => buildingTool.js} (64%)
diff --git a/src/models/bmdashboard/buildingTools.js b/src/models/bmdashboard/buildingTool.js
similarity index 64%
rename from src/models/bmdashboard/buildingTools.js
rename to src/models/bmdashboard/buildingTool.js
index 94468de42..6cec3b5d0 100644
--- a/src/models/bmdashboard/buildingTools.js
+++ b/src/models/bmdashboard/buildingTool.js
@@ -3,17 +3,14 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
const buildingTools = new Schema({
- inventoryItemId: { type: mongoose.SchemaTypes.ObjectId, ref: 'INVENTORY' }, // later ,INVENTORY needs to be changed as per inventory model
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
title: { type: String, required: true },
- image: { type: String, required: true },
rentedOnDate: { type: Date, required: true },
rentDuration: { type: Number, required: true }, // This value should be taken in number of days
- total: {type: Number, required: true},
- availableCount:{type: Number, required: true},
logInStatus:{Boolean},
- condition:{type: String, enum: ['Good', 'Needs Repair', 'Out of Order','Unused'], default: 'Condition'},
+ condition:{type: String, enum: ['Good', 'Needs Repair', 'Out of Order','Unused'], default: 'Good'},
userResponsible:{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- purchaseStatus:{type: String, enum: ['Rented', 'Purchased'], default: 'Status'},
+ purchaseStatus:{type: String, enum: ['Rented', 'Purchased'], default: 'Rented'},
});
module.exports = mongoose.model('buildingTools', buildingTools, 'buildingTools');
\ No newline at end of file
From 6caba89ed9724434646185094dcea04bf65ef54a Mon Sep 17 00:00:00 2001
From: Olga Yudkin
Date: Thu, 16 Nov 2023 15:17:40 -0500
Subject: [PATCH 153/272] initial commit
---
package-lock.json | 16 +++++++--------
.../bmdashboard/bmToolController.js | 20 +++++++++++++++++++
src/routes/bmdashboard/bmToolsRouter.js | 14 +++++++++++++
src/startup/routes.js | 2 ++
4 files changed, 44 insertions(+), 8 deletions(-)
create mode 100644 src/controllers/bmdashboard/bmToolController.js
create mode 100644 src/routes/bmdashboard/bmToolsRouter.js
diff --git a/package-lock.json b/package-lock.json
index 3fcc98986..c9a26d709 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": {
@@ -4429,7 +4429,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": {
@@ -4952,7 +4952,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": {
@@ -5215,7 +5215,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": {
@@ -5536,7 +5536,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",
@@ -5929,7 +5929,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": {
@@ -7887,7 +7887,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": {
@@ -7918,7 +7918,7 @@
"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": {
diff --git a/src/controllers/bmdashboard/bmToolController.js b/src/controllers/bmdashboard/bmToolController.js
new file mode 100644
index 000000000..c3c389ddd
--- /dev/null
+++ b/src/controllers/bmdashboard/bmToolController.js
@@ -0,0 +1,20 @@
+const bmToolController = (BuildingTool) => {
+ const fetchSingleTool = async (req, res) => {
+ const { toolId } = req.params;
+ try {
+ BuildingTool
+ .findById(toolId)
+ .populate([
+ // TO DO
+ ])
+ .exec()
+ .then(tool => res.status(200).send(tool))
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return fetchSingleTool;
+};
+
+module.exports = bmToolController;
diff --git a/src/routes/bmdashboard/bmToolsRouter.js b/src/routes/bmdashboard/bmToolsRouter.js
new file mode 100644
index 000000000..98dca3adf
--- /dev/null
+++ b/src/routes/bmdashboard/bmToolsRouter.js
@@ -0,0 +1,14 @@
+const express = require('express');
+
+const routes = function () {
+ const toolRouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmToolController')();
+
+ toolRouter.route('tools/:toolId')
+ .get(controller.fetchSingleTool);
+
+
+ return toolRouter;
+};
+
+module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 799b854fe..12ba780ef 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -62,6 +62,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
+const bmToolsRouter = require('../routes/bmdashboard/bmToolsRouter')();
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -97,4 +98,5 @@ module.exports = function (app) {
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
app.use('/api/bm', bmProjectRouter);
+ app.use('/api/bm', bmToolsRouter);
};
From 2afd85d263f38a25be78ac7012eb1c2f6e9e6121 Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Fri, 17 Nov 2023 08:27:12 -0800
Subject: [PATCH 154/272] Restore .gitattributes file to its original state
---
.gitattributes | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.gitattributes b/.gitattributes
index 6cf651ce7..d725bea56 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,6 +1,6 @@
# https://warlord0blog.wordpress.com/2019/09/04/vscode-crlf-vs-lf-battle/
-# text=lf
+ text=lf
*.css linguist-vendored eol=lf
*.scss linguist-vendored eol=lf
*.js linguist-vendored eol=lf
From 9c648baa6b2e1ad99d327e44c6fc5f803a9318c8 Mon Sep 17 00:00:00 2001
From: Bhagyashree Birajdar
Date: Fri, 17 Nov 2023 09:16:57 -0800
Subject: [PATCH 155/272] Remove extra spaces
---
.gitattributes | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.gitattributes b/.gitattributes
index d725bea56..3b75a78dd 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,6 +1,6 @@
# https://warlord0blog.wordpress.com/2019/09/04/vscode-crlf-vs-lf-battle/
- text=lf
+text=lf
*.css linguist-vendored eol=lf
*.scss linguist-vendored eol=lf
*.js linguist-vendored eol=lf
From 2fa50925a76c266ac918d48e4e50c5579c8b0425 Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Fri, 17 Nov 2023 13:45:37 -0600
Subject: [PATCH 156/272] fix email sending for setup profile
---
.../profileInitialSetupController.js | 27 ++++++++++++++-----
src/utilities/emailSender.js | 10 ++++++-
2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 18cf7376c..3e51e5578 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -76,6 +76,23 @@ function informManagerMessage(user) {
return message;
}
+const sendEmailWithAcknowledgment = (email, subject, message) => {
+ return new Promise((resolve, reject) => {
+ emailSender(
+ email,
+ subject,
+ message,
+ null,
+ null,
+ null,
+ (error,result) => {
+ if (result) resolve(result)
+ if (error) reject(result)
+ }
+ );
+ });
+};
+
const profileInitialSetupController = function (
ProfileInitialSetupToken,
userProfile,
@@ -114,15 +131,13 @@ const profileInitialSetupController = function (
const savedToken = await newToken.save();
const link = `${baseUrl}/ProfileInitialSetup/${savedToken.token}`;
- emailSender(
+ const acknowledgment = await sendEmailWithAcknowledgment(
email,
"NEEDED: Complete your One Community profile setup",
- sendLinkMessage(link),
- null,
- null
+ sendLinkMessage(link)
);
-
- res.status(200).send(link);
+
+ res.status(200).send(acknowledgment);
}
} catch (error) {
res.status(400).send(`Error: ${error}`);
diff --git a/src/utilities/emailSender.js b/src/utilities/emailSender.js
index b4864add6..b07f9a8c9 100644
--- a/src/utilities/emailSender.js
+++ b/src/utilities/emailSender.js
@@ -35,7 +35,7 @@ const closure = () => {
if (!nextItem) return;
const {
- recipient, subject, message, cc, bcc, replyTo,
+ recipient, subject, message, cc, bcc, replyTo, acknowledgingReceipt
} = nextItem;
try {
@@ -59,8 +59,14 @@ const closure = () => {
};
const result = await transporter.sendMail(mailOptions);
+ if (typeof acknowledgingReceipt === 'function') {
+ acknowledgingReceipt(null,result);
+ }
logger.logInfo(result);
} catch (error) {
+ if (typeof acknowledgingReceipt === 'function') {
+ acknowledgingReceipt(error,null);
+ }
logger.logException(error);
}
}, process.env.MAIL_QUEUE_INTERVAL || 1000);
@@ -72,6 +78,7 @@ const closure = () => {
cc = null,
bcc = null,
replyTo = null,
+ acknowledgingReceipt = null,
) {
if (process.env.sendEmail) {
queue.push({
@@ -81,6 +88,7 @@ const closure = () => {
cc,
bcc,
replyTo,
+ acknowledgingReceipt
});
}
};
From a973d9aa876df747c81b536d289407e459a89f93 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Fri, 17 Nov 2023 16:02:49 -0800
Subject: [PATCH 157/272] added validations before adding to db
---
.../bmdashboard/bmMaterialsController.js | 20 ++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 502a2014a..671cb0b24 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -89,7 +89,11 @@ const bmMaterialsController = function (ItemMaterial) {
const bmPostMaterialUpdateBulk = function (req, res) {
const materialUpdates= req.body;
- const updateRecordsToBeAdded = materialUpdates.map(payload => {
+ let errorFlag = false;
+ const updateRecordsToBeAdded = [];
+ for(let i=0;i ItemMaterial.updateOne(
{ _id: updateItem.updateId },
{
From a2bb72a83e5ac9946cec68f972ff03469650c229 Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Fri, 17 Nov 2023 20:08:10 -0600
Subject: [PATCH 158/272] update homeCountry,add profile picture
---
.../profileInitialSetupController.js | 31 ++++++++++---------
src/routes/profileInitialSetupRouter.js | 1 -
src/startup/middleware.js | 2 +-
3 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 21113c0fd..88902141d 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -213,6 +213,7 @@ const profileInitialSetupController = function (
newUser.collaborationPreference = req.body.collaborationPreference;
newUser.timeZone = req.body.timeZone || "America/Los_Angeles";
newUser.location = req.body.location;
+ newUser.profilePic = req.body.profilePicture;
newUser.permissions = {
frontPermissions: [],
backPermissions: []
@@ -247,7 +248,19 @@ const profileInitialSetupController = function (
const token = jwt.sign(jwtPayload, JWT_SECRET);
+ const locationData = {
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ jobTitle: req.body.jobTitle,
+ location: req.body.homeCountry,
+ }
+
res.send({ token }).status(200);
+
+ const mapEntryResult = await setMapLocation(locationData)
+ if(mapEntryResult.type === "Error"){
+ console.log(mapEntryResult.message)
+ }
const NewUserCache = {
permissions: savedUser.permissions,
@@ -298,26 +311,15 @@ const profileInitialSetupController = function (
}
};
-
- const setMapLocation = async (req,res) => {
+ const setMapLocation = async (locationData) => {
- const locationData = {
- firstName: req.body.firstName,
- lastName: req.body.lastName,
- jobTitle: req.body.jobTitle,
- location: req.body.location,
- }
const location = new MapLocation(locationData);
try {
const response = await location.save()
- if (!response) {
- throw new Error('Something went wrong during saving the location...')
- }
- res.status(200).send(response);
+ return response
} catch (err) {
- console.log(err.message)
- res.status(500).json({ message: err.message || 'Something went wrong...' });
+ return {type: "Error", message: err.message || 'An error occurred while saving the location'}
}
}
@@ -326,7 +328,6 @@ const profileInitialSetupController = function (
setUpNewUser,
validateSetupToken,
getTimeZoneAPIKeyByToken,
- setMapLocation
};
};
diff --git a/src/routes/profileInitialSetupRouter.js b/src/routes/profileInitialSetupRouter.js
index 0e5b050c7..9a87aa1a7 100644
--- a/src/routes/profileInitialSetupRouter.js
+++ b/src/routes/profileInitialSetupRouter.js
@@ -8,7 +8,6 @@ const routes = function (ProfileInitialSetupToken, userProfile, Project , mapLoc
ProfileInitialSetup.route('/ProfileInitialSetup').post(controller.setUpNewUser)
ProfileInitialSetup.route('/validateToken').post(controller.validateSetupToken)
ProfileInitialSetup.route('/getTimeZoneAPIKeyByToken').post(controller.getTimeZoneAPIKeyByToken)
- ProfileInitialSetup.route('/mapLocationsToken').post(controller.setMapLocation)
return ProfileInitialSetup;
diff --git a/src/startup/middleware.js b/src/startup/middleware.js
index 16916c9f3..23ce1d4a6 100644
--- a/src/startup/middleware.js
+++ b/src/startup/middleware.js
@@ -22,7 +22,7 @@ module.exports = function (app) {
next();
return;
}
- if (req.originalUrl === '/api/ProfileInitialSetup' || req.originalUrl === '/api/validateToken' || req.originalUrl === '/api/getTimeZoneAPIKeyByToken' && req.method === 'POST' || req.originalUrl === '/api/mapLocationsToken' && req.method === 'POST'
+ if (req.originalUrl === '/api/ProfileInitialSetup' || req.originalUrl === '/api/validateToken' || req.originalUrl === '/api/getTimeZoneAPIKeyByToken' && req.method === 'POST'
) {
next();
return;
From a418eaefcde0b3a65d2e4caae0aa7cd02258adcf Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Mon, 20 Nov 2023 11:45:18 +0800
Subject: [PATCH 159/272] fix permission issue
---
src/controllers/timeEntryController.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index 8adc6693d..011e466e2 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -110,7 +110,7 @@ const timeEntrycontroller = function (TimeEntry) {
}
if (!(await hasPermission(req.body.requestor, 'editTimeEntry')
- || ((type === 'default' || type === 'person') && timeEntry.personId.toString() === req.body.requestor.requestorId.toString()))) {
+ || (type === 'default' && timeEntry.personId.toString() === req.body.requestor.requestorId.toString()))) {
return res.status(403).send({ error: 'Unauthorized request' });
}
From 14a1745f0b723da0d93a572611f1fc39c71b2e98 Mon Sep 17 00:00:00 2001
From: Olga Yudkin
Date: Mon, 20 Nov 2023 15:08:36 -0500
Subject: [PATCH 160/272] remove duplictae conroller
---
.../bmdashboard/bmToolController.js | 20 -------------------
1 file changed, 20 deletions(-)
delete mode 100644 src/controllers/bmdashboard/bmToolController.js
diff --git a/src/controllers/bmdashboard/bmToolController.js b/src/controllers/bmdashboard/bmToolController.js
deleted file mode 100644
index c3c389ddd..000000000
--- a/src/controllers/bmdashboard/bmToolController.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const bmToolController = (BuildingTool) => {
- const fetchSingleTool = async (req, res) => {
- const { toolId } = req.params;
- try {
- BuildingTool
- .findById(toolId)
- .populate([
- // TO DO
- ])
- .exec()
- .then(tool => res.status(200).send(tool))
- .catch(error => res.status(500).send(error));
- } catch (err) {
- res.json(err);
- }
- };
- return fetchSingleTool;
-};
-
-module.exports = bmToolController;
From 10b371eceb0cfdd62fd7a0c69713b136334ea681 Mon Sep 17 00:00:00 2001
From: Olga Yudkin
Date: Mon, 20 Nov 2023 15:44:14 -0500
Subject: [PATCH 161/272] updated buildingtool controller and schema
---
src/controllers/bmdashboard/bmToolsController.js | 8 ++++++++
src/models/bmdashboard/buildingTool.js | 10 +++++-----
src/routes/bmdashboard/bmToolsRouter.js | 4 ++--
src/startup/routes.js | 4 ++--
4 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/src/controllers/bmdashboard/bmToolsController.js b/src/controllers/bmdashboard/bmToolsController.js
index 9bb17b2cf..09a820a3e 100644
--- a/src/controllers/bmdashboard/bmToolsController.js
+++ b/src/controllers/bmdashboard/bmToolsController.js
@@ -6,6 +6,14 @@ const bmToolsController = (BuildingTool) => {
.findById(toolId)
.populate([
// TO DO
+ {
+ path: 'itemType',
+ select: '',
+ },
+ {
+ path: 'userResponsible',
+ select: '_id firstName lastName',
+ },
])
.exec()
.then(tool => res.status(200).send(tool))
diff --git a/src/models/bmdashboard/buildingTool.js b/src/models/bmdashboard/buildingTool.js
index 6cec3b5d0..671eba630 100644
--- a/src/models/bmdashboard/buildingTool.js
+++ b/src/models/bmdashboard/buildingTool.js
@@ -7,10 +7,10 @@ const buildingTools = new Schema({
title: { type: String, required: true },
rentedOnDate: { type: Date, required: true },
rentDuration: { type: Number, required: true }, // This value should be taken in number of days
- logInStatus:{Boolean},
- condition:{type: String, enum: ['Good', 'Needs Repair', 'Out of Order','Unused'], default: 'Good'},
- userResponsible:{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- purchaseStatus:{type: String, enum: ['Rented', 'Purchased'], default: 'Rented'},
+ logInStatus: { type: Boolean },
+ condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order', 'Unused'], default: 'Good' },
+ userResponsible: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ purchaseStatus: { type: String, enum: ['Rented', 'Purchased'], default: 'Rented' },
});
-module.exports = mongoose.model('buildingTools', buildingTools, 'buildingTools');
\ No newline at end of file
+module.exports = mongoose.model('buildingTools', buildingTools, 'buildingTools');
diff --git a/src/routes/bmdashboard/bmToolsRouter.js b/src/routes/bmdashboard/bmToolsRouter.js
index 58af3f273..6112f3502 100644
--- a/src/routes/bmdashboard/bmToolsRouter.js
+++ b/src/routes/bmdashboard/bmToolsRouter.js
@@ -1,8 +1,8 @@
const express = require('express');
-const routes = function () {
+const routes = function (BuildingTool) {
const toolRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmToolsController')();
+ const controller = require('../../controllers/bmdashboard/bmToolsController')(BuildingTool);
toolRouter.route('tools/:toolId')
.get(controller.fetchSingleTool);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 12ba780ef..e4924bdba 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -22,7 +22,7 @@ const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const buildingProject = require('../models/bmdashboard/buildingProject');
-
+const buildingTools = require('../models/bmdashboard/buildingTool');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -62,7 +62,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
-const bmToolsRouter = require('../routes/bmdashboard/bmToolsRouter')();
+const bmToolsRouter = require('../routes/bmdashboard/bmToolsRouter')(buildingTool);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
From 9338492de79cde0b1d161caa0bdeefb7914d86f6 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Mon, 20 Nov 2023 12:49:17 -0800
Subject: [PATCH 162/272] add team, hours fields to team sub-doc in project
schema
---
src/models/bmdashboard/buildingProject.js | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/models/bmdashboard/buildingProject.js b/src/models/bmdashboard/buildingProject.js
index 566bc124e..df2b51e96 100644
--- a/src/models/bmdashboard/buildingProject.js
+++ b/src/models/bmdashboard/buildingProject.js
@@ -8,8 +8,12 @@ const buildingProject = new Schema({
template: String, // construction template (ie Earthbag Village)
location: String, // use lat/lng instead?
dateCreated: { type: Date, default: Date.now },
- buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }, // BM's id
- team: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }],
+ buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ members: [{
+ user: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ team: { type: mongoose.SchemaTypes.ObjectId, ref: 'teams' },
+ hours: { type: Number, default: 0 }, // tracked via the Member Check-In Page timer
+ }],
});
module.exports = mongoose.model('buildingProject', buildingProject, 'buildingProjects');
From 507c61fed22ddeab9b436b16ca3122a161f98a41 Mon Sep 17 00:00:00 2001
From: Olga Yudkin
Date: Wed, 22 Nov 2023 12:15:01 -0500
Subject: [PATCH 163/272] updated buildingtool schema and controller
---
src/controllers/bmdashboard/bmToolsController.js | 2 --
src/models/bmdashboard/buildingTool.js | 4 ++--
src/startup/routes.js | 2 +-
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/controllers/bmdashboard/bmToolsController.js b/src/controllers/bmdashboard/bmToolsController.js
index 09a820a3e..e1b2f58c7 100644
--- a/src/controllers/bmdashboard/bmToolsController.js
+++ b/src/controllers/bmdashboard/bmToolsController.js
@@ -5,10 +5,8 @@ const bmToolsController = (BuildingTool) => {
BuildingTool
.findById(toolId)
.populate([
- // TO DO
{
path: 'itemType',
- select: '',
},
{
path: 'userResponsible',
diff --git a/src/models/bmdashboard/buildingTool.js b/src/models/bmdashboard/buildingTool.js
index 671eba630..9877cc2f7 100644
--- a/src/models/bmdashboard/buildingTool.js
+++ b/src/models/bmdashboard/buildingTool.js
@@ -2,7 +2,7 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
-const buildingTools = new Schema({
+const buildingTool = new Schema({
itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
title: { type: String, required: true },
rentedOnDate: { type: Date, required: true },
@@ -13,4 +13,4 @@ const buildingTools = new Schema({
purchaseStatus: { type: String, enum: ['Rented', 'Purchased'], default: 'Rented' },
});
-module.exports = mongoose.model('buildingTools', buildingTools, 'buildingTools');
+module.exports = mongoose.model('buildingTool', buildingTool, 'buildingTools');
diff --git a/src/startup/routes.js b/src/startup/routes.js
index e4924bdba..5cdf15b6a 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -22,7 +22,7 @@ const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const buildingProject = require('../models/bmdashboard/buildingProject');
-const buildingTools = require('../models/bmdashboard/buildingTool');
+const buildingTool = require('../models/bmdashboard/buildingTool');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
From 565522521c7d7fe5bd99ce27b827008fa9538fca Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 22 Nov 2023 17:26:22 -0800
Subject: [PATCH 164/272] build aggregate operator, add sorted fields to return
array. add teams array field to buildingProject schema.
---
.../bmdashboard/bmProjectController.js | 72 ++++++++++++++-----
src/models/bmdashboard/buildingProject.js | 2 +-
2 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js
index 929aba4ba..8ca62ea77 100644
--- a/src/controllers/bmdashboard/bmProjectController.js
+++ b/src/controllers/bmdashboard/bmProjectController.js
@@ -1,3 +1,4 @@
+/* eslint-disable prefer-destructuring */
// TODO: uncomment when executing auth checks
// const jwt = require('jsonwebtoken');
// const config = require('../../config');
@@ -12,26 +13,63 @@ const bmMProjectController = function (BuildingProject) {
// const token = req.headers.authorization;
// const { userid } = jwt.verify(token, JWT_SECRET);
try {
- const projectData = await BuildingProject
- // TODO: uncomment this line to filter by buildingManager field
- // .find({ buildingManager: userid })
- .find()
- .populate([
- {
- path: 'buildingManager',
- select: '_id firstName lastName email',
+ BuildingProject.aggregate([
+ {
+ $match: { isActive: true },
+ },
+ {
+ $lookup: {
+ from: 'userProfiles',
+ let: { id: '$buildingManager' },
+ pipeline: [
+ { $match: { $expr: { $eq: ['$_id', '$$id'] } } },
+ { $project: { firstName: 1, lastName: 1, email: 1 } },
+ ],
+ as: 'buildingManager',
},
- {
- path: 'team',
- select: '_id firstName lastName email',
+ },
+ { $unwind: '$buildingManager' },
+ {
+ $lookup: {
+ from: 'buildingMaterials',
+ let: { id: '$_id' },
+ pipeline: [
+ { $match: { $expr: { $eq: ['$project', '$$id'] } } },
+ { $project: { updateRecord: 0, project: 0 } },
+ ],
+ as: 'materials',
},
- ])
- .exec()
- .then(result => result)
- .catch(error => res.status(500).send(error));
- res.status(200).send(projectData);
+ },
+ {
+ $project: {
+ name: 1,
+ isActive: 1,
+ template: 1,
+ location: 1,
+ dateCreated: 1,
+ buildingManager: 1,
+ teams: 1,
+ members: 1,
+ materials: 1,
+ hoursWorked: { $sum: '$members.hours' },
+ // cost values can be calculated once a process for purchasing inventory is created
+ totalMaterialsCost: { $sum: 1500 },
+ totalEquipmentCost: { $sum: 3000 },
+ },
+ },
+ ])
+ .then((results) => {
+ results.forEach((proj) => {
+ proj.mostMaterialWaste = proj.materials.sort((a, b) => b.stockWasted - a.stockWasted)[0];
+ proj.leastMaterialAvailable = proj.materials.sort((a, b) => a.stockAvailable - b.stockAvailable)[0];
+ proj.mostMaterialBought = proj.materials.sort((a, b) => b.stockBought - a.stockBought)[0];
+ proj.teamCount = proj.teams.length;
+ });
+ res.status(200).send(results);
+ })
+ .catch(error => res.status(500).send(error));
} catch (err) {
- res.json(err);
+ res.status(500).send(err);
}
};
diff --git a/src/models/bmdashboard/buildingProject.js b/src/models/bmdashboard/buildingProject.js
index df2b51e96..3ca4bf993 100644
--- a/src/models/bmdashboard/buildingProject.js
+++ b/src/models/bmdashboard/buildingProject.js
@@ -9,9 +9,9 @@ const buildingProject = new Schema({
location: String, // use lat/lng instead?
dateCreated: { type: Date, default: Date.now },
buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'teams' }], // teams assigned to the project
members: [{
user: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- team: { type: mongoose.SchemaTypes.ObjectId, ref: 'teams' },
hours: { type: Number, default: 0 }, // tracked via the Member Check-In Page timer
}],
});
From 403ca7445abc832068ea0bcc6adca4d36e9fc0aa Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Wed, 22 Nov 2023 21:17:26 -0600
Subject: [PATCH 165/272] Fix model, controller and route for AI prompt
---
src/controllers/dashBoardController.js | 16 ++++++++--------
...dashBoardData.js => weeklySummaryAIPrompt.js} | 4 ++--
src/routes/dashboardRouter.js | 4 ++--
src/startup/routes.js | 4 ++--
4 files changed, 14 insertions(+), 14 deletions(-)
rename src/models/{dashBoardData.js => weeklySummaryAIPrompt.js} (51%)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 66e559a6c..0159783d2 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -3,7 +3,7 @@ const fs = require("fs/promises");
const mongoose = require("mongoose");
const dashboardhelper = require("../helpers/dashboardhelper")();
const emailSender = require("../utilities/emailSender");
-const DashboardData = require('../models/dashBoardData');
+const AIPrompt = require('../models/weeklySummaryAIPrompt');
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -16,17 +16,17 @@ const dashboardcontroller = function () {
});
};
- const updateDashboardData = function (req, res) {
+ const updateAIPrompt = function (req, res) {
if (req.body.requestor.role === 'Owner') {
- DashboardData.findOneAndUpdate({ _id: 'ai-prompt' }, { ...req.body, aIPromptText: req.body.aIPromptText })
+ AIPrompt.findOneAndUpdate({ _id: 'ai-prompt' }, { ...req.body, aIPromptText: req.body.aIPromptText })
.then(() => {
res.status(200).send('Successfully saved AI prompt.');
}).catch(error => res.status(500).send(error));
}
};
- const getDashBoardData = function (req, res) {
- DashboardData.findById({ _id: 'ai-prompt' })
+ const getAIPrompt = function (req, res) {
+ AIPrompt.findById({ _id: 'ai-prompt' })
.then((result) => {
if (result) {
// If the GPT prompt exists, send it back.
@@ -37,7 +37,7 @@ const dashboardcontroller = function () {
_id: 'ai-prompt',
aIPromptText: "Please edit the following summary of my week's work. Make sure it is professionally written in 3rd person format.\nWrite it as only one paragraph. It must be only one paragraph. Keep it less than 500 words. Start the paragraph with 'This week'.\nMake sure the paragraph contains no links or URLs and write it in a tone that is matter-of-fact and without embellishment.\nDo not add flowery language, keep it simple and factual. Do not add a final summary sentence. Apply all this to the following:"
};
- DashboardData.create(defaultPrompt)
+ AIPrompt.create(defaultPrompt)
.then((newResult) => {
res.status(200).send(newResult);
})
@@ -292,8 +292,8 @@ const dashboardcontroller = function () {
return {
dashboarddata,
- getDashBoardData,
- updateDashboardData,
+ getAIPrompt,
+ updateAIPrompt,
monthlydata,
weeklydata,
leaderboarddata,
diff --git a/src/models/dashBoardData.js b/src/models/weeklySummaryAIPrompt.js
similarity index 51%
rename from src/models/dashBoardData.js
rename to src/models/weeklySummaryAIPrompt.js
index 2ae3a5482..a55db4a97 100644
--- a/src/models/dashBoardData.js
+++ b/src/models/weeklySummaryAIPrompt.js
@@ -2,9 +2,9 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
-const DashboardData = new Schema({
+const WeeklySummaryAIPrompt = new Schema({
_id: { type: mongoose.Schema.Types.String },
aIPromptText: { type: String },
});
-module.exports = mongoose.model('dashboardData', DashboardData, 'dashboard');
+module.exports = mongoose.model('weeklySummaryAIPrompt', WeeklySummaryAIPrompt, 'weeklySummaryAIPrompt');
diff --git a/src/routes/dashboardRouter.js b/src/routes/dashboardRouter.js
index 7b55fcb89..fc54a43a1 100644
--- a/src/routes/dashboardRouter.js
+++ b/src/routes/dashboardRouter.js
@@ -6,8 +6,8 @@ const route = function () {
const Dashboardrouter = express.Router();
Dashboardrouter.route('/dashboard/aiPrompt')
- .get(controller.getDashBoardData)
- .put(controller.updateDashboardData);
+ .get(controller.getAIPrompt)
+ .put(controller.updateAIPrompt);
Dashboardrouter.route('/dashboard/:userId')
.get(controller.dashboarddata);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index afe9d81f9..667185982 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -17,7 +17,7 @@ const role = require('../models/role');
const rolePreset = require('../models/rolePreset');
const ownerMessage = require('../models/ownerMessage');
const ownerStandardMessage = require('../models/ownerStandardMessage');
-const dashboardData = require('../models/dashBoardData');
+const weeklySummaryAIPrompt = require('../models/weeklySummaryAIPrompt');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
@@ -27,7 +27,7 @@ const buildingProject = require('../models/bmdashboard/buildingProject');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
-const dashboardRouter = require('../routes/dashboardRouter')(dashboardData);
+const dashboardRouter = require('../routes/dashboardRouter')(weeklySummaryAIPrompt);
const timeEntryRouter = require('../routes/timeentryRouter')(timeEntry);
const projectRouter = require('../routes/projectRouter')(project);
const informationRouter = require('../routes/informationRouter')(information);
From 2f35809bccfbc0c20974b3b518d8d7dc4d5a3318 Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Tue, 28 Nov 2023 09:18:38 +0000
Subject: [PATCH 166/272] added a line break to the email body
---
src/controllers/dashBoardController.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 68e88ae58..b1b62f9ae 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -172,6 +172,8 @@ const dashboardcontroller = function () {
args[3].lastName
}
:
+
+
⚹ Suggestion Category:
${args[0]}
⚹ Suggestion:
@@ -206,7 +208,8 @@ const dashboardcontroller = function () {
emailBody,
null,
null,
- email
+ email,
+ null
);
res.status(200).send("Success");
} catch {
From 83b031f76123cac63bd1e563e08306c80e2f65dc Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Tue, 28 Nov 2023 09:21:41 +0000
Subject: [PATCH 167/272] added a line break to the email body
---
src/controllers/dashBoardController.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 68e88ae58..b1b62f9ae 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -172,6 +172,8 @@ const dashboardcontroller = function () {
args[3].lastName
}
:
+
+
⚹ Suggestion Category:
${args[0]}
⚹ Suggestion:
@@ -206,7 +208,8 @@ const dashboardcontroller = function () {
emailBody,
null,
null,
- email
+ email,
+ null
);
res.status(200).send("Success");
} catch {
From 50f96f6459ddaebd63f4d66aac2133a7853df1dc Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Tue, 28 Nov 2023 13:42:03 +0000
Subject: [PATCH 168/272] bluesquare replyto improvement
---
src/helpers/userHelper.js | 635 ++++++++++++++++++++++----------------
1 file changed, 361 insertions(+), 274 deletions(-)
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index c75dd7b45..8bf04eb5f 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -13,7 +13,7 @@ const emailSender = require("../utilities/emailSender");
const logger = require("../startup/logger");
const hasPermission = require("../utilities/permissions");
const Reason = require("../models/reason");
-const token = require("../models/profileInitialSetupToken")
+const token = require("../models/profileInitialSetupToken");
const userHelper = function () {
const getTeamMembers = function (user) {
@@ -57,7 +57,7 @@ const userHelper = function () {
if (picParts.length < 2) {
return {
result: false,
- errors: "Invalid image"
+ errors: "Invalid image",
};
}
@@ -79,7 +79,7 @@ const userHelper = function () {
return {
result,
- errors
+ errors,
};
};
@@ -90,10 +90,11 @@ const userHelper = function () {
totalInfringements,
timeRemaining
) {
- let final_paragraph = '';
+ let final_paragraph = "";
if (timeRemaining == undefined) {
- final_paragraph = 'Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
';
+ final_paragraph =
+ "Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
";
} else {
final_paragraph = `Life happens and we understand that. Please make up the missed hours this following week though to avoid getting another blue square. So you know what’s needed, the missing/incomplete hours (${timeRemaining} hours) have been added to your current week and this new weekly total can be seen at the top of your dashboard.
Reminder also that each blue square is removed from your profile 1 year after it was issued.
`;
@@ -104,8 +105,8 @@ const userHelper = function () {
Date Assigned: ${infringement.date}
Description: ${infringement.description}
Total Infringements: This is your ${moment
- .localeData()
- .ordinal(totalInfringements)} blue square of 5.
+ .localeData()
+ .ordinal(totalInfringements)} blue square of 5.
${final_paragraph}
Thank you,
One Community
`;
@@ -124,9 +125,7 @@ const userHelper = function () {
* @return {void}
*/
const emailWeeklySummariesForAllUsers = async (weekIndex = 1) => {
- const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
`Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`
@@ -145,7 +144,11 @@ const userHelper = function () {
const weeklySummaryNotRequiredMessage =
'Weekly Summary: Not required for this user
';
- results.sort((a, b) => `${a.firstName} ${a.lastName}`.localeCompare(`${b.firstName} ${b.lastname}`));
+ results.sort((a, b) =>
+ `${a.firstName} ${a.lastName}`.localeCompare(
+ `${b.firstName} ${b.lastname}`
+ )
+ );
for (let i = 0; i < results.length; i += 1) {
const result = results[i];
@@ -157,7 +160,7 @@ const userHelper = function () {
mediaUrl,
weeklySummariesCount,
weeklycommittedHours,
- weeklySummaryOption
+ weeklySummaryOption,
} = result;
if (email !== undefined && email !== null) {
@@ -169,7 +172,9 @@ const userHelper = function () {
// hence totalSeconds[0] should be used
const hoursLogged = result.totalSeconds[0] / 3600 || 0;
- const mediaUrlLink = mediaUrl ? `${mediaUrl}` : 'Not provided!';
+ const mediaUrlLink = mediaUrl
+ ? `${mediaUrl}`
+ : "Not provided!";
let weeklySummaryMessage = weeklySummaryNotProvidedMessage;
const colorStyle = (() => {
@@ -192,16 +197,16 @@ const userHelper = function () {
Weekly Summary
(for the week ending on ${moment(dueDate)
- .tz("America/Los_Angeles")
- .format("YYYY-MMM-DD")}):
+ .tz("America/Los_Angeles")
+ .format("YYYY-MMM-DD")}):
${summary}
`;
} else if (
- weeklySummaryOption === 'Not Required'
- || (!weeklySummaryOption && result.weeklySummaryNotReq)
+ weeklySummaryOption === "Not Required" ||
+ (!weeklySummaryOption && result.weeklySummaryNotReq)
) {
weeklySummaryMessage = weeklySummaryNotRequiredMessage;
}
@@ -213,21 +218,26 @@ const userHelper = function () {
Name: ${firstName} ${lastName}
- Media URL: ${mediaUrlLink || 'Not provided!'}
+ Media URL: ${
+ mediaUrlLink || 'Not provided!'
+ }
- ${weeklySummariesCount === 8
- ? `Total Valid Weekly Summaries: ${weeklySummariesCount}
`
- : `Total Valid Weekly Summaries: ${weeklySummariesCount ||
- "No valid submissions yet!"}
`
+ ${
+ weeklySummariesCount === 8
+ ? `Total Valid Weekly Summaries: ${weeklySummariesCount}
`
+ : `Total Valid Weekly Summaries: ${
+ weeklySummariesCount || "No valid submissions yet!"
+ }
`
}
- ${hoursLogged >= weeklycommittedHours
-
- ? `Hours logged: ${hoursLogged.toFixed(2)} / ${weeklycommittedHours}
`
-
- : `Hours logged: ${hoursLogged.toFixed(
- 2
- )} / ${weeklycommittedHours}
`
+ ${
+ hoursLogged >= weeklycommittedHours
+ ? `Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
+ : `Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
}
${weeklySummaryMessage}
`;
@@ -254,7 +264,9 @@ const userHelper = function () {
"onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com",
"Weekly Summaries for all active users...",
emailBody,
- null
+ null,
+ null,
+ emailString
);
} catch (err) {
logger.logException(err);
@@ -275,18 +287,16 @@ const userHelper = function () {
weeklySummaries: {
$each: [
{
- dueDate: moment()
- .tz("America/Los_Angeles")
- .endOf("week"),
- summary: ""
- }
+ dueDate: moment().tz("America/Los_Angeles").endOf("week"),
+ summary: "",
+ },
],
$position: 0,
- $slice: 4
- }
- }
+ $slice: 4,
+ },
+ },
})
- .catch(error => logger.logException(error));
+ .catch((error) => logger.logException(error));
};
/**
@@ -297,18 +307,14 @@ const userHelper = function () {
*/
const assignBlueSquareForTimeNotMet = async () => {
try {
- const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
const currentUTCDate = moment
.tz("America/Los_Angeles")
.startOf("day")
.toISOString();
logger.logInfo(
-
- `Job for assigning blue square for commitment not met starting at ${currentFormattedDate}`,
-
+ `Job for assigning blue square for commitment not met starting at ${currentFormattedDate}`
);
const pdtStartOfLastWeek = moment()
@@ -321,7 +327,6 @@ const userHelper = function () {
.endOf("week")
.subtract(1, "week");
-
const users = await userProfile.find(
{ isActive: true },
"_id weeklycommittedHours weeklySummaries missedHours"
@@ -344,8 +349,10 @@ const userHelper = function () {
let hasWeeklySummary = false;
-
- if (Array.isArray(user.weeklySummaries) && user.weeklySummaries.length) {
+ if (
+ Array.isArray(user.weeklySummaries) &&
+ user.weeklySummaries.length
+ ) {
const { summary } = user.weeklySummaries[0];
if (summary) {
hasWeeklySummary = true;
@@ -371,31 +378,28 @@ const userHelper = function () {
const timeRemaining = weeklycommittedHours - timeSpent;
-
const updateResult = await userProfile.findByIdAndUpdate(
personId,
{
$inc: {
- totalTangibleHrs: timeSpent || 0
+ totalTangibleHrs: timeSpent || 0,
},
$max: {
- personalBestMaxHrs: timeSpent || 0
+ personalBestMaxHrs: timeSpent || 0,
},
$push: {
- savedTangibleHrs: { $each: [timeSpent || 0], $slice: -200 }
+ savedTangibleHrs: { $each: [timeSpent || 0], $slice: -200 },
},
$set: {
- lastWeekTangibleHrs: timeSpent || 0
- }
+ lastWeekTangibleHrs: timeSpent || 0,
+ },
},
{ new: true }
);
if (
-
- updateResult?.weeklySummaryOption === 'Not Required'
- || updateResult?.weeklySummaryNotReq
-
+ updateResult?.weeklySummaryOption === "Not Required" ||
+ updateResult?.weeklySummaryNotReq
) {
hasWeeklySummary = true;
}
@@ -419,8 +423,8 @@ const userHelper = function () {
personId,
{
$push: {
- oldInfringements: { $each: oldInfringements, $slice: -10 }
- }
+ oldInfringements: { $each: oldInfringements, $slice: -10 },
+ },
},
{ new: true }
);
@@ -431,11 +435,15 @@ const userHelper = function () {
description = foundReason.reason;
} else {
if (timeNotMet && !hasWeeklySummary) {
- description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${timeSpent.toFixed(2)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
+ description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${timeSpent.toFixed(
+ 2
+ )} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
"dddd YYYY-MM-DD"
)} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
} else if (timeNotMet) {
- description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${timeSpent.toFixed(2)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
+ description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${timeSpent.toFixed(
+ 2
+ )} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
"dddd YYYY-MM-DD"
)} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
} else {
@@ -446,46 +454,46 @@ const userHelper = function () {
}
const infringement = {
- date: moment()
- .utc()
- .format("YYYY-MM-DD"),
- description
+ date: moment().utc().format("YYYY-MM-DD"),
+ description,
};
const status = await userProfile.findByIdAndUpdate(
personId,
{
$push: {
- infringements: infringement
- }
+ infringements: infringement,
+ },
},
{ new: true }
);
- let emailBody = '';
- if (person.role == 'Core Team' && timeRemaining > 0) {
+ let emailBody = "";
+ if (person.role == "Core Team" && timeRemaining > 0) {
emailBody = getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
status.infringements.length,
- timeRemaining,
+ timeRemaining
);
} else {
emailBody = getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
- status.infringements.length,
+ status.infringements.length
);
}
emailSender(
status.email,
- 'New Infringement Assigned',
+ "New Infringement Assigned",
emailBody,
null,
- "onecommunityglobal@gmail.com"
+ "onecommunityglobal@gmail.com",
+ null,
+ status.email
);
const categories = await dashboardHelper.laborThisWeekByCategory(
@@ -520,15 +528,15 @@ const userHelper = function () {
await userProfile.findOneAndUpdate(
{
_id: personId,
- "categoryTangibleHrs.category": { $ne: elem._id }
+ "categoryTangibleHrs.category": { $ne: elem._id },
},
{
$addToSet: {
categoryTangibleHrs: {
category: elem._id,
- hrs: elem.timeSpent_hrs
- }
- }
+ hrs: elem.timeSpent_hrs,
+ },
+ },
}
);
}
@@ -545,8 +553,10 @@ const userHelper = function () {
for (let i = 0; i < inactiveUsers.length; i += 1) {
const user = inactiveUsers[i];
- await processWeeklySummariesByUserId(mongoose.Types.ObjectId(user._id), false);
-
+ await processWeeklySummariesByUserId(
+ mongoose.Types.ObjectId(user._id),
+ false
+ );
}
} catch (err) {
logger.logException(err);
@@ -555,9 +565,7 @@ const userHelper = function () {
const applyMissedHourForCoreTeam = async () => {
try {
- const currentDate = moment()
- .tz("America/Los_Angeles")
- .format();
+ const currentDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
`Job for applying missed hours for Core Team members starting at ${currentDate}`
@@ -579,8 +587,8 @@ const userHelper = function () {
{
$match: {
role: "Core Team",
- isActive: true
- }
+ isActive: true,
+ },
},
{
$lookup: {
@@ -594,14 +602,14 @@ const userHelper = function () {
$and: [
{ $eq: ["$isTangible", true] },
{ $gte: ["$dateOfWork", startOfLastWeek] },
- { $lte: ["$dateOfWork", endOfLastWeek] }
- ]
- }
- }
- }
+ { $lte: ["$dateOfWork", endOfLastWeek] },
+ ],
+ },
+ },
+ },
],
- as: "timeEntries"
- }
+ as: "timeEntries",
+ },
},
{
$project: {
@@ -611,9 +619,10 @@ const userHelper = function () {
{
$subtract: [
{
-
- $sum: [{ $ifNull: ['$missedHours', 0] }, '$weeklycommittedHours'],
-
+ $sum: [
+ { $ifNull: ["$missedHours", 0] },
+ "$weeklycommittedHours",
+ ],
},
{
$divide: [
@@ -621,30 +630,30 @@ const userHelper = function () {
$sum: {
$map: {
input: "$timeEntries",
- in: "$$this.totalSeconds"
- }
- }
+ in: "$$this.totalSeconds",
+ },
+ },
},
- 3600
- ]
- }
- ]
+ 3600,
+ ],
+ },
+ ],
},
- 0
- ]
- }
- }
- }
+ 0,
+ ],
+ },
+ },
+ },
]);
const bulkOps = [];
- missedHours.forEach(obj => {
+ missedHours.forEach((obj) => {
bulkOps.push({
updateOne: {
filter: { _id: obj._id },
- update: { missedHours: obj.missedHours }
- }
+ update: { missedHours: obj.missedHours },
+ },
});
});
@@ -655,17 +664,13 @@ const userHelper = function () {
};
const deleteBlueSquareAfterYear = async () => {
- const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
`Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`
);
- const cutOffDate = moment()
- .subtract(1, "year")
- .format("YYYY-MM-DD");
+ const cutOffDate = moment().subtract(1, "year").format("YYYY-MM-DD");
try {
const results = await userProfile.updateMany(
@@ -674,10 +679,10 @@ const userHelper = function () {
$pull: {
infringements: {
date: {
- $lte: cutOffDate
- }
- }
- }
+ $lte: cutOffDate,
+ },
+ },
+ },
}
);
@@ -688,9 +693,7 @@ const userHelper = function () {
};
const reActivateUser = async () => {
- const currentFormattedDate = moment()
- .tz("America/Los_Angeles")
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
`Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`
@@ -708,11 +711,11 @@ const userHelper = function () {
user._id,
{
$set: {
- isActive: true
+ isActive: true,
},
$unset: {
- endDate: user.endDate
- }
+ endDate: user.endDate,
+ },
},
{ new: true }
);
@@ -724,8 +727,12 @@ const userHelper = function () {
const id = user._id;
const person = await userProfile.findById(id);
- const endDate = moment(person.endDate).format('YYYY-MM-DD');
- logger.logInfo(`User with id: ${user._id} was re-acticated at ${moment().format()}.`);
+ const endDate = moment(person.endDate).format("YYYY-MM-DD");
+ logger.logInfo(
+ `User with id: ${
+ user._id
+ } was re-acticated at ${moment().format()}.`
+ );
const subject = `IMPORTANT:${person.firstName} ${person.lastName} has been RE-activated in the Highest Good Network`;
@@ -739,9 +746,14 @@ const userHelper = function () {
The HGN A.I. (and One Community)
`;
-
- emailSender('onecommunityglobal@gmail.com', subject, emailBody, null, null);
-
+ emailSender(
+ "onecommunityglobal@gmail.com",
+ subject,
+ emailBody,
+ null,
+ null,
+ person.email
+ );
}
}
} catch (err) {
@@ -749,24 +761,38 @@ const userHelper = function () {
}
};
-
- const notifyInfringements = function (original, current, firstName, lastName, emailAddress) {
-
+ const notifyInfringements = function (
+ original,
+ current,
+ firstName,
+ lastName,
+ emailAddress
+ ) {
if (!current) return;
const newOriginal = original.toObject();
const newCurrent = current.toObject();
const totalInfringements = newCurrent.length;
let newInfringements = [];
- newInfringements = _.differenceWith(newCurrent, newOriginal, (arrVal, othVal) => arrVal._id.equals(othVal._id));
+ newInfringements = _.differenceWith(
+ newCurrent,
+ newOriginal,
+ (arrVal, othVal) => arrVal._id.equals(othVal._id)
+ );
newInfringements.forEach((element) => {
emailSender(
emailAddress,
- 'New Infringement Assigned',
- getInfringementEmailBody(firstName, lastName, element, totalInfringements),
+ "New Infringement Assigned",
+ getInfringementEmailBody(
+ firstName,
+ lastName,
+ element,
+ totalInfringements
+ ),
null,
- "onecommunityglobal@gmail.com"
+ "onecommunityglobal@gmail.com",
+ emailAddress
);
});
};
@@ -778,10 +804,10 @@ const userHelper = function () {
$set: {
"badgeCollection.$.badge": newBadgeId,
"badgeCollection.$.lastModified": Date.now().toString(),
- "badgeCollection.$.count": 1
- }
+ "badgeCollection.$.count": 1,
+ },
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
@@ -796,9 +822,9 @@ const userHelper = function () {
{
$inc: { "badgeCollection.$.count": 1 },
$set: { "badgeCollection.$.lastModified": Date.now().toString() },
- $push: { "badgeCollection.$.earnedDate": earnedDateBadge() }
+ $push: { "badgeCollection.$.earnedDate": earnedDateBadge() },
},
- err => {
+ (err) => {
if (err) {
console.log(err);
}
@@ -812,17 +838,21 @@ const userHelper = function () {
count = 1,
featured = false
) {
- console.log('Adding Badge');
+ console.log("Adding Badge");
userProfile.findByIdAndUpdate(
personId,
{
$push: {
badgeCollection: {
- badge: badgeId, count, earnedDate: [earnedDateBadge()], featured, lastModified: Date.now().toString(),
+ badge: badgeId,
+ count,
+ earnedDate: [earnedDateBadge()],
+ featured,
+ lastModified: Date.now().toString(),
},
},
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
@@ -835,10 +865,10 @@ const userHelper = function () {
personId,
{
$pull: {
- badgeCollection: { badge: badgeId }
- }
+ badgeCollection: { badge: badgeId },
+ },
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
@@ -855,10 +885,10 @@ const userHelper = function () {
{
$set: {
"badgeCollection.$.count": count,
- "badgeCollection.$.lastModified": Date.now().toString()
- }
+ "badgeCollection.$.lastModified": Date.now().toString(),
+ },
},
- err => {
+ (err) => {
if (err) {
throw new Error(err);
}
@@ -869,8 +899,13 @@ const userHelper = function () {
// remove the last badge you earned on this streak(not including 1)
- const removePrevHrBadge = async function (personId, user, badgeCollection, hrs, weeks) {
-
+ const removePrevHrBadge = async function (
+ personId,
+ user,
+ badgeCollection,
+ hrs,
+ weeks
+ ) {
// Check each Streak Greater than One to check if it works
if (weeks < 3) {
return;
@@ -882,30 +917,29 @@ const userHelper = function () {
$match: {
type: "X Hours for X Week Streak",
weeks: { $gt: 1, $lt: weeks },
- totalHrs: hrs
- }
+ totalHrs: hrs,
+ },
},
{ $sort: { weeks: -1, totalHrs: -1 } },
{
$group: {
_id: "$weeks",
badges: {
- $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" }
- }
- }
- }
+ $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" },
+ },
+ },
+ },
])
- .then(results => {
- results.forEach(streak => {
- streak.badges.every(bdge => {
+ .then((results) => {
+ results.forEach((streak) => {
+ streak.badges.every((bdge) => {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
-
- badgeCollection[i].badge?.type === 'X Hours for X Week Streak'
- && badgeCollection[i].badge?.weeks === bdge.weeks
- && bdge.hrs === hrs
- && !removed
-
+ badgeCollection[i].badge?.type ===
+ "X Hours for X Week Streak" &&
+ badgeCollection[i].badge?.weeks === bdge.weeks &&
+ bdge.hrs === hrs &&
+ !removed
) {
changeBadgeCount(
personId,
@@ -924,15 +958,24 @@ const userHelper = function () {
// 'No Infringement Streak',
- const checkNoInfringementStreak = async function (personId, user, badgeCollection) {
+ const checkNoInfringementStreak = async function (
+ personId,
+ user,
+ badgeCollection
+ ) {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === 'No Infringement Streak') {
- if (badgeOfType && badgeOfType.months <= badgeCollection[i].badge.months) {
+ if (badgeCollection[i].badge?.type === "No Infringement Streak") {
+ if (
+ badgeOfType &&
+ badgeOfType.months <= badgeCollection[i].badge.months
+ ) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
- } else if (badgeOfType && badgeOfType.months > badgeCollection[i].badge.months) {
-
+ } else if (
+ badgeOfType &&
+ badgeOfType.months > badgeCollection[i].badge.months
+ ) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
badgeOfType = badgeCollection[i].badge;
@@ -942,28 +985,29 @@ const userHelper = function () {
await badge
.find({ type: "No Infringement Streak" })
.sort({ months: -1 })
- .then(results => {
+ .then((results) => {
if (!Array.isArray(results) || !results.length) {
return;
}
- results.every(elem => {
+ results.every((elem) => {
// Cannot account for time paused yet
if (elem.months <= 12) {
-
- if (moment().diff(moment(user.createdDate), 'months', true) >= elem.months) {
-
+ if (
+ moment().diff(moment(user.createdDate), "months", true) >=
+ elem.months
+ ) {
if (
user.infringements.length === 0 ||
Math.abs(
moment().diff(
-
- moment(user.infringements[user.infringements?.length - 1].date),
- 'months',
- true,
- ),
-
+ moment(
+ user.infringements[user.infringements?.length - 1].date
+ ),
+ "months",
+ true
+ )
) >= elem.months
) {
if (badgeOfType) {
@@ -981,21 +1025,23 @@ const userHelper = function () {
}
}
} else if (user?.infringements?.length === 0) {
-
- if (moment().diff(moment(user.createdDate), 'months', true) >= elem.months) {
-
+ if (
+ moment().diff(moment(user.createdDate), "months", true) >=
+ elem.months
+ ) {
if (
user.oldInfringements.length === 0 ||
Math.abs(
moment().diff(
-
- moment(user.oldInfringements[user.oldInfringements?.length - 1].date),
- 'months',
- true,
- ),
- )
- >= elem.months - 12
-
+ moment(
+ user.oldInfringements[user.oldInfringements?.length - 1]
+ .date
+ ),
+ "months",
+ true
+ )
+ ) >=
+ elem.months - 12
) {
if (badgeOfType) {
if (badgeOfType._id.toString() !== elem._id.toString()) {
@@ -1024,10 +1070,10 @@ const userHelper = function () {
badgeCollection
) {
const badgesOfType = badgeCollection
- .map(obj => obj.badge)
- .filter(badge => badge.type === 'Minimum Hours Multiple')
+ .map((obj) => obj.badge)
+ .filter((badge) => badge.type === "Minimum Hours Multiple");
await badge
- .find({ type: 'Minimum Hours Multiple' })
+ .find({ type: "Minimum Hours Multiple" })
.sort({ multiple: -1 })
.then((results) => {
if (!Array.isArray(results) || !results.length) {
@@ -1046,13 +1092,13 @@ const userHelper = function () {
);
return theBadge
? increaseBadgeCount(
- personId,
- mongoose.Types.ObjectId(theBadge._id)
- )
+ personId,
+ mongoose.Types.ObjectId(theBadge._id)
+ )
: addBadge(personId, mongoose.Types.ObjectId(elem._id));
}
}
- })
+ });
};
// 'Personal Max',
@@ -1065,7 +1111,7 @@ const userHelper = function () {
}
}
}
- await badge.findOne({ type: "Personal Max" }).then(results => {
+ await badge.findOne({ type: "Personal Max" }).then((results) => {
if (
user.lastWeekTangibleHrs &&
user.lastWeekTangibleHrs >= 1 &&
@@ -1078,9 +1124,11 @@ const userHelper = function () {
user.personalBestMaxHrs
);
} else {
-
- addBadge(personId, mongoose.Types.ObjectId(results._id), user.personalBestMaxHrs);
-
+ addBadge(
+ personId,
+ mongoose.Types.ObjectId(results._id),
+ user.personalBestMaxHrs
+ );
}
}
});
@@ -1090,13 +1138,13 @@ const userHelper = function () {
const checkMostHrsWeek = async function (personId, user, badgeCollection) {
if (
- user.weeklycommittedHours > 0
- && user.lastWeekTangibleHrs > user.weeklycommittedHours
+ user.weeklycommittedHours > 0 &&
+ user.lastWeekTangibleHrs > user.weeklycommittedHours
) {
const badgeOfType = badgeCollection
- .filter(object => object.badge.type === 'Most Hrs in Week')
- .map(object => object.badge);
- await badge.findOne({ type: 'Most Hrs in Week' }).then((results) => {
+ .filter((object) => object.badge.type === "Most Hrs in Week")
+ .map((object) => object.badge);
+ await badge.findOne({ type: "Most Hrs in Week" }).then((results) => {
userProfile
.aggregate([
{ $match: { isActive: true } },
@@ -1105,7 +1153,6 @@ const userHelper = function () {
.then((userResults) => {
if (badgeOfType.length > 1) {
removeDupBadge(user._id, badgeOfType[0]._id);
-
}
if (
@@ -1138,8 +1185,8 @@ const userHelper = function () {
await badge
.find({ type: "X Hours for X Week Streak", weeks: 1 })
.sort({ totalHrs: -1 })
- .then(results => {
- results.every(elem => {
+ .then((results) => {
+ results.every((elem) => {
if (elem.totalHrs <= user.lastWeekTangibleHrs) {
let theBadge;
for (let i = 0; i < badgesOfType.length; i += 1) {
@@ -1167,24 +1214,26 @@ const userHelper = function () {
$group: {
_id: "$weeks",
badges: {
- $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" }
- }
- }
- }
+ $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" },
+ },
+ },
+ },
])
- .then(results => {
+ .then((results) => {
let lastHr = -1;
- results.forEach(streak => {
- streak.badges.every(bdge => {
+ results.forEach((streak) => {
+ streak.badges.every((bdge) => {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
-
- badgeCollection[i].badge?.type === 'X Hours for X Week Streak'
- && badgeCollection[i].badge?.weeks === bdge.weeks
+ badgeCollection[i].badge?.type ===
+ "X Hours for X Week Streak" &&
+ badgeCollection[i].badge?.weeks === bdge.weeks
) {
- if (badgeOfType && badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs) {
-
+ if (
+ badgeOfType &&
+ badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
+ ) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
@@ -1217,7 +1266,13 @@ const userHelper = function () {
mongoose.Types.ObjectId(bdge._id)
);
- removePrevHrBadge(personId, user, badgeCollection, bdge.hrs, bdge.weeks);
+ removePrevHrBadge(
+ personId,
+ user,
+ badgeCollection,
+ bdge.hrs,
+ bdge.weeks
+ );
} else if (!badgeOfType) {
addBadge(personId, mongoose.Types.ObjectId(bdge._id));
removePrevHrBadge(
@@ -1228,9 +1283,17 @@ const userHelper = function () {
bdge.weeks
);
} else if (badgeOfType && badgeOfType.totalHrs === bdge.hrs) {
- increaseBadgeCount(personId, mongoose.Types.ObjectId(badgeOfType._id));
- removePrevHrBadge(personId, user, badgeCollection, bdge.hrs, bdge.weeks);
-
+ increaseBadgeCount(
+ personId,
+ mongoose.Types.ObjectId(badgeOfType._id)
+ );
+ removePrevHrBadge(
+ personId,
+ user,
+ badgeCollection,
+ bdge.hrs,
+ bdge.weeks
+ );
}
return false;
}
@@ -1243,16 +1306,25 @@ const userHelper = function () {
// 'Lead a team of X+'
-
- const checkLeadTeamOfXplus = async function (personId, user, badgeCollection) {
- const leaderRoles = ['Mentor', 'Manager', 'Administrator', 'Owner', 'Core Team'];
- const approvedRoles = ['Mentor', 'Manager'];
+ const checkLeadTeamOfXplus = async function (
+ personId,
+ user,
+ badgeCollection
+ ) {
+ const leaderRoles = [
+ "Mentor",
+ "Manager",
+ "Administrator",
+ "Owner",
+ "Core Team",
+ ];
+ const approvedRoles = ["Mentor", "Manager"];
if (!approvedRoles.includes(user.role)) return;
let teamMembers;
await getTeamMembers({
- _id: personId
- }).then(results => {
+ _id: personId,
+ }).then((results) => {
if (results) {
teamMembers = results.myteam;
} else {
@@ -1271,13 +1343,17 @@ const userHelper = function () {
});
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
-
- if (badgeCollection[i].badge?.type === 'Lead a team of X+') {
- if (badgeOfType && badgeOfType.people <= badgeCollection[i].badge.people) {
+ if (badgeCollection[i].badge?.type === "Lead a team of X+") {
+ if (
+ badgeOfType &&
+ badgeOfType.people <= badgeCollection[i].badge.people
+ ) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
- } else if (badgeOfType && badgeOfType.people > badgeCollection[i].badge.people) {
-
+ } else if (
+ badgeOfType &&
+ badgeOfType.people > badgeCollection[i].badge.people
+ ) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
badgeOfType = badgeCollection[i].badge;
@@ -1287,7 +1363,7 @@ const userHelper = function () {
await badge
.find({ type: "Lead a team of X+" })
.sort({ people: -1 })
- .then(results => {
+ .then((results) => {
if (!Array.isArray(results) || !results.length) {
return;
}
@@ -1295,16 +1371,14 @@ const userHelper = function () {
if (teamMembers && teamMembers.length >= badge.people) {
if (badgeOfType) {
if (
- badgeOfType._id.toString() !== badge._id.toString()
- && badgeOfType.people < badge.people
-
+ badgeOfType._id.toString() !== badge._id.toString() &&
+ badgeOfType.people < badge.people
) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(badge._id),
-
+ mongoose.Types.ObjectId(badge._id)
);
}
return false;
@@ -1327,19 +1401,18 @@ const userHelper = function () {
"education",
"society",
"economics",
- "stewardship"
+ "stewardship",
];
const badgesOfType = badgeCollection
- .filter(object => object.badge.type === "Total Hrs in Category")
- .map(object => object.badge);
+ .filter((object) => object.badge.type === "Total Hrs in Category")
+ .map((object) => object.badge);
- categories.forEach(async category => {
+ categories.forEach(async (category) => {
const categoryHrs = Object.keys(hoursByCategory).find(
- elem => elem === category
+ (elem) => elem === category
);
-
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
@@ -1365,16 +1438,16 @@ const userHelper = function () {
const newCatg = category.charAt(0).toUpperCase() + category.slice(1);
-
- await badge.find({ type: 'Total Hrs in Category', category: newCatg })
+ await badge
+ .find({ type: "Total Hrs in Category", category: newCatg })
.sort({ totalHrs: -1 })
- .then(results => {
+ .then((results) => {
if (!Array.isArray(results) || !results.length || !categoryHrs) {
return;
}
- results.every(elem => {
+ results.every((elem) => {
if (
hoursByCategory[categoryHrs] >= 100 &&
hoursByCategory[categoryHrs] >= elem.totalHrs
@@ -1415,9 +1488,9 @@ const userHelper = function () {
const awardNewBadges = async () => {
console.log("Awarding");
try {
-
- const users = await userProfile.find({ isActive: true }).populate('badgeCollection.badge');
-
+ const users = await userProfile
+ .find({ isActive: true })
+ .populate("badgeCollection.badge");
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -1439,20 +1512,25 @@ const userHelper = function () {
const getTangibleHoursReportedThisWeekByUserId = function (personId) {
const userId = mongoose.Types.ObjectId(personId);
- const pdtstart = moment().tz('America/Los_Angeles').startOf('week').format('YYYY-MM-DD');
- const pdtend = moment().tz('America/Los_Angeles').endOf('week').format('YYYY-MM-DD');
-
+ const pdtstart = moment()
+ .tz("America/Los_Angeles")
+ .startOf("week")
+ .format("YYYY-MM-DD");
+ const pdtend = moment()
+ .tz("America/Los_Angeles")
+ .endOf("week")
+ .format("YYYY-MM-DD");
return timeEntries
.find(
{
personId: userId,
dateOfWork: { $gte: pdtstart, $lte: pdtend },
- isTangible: true
+ isTangible: true,
},
"totalSeconds"
)
- .then(results => {
+ .then((results) => {
const totalTangibleWeeklySeconds = results.reduce(
(acc, { totalSeconds }) => acc + totalSeconds,
0
@@ -1475,15 +1553,19 @@ const userHelper = function () {
await userProfile.findByIdAndUpdate(
user._id,
user.set({
- isActive: false
+ isActive: false,
}),
{ new: true }
);
const id = user._id;
const person = await userProfile.findById(id);
- const lastDay = moment(person.endDate).format('YYYY-MM-DD');
- logger.logInfo(`User with id: ${user._id} was de-acticated at ${moment().format()}.`);
+ const lastDay = moment(person.endDate).format("YYYY-MM-DD");
+ logger.logInfo(
+ `User with id: ${
+ user._id
+ } was de-acticated at ${moment().format()}.`
+ );
const subject = `IMPORTANT:${person.firstName} ${person.lastName} has been deactivated in the Highest Good Network`;
@@ -1497,8 +1579,14 @@ const userHelper = function () {
The HGN A.I. (and One Community)
`;
-
- emailSender('onecommunityglobal@gmail.com', subject, emailBody, null, null);
+ emailSender(
+ "onecommunityglobal@gmail.com",
+ subject,
+ emailBody,
+ null,
+ null,
+ person.email
+ );
}
}
} catch (err) {
@@ -1514,8 +1602,7 @@ const userHelper = function () {
} catch (error) {
logger.logException(err);
}
- }
-
+ };
return {
getUserName,
@@ -1531,7 +1618,7 @@ const userHelper = function () {
emailWeeklySummariesForAllUsers,
awardNewBadges,
getTangibleHoursReportedThisWeekByUserId,
- deleteExpiredTokens
+ deleteExpiredTokens,
};
};
From 67b764a89a3fcebb233f9f2cb6d623d69ce9abec Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Tue, 28 Nov 2023 17:47:57 -0800
Subject: [PATCH 169/272] fix some response send result before set status code,
add empty string for teamCode in the team model, make team controller check
team name for duplicates when post new team
---
src/controllers/dashBoardController.js | 96 +++++++++++++-------------
src/controllers/logincontroller.js | 4 +-
src/controllers/teamController.js | 24 ++++---
src/models/team.js | 2 +-
4 files changed, 67 insertions(+), 59 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index b1b62f9ae..1cf730a5a 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -1,8 +1,8 @@
-const path = require("path");
-const fs = require("fs/promises");
-const mongoose = require("mongoose");
-const dashboardhelper = require("../helpers/dashboardhelper")();
-const emailSender = require("../utilities/emailSender");
+const path = require('path');
+const fs = require('fs/promises');
+const mongoose = require('mongoose');
+const dashboardhelper = require('../helpers/dashboardhelper')();
+const emailSender = require('../utilities/emailSender');
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -11,7 +11,7 @@ const dashboardcontroller = function () {
const snapshot = dashboardhelper.personaldetails(userId);
snapshot.then((results) => {
- res.send(results).status(200);
+ res.status(200).send(results);
});
};
@@ -20,13 +20,13 @@ const dashboardcontroller = function () {
const laborthismonth = dashboardhelper.laborthismonth(
userId,
req.params.fromDate,
- req.params.toDate
+ req.params.toDate,
);
laborthismonth.then((results) => {
if (!results || results.length === 0) {
const emptyresult = [
{
- projectName: "",
+ projectName: '',
timeSpent_hrs: 0,
},
];
@@ -42,10 +42,10 @@ const dashboardcontroller = function () {
const laborthisweek = dashboardhelper.laborthisweek(
userId,
req.params.fromDate,
- req.params.toDate
+ req.params.toDate,
);
laborthisweek.then((results) => {
- res.send(results).status(200);
+ res.status(200).send(results);
});
};
@@ -63,7 +63,7 @@ const dashboardcontroller = function () {
});
}
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
};
const orgData = function (req, res) {
@@ -73,7 +73,7 @@ const dashboardcontroller = function () {
.then((results) => {
res.status(200).send(results[0]);
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
};
const getBugReportEmailBody = function (
@@ -85,7 +85,7 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity
+ severity,
) {
const text = `New Bug Report From ${firstName} ${lastName}:
[Feature Name] Bug Title:
@@ -130,32 +130,32 @@ const dashboardcontroller = function () {
expected,
actual,
visual,
- severity
+ severity,
);
try {
emailSender(
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
`Bug Rport from ${firstName} ${lastName}`,
emailBody,
- email
+ email,
);
- res.status(200).send("Success");
+ res.status(200).send('Success');
} catch {
- res.status(500).send("Failed");
+ res.status(500).send('Failed');
}
};
const suggestionData = {
suggestion: [
- "Identify and remedy poor client and/or user service experiences",
- "Identify bright spots and enhance positive service experiences",
- "Make fundamental changes to our programs and/or operations",
- "Inform the development of new programs/projects",
- "Identify where we are less inclusive or equitable across demographic groups",
- "Strengthen relationships with the people we serve",
+ 'Identify and remedy poor client and/or user service experiences',
+ 'Identify bright spots and enhance positive service experiences',
+ 'Make fundamental changes to our programs and/or operations',
+ 'Inform the development of new programs/projects',
+ 'Identify where we are less inclusive or equitable across demographic groups',
+ 'Strengthen relationships with the people we serve',
"Understand people's needs and how we can help them achieve their goals",
- "Other",
+ 'Other',
],
field: [],
};
@@ -164,8 +164,8 @@ const dashboardcontroller = function () {
let fieldaaray = [];
if (suggestionData.field.length) {
fieldaaray = suggestionData.field.map(
- (item) => `${item}
- ${args[3][item]}
`
+ item => `${item}
+ ${args[3][item]}
`,
);
}
const text = `New Suggestion From ${args[3].firstName} ${
@@ -178,7 +178,7 @@ const dashboardcontroller = function () {
${args[0]}
⚹ Suggestion:
${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ""}
+ ${fieldaaray.length > 0 ? fieldaaray : ''}
⚹ Name of Suggester:
${args[3].firstName} ${args[3].lastName}
⚹ Email of Suggester:
@@ -193,27 +193,29 @@ const dashboardcontroller = function () {
// send suggestion email
const sendMakeSuggestion = async (req, res) => {
- const { suggestioncate, suggestion, confirm, email, ...rest } = req.body;
+ const {
+ suggestioncate, suggestion, confirm, email, ...rest
+} = req.body;
const emailBody = await getsuggestionEmailBody(
suggestioncate,
suggestion,
confirm,
rest,
- email
+ email,
);
try {
emailSender(
- "onecommunityglobal@gmail.com",
- "A new suggestion",
+ 'onecommunityglobal@gmail.com',
+ 'A new suggestion',
emailBody,
null,
null,
email,
- null
+ null,
);
- res.status(200).send("Success");
+ res.status(200).send('Success');
} catch {
- res.status(500).send("Failed");
+ res.status(500).send('Failed');
}
};
@@ -222,40 +224,40 @@ const dashboardcontroller = function () {
if (suggestionData) {
res.status(200).send(suggestionData);
} else {
- res.status(404).send("Suggestion data not found.");
+ res.status(404).send('Suggestion data not found.');
}
} catch (error) {
- console.error("Error getting suggestion data:", error);
- res.status(500).send("Internal Server Error");
+ console.error('Error getting suggestion data:', error);
+ res.status(500).send('Internal Server Error');
}
};
const editSuggestionOption = async (req, res) => {
try {
if (req.body.suggestion) {
- if (req.body.action === "add") {
+ if (req.body.action === 'add') {
suggestionData.suggestion.unshift(req.body.newField);
}
- if (req.body.action === "delete") {
+ if (req.body.action === 'delete') {
suggestionData.suggestion = suggestionData.suggestion.filter(
- (item, index) => index + 1 !== +req.body.newField
+ (item, index) => index + 1 !== +req.body.newField,
);
}
} else {
- if (req.body.action === "add") {
+ if (req.body.action === 'add') {
suggestionData.field.unshift(req.body.newField);
}
- if (req.body.action === "delete") {
+ if (req.body.action === 'delete') {
suggestionData.field = suggestionData.field.filter(
- (item) => item !== req.body.newField
+ item => item !== req.body.newField,
);
}
}
- res.status(200).send("success");
+ res.status(200).send('success');
} catch (error) {
- console.error("Error editing suggestion option:", error);
- res.status(500).send("Internal Server Error");
+ console.error('Error editing suggestion option:', error);
+ res.status(500).send('Internal Server Error');
}
};
diff --git a/src/controllers/logincontroller.js b/src/controllers/logincontroller.js
index cdeae9b37..b6da4cf8b 100644
--- a/src/controllers/logincontroller.js
+++ b/src/controllers/logincontroller.js
@@ -43,7 +43,7 @@ const logincontroller = function () {
new: true,
userId: user._id,
};
- res.send(result).status(200);
+ res.status(200).send(result);
} else if (isPasswordMatch && !isNewUser) {
const jwtPayload = {
userid: user._id,
@@ -57,7 +57,7 @@ const logincontroller = function () {
const token = jwt.sign(jwtPayload, JWT_SECRET);
- res.send({ token }).status(200);
+ res.status(200).send({ token });
} else {
res.status(403).send({
message: 'Invalid password.',
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index b204875a5..86733daf4 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -7,32 +7,38 @@ const teamcontroller = function (Team) {
const getAllTeams = function (req, res) {
Team.find({})
.sort({ teamName: 1 })
- .then(results => res.send(results).status(200))
- .catch(error => res.send(error).status(404));
+ .then(results => res.status(200).send(results))
+ .catch(error => res.status(404).send(error));
};
const getTeamById = function (req, res) {
const { teamId } = req.params;
Team.findById(teamId)
- .then(results => res.send(results).status(200))
- .catch(error => res.send(error).status(404));
+ .then(results => res.status(200).send(results))
+ .catch(error => res.status(404).send(error));
};
const postTeam = async function (req, res) {
if (!await hasPermission(req.body.requestor, 'postTeam')) {
res.status(403).send({ error: 'You are not authorized to create teams.' });
return;
}
+
+ if (await Team.exists({ teamName: req.body.teamName })) {
+ res.status(403).send({ error: `Team Name "${req.body.teamName}" already exists` });
+ return;
+ }
+
const team = new Team();
team.teamName = req.body.teamName;
- team.isACtive = req.body.isActive;
+ team.isACtive = true;
team.createdDatetime = Date.now();
team.modifiedDatetime = Date.now();
team
.save()
- .then(results => res.send(results).status(200))
- .catch(error => res.send(error).status(404));
+ .then(results => res.status(200).send(results))
+ .catch(error => res.status(404).send(error));
};
const deleteTeam = async function (req, res) {
if (!await hasPermission(req.body.requestor, 'deleteTeam')) {
@@ -49,7 +55,7 @@ const teamcontroller = function (Team) {
const deleteteam = record.remove();
Promise.all([removeteamfromprofile, deleteteam])
- .then(res.status(200).send({ message: ' Team successfully deleted and user profiles updated' }))
+ .then(res.status(200).send({ message: 'Team successfully deleted and user profiles updated' }))
.catch((errors) => {
res.status(400).send(errors);
});
@@ -87,7 +93,7 @@ const teamcontroller = function (Team) {
record
.save()
- .then(results => res.status(201).send(results._id))
+ .then(results => res.status(200).send(results._id))
.catch(errors => res.status(400).send(errors));
});
};
diff --git a/src/models/team.js b/src/models/team.js
index 00fbaf8e3..1df50b95a 100644
--- a/src/models/team.js
+++ b/src/models/team.js
@@ -18,7 +18,7 @@ const team = new Schema({
default: '',
validate: {
validator(v) {
- const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$/;
+ const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$|^$/;
return teamCoderegex.test(v);
},
message:
From 03acb2fe39661754b1b29f29e2b036c34f0c7c72 Mon Sep 17 00:00:00 2001
From: Olga Yudkin
Date: Thu, 30 Nov 2023 12:05:17 -0500
Subject: [PATCH 170/272] updates
---
src/controllers/bmdashboard/bmToolsController.js | 1 +
src/routes/bmdashboard/bmToolsRouter.js | 3 +--
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/bmdashboard/bmToolsController.js b/src/controllers/bmdashboard/bmToolsController.js
index e1b2f58c7..c54ac7b24 100644
--- a/src/controllers/bmdashboard/bmToolsController.js
+++ b/src/controllers/bmdashboard/bmToolsController.js
@@ -7,6 +7,7 @@ const bmToolsController = (BuildingTool) => {
.populate([
{
path: 'itemType',
+ select: '_id name description unit imageURL',
},
{
path: 'userResponsible',
diff --git a/src/routes/bmdashboard/bmToolsRouter.js b/src/routes/bmdashboard/bmToolsRouter.js
index 6112f3502..32ea64f20 100644
--- a/src/routes/bmdashboard/bmToolsRouter.js
+++ b/src/routes/bmdashboard/bmToolsRouter.js
@@ -4,10 +4,9 @@ const routes = function (BuildingTool) {
const toolRouter = express.Router();
const controller = require('../../controllers/bmdashboard/bmToolsController')(BuildingTool);
- toolRouter.route('tools/:toolId')
+ toolRouter.route('/tools/:toolId')
.get(controller.fetchSingleTool);
-
return toolRouter;
};
From b3e7dd1e063df76ed893178a7d340116636858c5 Mon Sep 17 00:00:00 2001
From: kaikane lacno <114305309+lacnoskillz@users.noreply.github.com>
Date: Thu, 30 Nov 2023 14:49:02 -0600
Subject: [PATCH 171/272] Update pull_request_template.md
---
.github/pull_request_template.md | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index c6fee8ab4..4816bd1e2 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -17,9 +17,10 @@ To test this backend PR you need to checkout the #XXX frontend PR.
## How to test:
1. check into current branch
2. do `npm install` and `...` to run this PR locally
-3. log as admin user
-4. go to dashboard→ Tasks→ task→…
-5. verify function “A” (feel free to include screenshot here)
+3. Clear site data/cache
+4. log as admin user
+5. go to dashboard→ Tasks→ task→…
+6. verify function “A” (feel free to include screenshot here)
## Screenshots or videos of changes:
From d71867ed9574a36efecc0ca073bf55328c166ef0 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Thu, 30 Nov 2023 13:35:10 -0800
Subject: [PATCH 172/272] update material changes
---
.../bmdashboard/bmMaterialsController.js | 4 ++--
.../bmdashboard/buildingInventoryType.js | 8 +++----
src/models/bmdashboard/buildingMaterial.js | 22 +++++++++++--------
3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 671cb0b24..b9c6438b4 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -88,7 +88,7 @@ const bmMaterialsController = function (ItemMaterial) {
};
const bmPostMaterialUpdateBulk = function (req, res) {
- const materialUpdates= req.body;
+ const materialUpdates= req.body.upadateMaterials;
let errorFlag = false;
const updateRecordsToBeAdded = [];
for(let i=0;i
Date: Thu, 30 Nov 2023 16:49:51 -0800
Subject: [PATCH 173/272] resolved conflicts
---
src/controllers/dashBoardController.js | 28 --------------------------
1 file changed, 28 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 6739043f3..b8294b93e 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -168,18 +168,6 @@ const dashboardcontroller = function () {
${args[3][item]}
`,
);
}
-<<<<<<< HEAD
- const text = `New Suggestion:
- Suggestion Category:
- ${args[0]}
- Suggestion:
- ${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ''}
- Wants Feedback:
- ${args[2]}
- Thank you,
- One Community
`;
-=======
const text = `New Suggestion From ${args[3].firstName} ${
args[3].lastName
}
@@ -197,33 +185,18 @@ const dashboardcontroller = function () {
${args[2]}
Thank you,
One Community`;
->>>>>>> development
return text;
};
// send suggestion email
const sendMakeSuggestion = async (req, res) => {
-<<<<<<< HEAD
- const {
- suggestioncate, suggestion, confirm, ...rest
-} = req.body;
-=======
const { suggestioncate, suggestion, confirm, email, ...rest } = req.body;
->>>>>>> development
const emailBody = await getsuggestionEmailBody(
suggestioncate,
suggestion,
confirm,
rest,
-<<<<<<< HEAD
- );
- try {
- emailSender(
- 'onecommunityglobal@gmail.com',
- 'A new suggestion',
- emailBody,
-=======
email
);
try {
@@ -234,7 +207,6 @@ const dashboardcontroller = function () {
null,
null,
email
->>>>>>> development
);
res.status(200).send('Success');
} catch {
From a9058c03c6166d0227f901cf54b5bca5f31b2b25 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Thu, 30 Nov 2023 18:04:38 -0800
Subject: [PATCH 174/272] resolved conflicts
---
src/controllers/dashBoardController.js | 33 +-
src/helpers/userHelper.js | 782 ++++++++++++++-----------
src/startup/routes.js | 15 +-
3 files changed, 477 insertions(+), 353 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index b8294b93e..30bddc871 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -1,8 +1,8 @@
-const path = require("path");
-const fs = require("fs/promises");
-const mongoose = require("mongoose");
-const dashboardhelper = require("../helpers/dashboardhelper")();
-const emailSender = require("../utilities/emailSender");
+const path = require('path');
+const fs = require('fs/promises');
+const mongoose = require('mongoose');
+const dashboardhelper = require('../helpers/dashboardhelper')();
+const emailSender = require('../utilities/emailSender');
const dashboardcontroller = function () {
const dashboarddata = function (req, res) {
@@ -11,7 +11,7 @@ const dashboardcontroller = function () {
const snapshot = dashboardhelper.personaldetails(userId);
snapshot.then((results) => {
- res.send(results).status(200);
+ res.status(200).send(results);
});
};
@@ -45,7 +45,7 @@ const dashboardcontroller = function () {
req.params.toDate,
);
laborthisweek.then((results) => {
- res.send(results).status(200);
+ res.status(200).send(results);
});
};
@@ -172,11 +172,13 @@ const dashboardcontroller = function () {
args[3].lastName
}
:
+
+
⚹ Suggestion Category:
${args[0]}
⚹ Suggestion:
${args[1]}
- ${fieldaaray.length > 0 ? fieldaaray : ""}
+ ${fieldaaray.length > 0 ? fieldaaray : ''}
⚹ Name of Suggester:
${args[3].firstName} ${args[3].lastName}
⚹ Email of Suggester:
@@ -191,22 +193,25 @@ const dashboardcontroller = function () {
// send suggestion email
const sendMakeSuggestion = async (req, res) => {
- const { suggestioncate, suggestion, confirm, email, ...rest } = req.body;
+ const {
+ suggestioncate, suggestion, confirm, email, ...rest
+} = req.body;
const emailBody = await getsuggestionEmailBody(
suggestioncate,
suggestion,
confirm,
rest,
- email
+ email,
);
try {
emailSender(
- "onecommunityglobal@gmail.com",
- "A new suggestion",
+ 'onecommunityglobal@gmail.com',
+ 'A new suggestion',
emailBody,
null,
null,
- email
+ email,
+ null
);
res.status(200).send('Success');
} catch {
@@ -269,4 +274,4 @@ const dashboardcontroller = function () {
};
};
-module.exports = dashboardcontroller;
+module.exports = dashboardcontroller;
\ No newline at end of file
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index ab6dcea9f..f639a4d37 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -1,28 +1,28 @@
/* eslint-disable no-continue */
/* eslint-disable no-await-in-loop */
-const mongoose = require('mongoose');
-const moment = require('moment-timezone');
-const _ = require('lodash');
-const userProfile = require('../models/userProfile');
-const timeEntries = require('../models/timeentry');
-const badge = require('../models/badge');
-const myTeam = require('./helperModels/myTeam');
-const dashboardHelper = require('./dashboardhelper')();
-const reportHelper = require('./reporthelper')();
-const emailSender = require('../utilities/emailSender');
-const logger = require('../startup/logger');
-const hasPermission = require('../utilities/permissions');
-const Reason = require('../models/reason');
-const token = require('../models/profileInitialSetupToken');
+const mongoose = require("mongoose");
+const moment = require("moment-timezone");
+const _ = require("lodash");
+const userProfile = require("../models/userProfile");
+const timeEntries = require("../models/timeentry");
+const badge = require("../models/badge");
+const myTeam = require("./helperModels/myTeam");
+const dashboardHelper = require("./dashboardhelper")();
+const reportHelper = require("./reporthelper")();
+const emailSender = require("../utilities/emailSender");
+const logger = require("../startup/logger");
+const hasPermission = require("../utilities/permissions");
+const Reason = require("../models/reason");
+const token = require("../models/profileInitialSetupToken");
const userHelper = function () {
const getTeamMembers = function (user) {
const userId = mongoose.Types.ObjectId(user._id);
// var teamid = userdetails.teamId;
return myTeam.findById(userId).select({
- 'myTeam._id': 0,
- 'myTeam.role': 0,
- 'myTeam.fullName': 0,
+ "myTeam._id": 0,
+ "myTeam.role": 0,
+ "myTeam.fullName": 0,
_id: 0,
});
};
@@ -46,33 +46,34 @@ const userHelper = function () {
const getUserName = async function (userId) {
const userid = mongoose.Types.ObjectId(userId);
- return userProfile.findById(userid, 'firstName lastName');
+ return userProfile.findById(userid, "firstName lastName");
};
const validateProfilePic = function (profilePic) {
- const picParts = profilePic.split('base64');
+ const picParts = profilePic.split("base64");
let result = true;
const errors = [];
if (picParts.length < 2) {
return {
result: false,
- errors: 'Invalid image',
+ errors: "Invalid image",
};
}
// validate size
const imageSize = picParts[1].length;
- const sizeInBytes = (4 * Math.ceil(imageSize / 3) * 0.5624896334383812) / 1024;
+ const sizeInBytes =
+ (4 * Math.ceil(imageSize / 3) * 0.5624896334383812) / 1024;
if (sizeInBytes > 50) {
- errors.push('Image size should not exceed 50KB');
+ errors.push("Image size should not exceed 50KB");
result = false;
}
- const imageType = picParts[0].split('/')[1];
- if (imageType !== 'jpeg;' && imageType !== 'png;') {
- errors.push('Image type shoud be either jpeg or png.');
+ const imageType = picParts[0].split("/")[1];
+ if (imageType !== "jpeg;" && imageType !== "png;") {
+ errors.push("Image type shoud be either jpeg or png.");
result = false;
}
@@ -89,10 +90,11 @@ const userHelper = function () {
totalInfringements,
timeRemaining
) {
- let final_paragraph = '';
+ let final_paragraph = "";
if (timeRemaining == undefined) {
- final_paragraph = 'Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
';
+ final_paragraph =
+ "Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
";
} else {
final_paragraph = `Life happens and we understand that. Please make up the missed hours this following week though to avoid getting another blue square. So you know what’s needed, the missing/incomplete hours (${timeRemaining} hours) have been added to your current week and this new weekly total can be seen at the top of your dashboard.
Reminder also that each blue square is removed from your profile 1 year after it was issued.
`;
@@ -103,8 +105,8 @@ const userHelper = function () {
Date Assigned: ${infringement.date}
Description: ${infringement.description}
Total Infringements: This is your ${moment
- .localeData()
- .ordinal(totalInfringements)} blue square of 5.
+ .localeData()
+ .ordinal(totalInfringements)} blue square of 5.
${final_paragraph}
Thank you,
One Community
`;
@@ -123,12 +125,10 @@ const userHelper = function () {
* @return {void}
*/
const emailWeeklySummariesForAllUsers = async (weekIndex = 1) => {
- const currentFormattedDate = moment()
- .tz('America/Los_Angeles')
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
- `Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`,
+ `Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`
);
const emails = [];
@@ -136,13 +136,19 @@ const userHelper = function () {
try {
const results = await reportHelper.weeklySummaries(weekIndex, weekIndex);
- let emailBody = 'Weekly Summaries for all active users:
';
+ let emailBody = "Weekly Summaries for all active users:
";
- const weeklySummaryNotProvidedMessage = 'Weekly Summary: Not provided!
';
+ const weeklySummaryNotProvidedMessage =
+ 'Weekly Summary: Not provided!
';
- const weeklySummaryNotRequiredMessage = 'Weekly Summary: Not required for this user
';
+ const weeklySummaryNotRequiredMessage =
+ 'Weekly Summary: Not required for this user
';
- results.sort((a, b) => `${a.firstName} ${a.lastName}`.localeCompare(`${b.firstName} ${b.lastname}`));
+ results.sort((a, b) =>
+ `${a.firstName} ${a.lastName}`.localeCompare(
+ `${b.firstName} ${b.lastname}`
+ )
+ );
for (let i = 0; i < results.length; i += 1) {
const result = results[i];
@@ -166,19 +172,21 @@ const userHelper = function () {
// hence totalSeconds[0] should be used
const hoursLogged = result.totalSeconds[0] / 3600 || 0;
- const mediaUrlLink = mediaUrl ? `${mediaUrl}` : 'Not provided!';
+ const mediaUrlLink = mediaUrl
+ ? `${mediaUrl}`
+ : "Not provided!";
let weeklySummaryMessage = weeklySummaryNotProvidedMessage;
const colorStyle = (() => {
switch (weeklySummaryOption) {
- case 'Team':
+ case "Team":
return 'style="color: magenta;"';
- case 'Not Required':
+ case "Not Required":
return 'style="color: green"';
- case 'Required':
- return '';
+ case "Required":
+ return "";
default:
- return result.weeklySummaryNotReq ? 'style="color: green"' : '';
+ return result.weeklySummaryNotReq ? 'style="color: green"' : "";
}
})();
// weeklySummaries array should only have one item if any, hence weeklySummaries[0] needs be used to access it.
@@ -189,16 +197,16 @@ const userHelper = function () {
Weekly Summary
(for the week ending on ${moment(dueDate)
- .tz('America/Los_Angeles')
- .format('YYYY-MMM-DD')}):
+ .tz("America/Los_Angeles")
+ .format("YYYY-MMM-DD")}):
${summary}
`;
} else if (
- weeklySummaryOption === 'Not Required'
- || (!weeklySummaryOption && result.weeklySummaryNotReq)
+ weeklySummaryOption === "Not Required" ||
+ (!weeklySummaryOption && result.weeklySummaryNotReq)
) {
weeklySummaryMessage = weeklySummaryNotRequiredMessage;
}
@@ -210,21 +218,26 @@ const userHelper = function () {
Name: ${firstName} ${lastName}
- Media URL: ${mediaUrlLink || 'Not provided!'}
+ Media URL: ${
+ mediaUrlLink || 'Not provided!'
+ }
- ${weeklySummariesCount === 8
- ? `Total Valid Weekly Summaries: ${weeklySummariesCount}
`
- : `Total Valid Weekly Summaries: ${weeklySummariesCount
- || 'No valid submissions yet!'}
`
+ ${
+ weeklySummariesCount === 8
+ ? `Total Valid Weekly Summaries: ${weeklySummariesCount}
`
+ : `Total Valid Weekly Summaries: ${
+ weeklySummariesCount || "No valid submissions yet!"
+ }
`
}
- ${hoursLogged >= weeklycommittedHours
-
- ? `Hours logged: ${hoursLogged.toFixed(2)} / ${weeklycommittedHours}
`
-
- : `Hours logged: ${hoursLogged.toFixed(
- 2,
- )} / ${weeklycommittedHours}
`
+ ${
+ hoursLogged >= weeklycommittedHours
+ ? `Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
+ : `Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
}
${weeklySummaryMessage}
`;
@@ -233,8 +246,10 @@ const userHelper = function () {
// Necessary because our version of node is outdated
// and doesn't have String.prototype.replaceAll
let emailString = [...new Set(emails)].toString();
- while (emailString.includes(',')) emailString = emailString.replace(',', '\n');
- while (emailString.includes('\n')) emailString = emailString.replace('\n', ', ');
+ while (emailString.includes(","))
+ emailString = emailString.replace(",", "\n");
+ while (emailString.includes("\n"))
+ emailString = emailString.replace("\n", ", ");
emailBody += `\n
@@ -246,10 +261,12 @@ const userHelper = function () {
`;
emailSender(
- 'onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com',
- 'Weekly Summaries for all active users...',
+ "onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com",
+ "Weekly Summaries for all active users...",
emailBody,
null,
+ null,
+ emailString
);
} catch (err) {
logger.logException(err);
@@ -270,10 +287,8 @@ const userHelper = function () {
weeklySummaries: {
$each: [
{
- dueDate: moment()
- .tz('America/Los_Angeles')
- .endOf('week'),
- summary: '',
+ dueDate: moment().tz("America/Los_Angeles").endOf("week"),
+ summary: "",
},
],
$position: 0,
@@ -281,7 +296,7 @@ const userHelper = function () {
},
},
})
- .catch(error => logger.logException(error));
+ .catch((error) => logger.logException(error));
};
/**
@@ -292,39 +307,34 @@ const userHelper = function () {
*/
const assignBlueSquareForTimeNotMet = async () => {
try {
- const currentFormattedDate = moment()
- .tz('America/Los_Angeles')
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
const currentUTCDate = moment
- .tz('America/Los_Angeles')
- .startOf('day')
+ .tz("America/Los_Angeles")
+ .startOf("day")
.toISOString();
logger.logInfo(
-
- `Job for assigning blue square for commitment not met starting at ${currentFormattedDate}`,
-
+ `Job for assigning blue square for commitment not met starting at ${currentFormattedDate}`
);
const pdtStartOfLastWeek = moment()
- .tz('America/Los_Angeles')
- .startOf('week')
- .subtract(1, 'week');
+ .tz("America/Los_Angeles")
+ .startOf("week")
+ .subtract(1, "week");
const pdtEndOfLastWeek = moment()
- .tz('America/Los_Angeles')
- .endOf('week')
- .subtract(1, 'week');
-
+ .tz("America/Los_Angeles")
+ .endOf("week")
+ .subtract(1, "week");
const users = await userProfile.find(
{ isActive: true },
- '_id weeklycommittedHours weeklySummaries missedHours',
+ "_id weeklycommittedHours weeklySummaries missedHours"
);
- // this part is supposed to be a for, so it'll be slower when sending emails, so the emails will not be
- // targeted as spam
- // There's no need to put Promise.all here
+ //this part is supposed to be a for, so it'll be slower when sending emails, so the emails will not be
+ //targeted as spam
+ //There's no need to put Promise.all here
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -339,8 +349,10 @@ const userHelper = function () {
let hasWeeklySummary = false;
-
- if (Array.isArray(user.weeklySummaries) && user.weeklySummaries.length) {
+ if (
+ Array.isArray(user.weeklySummaries) &&
+ user.weeklySummaries.length
+ ) {
const { summary } = user.weeklySummaries[0];
if (summary) {
hasWeeklySummary = true;
@@ -353,19 +365,19 @@ const userHelper = function () {
const results = await dashboardHelper.laborthisweek(
personId,
pdtStartOfLastWeek,
- pdtEndOfLastWeek,
+ pdtEndOfLastWeek
);
const { timeSpent_hrs: timeSpent } = results[0];
- const weeklycommittedHours = user.weeklycommittedHours + (user.missedHours ?? 0);
+ const weeklycommittedHours =
+ user.weeklycommittedHours + (user.missedHours ?? 0);
const timeNotMet = timeSpent < weeklycommittedHours;
let description;
const timeRemaining = weeklycommittedHours - timeSpent;
-
const updateResult = await userProfile.findByIdAndUpdate(
personId,
{
@@ -382,25 +394,23 @@ const userHelper = function () {
lastWeekTangibleHrs: timeSpent || 0,
},
},
- { new: true },
+ { new: true }
);
if (
-
- updateResult?.weeklySummaryOption === 'Not Required'
- || updateResult?.weeklySummaryNotReq
-
+ updateResult?.weeklySummaryOption === "Not Required" ||
+ updateResult?.weeklySummaryNotReq
) {
hasWeeklySummary = true;
}
- const cutOffDate = moment().subtract(1, 'year');
+ const cutOffDate = moment().subtract(1, "year");
const oldInfringements = [];
for (let k = 0; k < updateResult?.infringements.length; k += 1) {
if (
- updateResult?.infringements
- && moment(updateResult?.infringements[k].date).diff(cutOffDate) >= 0
+ updateResult?.infringements &&
+ moment(updateResult?.infringements[k].date).diff(cutOffDate) >= 0
) {
oldInfringements.push(updateResult.infringements[k]);
} else {
@@ -416,31 +426,35 @@ const userHelper = function () {
oldInfringements: { $each: oldInfringements, $slice: -10 },
},
},
- { new: true },
+ { new: true }
);
}
if (timeNotMet || !hasWeeklySummary) {
if (foundReason) {
description = foundReason.reason;
- } else if (timeNotMet && !hasWeeklySummary) {
- description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${timeSpent.toFixed(2)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
- 'dddd YYYY-MM-DD',
- )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
+ } else {
+ if (timeNotMet && !hasWeeklySummary) {
+ description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${timeSpent.toFixed(
+ 2
+ )} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
+ "dddd YYYY-MM-DD"
+ )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
} else if (timeNotMet) {
- description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${timeSpent.toFixed(2)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
- 'dddd YYYY-MM-DD',
- )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
+ description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${timeSpent.toFixed(
+ 2
+ )} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
+ "dddd YYYY-MM-DD"
+ )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
} else {
description = `System auto-assigned infringement for not submitting a weekly summary for the week starting ${pdtStartOfLastWeek.format(
- 'dddd YYYY-MM-DD',
- )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
+ "dddd YYYY-MM-DD"
+ )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
}
+ }
const infringement = {
- date: moment()
- .utc()
- .format('YYYY-MM-DD'),
+ date: moment().utc().format("YYYY-MM-DD"),
description,
};
@@ -451,45 +465,47 @@ const userHelper = function () {
infringements: infringement,
},
},
- { new: true },
+ { new: true }
);
- let emailBody = '';
- if (person.role == 'Core Team' && timeRemaining > 0) {
+ let emailBody = "";
+ if (person.role == "Core Team" && timeRemaining > 0) {
emailBody = getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
status.infringements.length,
- timeRemaining,
+ timeRemaining
);
} else {
emailBody = getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
- status.infringements.length,
+ status.infringements.length
);
}
emailSender(
status.email,
- 'New Infringement Assigned',
+ "New Infringement Assigned",
emailBody,
null,
- 'onecommunityglobal@gmail.com',
+ "onecommunityglobal@gmail.com",
+ null,
+ status.email
);
const categories = await dashboardHelper.laborThisWeekByCategory(
personId,
pdtStartOfLastWeek,
- pdtEndOfLastWeek,
+ pdtEndOfLastWeek
);
if (Array.isArray(categories) && categories.length > 0) {
await userProfile.findOneAndUpdate(
{ _id: personId, categoryTangibleHrs: { $exists: false } },
- { $set: { categoryTangibleHrs: [] } },
+ { $set: { categoryTangibleHrs: [] } }
);
} else {
continue;
@@ -499,20 +515,20 @@ const userHelper = function () {
const elem = categories[j];
if (elem._id == null) {
- elem._id = 'Other';
+ elem._id = "Other";
}
const updateResult2 = await userProfile.findOneAndUpdate(
- { _id: personId, 'categoryTangibleHrs.category': elem._id },
- { $inc: { 'categoryTangibleHrs.$.hrs': elem.timeSpent_hrs } },
- { new: true },
+ { _id: personId, "categoryTangibleHrs.category": elem._id },
+ { $inc: { "categoryTangibleHrs.$.hrs": elem.timeSpent_hrs } },
+ { new: true }
);
if (!updateResult2) {
await userProfile.findOneAndUpdate(
{
_id: personId,
- 'categoryTangibleHrs.category': { $ne: elem._id },
+ "categoryTangibleHrs.category": { $ne: elem._id },
},
{
$addToSet: {
@@ -521,7 +537,7 @@ const userHelper = function () {
hrs: elem.timeSpent_hrs,
},
},
- },
+ }
);
}
}
@@ -533,11 +549,14 @@ const userHelper = function () {
// processWeeklySummaries for nonActive users
try {
- const inactiveUsers = await userProfile.find({ isActive: false }, '_id');
+ const inactiveUsers = await userProfile.find({ isActive: false }, "_id");
for (let i = 0; i < inactiveUsers.length; i += 1) {
const user = inactiveUsers[i];
- await processWeeklySummariesByUserId(mongoose.Types.ObjectId(user._id), false);
+ await processWeeklySummariesByUserId(
+ mongoose.Types.ObjectId(user._id),
+ false
+ );
}
} catch (err) {
logger.logException(err);
@@ -546,52 +565,50 @@ const userHelper = function () {
const applyMissedHourForCoreTeam = async () => {
try {
- const currentDate = moment()
- .tz('America/Los_Angeles')
- .format();
+ const currentDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
- `Job for applying missed hours for Core Team members starting at ${currentDate}`,
+ `Job for applying missed hours for Core Team members starting at ${currentDate}`
);
const startOfLastWeek = moment()
- .tz('America/Los_Angeles')
- .startOf('week')
- .subtract(1, 'week')
- .format('YYYY-MM-DD');
+ .tz("America/Los_Angeles")
+ .startOf("week")
+ .subtract(1, "week")
+ .format("YYYY-MM-DD");
const endOfLastWeek = moment()
- .tz('America/Los_Angeles')
- .endOf('week')
- .subtract(1, 'week')
- .format('YYYY-MM-DD');
+ .tz("America/Los_Angeles")
+ .endOf("week")
+ .subtract(1, "week")
+ .format("YYYY-MM-DD");
const missedHours = await userProfile.aggregate([
{
$match: {
- role: 'Core Team',
+ role: "Core Team",
isActive: true,
},
},
{
$lookup: {
- from: 'timeEntries',
- localField: '_id',
- foreignField: 'personId',
+ from: "timeEntries",
+ localField: "_id",
+ foreignField: "personId",
pipeline: [
{
$match: {
$expr: {
$and: [
- { $eq: ['$isTangible', true] },
- { $gte: ['$dateOfWork', startOfLastWeek] },
- { $lte: ['$dateOfWork', endOfLastWeek] },
+ { $eq: ["$isTangible", true] },
+ { $gte: ["$dateOfWork", startOfLastWeek] },
+ { $lte: ["$dateOfWork", endOfLastWeek] },
],
},
},
},
],
- as: 'timeEntries',
+ as: "timeEntries",
},
},
{
@@ -602,17 +619,18 @@ const userHelper = function () {
{
$subtract: [
{
-
- $sum: [{ $ifNull: ['$missedHours', 0] }, '$weeklycommittedHours'],
-
+ $sum: [
+ { $ifNull: ["$missedHours", 0] },
+ "$weeklycommittedHours",
+ ],
},
{
$divide: [
{
$sum: {
$map: {
- input: '$timeEntries',
- in: '$$this.totalSeconds',
+ input: "$timeEntries",
+ in: "$$this.totalSeconds",
},
},
},
@@ -646,17 +664,13 @@ const userHelper = function () {
};
const deleteBlueSquareAfterYear = async () => {
- const currentFormattedDate = moment()
- .tz('America/Los_Angeles')
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
- `Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`,
+ `Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`
);
- const cutOffDate = moment()
- .subtract(1, 'year')
- .format('YYYY-MM-DD');
+ const cutOffDate = moment().subtract(1, "year").format("YYYY-MM-DD");
try {
const results = await userProfile.updateMany(
@@ -669,7 +683,7 @@ const userHelper = function () {
},
},
},
- },
+ }
);
logger.logInfo(results);
@@ -679,18 +693,16 @@ const userHelper = function () {
};
const reActivateUser = async () => {
- const currentFormattedDate = moment()
- .tz('America/Los_Angeles')
- .format();
+ const currentFormattedDate = moment().tz("America/Los_Angeles").format();
logger.logInfo(
- `Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`,
+ `Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`
);
try {
const users = await userProfile.find(
{ isActive: false, reactivationDate: { $exists: true } },
- '_id isActive reactivationDate',
+ "_id isActive reactivationDate"
);
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -705,18 +717,22 @@ const userHelper = function () {
endDate: user.endDate,
},
},
- { new: true },
+ { new: true }
);
logger.logInfo(
`User with id: ${user._id} was re-acticated at ${moment()
- .tz('America/Los_Angeles')
- .format()}.`,
+ .tz("America/Los_Angeles")
+ .format()}.`
);
const id = user._id;
const person = await userProfile.findById(id);
- const endDate = moment(person.endDate).format('YYYY-MM-DD');
- logger.logInfo(`User with id: ${user._id} was re-acticated at ${moment().format()}.`);
+ const endDate = moment(person.endDate).format("YYYY-MM-DD");
+ logger.logInfo(
+ `User with id: ${
+ user._id
+ } was re-acticated at ${moment().format()}.`
+ );
const subject = `IMPORTANT:${person.firstName} ${person.lastName} has been RE-activated in the Highest Good Network`;
@@ -730,8 +746,14 @@ const userHelper = function () {
The HGN A.I. (and One Community)
`;
-
- emailSender('onecommunityglobal@gmail.com', subject, emailBody, null, null);
+ emailSender(
+ "onecommunityglobal@gmail.com",
+ subject,
+ emailBody,
+ null,
+ null,
+ person.email
+ );
}
}
} catch (err) {
@@ -739,59 +761,74 @@ const userHelper = function () {
}
};
-
- const notifyInfringements = function (original, current, firstName, lastName, emailAddress) {
+ const notifyInfringements = function (
+ original,
+ current,
+ firstName,
+ lastName,
+ emailAddress
+ ) {
if (!current) return;
const newOriginal = original.toObject();
const newCurrent = current.toObject();
const totalInfringements = newCurrent.length;
let newInfringements = [];
- newInfringements = _.differenceWith(newCurrent, newOriginal, (arrVal, othVal) => arrVal._id.equals(othVal._id));
+ newInfringements = _.differenceWith(
+ newCurrent,
+ newOriginal,
+ (arrVal, othVal) => arrVal._id.equals(othVal._id)
+ );
newInfringements.forEach((element) => {
emailSender(
emailAddress,
- 'New Infringement Assigned',
- getInfringementEmailBody(firstName, lastName, element, totalInfringements),
+ "New Infringement Assigned",
+ getInfringementEmailBody(
+ firstName,
+ lastName,
+ element,
+ totalInfringements
+ ),
null,
- 'onecommunityglobal@gmail.com',
+ "onecommunityglobal@gmail.com",
+ emailAddress
);
});
};
const replaceBadge = async function (personId, oldBadgeId, newBadgeId) {
userProfile.updateOne(
- { _id: personId, 'badgeCollection.badge': oldBadgeId },
+ { _id: personId, "badgeCollection.badge": oldBadgeId },
{
$set: {
- 'badgeCollection.$.badge': newBadgeId,
- 'badgeCollection.$.lastModified': Date.now().toString(),
- 'badgeCollection.$.count': 1,
+ "badgeCollection.$.badge": newBadgeId,
+ "badgeCollection.$.lastModified": Date.now().toString(),
+ "badgeCollection.$.count": 1,
},
},
(err) => {
if (err) {
throw new Error(err);
}
- },
+ }
);
};
const increaseBadgeCount = async function (personId, badgeId) {
- console.log('Increase Badge Count', personId, badgeId);
+ console.log("Increase Badge Count", personId, badgeId);
userProfile.updateOne(
- { _id: personId, 'badgeCollection.badge': badgeId },
+ { _id: personId, "badgeCollection.badge": badgeId },
{
- $inc: { 'badgeCollection.$.count': 1 },
- $set: { 'badgeCollection.$.lastModified': Date.now().toString() },
- $push: { 'badgeCollection.$.earnedDate': earnedDateBadge() },
+ $inc: { "badgeCollection.$.count": 1 },
+ $set: { "badgeCollection.$.lastModified": Date.now().toString() },
+ $push: { "badgeCollection.$.earnedDate": earnedDateBadge() },
},
(err) => {
if (err) {
console.log(err);
}
- },
+ }
);
};
@@ -799,15 +836,19 @@ const userHelper = function () {
personId,
badgeId,
count = 1,
- featured = false,
+ featured = false
) {
- console.log('Adding Badge');
+ console.log("Adding Badge");
userProfile.findByIdAndUpdate(
personId,
{
$push: {
badgeCollection: {
- badge: badgeId, count, earnedDate: [earnedDateBadge()], featured, lastModified: Date.now().toString(),
+ badge: badgeId,
+ count,
+ earnedDate: [earnedDateBadge()],
+ featured,
+ lastModified: Date.now().toString(),
},
},
},
@@ -815,7 +856,7 @@ const userHelper = function () {
if (err) {
throw new Error(err);
}
- },
+ }
);
};
@@ -831,7 +872,7 @@ const userHelper = function () {
if (err) {
throw new Error(err);
}
- },
+ }
);
};
@@ -840,25 +881,31 @@ const userHelper = function () {
removeDupBadge(personId, badgeId);
} else if (count) {
userProfile.updateOne(
- { _id: personId, 'badgeCollection.badge': badgeId },
+ { _id: personId, "badgeCollection.badge": badgeId },
{
$set: {
- 'badgeCollection.$.count': count,
- 'badgeCollection.$.lastModified': Date.now().toString(),
+ "badgeCollection.$.count": count,
+ "badgeCollection.$.lastModified": Date.now().toString(),
},
},
(err) => {
if (err) {
throw new Error(err);
}
- },
+ }
);
}
};
// remove the last badge you earned on this streak(not including 1)
- const removePrevHrBadge = async function (personId, user, badgeCollection, hrs, weeks) {
+ const removePrevHrBadge = async function (
+ personId,
+ user,
+ badgeCollection,
+ hrs,
+ weeks
+ ) {
// Check each Streak Greater than One to check if it works
if (weeks < 3) {
return;
@@ -868,7 +915,7 @@ const userHelper = function () {
.aggregate([
{
$match: {
- type: 'X Hours for X Week Streak',
+ type: "X Hours for X Week Streak",
weeks: { $gt: 1, $lt: weeks },
totalHrs: hrs,
},
@@ -876,9 +923,9 @@ const userHelper = function () {
{ $sort: { weeks: -1, totalHrs: -1 } },
{
$group: {
- _id: '$weeks',
+ _id: "$weeks",
badges: {
- $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' },
+ $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" },
},
},
},
@@ -888,17 +935,16 @@ const userHelper = function () {
streak.badges.every((bdge) => {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
-
- badgeCollection[i].badge?.type === 'X Hours for X Week Streak'
- && badgeCollection[i].badge?.weeks === bdge.weeks
- && bdge.hrs === hrs
- && !removed
-
+ badgeCollection[i].badge?.type ===
+ "X Hours for X Week Streak" &&
+ badgeCollection[i].badge?.weeks === bdge.weeks &&
+ bdge.hrs === hrs &&
+ !removed
) {
changeBadgeCount(
personId,
badgeCollection[i].badge._id,
- badgeCollection[i].badge.count - 1,
+ badgeCollection[i].badge.count - 1
);
removed = true;
return false;
@@ -912,14 +958,24 @@ const userHelper = function () {
// 'No Infringement Streak',
- const checkNoInfringementStreak = async function (personId, user, badgeCollection) {
+ const checkNoInfringementStreak = async function (
+ personId,
+ user,
+ badgeCollection
+ ) {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === 'No Infringement Streak') {
- if (badgeOfType && badgeOfType.months <= badgeCollection[i].badge.months) {
+ if (badgeCollection[i].badge?.type === "No Infringement Streak") {
+ if (
+ badgeOfType &&
+ badgeOfType.months <= badgeCollection[i].badge.months
+ ) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
- } else if (badgeOfType && badgeOfType.months > badgeCollection[i].badge.months) {
+ } else if (
+ badgeOfType &&
+ badgeOfType.months > badgeCollection[i].badge.months
+ ) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
badgeOfType = badgeCollection[i].badge;
@@ -927,7 +983,7 @@ const userHelper = function () {
}
}
await badge
- .find({ type: 'No Infringement Streak' })
+ .find({ type: "No Infringement Streak" })
.sort({ months: -1 })
.then((results) => {
if (!Array.isArray(results) || !results.length) {
@@ -938,17 +994,20 @@ const userHelper = function () {
// Cannot account for time paused yet
if (elem.months <= 12) {
- if (moment().diff(moment(user.createdDate), 'months', true) >= elem.months) {
+ if (
+ moment().diff(moment(user.createdDate), "months", true) >=
+ elem.months
+ ) {
if (
- user.infringements.length === 0
- || Math.abs(
+ user.infringements.length === 0 ||
+ Math.abs(
moment().diff(
-
- moment(user.infringements[user.infringements?.length - 1].date),
- 'months',
- true,
- ),
-
+ moment(
+ user.infringements[user.infringements?.length - 1].date
+ ),
+ "months",
+ true
+ )
) >= elem.months
) {
if (badgeOfType) {
@@ -956,7 +1015,7 @@ const userHelper = function () {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id),
+ mongoose.Types.ObjectId(elem._id)
);
}
return false;
@@ -966,26 +1025,30 @@ const userHelper = function () {
}
}
} else if (user?.infringements?.length === 0) {
- if (moment().diff(moment(user.createdDate), 'months', true) >= elem.months) {
+ if (
+ moment().diff(moment(user.createdDate), "months", true) >=
+ elem.months
+ ) {
if (
- user.oldInfringements.length === 0
- || Math.abs(
+ user.oldInfringements.length === 0 ||
+ Math.abs(
moment().diff(
-
- moment(user.oldInfringements[user.oldInfringements?.length - 1].date),
- 'months',
- true,
- ),
- )
- >= elem.months - 12
-
+ moment(
+ user.oldInfringements[user.oldInfringements?.length - 1]
+ .date
+ ),
+ "months",
+ true
+ )
+ ) >=
+ elem.months - 12
) {
if (badgeOfType) {
if (badgeOfType._id.toString() !== elem._id.toString()) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id),
+ mongoose.Types.ObjectId(elem._id)
);
}
return false;
@@ -1004,13 +1067,13 @@ const userHelper = function () {
const checkMinHoursMultiple = async function (
personId,
user,
- badgeCollection,
+ badgeCollection
) {
const badgesOfType = badgeCollection
- .map(obj => obj.badge)
- .filter(badge => badge.type === 'Minimum Hours Multiple');
+ .map((obj) => obj.badge)
+ .filter((badge) => badge.type === "Minimum Hours Multiple");
await badge
- .find({ type: 'Minimum Hours Multiple' })
+ .find({ type: "Minimum Hours Multiple" })
.sort({ multiple: -1 })
.then((results) => {
if (!Array.isArray(results) || !results.length) {
@@ -1021,17 +1084,17 @@ const userHelper = function () {
const elem = results[i]; // making variable elem accessible for below code
if (
- user.lastWeekTangibleHrs / user.weeklycommittedHours
- >= elem.multiple
+ user.lastWeekTangibleHrs / user.weeklycommittedHours >=
+ elem.multiple
) {
const theBadge = badgesOfType.find(
- badge => badge._id.toString() === elem._id.toString(),
+ (badge) => badge._id.toString() === elem._id.toString()
);
return theBadge
? increaseBadgeCount(
- personId,
- mongoose.Types.ObjectId(theBadge._id),
- )
+ personId,
+ mongoose.Types.ObjectId(theBadge._id)
+ )
: addBadge(personId, mongoose.Types.ObjectId(elem._id));
}
}
@@ -1042,26 +1105,30 @@ const userHelper = function () {
const checkPersonalMax = async function (personId, user, badgeCollection) {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === 'Personal Max') {
+ if (badgeCollection[i].badge?.type === "Personal Max") {
if (badgeOfType) {
removeDupBadge(personId, badgeOfType._id);
}
}
}
- await badge.findOne({ type: 'Personal Max' }).then((results) => {
+ await badge.findOne({ type: "Personal Max" }).then((results) => {
if (
- user.lastWeekTangibleHrs
- && user.lastWeekTangibleHrs >= 1
- && user.lastWeekTangibleHrs === user.personalBestMaxHrs
+ user.lastWeekTangibleHrs &&
+ user.lastWeekTangibleHrs >= 1 &&
+ user.lastWeekTangibleHrs === user.personalBestMaxHrs
) {
if (badgeOfType) {
changeBadgeCount(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- user.personalBestMaxHrs,
+ user.personalBestMaxHrs
);
} else {
- addBadge(personId, mongoose.Types.ObjectId(results._id), user.personalBestMaxHrs);
+ addBadge(
+ personId,
+ mongoose.Types.ObjectId(results._id),
+ user.personalBestMaxHrs
+ );
}
}
});
@@ -1071,17 +1138,17 @@ const userHelper = function () {
const checkMostHrsWeek = async function (personId, user, badgeCollection) {
if (
- user.weeklycommittedHours > 0
- && user.lastWeekTangibleHrs > user.weeklycommittedHours
+ user.weeklycommittedHours > 0 &&
+ user.lastWeekTangibleHrs > user.weeklycommittedHours
) {
const badgeOfType = badgeCollection
- .filter(object => object.badge.type === 'Most Hrs in Week')
- .map(object => object.badge);
- await badge.findOne({ type: 'Most Hrs in Week' }).then((results) => {
+ .filter((object) => object.badge.type === "Most Hrs in Week")
+ .map((object) => object.badge);
+ await badge.findOne({ type: "Most Hrs in Week" }).then((results) => {
userProfile
.aggregate([
{ $match: { isActive: true } },
- { $group: { _id: 1, maxHours: { $max: '$lastWeekTangibleHrs' } } },
+ { $group: { _id: 1, maxHours: { $max: "$lastWeekTangibleHrs" } } },
])
.then((userResults) => {
if (badgeOfType.length > 1) {
@@ -1089,13 +1156,13 @@ const userHelper = function () {
}
if (
- user.lastWeekTangibleHrs
- && user.lastWeekTangibleHrs >= userResults[0].maxHours
+ user.lastWeekTangibleHrs &&
+ user.lastWeekTangibleHrs >= userResults[0].maxHours
) {
if (badgeOfType.length) {
increaseBadgeCount(
personId,
- mongoose.Types.ObjectId(badgeOfType[0]._id),
+ mongoose.Types.ObjectId(badgeOfType[0]._id)
);
} else {
addBadge(personId, mongoose.Types.ObjectId(results._id));
@@ -1111,12 +1178,12 @@ const userHelper = function () {
// Handle Increasing the 1 week streak badges
const badgesOfType = [];
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === 'X Hours for X Week Streak') {
+ if (badgeCollection[i].badge?.type === "X Hours for X Week Streak") {
badgesOfType.push(badgeCollection[i].badge);
}
}
await badge
- .find({ type: 'X Hours for X Week Streak', weeks: 1 })
+ .find({ type: "X Hours for X Week Streak", weeks: 1 })
.sort({ totalHrs: -1 })
.then((results) => {
results.every((elem) => {
@@ -1141,13 +1208,13 @@ const userHelper = function () {
// Check each Streak Greater than One to check if it works
await badge
.aggregate([
- { $match: { type: 'X Hours for X Week Streak', weeks: { $gt: 1 } } },
+ { $match: { type: "X Hours for X Week Streak", weeks: { $gt: 1 } } },
{ $sort: { weeks: -1, totalHrs: -1 } },
{
$group: {
- _id: '$weeks',
+ _id: "$weeks",
badges: {
- $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' },
+ $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" },
},
},
},
@@ -1159,16 +1226,19 @@ const userHelper = function () {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
-
- badgeCollection[i].badge?.type === 'X Hours for X Week Streak'
- && badgeCollection[i].badge?.weeks === bdge.weeks
+ badgeCollection[i].badge?.type ===
+ "X Hours for X Week Streak" &&
+ badgeCollection[i].badge?.weeks === bdge.weeks
) {
- if (badgeOfType && badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs) {
+ if (
+ badgeOfType &&
+ badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
+ ) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType
- && badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
+ badgeOfType &&
+ badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -1193,10 +1263,16 @@ const userHelper = function () {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(bdge._id),
+ mongoose.Types.ObjectId(bdge._id)
);
- removePrevHrBadge(personId, user, badgeCollection, bdge.hrs, bdge.weeks);
+ removePrevHrBadge(
+ personId,
+ user,
+ badgeCollection,
+ bdge.hrs,
+ bdge.weeks
+ );
} else if (!badgeOfType) {
addBadge(personId, mongoose.Types.ObjectId(bdge._id));
removePrevHrBadge(
@@ -1204,11 +1280,20 @@ const userHelper = function () {
user,
badgeCollection,
bdge.hrs,
- bdge.weeks,
+ bdge.weeks
);
} else if (badgeOfType && badgeOfType.totalHrs === bdge.hrs) {
- increaseBadgeCount(personId, mongoose.Types.ObjectId(badgeOfType._id));
- removePrevHrBadge(personId, user, badgeCollection, bdge.hrs, bdge.weeks);
+ increaseBadgeCount(
+ personId,
+ mongoose.Types.ObjectId(badgeOfType._id)
+ );
+ removePrevHrBadge(
+ personId,
+ user,
+ badgeCollection,
+ bdge.hrs,
+ bdge.weeks
+ );
}
return false;
}
@@ -1221,10 +1306,19 @@ const userHelper = function () {
// 'Lead a team of X+'
-
- const checkLeadTeamOfXplus = async function (personId, user, badgeCollection) {
- const leaderRoles = ['Mentor', 'Manager', 'Administrator', 'Owner', 'Core Team'];
- const approvedRoles = ['Mentor', 'Manager'];
+ const checkLeadTeamOfXplus = async function (
+ personId,
+ user,
+ badgeCollection
+ ) {
+ const leaderRoles = [
+ "Mentor",
+ "Manager",
+ "Administrator",
+ "Owner",
+ "Core Team",
+ ];
+ const approvedRoles = ["Mentor", "Manager"];
if (!approvedRoles.includes(user.role)) return;
let teamMembers;
@@ -1249,11 +1343,17 @@ const userHelper = function () {
});
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === 'Lead a team of X+') {
- if (badgeOfType && badgeOfType.people <= badgeCollection[i].badge.people) {
+ if (badgeCollection[i].badge?.type === "Lead a team of X+") {
+ if (
+ badgeOfType &&
+ badgeOfType.people <= badgeCollection[i].badge.people
+ ) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
- } else if (badgeOfType && badgeOfType.people > badgeCollection[i].badge.people) {
+ } else if (
+ badgeOfType &&
+ badgeOfType.people > badgeCollection[i].badge.people
+ ) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
badgeOfType = badgeCollection[i].badge;
@@ -1261,7 +1361,7 @@ const userHelper = function () {
}
}
await badge
- .find({ type: 'Lead a team of X+' })
+ .find({ type: "Lead a team of X+" })
.sort({ people: -1 })
.then((results) => {
if (!Array.isArray(results) || !results.length) {
@@ -1271,16 +1371,14 @@ const userHelper = function () {
if (teamMembers && teamMembers.length >= badge.people) {
if (badgeOfType) {
if (
- badgeOfType._id.toString() !== badge._id.toString()
- && badgeOfType.people < badge.people
-
+ badgeOfType._id.toString() !== badge._id.toString() &&
+ badgeOfType.people < badge.people
) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(badge._id),
-
+ mongoose.Types.ObjectId(badge._id)
);
}
return false;
@@ -1297,40 +1395,39 @@ const userHelper = function () {
const checkTotalHrsInCat = async function (personId, user, badgeCollection) {
const hoursByCategory = user.hoursByCategory || {};
const categories = [
- 'food',
- 'energy',
- 'housing',
- 'education',
- 'society',
- 'economics',
- 'stewardship',
+ "food",
+ "energy",
+ "housing",
+ "education",
+ "society",
+ "economics",
+ "stewardship",
];
const badgesOfType = badgeCollection
- .filter(object => object.badge.type === 'Total Hrs in Category')
- .map(object => object.badge);
+ .filter((object) => object.badge.type === "Total Hrs in Category")
+ .map((object) => object.badge);
categories.forEach(async (category) => {
const categoryHrs = Object.keys(hoursByCategory).find(
- elem => elem === category,
+ (elem) => elem === category
);
-
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
- badgeCollection[i].badge?.type === 'Total Hrs in Category'
- && badgeCollection[i].badge?.category === category
+ badgeCollection[i].badge?.type === "Total Hrs in Category" &&
+ badgeCollection[i].badge?.category === category
) {
if (
- badgeOfType
- && badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
+ badgeOfType &&
+ badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType
- && badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
+ badgeOfType &&
+ badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -1341,8 +1438,8 @@ const userHelper = function () {
const newCatg = category.charAt(0).toUpperCase() + category.slice(1);
-
- await badge.find({ type: 'Total Hrs in Category', category: newCatg })
+ await badge
+ .find({ type: "Total Hrs in Category", category: newCatg })
.sort({ totalHrs: -1 })
.then((results) => {
@@ -1352,8 +1449,8 @@ const userHelper = function () {
results.every((elem) => {
if (
- hoursByCategory[categoryHrs] >= 100
- && hoursByCategory[categoryHrs] >= elem.totalHrs
+ hoursByCategory[categoryHrs] >= 100 &&
+ hoursByCategory[categoryHrs] >= elem.totalHrs
) {
let theBadge;
for (let i = 0; i < badgesOfType.length; i += 1) {
@@ -1368,13 +1465,13 @@ const userHelper = function () {
}
if (badgeOfType) {
if (
- badgeOfType._id.toString() !== elem._id.toString()
- && badgeOfType.totalHrs < elem.totalHrs
+ badgeOfType._id.toString() !== elem._id.toString() &&
+ badgeOfType.totalHrs < elem.totalHrs
) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id),
+ mongoose.Types.ObjectId(elem._id)
);
}
return false;
@@ -1389,10 +1486,11 @@ const userHelper = function () {
};
const awardNewBadges = async () => {
- console.log('Awarding');
+ console.log("Awarding");
try {
- const users = await userProfile.find({ isActive: true }).populate('badgeCollection.badge');
-
+ const users = await userProfile
+ .find({ isActive: true })
+ .populate("badgeCollection.badge");
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -1414,9 +1512,14 @@ const userHelper = function () {
const getTangibleHoursReportedThisWeekByUserId = function (personId) {
const userId = mongoose.Types.ObjectId(personId);
- const pdtstart = moment().tz('America/Los_Angeles').startOf('week').format('YYYY-MM-DD');
- const pdtend = moment().tz('America/Los_Angeles').endOf('week').format('YYYY-MM-DD');
-
+ const pdtstart = moment()
+ .tz("America/Los_Angeles")
+ .startOf("week")
+ .format("YYYY-MM-DD");
+ const pdtend = moment()
+ .tz("America/Los_Angeles")
+ .endOf("week")
+ .format("YYYY-MM-DD");
return timeEntries
.find(
@@ -1425,12 +1528,12 @@ const userHelper = function () {
dateOfWork: { $gte: pdtstart, $lte: pdtend },
isTangible: true,
},
- 'totalSeconds',
+ "totalSeconds"
)
.then((results) => {
const totalTangibleWeeklySeconds = results.reduce(
(acc, { totalSeconds }) => acc + totalSeconds,
- 0,
+ 0
);
return (totalTangibleWeeklySeconds / 3600).toFixed(2);
});
@@ -1440,25 +1543,29 @@ const userHelper = function () {
try {
const users = await userProfile.find(
{ isActive: true, endDate: { $exists: true } },
- '_id isActive endDate',
+ "_id isActive endDate"
);
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
const { endDate } = user;
endDate.setHours(endDate.getHours() + 7);
- if (moment().isAfter(moment(endDate).add(1, 'days'))) {
+ if (moment().isAfter(moment(endDate).add(1, "days"))) {
await userProfile.findByIdAndUpdate(
user._id,
user.set({
isActive: false,
}),
- { new: true },
+ { new: true }
);
const id = user._id;
const person = await userProfile.findById(id);
- const lastDay = moment(person.endDate).format('YYYY-MM-DD');
- logger.logInfo(`User with id: ${user._id} was de-acticated at ${moment().format()}.`);
+ const lastDay = moment(person.endDate).format("YYYY-MM-DD");
+ logger.logInfo(
+ `User with id: ${
+ user._id
+ } was de-acticated at ${moment().format()}.`
+ );
const subject = `IMPORTANT:${person.firstName} ${person.lastName} has been deactivated in the Highest Good Network`;
@@ -1472,8 +1579,14 @@ const userHelper = function () {
The HGN A.I. (and One Community)
`;
-
- emailSender('onecommunityglobal@gmail.com', subject, emailBody, null, null);
+ emailSender(
+ "onecommunityglobal@gmail.com",
+ subject,
+ emailBody,
+ null,
+ null,
+ person.email
+ );
}
}
} catch (err) {
@@ -1491,7 +1604,6 @@ const userHelper = function () {
}
};
-
return {
getUserName,
getTeamMembers,
@@ -1510,4 +1622,4 @@ const userHelper = function () {
};
};
-module.exports = userHelper;
+module.exports = userHelper;
\ No newline at end of file
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 1713d6a67..8b8cf98f4 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -20,9 +20,11 @@ const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
-const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
+const inventoryItemMaterial = require('../models/inventoryItemMaterial');
+const mapLocations = require('../models/mapLocation');
const buildingProject = require('../models/bmdashboard/buildingProject');
const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
+const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -58,10 +60,13 @@ const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter
const reasonRouter = require('../routes/reasonRouter')(reason, userProfile);
const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverText);
+const mapLocationRouter = require('../routes/mapLocationsRouter')(mapLocations);
+
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(buildingMaterial);
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, buildingMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
+const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(buildingInventoryType);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -93,8 +98,10 @@ module.exports = function (app) {
app.use('/api', informationRouter);
app.use('/api', mouseoverTextRouter);
app.use('/api', isEmailExistsRouter);
+ app.use('/api', mapLocationRouter);
// bm dashboard
app.use('/api/bm', bmLoginRouter);
- app.use('/api/bm', bmProjectRouter);
app.use('/api/bm', bmMaterialsRouter);
-};
+ app.use('/api/bm', bmProjectRouter);
+ app.use('/api/bm', bmInventoryTypeRouter);
+};
\ No newline at end of file
From c1294d44413f8b67abbadbb0ac8ab1e953ab967d Mon Sep 17 00:00:00 2001
From: lacnoskillz
Date: Fri, 1 Dec 2023 12:14:46 -0600
Subject: [PATCH 175/272] remake branch without package-lock.json modifications
---
.../bmdashboard/bmInventoryTypeController.js | 53 +++++++++++++++----
.../bmdashboard/bmInventoryTypeRouter.js | 5 ++
2 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index b9ced243e..f7e964f86 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -1,19 +1,54 @@
const bmInventoryTypeController = function (InvType) {
const fetchMaterialTypes = async (req, res) => {
try {
- InvType
- .find()
- .exec()
- .then(result => res.status(200).send(result))
- .catch(error => res.status(500).send(error));
- } catch (err) {
- res.json(err);
+ const result = await InvType.find().exec();
+ res.status(200).send(result);
+ } catch (error) {
+ res.status(500).send(error);
}
};
+ const fetchSingleInventoryType = async (req, res) => {
+ const { invtypeId } = req.params;
+ try {
+ const result = await InvType.findById(invtypeId).exec();
+ res.status(200).send(result);
+ } catch (error) {
+ res.status(500).send(error);
+ }
+ };
+
+ const updateNameAndUnit = async (req, res) => {
+ try {
+ const { invtypeId } = req.params;
+ const { name, unit } = req.body;
+
+ const updateData = {};
- return {
- fetchMaterialTypes,
+ if (name) {
+ updateData.name = name;
+ }
+
+ if (unit) {
+ updateData.unit = unit;
+ }
+
+ const updatedInvType = await InvType.findByIdAndUpdate(
+ invtypeId,
+ updateData,
+ { new: true, runValidators: true },
+ );
+
+ if (!updatedInvType) {
+ return res.status(404).json({ error: 'invType Material not found check Id' });
+ }
+
+ res.status(200).json(updatedInvType);
+ } catch (error) {
+ res.status(500).send(error);
+ }
};
+
+ return { fetchMaterialTypes, fetchSingleInventoryType, updateNameAndUnit };
};
module.exports = bmInventoryTypeController;
diff --git a/src/routes/bmdashboard/bmInventoryTypeRouter.js b/src/routes/bmdashboard/bmInventoryTypeRouter.js
index ceae439dc..e62e71c07 100644
--- a/src/routes/bmdashboard/bmInventoryTypeRouter.js
+++ b/src/routes/bmdashboard/bmInventoryTypeRouter.js
@@ -4,9 +4,14 @@ const routes = function (invType) {
const inventoryTypeRouter = express.Router();
const controller = require('../../controllers/bmdashboard/bmInventoryTypeController')(invType);
+ // Route for fetching all material types
inventoryTypeRouter.route('/invtypes/materials')
.get(controller.fetchMaterialTypes);
+ // Combined routes for getting a single inventory type and updating its name and unit of measurement
+ inventoryTypeRouter.route('/invtypes/material/:invtypeId')
+ .get(controller.fetchSingleInventoryType)
+ .put(controller.updateNameAndUnit);
return inventoryTypeRouter;
};
From 28badf296ee9d88dd2c50b0d0b9c9e9e858cc2fe Mon Sep 17 00:00:00 2001
From: lacnoskillz
Date: Fri, 1 Dec 2023 12:34:55 -0600
Subject: [PATCH 176/272] changed fetchMaterialTypes back to how it was before
---
.../bmdashboard/bmInventoryTypeController.js | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index f7e964f86..5460f529c 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -1,10 +1,13 @@
const bmInventoryTypeController = function (InvType) {
const fetchMaterialTypes = async (req, res) => {
try {
- const result = await InvType.find().exec();
- res.status(200).send(result);
- } catch (error) {
- res.status(500).send(error);
+ InvType
+ .find()
+ .exec()
+ .then(result => res.status(200).send(result))
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
}
};
const fetchSingleInventoryType = async (req, res) => {
From 40e044a474dd2ca6be9a517ac4963ebb0d09acf6 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 1 Dec 2023 12:17:24 -0800
Subject: [PATCH 177/272] update fetchAllProjects func to populate itemType
field
---
src/controllers/bmdashboard/bmProjectController.js | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js
index 8ca62ea77..b6b3e4e18 100644
--- a/src/controllers/bmdashboard/bmProjectController.js
+++ b/src/controllers/bmdashboard/bmProjectController.js
@@ -36,6 +36,17 @@ const bmMProjectController = function (BuildingProject) {
pipeline: [
{ $match: { $expr: { $eq: ['$project', '$$id'] } } },
{ $project: { updateRecord: 0, project: 0 } },
+ {
+ $lookup: {
+ from: 'buildingInventoryTypes',
+ localField: 'itemType',
+ foreignField: '_id',
+ as: 'itemType',
+ },
+ },
+ {
+ $unwind: '$itemType',
+ },
],
as: 'materials',
},
@@ -63,7 +74,6 @@ const bmMProjectController = function (BuildingProject) {
proj.mostMaterialWaste = proj.materials.sort((a, b) => b.stockWasted - a.stockWasted)[0];
proj.leastMaterialAvailable = proj.materials.sort((a, b) => a.stockAvailable - b.stockAvailable)[0];
proj.mostMaterialBought = proj.materials.sort((a, b) => b.stockBought - a.stockBought)[0];
- proj.teamCount = proj.teams.length;
});
res.status(200).send(results);
})
From be6b67f1074864b7eb440c45d992fe4d056eabc3 Mon Sep 17 00:00:00 2001
From: Olga Yudkin
Date: Fri, 1 Dec 2023 15:25:44 -0500
Subject: [PATCH 178/272] renamed tool router and controller and fixed syntax
error
---
.../bmdashboard/bmToolController.js | 27 +++++++++++++++++++
.../bmdashboard/bmToolsController.js | 27 -------------------
.../{bmToolsRouter.js => bmToolRouter.js} | 2 +-
src/startup/routes.js | 4 +--
4 files changed, 30 insertions(+), 30 deletions(-)
create mode 100644 src/controllers/bmdashboard/bmToolController.js
delete mode 100644 src/controllers/bmdashboard/bmToolsController.js
rename src/routes/bmdashboard/{bmToolsRouter.js => bmToolRouter.js} (90%)
diff --git a/src/controllers/bmdashboard/bmToolController.js b/src/controllers/bmdashboard/bmToolController.js
new file mode 100644
index 000000000..2b29101f3
--- /dev/null
+++ b/src/controllers/bmdashboard/bmToolController.js
@@ -0,0 +1,27 @@
+const bmToolController = (BuildingTool) => {
+ const fetchSingleTool = async (req, res) => {
+ const { toolId } = req.params;
+ try {
+ BuildingTool
+ .findById(toolId)
+ // .populate([
+ // {
+ // path: 'itemType',
+ // select: '_id name description unit imageURL',
+ // },
+ // {
+ // path: 'userResponsible',
+ // select: '_id firstName lastName',
+ // },
+ // ])
+ .exec()
+ .then(tool => res.status(200).send(tool))
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
+ }
+ };
+ return { fetchSingleTool };
+};
+
+module.exports = bmToolController;
diff --git a/src/controllers/bmdashboard/bmToolsController.js b/src/controllers/bmdashboard/bmToolsController.js
deleted file mode 100644
index c54ac7b24..000000000
--- a/src/controllers/bmdashboard/bmToolsController.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const bmToolsController = (BuildingTool) => {
- const fetchSingleTool = async (req, res) => {
- const { toolId } = req.params;
- try {
- BuildingTool
- .findById(toolId)
- .populate([
- {
- path: 'itemType',
- select: '_id name description unit imageURL',
- },
- {
- path: 'userResponsible',
- select: '_id firstName lastName',
- },
- ])
- .exec()
- .then(tool => res.status(200).send(tool))
- .catch(error => res.status(500).send(error));
- } catch (err) {
- res.json(err);
- }
- };
- return fetchSingleTool;
-};
-
-module.exports = bmToolsController;
diff --git a/src/routes/bmdashboard/bmToolsRouter.js b/src/routes/bmdashboard/bmToolRouter.js
similarity index 90%
rename from src/routes/bmdashboard/bmToolsRouter.js
rename to src/routes/bmdashboard/bmToolRouter.js
index 32ea64f20..a1a30ea40 100644
--- a/src/routes/bmdashboard/bmToolsRouter.js
+++ b/src/routes/bmdashboard/bmToolRouter.js
@@ -2,7 +2,7 @@ const express = require('express');
const routes = function (BuildingTool) {
const toolRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmToolsController')(BuildingTool);
+ const controller = require('../../controllers/bmdashboard/bmToolController')(BuildingTool);
toolRouter.route('/tools/:toolId')
.get(controller.fetchSingleTool);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 5cdf15b6a..6cd7d3771 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -62,7 +62,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
-const bmToolsRouter = require('../routes/bmdashboard/bmToolsRouter')(buildingTool);
+const bmToolRouter = require('../routes/bmdashboard/bmToolRouter')(buildingTool);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -98,5 +98,5 @@ module.exports = function (app) {
app.use('/api/bm', bmLoginRouter);
app.use('/api/bm', bmMaterialsRouter);
app.use('/api/bm', bmProjectRouter);
- app.use('/api/bm', bmToolsRouter);
+ app.use('/api/bm', bmToolRouter);
};
From f67d2b46f3604ce625dfaeff447d5ae338749310 Mon Sep 17 00:00:00 2001
From: Oleksandr Riazantsev
Date: Fri, 1 Dec 2023 17:15:06 -0500
Subject: [PATCH 179/272] Cron job - change main locations
---
src/cronjobs/userProfileJobs.js | 2 +-
src/helpers/userHelper.js | 104 ++++++++++++++++++++++++++------
2 files changed, 85 insertions(+), 21 deletions(-)
diff --git a/src/cronjobs/userProfileJobs.js b/src/cronjobs/userProfileJobs.js
index f3903c057..1e4c6392a 100644
--- a/src/cronjobs/userProfileJobs.js
+++ b/src/cronjobs/userProfileJobs.js
@@ -18,12 +18,12 @@ const userProfileJobs = () => {
await userhelper.awardNewBadges();
await userhelper.reActivateUser();
await userhelper.deActivateUser();
+ await userhelper.oneTimeLocationUpdate();
},
null,
false,
'America/Los_Angeles',
);
-
allUserProfileJobs.start();
};
module.exports = userProfileJobs;
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 8bf04eb5f..1e349245c 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -105,8 +105,8 @@ const userHelper = function () {
Date Assigned: ${infringement.date}
Description: ${infringement.description}
Total Infringements: This is your ${moment
- .localeData()
- .ordinal(totalInfringements)} blue square of 5.
+ .localeData()
+ .ordinal(totalInfringements)} blue square of 5.
${final_paragraph}
Thank you,
One Community
`;
@@ -197,8 +197,8 @@ const userHelper = function () {
Weekly Summary
(for the week ending on ${moment(dueDate)
- .tz("America/Los_Angeles")
- .format("YYYY-MMM-DD")}):
+ .tz("America/Los_Angeles")
+ .format("YYYY-MMM-DD")}):
${summary}
@@ -220,24 +220,24 @@ const userHelper = function () {
Media URL: ${
mediaUrlLink || '
Not provided!'
- }
+ }
${
weeklySummariesCount === 8
- ? `
Total Valid Weekly Summaries: ${weeklySummariesCount}
`
- : `
Total Valid Weekly Summaries: ${
+ ? `
Total Valid Weekly Summaries: ${weeklySummariesCount}
`
+ : `
Total Valid Weekly Summaries: ${
weeklySummariesCount || "No valid submissions yet!"
- }
`
+ }`
}
${
hoursLogged >= weeklycommittedHours
- ? `
Hours logged: ${hoursLogged.toFixed(
- 2
- )} / ${weeklycommittedHours}
`
- : `
Hours logged: ${hoursLogged.toFixed(
- 2
- )} / ${weeklycommittedHours}
`
+ ? `
Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
+ : `
Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
}
${weeklySummaryMessage}
`;
@@ -298,6 +298,69 @@ const userHelper = function () {
})
.catch((error) => logger.logException(error));
};
+ async function wait(ms) {
+ return new Promise((r) => setTimeout(r, ms));
+ }
+ const oneTimeLocationUpdate = async () => {
+ const users = await userProfile.find({}, '_id');
+
+ for (let i = 0; i < users.length; i += 1) {
+ const user = users[i];
+ const person = await userProfile.findById(user._id);
+ if (!person.location.coords && !person.location.country && !person.location.city && !person.location.userProvided) {
+ const personLoc = person.location || '';
+ let location;
+ if (personLoc) {
+ try {
+ const res = await fetch(`https://api.opencagedata.com/geocode/v1/json?key=d093a5e0eee34aea8043f4e6edb0e9f7&q=${encodeURIComponent(personLoc)}&pretty=1&limit=1`);
+ if (!res) {
+ throw new Error();
+ } else {
+ const data = await res.json();
+ location = {
+ userProvided: personLoc || '',
+ coords: {
+ lat: data.results[0].geometry.lat || '',
+ lng: data.results[0].geometry.lng || '',
+ },
+ country: data.results[0].components.country || '',
+ city: data.results[0].components.city || '',
+ };
+ }
+ } catch (err) {
+ console.log(err);
+ location = {
+ userProvided: personLoc,
+ coords: {
+ lat: 'err',
+ lng: '',
+ },
+ country: '',
+ city: '',
+ }
+ }
+ } else {
+ location = {
+ userProvided: personLoc || '',
+ coords: {
+ lat: '',
+ lng: '',
+ },
+ country: '',
+ city: '',
+ };
+ }
+ await userProfile.findOneAndUpdate({ _id: user._id }, {
+ $set: {
+ location,
+ },
+ });
+ }
+
+ await wait(2000);
+ }
+ };
+
/**
* This function is called by a cron job to do 3 things to all active users:
@@ -936,7 +999,7 @@ const userHelper = function () {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
badgeCollection[i].badge?.type ===
- "X Hours for X Week Streak" &&
+ "X Hours for X Week Streak" &&
badgeCollection[i].badge?.weeks === bdge.weeks &&
bdge.hrs === hrs &&
!removed
@@ -1041,7 +1104,7 @@ const userHelper = function () {
true
)
) >=
- elem.months - 12
+ elem.months - 12
) {
if (badgeOfType) {
if (badgeOfType._id.toString() !== elem._id.toString()) {
@@ -1092,9 +1155,9 @@ const userHelper = function () {
);
return theBadge
? increaseBadgeCount(
- personId,
- mongoose.Types.ObjectId(theBadge._id)
- )
+ personId,
+ mongoose.Types.ObjectId(theBadge._id)
+ )
: addBadge(personId, mongoose.Types.ObjectId(elem._id));
}
}
@@ -1227,7 +1290,7 @@ const userHelper = function () {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
badgeCollection[i].badge?.type ===
- "X Hours for X Week Streak" &&
+ "X Hours for X Week Streak" &&
badgeCollection[i].badge?.weeks === bdge.weeks
) {
if (
@@ -1619,6 +1682,7 @@ const userHelper = function () {
awardNewBadges,
getTangibleHoursReportedThisWeekByUserId,
deleteExpiredTokens,
+ oneTimeLocationUpdate,
};
};
From 37dbad95613343a6f7dc0b7c58d29f53521f0a60 Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Fri, 1 Dec 2023 17:12:06 -0800
Subject: [PATCH 180/272] Fix end anchor symbol in escapeRegex
---
src/utilities/escapeRegex.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/utilities/escapeRegex.js b/src/utilities/escapeRegex.js
index 01a65ea50..cf7563e26 100644
--- a/src/utilities/escapeRegex.js
+++ b/src/utilities/escapeRegex.js
@@ -1,6 +1,6 @@
const escapeRegex = function (text) {
- return `^${text.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&')}&`;
+ return `^${text.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&')}$`;
};
module.exports = escapeRegex;
From 051cd4bc1bc1b920e52183b8f1b752f3ec1b268d Mon Sep 17 00:00:00 2001
From: One Community
Date: Sat, 2 Dec 2023 00:19:36 -0800
Subject: [PATCH 181/272] Revert "Cron job - change main locations"
---
src/cronjobs/userProfileJobs.js | 2 +-
src/helpers/userHelper.js | 104 ++++++--------------------------
2 files changed, 21 insertions(+), 85 deletions(-)
diff --git a/src/cronjobs/userProfileJobs.js b/src/cronjobs/userProfileJobs.js
index 1e4c6392a..f3903c057 100644
--- a/src/cronjobs/userProfileJobs.js
+++ b/src/cronjobs/userProfileJobs.js
@@ -18,12 +18,12 @@ const userProfileJobs = () => {
await userhelper.awardNewBadges();
await userhelper.reActivateUser();
await userhelper.deActivateUser();
- await userhelper.oneTimeLocationUpdate();
},
null,
false,
'America/Los_Angeles',
);
+
allUserProfileJobs.start();
};
module.exports = userProfileJobs;
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 1e349245c..8bf04eb5f 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -105,8 +105,8 @@ const userHelper = function () {
Date Assigned: ${infringement.date}
Description: ${infringement.description}
Total Infringements: This is your ${moment
- .localeData()
- .ordinal(totalInfringements)} blue square of 5.
+ .localeData()
+ .ordinal(totalInfringements)} blue square of 5.
${final_paragraph}
Thank you,
One Community
`;
@@ -197,8 +197,8 @@ const userHelper = function () {
Weekly Summary
(for the week ending on ${moment(dueDate)
- .tz("America/Los_Angeles")
- .format("YYYY-MMM-DD")}):
+ .tz("America/Los_Angeles")
+ .format("YYYY-MMM-DD")}):
${summary}
@@ -220,24 +220,24 @@ const userHelper = function () {
Media URL: ${
mediaUrlLink || '
Not provided!'
- }
+ }
${
weeklySummariesCount === 8
- ? `
Total Valid Weekly Summaries: ${weeklySummariesCount}
`
- : `
Total Valid Weekly Summaries: ${
+ ? `
Total Valid Weekly Summaries: ${weeklySummariesCount}
`
+ : `
Total Valid Weekly Summaries: ${
weeklySummariesCount || "No valid submissions yet!"
- }
`
+ }`
}
${
hoursLogged >= weeklycommittedHours
- ? `
Hours logged: ${hoursLogged.toFixed(
- 2
- )} / ${weeklycommittedHours}
`
- : `
Hours logged: ${hoursLogged.toFixed(
- 2
- )} / ${weeklycommittedHours}
`
+ ? `
Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
+ : `
Hours logged: ${hoursLogged.toFixed(
+ 2
+ )} / ${weeklycommittedHours}
`
}
${weeklySummaryMessage}
`;
@@ -298,69 +298,6 @@ const userHelper = function () {
})
.catch((error) => logger.logException(error));
};
- async function wait(ms) {
- return new Promise((r) => setTimeout(r, ms));
- }
- const oneTimeLocationUpdate = async () => {
- const users = await userProfile.find({}, '_id');
-
- for (let i = 0; i < users.length; i += 1) {
- const user = users[i];
- const person = await userProfile.findById(user._id);
- if (!person.location.coords && !person.location.country && !person.location.city && !person.location.userProvided) {
- const personLoc = person.location || '';
- let location;
- if (personLoc) {
- try {
- const res = await fetch(`https://api.opencagedata.com/geocode/v1/json?key=d093a5e0eee34aea8043f4e6edb0e9f7&q=${encodeURIComponent(personLoc)}&pretty=1&limit=1`);
- if (!res) {
- throw new Error();
- } else {
- const data = await res.json();
- location = {
- userProvided: personLoc || '',
- coords: {
- lat: data.results[0].geometry.lat || '',
- lng: data.results[0].geometry.lng || '',
- },
- country: data.results[0].components.country || '',
- city: data.results[0].components.city || '',
- };
- }
- } catch (err) {
- console.log(err);
- location = {
- userProvided: personLoc,
- coords: {
- lat: 'err',
- lng: '',
- },
- country: '',
- city: '',
- }
- }
- } else {
- location = {
- userProvided: personLoc || '',
- coords: {
- lat: '',
- lng: '',
- },
- country: '',
- city: '',
- };
- }
- await userProfile.findOneAndUpdate({ _id: user._id }, {
- $set: {
- location,
- },
- });
- }
-
- await wait(2000);
- }
- };
-
/**
* This function is called by a cron job to do 3 things to all active users:
@@ -999,7 +936,7 @@ const userHelper = function () {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
badgeCollection[i].badge?.type ===
- "X Hours for X Week Streak" &&
+ "X Hours for X Week Streak" &&
badgeCollection[i].badge?.weeks === bdge.weeks &&
bdge.hrs === hrs &&
!removed
@@ -1104,7 +1041,7 @@ const userHelper = function () {
true
)
) >=
- elem.months - 12
+ elem.months - 12
) {
if (badgeOfType) {
if (badgeOfType._id.toString() !== elem._id.toString()) {
@@ -1155,9 +1092,9 @@ const userHelper = function () {
);
return theBadge
? increaseBadgeCount(
- personId,
- mongoose.Types.ObjectId(theBadge._id)
- )
+ personId,
+ mongoose.Types.ObjectId(theBadge._id)
+ )
: addBadge(personId, mongoose.Types.ObjectId(elem._id));
}
}
@@ -1290,7 +1227,7 @@ const userHelper = function () {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
badgeCollection[i].badge?.type ===
- "X Hours for X Week Streak" &&
+ "X Hours for X Week Streak" &&
badgeCollection[i].badge?.weeks === bdge.weeks
) {
if (
@@ -1682,7 +1619,6 @@ const userHelper = function () {
awardNewBadges,
getTangibleHoursReportedThisWeekByUserId,
deleteExpiredTokens,
- oneTimeLocationUpdate,
};
};
From 081c1bba112e3c603d582ef6642dc1dae6b7889b Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 5 Dec 2023 11:38:48 -0800
Subject: [PATCH 182/272] add records subdocuments
---
src/models/bmdashboard/buildingTool.js | 38 ++++++++++++++++++++------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/src/models/bmdashboard/buildingTool.js b/src/models/bmdashboard/buildingTool.js
index 6cec3b5d0..95be0c4d5 100644
--- a/src/models/bmdashboard/buildingTool.js
+++ b/src/models/bmdashboard/buildingTool.js
@@ -2,15 +2,35 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
-const buildingTools = new Schema({
+const buildingTool = new Schema({
itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
- title: { type: String, required: true },
- rentedOnDate: { type: Date, required: true },
- rentDuration: { type: Number, required: true }, // This value should be taken in number of days
- logInStatus:{Boolean},
- condition:{type: String, enum: ['Good', 'Needs Repair', 'Out of Order','Unused'], default: 'Good'},
- userResponsible:{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- purchaseStatus:{type: String, enum: ['Rented', 'Purchased'], default: 'Rented'},
+ code: { type: Number, required: true }, // add function to create code for on-site tool tracking
+ purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
+ // add discriminator based on rental or purchase so these fields are required if tool is rented
+ rentedOnDate: Date,
+ rentalDue: Date,
+ userResponsible: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ purchaseRecord: [{ // track purchase/rental requests
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ brand: String,
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+ }],
+ updateRecord: [{ // track tool condition updates
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
+ }],
+ logRecord: [{ // track tool daily check in/out and use
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ type: { type: String, enum: ['Check In', 'Check Out'] }, // default = opposite of current log status?
+ }],
});
-module.exports = mongoose.model('buildingTools', buildingTools, 'buildingTools');
\ No newline at end of file
+module.exports = mongoose.model('buildingTool', buildingTool, 'buildingTools');
From 35b1b6c36220b8af1a83194b7923cf7f301f2a5d Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 6 Dec 2023 08:44:49 -0800
Subject: [PATCH 183/272] add new model template
---
src/models/bmdashboard/buildingReusable.js | 29 ++++++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 src/models/bmdashboard/buildingReusable.js
diff --git a/src/models/bmdashboard/buildingReusable.js b/src/models/bmdashboard/buildingReusable.js
new file mode 100644
index 000000000..1d0503010
--- /dev/null
+++ b/src/models/bmdashboard/buildingReusable.js
@@ -0,0 +1,29 @@
+const mongoose = require('mongoose');
+
+const { Schema } = mongoose;
+
+const buildingReusable = new Schema({
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+ stockBought: { type: Number, default: 0 },
+ stockDestroyed: { type: Number, default: 0 },
+ stockAvailable: { type: Number, default: 0 },
+ purchaseRecord: [{
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantity: { type: Number, required: true },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ brand: String,
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+ }],
+ updateRecord: [{
+ _id: false,
+ date: { type: Date, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantityUsed: { type: Number, required: true },
+ quantityDestroyed: { type: Number, required: true },
+ }],
+});
+
+module.exports = mongoose.model('buildingReusable', buildingReusable, 'buildingReusables');
From 0976b730a58bb2f6c0a21d13d15e45df3861c672 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 6 Dec 2023 09:43:10 -0800
Subject: [PATCH 184/272] removed mongo-round package
---
package.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/package.json b/package.json
index 32d23ee6a..1c6b8a5d4 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,6 @@
"lodash": "^4.17.21",
"moment": "^2.29.4",
"moment-timezone": "^0.5.35",
- "mongo-round": "^1.0.0",
"mongodb": "^3.7.3",
"mongoose": "^5.13.15",
"mongoose-validator": "^2.1.0",
From 0a30abbaa285dff8ca19f219a92077beb40183a2 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Wed, 6 Dec 2023 17:16:44 -0500
Subject: [PATCH 185/272] added timeOffFrom and timeOffTill fields to mongoDB
---
src/controllers/reasonSchedulingController.js | 188 ++++++----
src/helpers/dashboardhelper.js | 339 +++++++++---------
src/models/userProfile.js | 104 +++---
3 files changed, 348 insertions(+), 283 deletions(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index e310049c2..89b312bc2 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 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,61 @@ 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,
});
}
+ // new changes
+
+ if (
+ foundUser.hasOwnProperty("timeOffFrom") &&
+ foundUser.hasOwnProperty("timeOffTill")
+ ) {
+ if (currentDate >= foundUser.timeOffTill) {
+ await UserModel.findOneAndUpdate(
+ {
+ _id: userId,
+ },
+ {
+ $set: {
+ timeOffFrom: currentDate,
+ timeOffTill: newDate,
+ },
+ }
+ );
+ } else {
+ await UserModel.findOneAndUpdate(
+ {
+ _id: userId,
+ },
+ {
+ $set: {
+ timeOffTill: newDate,
+ },
+ }
+ );
+ }
+ } else {
+ 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 +112,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,16 +128,13 @@ const postReason = async (req, res) => {
userId,
});
-
//await newReason.save();
- const savedData = await newReason.save();
- if(savedData)
- {
-
+ 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.
@@ -104,23 +143,21 @@ const postReason = async (req, res) => {
Thank you,
One Community
`;
-
-
- // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null);
- // 2 user email -
- emailSender(`${foundUser.email}`, subject, emailBody, null, null);
+ // 1 hardcoded email- emailSender('@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);
+ // 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);
+ }
+
+ return res.sendStatus(200);
} catch (error) {
console.log(error);
return res.status(400).json({
- errMessage: 'Something went wrong',
+ errMessage: "Something went wrong",
});
}
};
@@ -143,7 +180,7 @@ const getAllReasons = async (req, res) => {
// error case 2
if (!foundUser) {
return res.status(404).json({
- message: 'User not found',
+ message: "User not found",
});
}
@@ -157,7 +194,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",
});
}
};
@@ -181,24 +218,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,
});
}
@@ -207,7 +244,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",
});
}
};
@@ -228,7 +265,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,
});
}
@@ -238,36 +275,34 @@ 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,
});
}
foundReason.reason = reasonData.message;
-
+
const savedData = await foundReason.save();
- if(savedData)
- {
-
+ 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.
@@ -276,25 +311,22 @@ const patchReason = async (req, res) => {
Thank you,
One Community
`;
-
-
- // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null);
- // 2 user email -
- emailSender(`${foundUser.email}`, subject, emailBody, null, null);
+ // 1 hardcoded email- emailSender('@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);
-
-
- }
+ // 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);
+ }
return res.status(200).json({
- 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",
});
}
};
@@ -305,10 +337,10 @@ 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,
});
}
@@ -318,21 +350,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,
});
}
@@ -340,13 +372,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 34d464583..64c867f71 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -1,26 +1,26 @@
-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 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 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:
@@ -39,35 +39,35 @@ 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],
},
],
},
@@ -77,7 +77,7 @@ const dashboardhelper = function () {
},
{
$unwind: {
- path: '$timeEntryData',
+ path: "$timeEntryData",
preserveNullAndEmptyArrays: true,
},
},
@@ -88,27 +88,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,
],
},
@@ -117,17 +117,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] },
},
},
},
@@ -135,15 +135,15 @@ const dashboardhelper = function () {
$group: {
_id: 0,
memberCount: { $sum: 1 },
- totalweeklycommittedHours: { $sum: '$_id.weeklycommittedHours' },
+ totalweeklycommittedHours: { $sum: "$_id.weeklycommittedHours" },
totaltime_hrs: {
- $sum: '$time_hrs',
+ $sum: "$time_hrs",
},
totaltangibletime_hrs: {
- $sum: '$tangibletime_hrs',
+ $sum: "$tangibletime_hrs",
},
totalintangibletime_hrs: {
- $sum: '$intangibletime_hrs',
+ $sum: "$intangibletime_hrs",
},
},
},
@@ -155,13 +155,13 @@ const dashboardhelper = function () {
const getLeaderboard = function (userId) {
const userid = mongoose.Types.ObjectId(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 myTeam.aggregate([
{
$match: {
@@ -169,22 +169,22 @@ const dashboardhelper = function () {
},
},
{
- $unwind: '$myteam',
+ $unwind: "$myteam",
},
{
$project: {
_id: 0,
role: 1,
- personId: '$myteam._id',
- name: '$myteam.fullName',
+ personId: "$myteam._id",
+ name: "$myteam.fullName",
},
},
{
$lookup: {
- from: 'userProfiles',
- localField: 'personId',
- foreignField: '_id',
- as: 'persondata',
+ from: "userProfiles",
+ localField: "personId",
+ foreignField: "_id",
+ as: "persondata",
},
},
{
@@ -192,31 +192,37 @@ const dashboardhelper = function () {
// leaderboard user roles hierarchy
$or: [
{
- role: { $in: ['Owner', 'Core Team'] },
+ role: { $in: ["Owner", "Core Team"] },
},
{
$and: [
{
- role: 'Administrator',
+ role: "Administrator",
},
- { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ]
+ { "persondata.0.role": { $nin: ["Owner", "Administrator"] } },
+ ],
},
{
$and: [
{
- role: { $in: ['Manager', 'Mentor'] },
+ role: { $in: ["Manager", "Mentor"] },
},
{
- 'persondata.0.role': {
- $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ "persondata.0.role": {
+ $nin: [
+ "Manager",
+ "Mentor",
+ "Core Team",
+ "Administrator",
+ "Owner",
+ ],
},
},
],
},
- { 'persondata.0._id': userId },
- { 'persondata.0.role': 'Volunteer' },
- { 'persondata.0.isVisible': true },
+ { "persondata.0._id": userId },
+ { "persondata.0.role": "Volunteer" },
+ { "persondata.0.isVisible": true },
],
},
},
@@ -225,31 +231,31 @@ const dashboardhelper = function () {
personId: 1,
name: 1,
role: {
- $arrayElemAt: ['$persondata.role', 0],
+ $arrayElemAt: ["$persondata.role", 0],
},
isVisible: {
- $arrayElemAt: ['$persondata.isVisible', 0],
+ $arrayElemAt: ["$persondata.isVisible", 0],
},
hasSummary: {
$ne: [
{
$arrayElemAt: [
{
- $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
+ $arrayElemAt: ["$persondata.weeklySummaries.summary", 0],
},
0,
],
},
- '',
+ "",
],
},
weeklycommittedHours: {
$sum: [
{
- $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ $arrayElemAt: ["$persondata.weeklycommittedHours", 0],
},
{
- $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0],
},
],
},
@@ -257,10 +263,10 @@ const dashboardhelper = function () {
},
{
$lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "personId",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -273,15 +279,15 @@ const dashboardhelper = function () {
weeklycommittedHours: 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],
},
],
},
@@ -291,7 +297,7 @@ const dashboardhelper = function () {
},
{
$unwind: {
- path: '$timeEntryData',
+ path: "$timeEntryData",
preserveNullAndEmptyArrays: true,
},
},
@@ -306,18 +312,18 @@ const dashboardhelper = function () {
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,
],
},
@@ -328,18 +334,18 @@ const dashboardhelper = function () {
tangibletime: {
$cond: [
{
- $eq: ['$isTangible', true],
+ $eq: ["$isTangible", true],
},
- '$totalSeconds',
+ "$totalSeconds",
0,
],
},
intangibletime: {
$cond: [
{
- $eq: ['$isTangible', false],
+ $eq: ["$isTangible", false],
},
- '$totalSeconds',
+ "$totalSeconds",
0,
],
},
@@ -348,58 +354,65 @@ const dashboardhelper = function () {
{
$group: {
_id: {
- personId: '$personId',
- weeklycommittedHours: '$weeklycommittedHours',
- name: '$name',
- role: '$role',
- isVisible: '$isVisible',
- hasSummary: '$hasSummary',
+ personId: "$personId",
+ weeklycommittedHours: "$weeklycommittedHours",
+ name: "$name",
+ role: "$role",
+ isVisible: "$isVisible",
+ hasSummary: "$hasSummary",
},
totalSeconds: {
- $sum: '$totalSeconds',
+ $sum: "$totalSeconds",
},
tangibletime: {
- $sum: '$tangibletime',
+ $sum: "$tangibletime",
},
intangibletime: {
- $sum: '$intangibletime',
+ $sum: "$intangibletime",
},
},
},
{
$project: {
_id: 0,
- personId: '$_id.personId',
- name: '$_id.name',
- role: '$_id.role',
- isVisible: '$_id.isVisible',
- hasSummary: '$_id.hasSummary',
- weeklycommittedHours: '$_id.weeklycommittedHours',
+ personId: "$_id.personId",
+ name: "$_id.name",
+ role: "$_id.role",
+ isVisible: "$_id.isVisible",
+ hasSummary: "$_id.hasSummary",
+ weeklycommittedHours: "$_id.weeklycommittedHours",
totaltime_hrs: {
- $divide: ['$totalSeconds', 3600],
+ $divide: ["$totalSeconds", 3600],
},
totaltangibletime_hrs: {
- $divide: ['$tangibletime', 3600],
+ $divide: ["$tangibletime", 3600],
},
totalintangibletime_hrs: {
- $divide: ['$intangibletime', 3600],
+ $divide: ["$intangibletime", 3600],
},
percentagespentintangible: {
$cond: [
{
- $eq: ['$totalSeconds', 0],
+ $eq: ["$totalSeconds", 0],
},
0,
{
$multiply: [
{
- $divide: ['$tangibletime', '$totalSeconds'],
+ $divide: ["$tangibletime", "$totalSeconds"],
},
100,
],
},
],
},
+ timeOffFrom: {
+ $ifNull: ["$persondata.timeOffFrom", null],
+ },
+ timeOffTill: {
+ $ifNull: ["$persondata.timeOffTill", null],
+ },
+ currentDate: { $toDate: new Date() },
},
},
{
@@ -420,14 +433,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,
@@ -457,7 +470,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,
@@ -470,8 +483,8 @@ const dashboardhelper = function () {
} catch (err) {
return [
{
- personId: 'error',
- name: 'Error Error',
+ personId: "error",
+ name: "Error Error",
totaltime_hrs: 0,
totaltangibletime_hrs: 0,
totalintangibletime_hrs: 0,
@@ -482,8 +495,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([
{
@@ -499,19 +512,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",
},
},
{
@@ -520,13 +533,13 @@ const dashboardhelper = function () {
projectName: {
$ifNull: [
{
- $arrayElemAt: ['$project.projectName', 0],
+ $arrayElemAt: ["$project.projectName", 0],
},
- 'Undefined',
+ "Undefined",
],
},
timeSpent_hrs: {
- $divide: ['$labor', 3600],
+ $divide: ["$labor", 3600],
},
},
},
@@ -534,8 +547,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([
{
@@ -551,10 +564,10 @@ const dashboardhelper = function () {
},
{
$lookup: {
- from: 'timeEntries',
- localField: '_id',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "_id",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -562,18 +575,18 @@ 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],
},
],
},
@@ -583,27 +596,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],
},
},
},
@@ -611,8 +624,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([
{
@@ -628,10 +641,10 @@ const dashboardhelper = function () {
},
{
$lookup: {
- from: 'timeEntries',
- localField: '_id',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "_id",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -639,18 +652,18 @@ 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],
},
],
},
@@ -660,37 +673,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",
},
},
},
@@ -698,7 +711,7 @@ const dashboardhelper = function () {
$project: {
_id: 1,
timeSpent_hrs: {
- $divide: ['$effort', 3600],
+ $divide: ["$effort", 3600],
},
},
},
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index e3f8d4a48..762b61c02 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,25 @@ 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 },
+ },
],
privacySettings: {
blueSquares: { type: Boolean, default: true },
@@ -104,7 +114,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 +144,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 +162,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"
+);
From 9e5ae9875eb5422b5d6ec260d5617ab314f905a4 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Wed, 6 Dec 2023 20:01:06 -0800
Subject: [PATCH 186/272] experimenting with discriminators
---
.../bmdashboard/bmMaterialsController.js | 12 ++++-
src/models/bmdashboard/buildingMaterial.js | 49 +++++++++++++++++--
2 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index a8090ebd9..c3dcd8c69 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -47,6 +47,8 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
};
const bmPurchaseMaterials = async function (req, res) {
+ console.log(BuildingMaterial);
+ console.log(req.body);
const {
projectId,
matTypeId,
@@ -83,7 +85,10 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
};
BuildingMaterial
.create(newDoc)
- .then(() => res.status(201).send())
+ .then((result) => {
+ console.log('result new: ', result);
+ res.status(201).send();
+ })
.catch(error => res.status(500).send(error));
return;
}
@@ -93,7 +98,10 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
{ $push: { purchaseRecord: newPurchaseRecord } },
)
.exec()
- .then(() => res.status(201).send())
+ .then((result) => {
+ console.log('result old: ', result);
+ res.status(201).send();
+ })
.catch(error => res.status(500).send(error));
} catch (error) {
res.status(500).send(error);
diff --git a/src/models/bmdashboard/buildingMaterial.js b/src/models/bmdashboard/buildingMaterial.js
index 4170443e0..d9a6be194 100644
--- a/src/models/bmdashboard/buildingMaterial.js
+++ b/src/models/bmdashboard/buildingMaterial.js
@@ -2,7 +2,14 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
-const buildingMaterial = new Schema({
+const inventoryBaseSchema = new Schema({
+ testField1: { type: String, default: 'hello world' },
+ testField2: { type: Number, default: 101 },
+});
+
+const InvBase = mongoose.model('InvBase', inventoryBaseSchema);
+
+const buildingMaterial = InvBase.discriminator('buildingMaterial', new Schema({
itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
@@ -25,6 +32,42 @@ const buildingMaterial = new Schema({
quantityUsed: { type: Number, required: true },
quantityWasted: { type: Number, required: true },
}],
-});
+}));
+
+// common fields
+const eventDefinition = { time: Date }
+// specific fields
+const ClickedLinkEventDefinition = {...eventDefinition, url: String}
+
+// completely separate models and collections on db level
+const eventSchema = new mongoose.Schema(eventDefinition, options);
+const Event = mongoose.model('Event', eventSchema);
+
+const ClickedLinkEvent = new mongoose.Schema(ClickedLinkEventDefinition , options);
+
+// const buildingMaterial = new Schema({
+// itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+// project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+// stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+// stockUsed: { type: Number, default: 0 }, // total amount of item used successfully in the project
+// stockWasted: { type: Number, default: 0 }, // total amount of item wasted/ruined/lost in the project
+// stockAvailable: { type: Number, default: 0 }, // bought - (used + wasted)
+// purchaseRecord: [{
+// _id: false, // do not add _id field to subdocument
+// date: { type: Date, default: Date.now() },
+// requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// quantity: { type: Number, required: true },
+// priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+// brand: String,
+// status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+// }],
+// updateRecord: [{
+// _id: false,
+// date: { type: Date, required: true },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// quantityUsed: { type: Number, required: true },
+// quantityWasted: { type: Number, required: true },
+// }],
+// });
-module.exports = mongoose.model('buildingMaterial', buildingMaterial, 'buildingMaterials');
+module.exports = buildingMaterial;
From d54cc867e1efe980f5bfcc955ddfff34d5414802 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 7 Dec 2023 16:57:12 -0800
Subject: [PATCH 187/272] add baseInvSchema file, update material and reusable
schemas with discriminators
---
.../bmdashboard/bmMaterialsController.js | 14 +---
src/models/bmdashboard/baseInvSchema.js | 23 +++++++
src/models/bmdashboard/buildingMaterial.js | 66 +++----------------
src/models/bmdashboard/buildingReusable.js | 22 ++-----
4 files changed, 41 insertions(+), 84 deletions(-)
create mode 100644 src/models/bmdashboard/baseInvSchema.js
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index c3dcd8c69..c79cbb56c 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -47,8 +47,6 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
};
const bmPurchaseMaterials = async function (req, res) {
- console.log(BuildingMaterial);
- console.log(req.body);
const {
projectId,
matTypeId,
@@ -60,7 +58,7 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
const newPurchaseRecord = {
quantity,
priority,
- brand,
+ brandPref: brand,
requestedBy: requestorId,
};
try {
@@ -85,10 +83,7 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
};
BuildingMaterial
.create(newDoc)
- .then((result) => {
- console.log('result new: ', result);
- res.status(201).send();
- })
+ .then(() => res.status(201).send())
.catch(error => res.status(500).send(error));
return;
}
@@ -98,10 +93,7 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
{ $push: { purchaseRecord: newPurchaseRecord } },
)
.exec()
- .then((result) => {
- console.log('result old: ', result);
- res.status(201).send();
- })
+ .then(() => res.status(201).send())
.catch(error => res.status(500).send(error));
} catch (error) {
res.status(500).send(error);
diff --git a/src/models/bmdashboard/baseInvSchema.js b/src/models/bmdashboard/baseInvSchema.js
new file mode 100644
index 000000000..7eff943e7
--- /dev/null
+++ b/src/models/bmdashboard/baseInvSchema.js
@@ -0,0 +1,23 @@
+const mongoose = require('mongoose');
+
+// base schema for all categories of inventory (Consumable, Material, Reusable, Tool, Equipment)
+// this schema is extended by the individual schemas for each inventory type
+// all documents derived from this schema are saved to the collection 'buildingInventoryItems'
+
+const baseInvSchema = mongoose.Schema({
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+ purchaseRecord: [{
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantity: { type: Number, required: true },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ brandPref: String,
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+ }],
+});
+
+const baseInv = mongoose.model('buildingInventory', baseInvSchema, 'buildingInventoryItems');
+
+module.exports = baseInv;
diff --git a/src/models/bmdashboard/buildingMaterial.js b/src/models/bmdashboard/buildingMaterial.js
index d9a6be194..caf61e4c0 100644
--- a/src/models/bmdashboard/buildingMaterial.js
+++ b/src/models/bmdashboard/buildingMaterial.js
@@ -1,73 +1,23 @@
const mongoose = require('mongoose');
-const { Schema } = mongoose;
+const baseInv = require('./baseInvSchema');
-const inventoryBaseSchema = new Schema({
- testField1: { type: String, default: 'hello world' },
- testField2: { type: Number, default: 101 },
-});
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "buildingMaterial" }
-const InvBase = mongoose.model('InvBase', inventoryBaseSchema);
-
-const buildingMaterial = InvBase.discriminator('buildingMaterial', new Schema({
- itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
- project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+const buildingMaterial = baseInv.discriminator('buildingMaterial', new mongoose.Schema({
stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
- stockUsed: { type: Number, default: 0 }, // total amount of item used successfully in the project
- stockWasted: { type: Number, default: 0 }, // total amount of item wasted/ruined/lost in the project
- stockAvailable: { type: Number, default: 0 }, // bought - (used + wasted)
- purchaseRecord: [{
- _id: false, // do not add _id field to subdocument
- date: { type: Date, default: Date.now() },
- requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantity: { type: Number, required: true },
- priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
- brand: String,
- status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
- }],
+ stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
+ stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
+ stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
updateRecord: [{
_id: false,
date: { type: Date, required: true },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
quantityUsed: { type: Number, required: true },
quantityWasted: { type: Number, required: true },
+ test: { type: String, default: 'testing this field' },
}],
}));
-// common fields
-const eventDefinition = { time: Date }
-// specific fields
-const ClickedLinkEventDefinition = {...eventDefinition, url: String}
-
-// completely separate models and collections on db level
-const eventSchema = new mongoose.Schema(eventDefinition, options);
-const Event = mongoose.model('Event', eventSchema);
-
-const ClickedLinkEvent = new mongoose.Schema(ClickedLinkEventDefinition , options);
-
-// const buildingMaterial = new Schema({
-// itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
-// project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
-// stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
-// stockUsed: { type: Number, default: 0 }, // total amount of item used successfully in the project
-// stockWasted: { type: Number, default: 0 }, // total amount of item wasted/ruined/lost in the project
-// stockAvailable: { type: Number, default: 0 }, // bought - (used + wasted)
-// purchaseRecord: [{
-// _id: false, // do not add _id field to subdocument
-// date: { type: Date, default: Date.now() },
-// requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// quantity: { type: Number, required: true },
-// priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
-// brand: String,
-// status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
-// }],
-// updateRecord: [{
-// _id: false,
-// date: { type: Date, required: true },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// quantityUsed: { type: Number, required: true },
-// quantityWasted: { type: Number, required: true },
-// }],
-// });
-
module.exports = buildingMaterial;
diff --git a/src/models/bmdashboard/buildingReusable.js b/src/models/bmdashboard/buildingReusable.js
index 1d0503010..1f2ceaa48 100644
--- a/src/models/bmdashboard/buildingReusable.js
+++ b/src/models/bmdashboard/buildingReusable.js
@@ -1,22 +1,14 @@
const mongoose = require('mongoose');
-const { Schema } = mongoose;
+const baseInv = require('./baseInvSchema');
-const buildingReusable = new Schema({
- itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
- project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "buildingReusable" }
+
+const buildingReusable = baseInv.discriminator('buildingReusable', new mongoose.Schema({
stockBought: { type: Number, default: 0 },
stockDestroyed: { type: Number, default: 0 },
stockAvailable: { type: Number, default: 0 },
- purchaseRecord: [{
- _id: false, // do not add _id field to subdocument
- date: { type: Date, default: Date.now() },
- requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantity: { type: Number, required: true },
- priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
- brand: String,
- status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
- }],
updateRecord: [{
_id: false,
date: { type: Date, required: true },
@@ -24,6 +16,6 @@ const buildingReusable = new Schema({
quantityUsed: { type: Number, required: true },
quantityDestroyed: { type: Number, required: true },
}],
-});
+}));
-module.exports = mongoose.model('buildingReusable', buildingReusable, 'buildingReusables');
+module.exports = buildingReusable;
From e799a5ed88bdd7bdf710fb6898babb5249ffef2e Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Fri, 8 Dec 2023 12:56:53 -0500
Subject: [PATCH 188/272] Fix: Assigned badges have no earned date - Modified
earned date format function in userHelper.js - Added data validation for
earned date and badge count mismatch in badgeController.js - Added
fillEarnedDateToMatchCount function to resolve earned date and badge count
mismatch in badgeController.js - Refactored data validation for duplicate
badge id in badgeController.js - Added data validation for badge count should
greater than 0 in badgeController.js - Added formatDate function to format
date to MMM-DD-YY in badgeController.js
---
src/controllers/badgeController.js | 205 ++++++++++++++++++++---------
src/helpers/userHelper.js | 34 +++--
2 files changed, 167 insertions(+), 72 deletions(-)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 366c9323e..a438df505 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -3,10 +3,11 @@ const UserProfile = require('../models/userProfile');
const { hasPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const cache = require('../utilities/nodeCache')();
+// const userHelper = require('../helpers/userHelper');
const badgeController = function (Badge) {
const getAllBadges = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'seeBadges')) {
+ if (!(await hasPermission(req.body.requestor, 'seeBadges'))) {
res.status(403).send('You are not authorized to view all badge data.');
return;
}
@@ -14,10 +15,11 @@ const badgeController = function (Badge) {
Badge.find(
{},
'badgeName type multiple weeks months totalHrs people imageUrl category project ranking description showReport',
- ).populate({
- path: 'project',
- select: '_id projectName',
- })
+ )
+ .populate({
+ path: 'project',
+ select: '_id projectName',
+ })
.sort({
ranking: 1,
badgeName: 1,
@@ -26,8 +28,51 @@ const badgeController = function (Badge) {
.catch(error => res.status(404).send(error));
};
+ /**
+ * Updated Date: 12/06/2023
+ * Updated By: Shengwei
+ * Function added:
+ * - Added data validation for earned date and badge count mismatch.
+ * - Added fillEarnedDateToMatchCount function to resolve earned date and badge count mismatch.
+ * - Refactored data validation for duplicate badge id.
+ * - Added data validation for badge count should greater than 0.
+ * - Added formatDate function to format date to MMM-DD-YY.
+ */
+
+ const formatDate = () => {
+ const currentDate = new Date(Date.now());
+ const monthNames = [
+ 'Jan',
+ 'Feb',
+ 'Mar',
+ 'Apr',
+ 'May',
+ 'Jun',
+ 'Jul',
+ 'Aug',
+ 'Sep',
+ 'Oct',
+ 'Nov',
+ 'Dec',
+ ];
+
+ const month = monthNames[currentDate.getMonth()];
+ const day = currentDate.getDate();
+ const year = currentDate.getFullYear().toString().slice(-2); // Get last two digits of the year
+
+ return `${month}-${day}-${year}`;
+ };
+
+ const fillEarnedDateToMatchCount = (earnedDate, count) => {
+ const result = [...earnedDate];
+ while (result.length < count) {
+ result.push(formatDate());
+ }
+ return result;
+ };
+
const assignBadges = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'assignBadges')) {
+ if (!(await hasPermission(req.body.requestor, 'assignBadges'))) {
res.status(403).send('You are not authorized to assign badges.');
return;
}
@@ -39,63 +84,90 @@ const badgeController = function (Badge) {
res.status(400).send('Can not find the user to be assigned.');
return;
}
- const grouped = req.body.badgeCollection.reduce((groupd, item) => {
- const propertyValue = item.badge;
- groupd[propertyValue] = (groupd[propertyValue] || 0) + 1;
- return groupd;
- }, {});
- const result = Object.keys(grouped).every(bdge => grouped[bdge] <= 1);
- if (result) {
- record.badgeCollection = req.body.badgeCollection;
-
- if (cache.hasCache(`user-${userToBeAssigned}`)) cache.removeCache(`user-${userToBeAssigned}`);
-
- record.save()
- .then(results => res.status(201).send(results._id))
- .catch(errors => res.status(500).send(errors));
- } else {
- res.status(500).send('Duplicate badges sent in.');
+ const badgeCounts = {};
+ // This line is using the forEach function to group badges in the badgeCollection
+ // array in the request body.
+ // Validation: No duplicate badge id;
+ try {
+ req.body.badgeCollection.forEach((element) => {
+ if (badgeCounts[element.badge]) {
+ res.status(500).send('Duplicate badges sent in.');
+ return;
+ }
+ badgeCounts[element.badge] = element.count;
+ // Validation: count should be greater than 0
+ if (element.count < 1) {
+ throw new Error('Badge count should be greater than 0.');
+ }
+ if (element.count !== element.earnedDate.length) {
+ element.earnedDate = fillEarnedDateToMatchCount(
+ element.earnedDate,
+ element.count,
+ );
+ }
+ });
+ } catch (err) {
+ res.status(500).send('Internal Err: Badge Collection.');
+ return;
}
+ record.badgeCollection = req.body.badgeCollection;
+
+ if (cache.hasCache(`user-${userToBeAssigned}`)) { cache.removeCache(`user-${userToBeAssigned}`); }
+ // Save Updated User Profile
+ record
+ .save()
+ .then(results => res.status(201).send(results._id))
+ .catch(errors => res.status(500).send(errors));
});
};
const postBadge = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'createBadges')) {
- res.status(403).send({ error: 'You are not authorized to create new badges.' });
+ if (!(await hasPermission(req.body.requestor, 'createBadges'))) {
+ res
+ .status(403)
+ .send({ error: 'You are not authorized to create new badges.' });
return;
}
- Badge.find({ badgeName: { $regex: escapeRegex(req.body.badgeName), $options: 'i' } })
- .then((result) => {
- if (result.length > 0) {
- res.status(400).send({ error: `Another badge with name ${result[0].badgeName} already exists. Sorry, but badge names should be like snowflakes, no two should be the same. Please choose a different name for this badge so it can be proudly unique.` });
- return;
- }
- const badge = new Badge();
-
- badge.badgeName = req.body.badgeName;
- badge.category = req.body.category;
- badge.type = req.body.type;
- badge.multiple = req.body.multiple;
- badge.totalHrs = req.body.totalHrs;
- badge.weeks = req.body.weeks;
- badge.months = req.body.months;
- badge.people = req.body.people;
- badge.project = req.body.project;
- badge.imageUrl = req.body.imageUrl;
- badge.ranking = req.body.ranking;
- badge.description = req.body.description;
- badge.showReport = req.body.showReport;
-
- badge.save()
- .then(results => res.status(201).send(results))
- .catch(errors => res.status(500).send(errors));
- });
+ Badge.find({
+ badgeName: { $regex: escapeRegex(req.body.badgeName), $options: 'i' },
+ }).then((result) => {
+ if (result.length > 0) {
+ res
+ .status(400)
+ .send({
+ error: `Another badge with name ${result[0].badgeName} already exists. Sorry, but badge names should be like snowflakes, no two should be the same. Please choose a different name for this badge so it can be proudly unique.`,
+ });
+ return;
+ }
+ const badge = new Badge();
+
+ badge.badgeName = req.body.badgeName;
+ badge.category = req.body.category;
+ badge.type = req.body.type;
+ badge.multiple = req.body.multiple;
+ badge.totalHrs = req.body.totalHrs;
+ badge.weeks = req.body.weeks;
+ badge.months = req.body.months;
+ badge.people = req.body.people;
+ badge.project = req.body.project;
+ badge.imageUrl = req.body.imageUrl;
+ badge.ranking = req.body.ranking;
+ badge.description = req.body.description;
+ badge.showReport = req.body.showReport;
+
+ badge
+ .save()
+ .then(results => res.status(201).send(results))
+ .catch(errors => res.status(500).send(errors));
+ });
};
const deleteBadge = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'deleteBadges')) {
- res.status(403).send({ error: 'You are not authorized to delete badges.' });
+ if (!(await hasPermission(req.body.requestor, 'deleteBadges'))) {
+ res
+ .status(403)
+ .send({ error: 'You are not authorized to delete badges.' });
return;
}
const { badgeId } = req.params;
@@ -104,19 +176,33 @@ const badgeController = function (Badge) {
res.status(400).send({ error: 'No valid records found' });
return;
}
- const removeBadgeFromProfile = UserProfile.updateMany({}, { $pull: { badgeCollection: { badge: record._id } } }).exec();
+ const removeBadgeFromProfile = UserProfile.updateMany(
+ {},
+ { $pull: { badgeCollection: { badge: record._id } } },
+ ).exec();
const deleteRecord = record.remove();
Promise.all([removeBadgeFromProfile, deleteRecord])
- .then(res.status(200).send({ message: 'Badge successfully deleted and user profiles updated' }))
- .catch((errors) => { res.status(500).send(errors); });
- })
- .catch((error) => { res.status(500).send(error); });
+ .then(
+ res
+ .status(200)
+ .send({
+ message: 'Badge successfully deleted and user profiles updated',
+ }),
+ )
+ .catch((errors) => {
+ res.status(500).send(errors);
+ });
+ }).catch((error) => {
+ res.status(500).send(error);
+ });
};
const putBadge = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'updateBadges')) {
- res.status(403).send({ error: 'You are not authorized to update badges.' });
+ if (!(await hasPermission(req.body.requestor, 'updateBadges'))) {
+ res
+ .status(403)
+ .send({ error: 'You are not authorized to update badges.' });
return;
}
const { badgeId } = req.params;
@@ -129,7 +215,6 @@ const badgeController = function (Badge) {
// store onto Azure and return url
}
-
const data = {
badgeName: req.body.name || req.body.badgeName,
description: req.body.description,
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index f639a4d37..b25328e28 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -27,21 +27,31 @@ const userHelper = function () {
});
};
+ // Updated By: Shengwei
+ // Updated Date: 12/08/2023
+ // Update format to "MMM-DD-YY" from "YYYY-MMM-DD" (Confirmed with Jae)
const earnedDateBadge = () => {
- const today = new Date();
- const yyyy = today.getFullYear();
- // Add 1 beacuse the month start at zero
- let mm = today.getMonth() + 1;
- let dd = today.getDate();
-
- // eslint-disable-next-line no-unused-expressions
- mm = mm < 10 ? `0${mm}` : mm;
- // eslint-disable-next-line no-unused-expressions
- dd = dd < 10 ? `0${dd}` : dd;
+ const currentDate = new Date(Date.now());
+ const monthNames = [
+ 'Jan',
+ 'Feb',
+ 'Mar',
+ 'Apr',
+ 'May',
+ 'Jun',
+ 'Jul',
+ 'Aug',
+ 'Sep',
+ 'Oct',
+ 'Nov',
+ 'Dec',
+ ];
- const formatedDate = `${yyyy}-${mm}-${dd}`;
+ const month = monthNames[currentDate.getMonth()];
+ const day = currentDate.getDate();
+ const year = currentDate.getFullYear().toString().slice(-2); // Get last two digits of the year
- return formatedDate;
+ return `${month}-${day}-${year}`;
};
const getUserName = async function (userId) {
From 07835ede44e255d2e8705608a89ce16a61728fb6 Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Fri, 8 Dec 2023 13:11:35 -0500
Subject: [PATCH 189/272] Update: Modified date format function - Update
fromatDate in badgeController using moment timezone library - Update
earnedDateBadge in userHelper using moment timezone library
---
src/controllers/badgeController.js | 22 ++--------------------
src/helpers/userHelper.js | 22 ++--------------------
2 files changed, 4 insertions(+), 40 deletions(-)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index a438df505..89c47ba79 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -41,28 +41,10 @@ const badgeController = function (Badge) {
const formatDate = () => {
const currentDate = new Date(Date.now());
- const monthNames = [
- 'Jan',
- 'Feb',
- 'Mar',
- 'Apr',
- 'May',
- 'Jun',
- 'Jul',
- 'Aug',
- 'Sep',
- 'Oct',
- 'Nov',
- 'Dec',
- ];
-
- const month = monthNames[currentDate.getMonth()];
- const day = currentDate.getDate();
- const year = currentDate.getFullYear().toString().slice(-2); // Get last two digits of the year
-
- return `${month}-${day}-${year}`;
+ return moment(currentDate).tz('America/Los_Angeles').format();
};
+
const fillEarnedDateToMatchCount = (earnedDate, count) => {
const result = [...earnedDate];
while (result.length < count) {
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index b25328e28..c9d5ca1bf 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -15,6 +15,7 @@ const hasPermission = require("../utilities/permissions");
const Reason = require("../models/reason");
const token = require("../models/profileInitialSetupToken");
+
const userHelper = function () {
const getTeamMembers = function (user) {
const userId = mongoose.Types.ObjectId(user._id);
@@ -32,26 +33,7 @@ const userHelper = function () {
// Update format to "MMM-DD-YY" from "YYYY-MMM-DD" (Confirmed with Jae)
const earnedDateBadge = () => {
const currentDate = new Date(Date.now());
- const monthNames = [
- 'Jan',
- 'Feb',
- 'Mar',
- 'Apr',
- 'May',
- 'Jun',
- 'Jul',
- 'Aug',
- 'Sep',
- 'Oct',
- 'Nov',
- 'Dec',
- ];
-
- const month = monthNames[currentDate.getMonth()];
- const day = currentDate.getDate();
- const year = currentDate.getFullYear().toString().slice(-2); // Get last two digits of the year
-
- return `${month}-${day}-${year}`;
+ return moment(currentDate).tz('America/Los_Angeles').format();
};
const getUserName = async function (userId) {
From 1e08bdbf405f756e40fb36fb93f949bb8ea9b8b8 Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Fri, 8 Dec 2023 13:35:59 -0500
Subject: [PATCH 190/272] Fix: Added format MMM-DD-YY for moment format
function
---
src/controllers/badgeController.js | 4 ++--
src/helpers/userHelper.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 89c47ba79..4c92bd9a5 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -1,9 +1,9 @@
+const moment = require('moment-timezone');
const mongoose = require('mongoose');
const UserProfile = require('../models/userProfile');
const { hasPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const cache = require('../utilities/nodeCache')();
-// const userHelper = require('../helpers/userHelper');
const badgeController = function (Badge) {
const getAllBadges = async function (req, res) {
@@ -41,7 +41,7 @@ const badgeController = function (Badge) {
const formatDate = () => {
const currentDate = new Date(Date.now());
- return moment(currentDate).tz('America/Los_Angeles').format();
+ return moment(currentDate).tz('America/Los_Angeles').format('MMM-DD-YY');
};
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index c9d5ca1bf..fa0115271 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -33,7 +33,7 @@ const userHelper = function () {
// Update format to "MMM-DD-YY" from "YYYY-MMM-DD" (Confirmed with Jae)
const earnedDateBadge = () => {
const currentDate = new Date(Date.now());
- return moment(currentDate).tz('America/Los_Angeles').format();
+ return moment(currentDate).tz('America/Los_Angeles').format('MMM-DD-YY');
};
const getUserName = async function (userId) {
From a63f976b36e4df494356409759803e4bc817e6f8 Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Fri, 8 Dec 2023 15:02:00 -0500
Subject: [PATCH 191/272] Added a logger for the function responsible for
filling mismatched badge earned dates
---
src/controllers/badgeController.js | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 4c92bd9a5..11ee56ea4 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -4,6 +4,7 @@ const UserProfile = require('../models/userProfile');
const { hasPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const cache = require('../utilities/nodeCache')();
+const logger = require('../startup/logger');
const badgeController = function (Badge) {
const getAllBadges = async function (req, res) {
@@ -44,7 +45,6 @@ const badgeController = function (Badge) {
return moment(currentDate).tz('America/Los_Angeles').format('MMM-DD-YY');
};
-
const fillEarnedDateToMatchCount = (earnedDate, count) => {
const result = [...earnedDate];
while (result.length < count) {
@@ -86,6 +86,12 @@ const badgeController = function (Badge) {
element.earnedDate,
element.count,
);
+ element.lastModified = Date.now();
+ logger.logInfo(
+ `Badge count and earned dates mismatched found. ${Date.now()} was generated for user ${userToBeAssigned}. Badge record ID ${
+ element._id
+ }; Badge Type ID ${element.badge}`,
+ );
}
});
} catch (err) {
@@ -94,7 +100,9 @@ const badgeController = function (Badge) {
}
record.badgeCollection = req.body.badgeCollection;
- if (cache.hasCache(`user-${userToBeAssigned}`)) { cache.removeCache(`user-${userToBeAssigned}`); }
+ if (cache.hasCache(`user-${userToBeAssigned}`)) {
+ cache.removeCache(`user-${userToBeAssigned}`);
+ }
// Save Updated User Profile
record
.save()
@@ -115,11 +123,9 @@ const badgeController = function (Badge) {
badgeName: { $regex: escapeRegex(req.body.badgeName), $options: 'i' },
}).then((result) => {
if (result.length > 0) {
- res
- .status(400)
- .send({
- error: `Another badge with name ${result[0].badgeName} already exists. Sorry, but badge names should be like snowflakes, no two should be the same. Please choose a different name for this badge so it can be proudly unique.`,
- });
+ res.status(400).send({
+ error: `Another badge with name ${result[0].badgeName} already exists. Sorry, but badge names should be like snowflakes, no two should be the same. Please choose a different name for this badge so it can be proudly unique.`,
+ });
return;
}
const badge = new Badge();
@@ -166,11 +172,9 @@ const badgeController = function (Badge) {
Promise.all([removeBadgeFromProfile, deleteRecord])
.then(
- res
- .status(200)
- .send({
- message: 'Badge successfully deleted and user profiles updated',
- }),
+ res.status(200).send({
+ message: 'Badge successfully deleted and user profiles updated',
+ }),
)
.catch((errors) => {
res.status(500).send(errors);
From b2608a817416abce1293a6780704ff3543888514 Mon Sep 17 00:00:00 2001
From: Nathan Hoffman
Date: Fri, 8 Dec 2023 14:41:38 -0800
Subject: [PATCH 192/272] Update minimum permissions
---
src/utilities/createInitialPermissions.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/utilities/createInitialPermissions.js b/src/utilities/createInitialPermissions.js
index 9cdf7f9e0..86a79b94c 100644
--- a/src/utilities/createInitialPermissions.js
+++ b/src/utilities/createInitialPermissions.js
@@ -6,6 +6,9 @@ const permissionsRoles = [
{
roleName: 'Administrator',
permissions: [
+ // Reports
+ 'getWeeklySummaries',
+ 'getReports', // Doesn't do anything on back-end.
// Badges
'seeBadges',
'assignBadges',
@@ -65,8 +68,7 @@ const permissionsRoles = [
// General
'getUserProfiles',
'getProjectMembers',
- 'getWeeklySummaries',
- // 'getReportsPage',?
+
'getTimeZoneAPIKey',
'checkLeadTeamOfXplus',
],
@@ -97,6 +99,7 @@ const permissionsRoles = [
'getAllInvType',
'postInvType',
'getWeeklySummaries',
+ 'getReports',
'getTimeZoneAPIKey',
'checkLeadTeamOfXplus',
],
@@ -124,7 +127,6 @@ const permissionsRoles = [
'putInvType',
'getAllInvType',
'postInvType',
- 'getWeeklySummaries',
'getTimeZoneAPIKey',
'checkLeadTeamOfXplus',
],
@@ -151,7 +153,6 @@ const permissionsRoles = [
'putInvType',
'getAllInvType',
'postInvType',
- 'getWeeklySummaries',
'getTimeZoneAPIKey',
'checkLeadTeamOfXplus',
],
@@ -212,6 +213,7 @@ const permissionsRoles = [
'getAllInvType',
'postInvType',
'getWeeklySummaries',
+ 'getReports',
'getTimeZoneAPIKey',
'checkLeadTeamOfXplus',
'editTeamCode',
From 778217620b5fb6c11e3522f671e35cdd45d758ef Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 8 Dec 2023 14:47:04 -0800
Subject: [PATCH 193/272] add single inventory file to hold base and extended
schemas
---
.../bmdashboard/buildingInventoryItem.js | 94 +++++++++++++++++++
src/startup/routes.js | 2 +-
2 files changed, 95 insertions(+), 1 deletion(-)
create mode 100644 src/models/bmdashboard/buildingInventoryItem.js
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
new file mode 100644
index 000000000..db5c3012c
--- /dev/null
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -0,0 +1,94 @@
+const mongoose = require('mongoose');
+
+//----------------------
+// BASE INVENTORY SCHEMA
+//----------------------
+
+// base schema for all categories of inventory (Consumable, Material, Reusable, Tool, Equipment)
+// this schema is extended by the individual schemas for each inventory type
+// all documents derived from this schema are saved to the collection 'buildingInventoryItems'
+
+const baseInvSchema = mongoose.Schema({
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+ purchaseRecord: [{
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantity: { type: Number, required: true },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ brandPref: String,
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+ }],
+});
+
+const baseInv = mongoose.model('buildingInventory', baseInvSchema, 'buildingInventoryItems');
+
+//-----------------
+// MATERIALS SCHEMA
+//-----------------
+
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "material" }
+// ex: sand, stone, bricks, lumber, insulation
+
+const buildingMaterial = baseInv.discriminator('material', new mongoose.Schema({
+ stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+ stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
+ stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
+ stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
+ updateRecord: [{
+ _id: false,
+ date: { type: Date, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantityUsed: { type: Number, required: true },
+ quantityWasted: { type: Number, required: true },
+ }],
+}));
+
+//-----------------
+// REUSABLES SCHEMA
+//-----------------
+
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "reusable" }
+// ex: hammers, screwdrivers, mallets, brushes, gloves
+
+const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
+ stockBought: { type: Number, default: 0 },
+ stockDestroyed: { type: Number, default: 0 },
+ stockAvailable: { type: Number, default: 0 },
+ updateRecord: [{
+ _id: false,
+ date: { type: Date, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantityUsed: { type: Number, required: true },
+ quantityDestroyed: { type: Number, required: true },
+ }],
+}));
+
+//-----------------
+// CONSUMABLES SCHEMA
+//-----------------
+
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "consumable" }
+// ex: screws, nails, staples
+
+//-------------
+// TOOLS SCHEMA
+//-------------
+
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "tool" }
+// ex: power drills, wheelbarrows, shovels
+
+// const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
+
+// }));
+
+
+module.exports = {
+ buildingMaterial,
+ buildingReusable,
+};
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 2d95ea639..5f77a413d 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -24,7 +24,7 @@ const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const mapLocations = require('../models/mapLocation');
const buildingProject = require('../models/bmdashboard/buildingProject');
const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
-const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
+const { buildingMaterial } = require('../models/bmdashboard/buildingInventoryItem');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
From 5dd37d817997961c79b5db65a059d39b771116a4 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Sat, 9 Dec 2023 14:55:41 -0800
Subject: [PATCH 194/272] add building tool inv to schema file
---
.../bmdashboard/buildingInventoryItem.js | 32 +++++++++++++++++--
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
index db5c3012c..0d357ae7a 100644
--- a/src/models/bmdashboard/buildingInventoryItem.js
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -83,9 +83,35 @@ const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
// each document derived from this schema includes key field { __t: "tool" }
// ex: power drills, wheelbarrows, shovels
-// const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
-
-// }));
+const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
+ code: { type: Number, required: true }, // add function to create code for on-site tool tracking
+ purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
+ // add discriminator based on rental or purchase so these fields are required if tool is rented
+ rentedOnDate: Date,
+ rentalDue: Date,
+ userResponsible: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ purchaseRecord: [{ // track purchase/rental requests
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ brand: String,
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+ }],
+ updateRecord: [{ // track tool condition updates
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
+ }],
+ logRecord: [{ // track tool daily check in/out and use
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ type: { type: String, enum: ['Check In', 'Check Out'] }, // default = opposite of current log status?
+ }],
+}));
module.exports = {
From 6f36edd374fe2e4052a79a36649cfc67b5302394 Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Sun, 10 Dec 2023 00:16:26 -0500
Subject: [PATCH 195/272] Update error handling in badge assginment feature
---
src/controllers/badgeController.js | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/controllers/badgeController.js b/src/controllers/badgeController.js
index 11ee56ea4..5dd2113a6 100644
--- a/src/controllers/badgeController.js
+++ b/src/controllers/badgeController.js
@@ -73,8 +73,9 @@ const badgeController = function (Badge) {
try {
req.body.badgeCollection.forEach((element) => {
if (badgeCounts[element.badge]) {
- res.status(500).send('Duplicate badges sent in.');
- return;
+ throw new Error('Duplicate badges sent in.');
+ // res.status(500).send('Duplicate badges sent in.');
+ // return;
}
badgeCounts[element.badge] = element.count;
// Validation: count should be greater than 0
@@ -95,7 +96,7 @@ const badgeController = function (Badge) {
}
});
} catch (err) {
- res.status(500).send('Internal Err: Badge Collection.');
+ res.status(500).send(`Internal Error: Badge Collection. ${ err.message}`);
return;
}
record.badgeCollection = req.body.badgeCollection;
@@ -107,7 +108,10 @@ const badgeController = function (Badge) {
record
.save()
.then(results => res.status(201).send(results._id))
- .catch(errors => res.status(500).send(errors));
+ .catch((err) => {
+ logger.logException(err);
+ res.status(500).send('Internal Error: Unable to save the record.');
+ });
});
};
From 4a9deec48787963f3993f3a8faeb232280623d15 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sat, 9 Dec 2023 23:53:58 -0800
Subject: [PATCH 196/272] integrate ownerMessage and ownerStandardMessage,
simplify route and controller logic
---
src/controllers/ownerMessageController.js | 88 +++++++++++------------
src/models/ownerMessage.js | 3 +-
src/routes/ownerMessageRouter.js | 11 ++-
src/startup/routes.js | 6 +-
4 files changed, 52 insertions(+), 56 deletions(-)
diff --git a/src/controllers/ownerMessageController.js b/src/controllers/ownerMessageController.js
index b4a00431b..f09a32030 100644
--- a/src/controllers/ownerMessageController.js
+++ b/src/controllers/ownerMessageController.js
@@ -1,63 +1,61 @@
const ownerMessageController = function (OwnerMessage) {
- const postOwnerMessage = function (req, res) {
- if (req.body.requestor.role !== 'Owner') {
- res.status(403).send('You are not authorized to create messages!');
+ const getOwnerMessage = async function (req, res) {
+ try {
+ const results = await OwnerMessage.find({});
+ if (results.length === 0) { // first time initialization
+ const ownerMessage = new OwnerMessage();
+ await ownerMessage.save();
+ res.status(200).send({ ownerMessage });
+ } else {
+ res.status(200).send({ ownerMessage: results[0] });
+ }
+ } catch (error) {
+ res.status(404).send(error);
}
- const ownerMessage = new OwnerMessage();
- ownerMessage.message = req.body.newMessage;
- ownerMessage.save().then(() => res.status(201).json({
- _serverMessage: 'Message succesfuly created!',
- ownerMessage,
- })).catch(err => res.status(500).send({ err }));
- };
-
- const getOwnerMessage = function (req, res) {
- OwnerMessage.find()
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
};
- const deleteOwnerMessage = function (req, res) {
+ const updateOwnerMessage = async function (req, res) {
if (req.body.requestor.role !== 'Owner') {
- res.status(403).send('You are not authorized to delete messages!');
+ res.status(403).send('You are not authorized to create messages!');
+ }
+ const { standardMessage, message } = req.body;
+ try {
+ const results = await OwnerMessage.find({});
+ const ownerMessage = results[0];
+ if (standardMessage) {
+ ownerMessage.standardMessage = standardMessage;
+ } else {
+ ownerMessage.message = message;
+ }
+ await ownerMessage.save();
+ res.status(201).send({
+ _serverMessage: 'Update successfully!',
+ ownerMessage: { standardMessage, message },
+ });
+ } catch (error) {
+ res.status(500).send(error);
}
- OwnerMessage.deleteMany({})
- .then((result) => {
- result
- .then(res.status(200).send({ _serverMessage: 'Message deleted!' }))
- .catch((error) => {
- res.status(400).send(error);
- });
- })
- .catch((error) => {
- res.status(400).send(error);
- });
};
- const updateOwnerMessage = function (req, res) {
+ const deleteOwnerMessage = async function (req, res) {
if (req.body.requestor.role !== 'Owner') {
- res.status(403).send('You are not authorized to update messages!');
+ res.status(403).send('You are not authorized to delete messages!');
+ }
+ try {
+ const results = await OwnerMessage.find({});
+ const ownerMessage = results[0];
+ ownerMessage.message = '';
+ await ownerMessage.save();
+ res.status(200).send({ _serverMessage: 'Delete successfully!', ownerMessage });
+ } catch (error) {
+ res.status(500).send(error);
}
- const { id } = req.params;
-
- return OwnerMessage.findById(id, (error, ownerMessage) => {
- if (error || ownerMessage === null) {
- res.status(400).send('No ownerMessage found');
- return;
- }
-
- ownerMessage.message = req.body.newMessage;
- ownerMessage.save()
- .then(results => res.status(201).send(results))
- .catch(errors => res.status(400).send(errors));
- });
};
return {
- postOwnerMessage,
getOwnerMessage,
- deleteOwnerMessage,
updateOwnerMessage,
+ deleteOwnerMessage,
};
};
diff --git a/src/models/ownerMessage.js b/src/models/ownerMessage.js
index be953c3a3..a6314c929 100644
--- a/src/models/ownerMessage.js
+++ b/src/models/ownerMessage.js
@@ -3,7 +3,8 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
const OwnerMessage = new Schema({
- message: { type: String },
+ message: { type: String, default: '' },
+ standardMessage: { type: String, default: '' },
});
module.exports = mongoose.model('ownerMessage', OwnerMessage, 'ownerMessage');
diff --git a/src/routes/ownerMessageRouter.js b/src/routes/ownerMessageRouter.js
index e436deed8..6f5716fe9 100644
--- a/src/routes/ownerMessageRouter.js
+++ b/src/routes/ownerMessageRouter.js
@@ -5,14 +5,11 @@ const routes = function (ownerMessage) {
const OwnerMessageRouter = express.Router();
OwnerMessageRouter.route('/ownerMessage')
- .post(controller.postOwnerMessage)
- .get(controller.getOwnerMessage)
- .delete(controller.deleteOwnerMessage);
+ .get(controller.getOwnerMessage)
+ .put(controller.updateOwnerMessage)
+ .delete(controller.deleteOwnerMessage);
- OwnerMessageRouter.route('/ownerMessage/:id')
- .put(controller.updateOwnerMessage);
-
-return OwnerMessageRouter;
+ return OwnerMessageRouter;
};
module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 2d95ea639..e7c91dab0 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -16,7 +16,7 @@ const inventoryItemType = require('../models/inventoryItemType');
const role = require('../models/role');
const rolePreset = require('../models/rolePreset');
const ownerMessage = require('../models/ownerMessage');
-const ownerStandardMessage = require('../models/ownerStandardMessage');
+// const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
@@ -55,7 +55,7 @@ const taskEditSuggestionRouter = require('../routes/taskEditSuggestionRouter')(t
const roleRouter = require('../routes/roleRouter')(role);
const rolePresetRouter = require('../routes/rolePresetRouter')(rolePreset);
const ownerMessageRouter = require('../routes/ownerMessageRouter')(ownerMessage);
-const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter')(ownerStandardMessage);
+// const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter')(ownerStandardMessage);
const reasonRouter = require('../routes/reasonRouter')(reason, userProfile);
const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverText);
@@ -92,7 +92,7 @@ module.exports = function (app) {
app.use('/api', roleRouter);
app.use('/api', rolePresetRouter);
app.use('/api', ownerMessageRouter);
- app.use('/api', ownerStandardMessageRouter);
+ // app.use('/api', ownerStandardMessageRouter);
app.use('/api', profileInitialSetupRouter);
app.use('/api', reasonRouter);
app.use('/api', informationRouter);
From 1128f8937e0ae2acf8e237a45a947813f87a0abb Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sun, 10 Dec 2023 14:28:16 -0800
Subject: [PATCH 197/272] remove unused files and codes related to
ownerStandardMessage
---
.../ownerStandardMessageController.js | 64 -------------------
src/models/ownerStandardMessage.js | 9 ---
src/routes/ownerStandardMessageRouter.js | 18 ------
src/startup/routes.js | 3 -
4 files changed, 94 deletions(-)
delete mode 100644 src/controllers/ownerStandardMessageController.js
delete mode 100644 src/models/ownerStandardMessage.js
delete mode 100644 src/routes/ownerStandardMessageRouter.js
diff --git a/src/controllers/ownerStandardMessageController.js b/src/controllers/ownerStandardMessageController.js
deleted file mode 100644
index efd933888..000000000
--- a/src/controllers/ownerStandardMessageController.js
+++ /dev/null
@@ -1,64 +0,0 @@
-const ownerStandardMessageController = function (OwnerStandardMessage) {
- const postOwnerStandardMessage = function (req, res) {
- if (req.body.requestor.role !== 'Owner') {
- res.status(403).send('You are not authorized to create messages!');
- }
- const ownerStandardMessage = new OwnerStandardMessage();
- ownerStandardMessage.message = req.body.newStandardMessage;
- ownerStandardMessage.save().then(() => res.status(201).json({
- _serverMessage: 'Message succesfuly created!',
- ownerStandardMessage,
- })).catch(err => res.status(500).send({ err }));
- };
-
- const getOwnerStandardMessage = function (req, res) {
- OwnerStandardMessage.find()
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
- };
-
- const deleteOwnerStandardMessage = function (req, res) {
- if (req.body.requestor.role !== 'Owner') {
- res.status(403).send('You are not authorized to delete messages!');
- }
- OwnerStandardMessage.deleteMany({})
- .then((result) => {
- result
- .then(res.status(200).send({ _serverMessage: 'Standard Message deleted!' }))
- .catch((error) => {
- res.status(400).send(error);
- });
- })
- .catch((error) => {
- res.status(400).send(error);
- });
- };
-
- const updateOwnerStandardMessage = function (req, res) {
- if (req.body.requestor.role !== 'Owner') {
- res.status(403).send('You are not authorized to update messages!');
- }
- const { id } = req.params;
-
- return OwnerStandardMessage.findById(id, (error, ownerStandardMessage) => {
- if (error || ownerStandardMessage === null) {
- res.status(400).send('No ownerStandardMessage found');
- return;
- }
-
- ownerStandardMessage.message = req.body.newStandardMessage;
- ownerStandardMessage.save()
- .then(results => res.status(201).send(results))
- .catch(errors => res.status(400).send(errors));
- });
- };
-
- return {
- postOwnerStandardMessage,
- getOwnerStandardMessage,
- deleteOwnerStandardMessage,
- updateOwnerStandardMessage,
- };
-};
-
-module.exports = ownerStandardMessageController;
diff --git a/src/models/ownerStandardMessage.js b/src/models/ownerStandardMessage.js
deleted file mode 100644
index d344a773f..000000000
--- a/src/models/ownerStandardMessage.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const mongoose = require('mongoose');
-
-const { Schema } = mongoose;
-
-const OwnerStandardMessage = new Schema({
- message: { type: String },
-});
-
-module.exports = mongoose.model('ownerStandardMessage', OwnerStandardMessage, 'ownerStandardMessage');
diff --git a/src/routes/ownerStandardMessageRouter.js b/src/routes/ownerStandardMessageRouter.js
deleted file mode 100644
index 08e629c3d..000000000
--- a/src/routes/ownerStandardMessageRouter.js
+++ /dev/null
@@ -1,18 +0,0 @@
-const express = require('express');
-
-const routes = function (ownerStandardMessage) {
- const controller = require('../controllers/ownerStandardMessageController')(ownerStandardMessage);
- const OwnerStandardMessageRouter = express.Router();
-
- OwnerStandardMessageRouter.route('/ownerStandardMessage')
- .post(controller.postOwnerStandardMessage)
- .get(controller.getOwnerStandardMessage)
- .delete(controller.deleteOwnerStandardMessage);
-
- OwnerStandardMessageRouter.route('/ownerStandardMessage/:id')
- .put(controller.updateOwnerStandardMessage);
-
-return OwnerStandardMessageRouter;
-};
-
-module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index e7c91dab0..ff5d01b2b 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -16,7 +16,6 @@ const inventoryItemType = require('../models/inventoryItemType');
const role = require('../models/role');
const rolePreset = require('../models/rolePreset');
const ownerMessage = require('../models/ownerMessage');
-// const ownerStandardMessage = require('../models/ownerStandardMessage');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
@@ -55,7 +54,6 @@ const taskEditSuggestionRouter = require('../routes/taskEditSuggestionRouter')(t
const roleRouter = require('../routes/roleRouter')(role);
const rolePresetRouter = require('../routes/rolePresetRouter')(rolePreset);
const ownerMessageRouter = require('../routes/ownerMessageRouter')(ownerMessage);
-// const ownerStandardMessageRouter = require('../routes/ownerStandardMessageRouter')(ownerStandardMessage);
const reasonRouter = require('../routes/reasonRouter')(reason, userProfile);
const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverText);
@@ -92,7 +90,6 @@ module.exports = function (app) {
app.use('/api', roleRouter);
app.use('/api', rolePresetRouter);
app.use('/api', ownerMessageRouter);
- // app.use('/api', ownerStandardMessageRouter);
app.use('/api', profileInitialSetupRouter);
app.use('/api', reasonRouter);
app.use('/api', informationRouter);
From 7895974de7e6d864000daba5810319c316b5274a Mon Sep 17 00:00:00 2001
From: wantingxu
Date: Sun, 10 Dec 2023 21:09:27 -0800
Subject: [PATCH 198/272] add teamcode
---
src/controllers/userProfileController.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index a8c0cf230..1a3dd504f 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -241,6 +241,7 @@ const userProfileController = function (UserProfile) {
);
const canEditTeamCode = req.body.requestor.role === 'Owner'
+ || req.body.requestor.role === 'Administrator'
|| req.body.requestor.permissions?.frontPermissions.includes('editTeamCode');
if (!isRequestorAuthorized) {
@@ -575,6 +576,7 @@ const userProfileController = function (UserProfile) {
if (key === 'teamCode') {
const canEditTeamCode = req.body.requestor.role === 'Owner'
+ || req.body.requestor.role === 'Administrator'
|| req.body.requestor.permissions?.frontPermissions.includes('editTeamCode');
if (!canEditTeamCode) {
From 4cef847de5eb3711b72dd94838f54dee69325a2b Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sun, 10 Dec 2023 21:23:20 -0800
Subject: [PATCH 199/272] make update standard message to empty message
---
src/controllers/ownerMessageController.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/controllers/ownerMessageController.js b/src/controllers/ownerMessageController.js
index f09a32030..1b2c30205 100644
--- a/src/controllers/ownerMessageController.js
+++ b/src/controllers/ownerMessageController.js
@@ -18,16 +18,18 @@ const ownerMessageController = function (OwnerMessage) {
if (req.body.requestor.role !== 'Owner') {
res.status(403).send('You are not authorized to create messages!');
}
- const { standardMessage, message } = req.body;
+ const { isStandard, newMessage } = req.body;
try {
const results = await OwnerMessage.find({});
const ownerMessage = results[0];
- if (standardMessage) {
- ownerMessage.standardMessage = standardMessage;
+ if (isStandard) {
+ ownerMessage.standardMessage = newMessage;
+ ownerMessage.message = '';
} else {
- ownerMessage.message = message;
+ ownerMessage.message = newMessage;
}
await ownerMessage.save();
+ const { standardMessage, message } = ownerMessage;
res.status(201).send({
_serverMessage: 'Update successfully!',
ownerMessage: { standardMessage, message },
From acefbbb69d072699f1e556e3b294684770b7617c Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Mon, 11 Dec 2023 18:08:12 -0800
Subject: [PATCH 200/272] Leaderboard api fix
---
src/helpers/dashboardhelper.js | 603 +++++++++++++++++++--------------
1 file changed, 355 insertions(+), 248 deletions(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index fe2007281..59b1d7f51 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -3,6 +3,7 @@ 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) {
@@ -152,8 +153,13 @@ const dashboardhelper = function () {
return output;
};
- const getLeaderboard = function (userId) {
+ const getLeaderboard = async function (userId) {
const userid = mongoose.Types.ObjectId(userId);
+ const userById = await userProfile.findOne({ _id: userid , isActive:true}, {role:1})
+ .then((res)=>{ return res; }).catch((e)=>{});
+
+ if(userById==null) return null;
+ const userRole = userById.role;
const pdtstart = moment()
.tz('America/Los_Angeles')
.startOf('week')
@@ -162,254 +168,355 @@ const dashboardhelper = function () {
.tz('America/Los_Angeles')
.endOf('week')
.format('YYYY-MM-DD');
- return myTeam.aggregate([
- {
- $match: {
- _id: userid,
- },
- },
- {
- $unwind: '$myteam',
- },
- {
- $project: {
- _id: 0,
- role: 1,
- personId: '$myteam._id',
- name: '$myteam.fullName',
- },
- },
- {
- $lookup: {
- from: 'userProfiles',
- localField: 'personId',
- foreignField: '_id',
- as: 'persondata',
- },
- },
- {
- $match: {
- // leaderboard user roles hierarchy
- $or: [
- {
- role: { $in: ['Owner', 'Core Team'] },
- },
- {
- $and: [
- {
- role: 'Administrator',
- },
- { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ],
- },
- {
- $and: [
- {
- role: { $in: ['Manager', 'Mentor'] },
- },
- {
- 'persondata.0.role': {
- $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
- },
- },
- ],
- },
- { 'persondata.0._id': userId },
- { 'persondata.0.role': 'Volunteer' },
- { 'persondata.0.isVisible': true },
- ],
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: {
- $arrayElemAt: ['$persondata.role', 0],
- },
- isVisible: {
- $arrayElemAt: ['$persondata.isVisible', 0],
- },
- hasSummary: {
- $ne: [
- {
- $arrayElemAt: [
- {
- $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
- },
- 0,
- ],
- },
- '',
- ],
- },
- weeklycommittedHours: {
- $sum: [
- {
- $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
- },
- {
- $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
- },
- ],
- },
- },
- },
- {
- $lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- timeEntryData: {
- $filter: {
- input: '$timeEntryData',
- as: 'timeentry',
- cond: {
- $and: [
- {
- $gte: ['$$timeentry.dateOfWork', pdtstart],
- },
- {
- $lte: ['$$timeentry.dateOfWork', pdtend],
- },
- ],
- },
- },
- },
- },
- },
- {
- $unwind: {
- path: '$timeEntryData',
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- totalSeconds: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.totalSeconds',
- 0,
- ],
- },
- isTangible: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.isTangible',
- false,
- ],
- },
- },
- },
- {
- $addFields: {
- tangibletime: {
- $cond: [
- {
- $eq: ['$isTangible', true],
- },
- '$totalSeconds',
- 0,
- ],
- },
- intangibletime: {
- $cond: [
- {
- $eq: ['$isTangible', false],
- },
- '$totalSeconds',
- 0,
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- personId: '$personId',
- weeklycommittedHours: '$weeklycommittedHours',
- name: '$name',
- role: '$role',
- isVisible: '$isVisible',
- hasSummary: '$hasSummary',
- },
- totalSeconds: {
- $sum: '$totalSeconds',
- },
- tangibletime: {
- $sum: '$tangibletime',
- },
- intangibletime: {
- $sum: '$intangibletime',
- },
- },
- },
- {
- $project: {
- _id: 0,
- personId: '$_id.personId',
- name: '$_id.name',
- role: '$_id.role',
- isVisible: '$_id.isVisible',
- hasSummary: '$_id.hasSummary',
- weeklycommittedHours: '$_id.weeklycommittedHours',
- totaltime_hrs: {
- $divide: ['$totalSeconds', 3600],
- },
- totaltangibletime_hrs: {
- $divide: ['$tangibletime', 3600],
- },
- totalintangibletime_hrs: {
- $divide: ['$intangibletime', 3600],
- },
- percentagespentintangible: {
- $cond: [
- {
- $eq: ['$totalSeconds', 0],
- },
- 0,
- {
- $multiply: [
- {
- $divide: ['$tangibletime', '$totalSeconds'],
- },
- 100,
- ],
- },
- ],
- },
- },
- },
- {
- $sort: {
- totaltangibletime_hrs: -1,
- name: 1,
- role: 1,
- },
+
+ 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)=>{ return res; }).catch((e)=>{})
+
+ 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,isVisible:1,weeklycommittedHours:1,weeklySummaries:1})
+ .then((res)=>{ return 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)=>{ return 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})
+ .then((res)=>{ return res; }).catch((e)=>{})
+ }
+
+
+ }
+
+ teamMemberIds = teamMembers.map(member => member._id);
+
+ const timeEntries = await timeentry.find({
+ dateOfWork: {
+ $gte: pdtstart,
+ $lte: pdtend,
},
- ]);
+ personId: { $in: teamMemberIds }
+ });
+
+ let timeEntryByPerson = {}
+ timeEntries.map((timeEntry)=>{
+
+ let personIdStr = timeEntry.personId.toString();
+
+ if(timeEntryByPerson[personIdStr]==null)
+ timeEntryByPerson[personIdStr] = {tangibleSeconds:0,intangibleSeconds:0,totalSeconds:0};
+
+ if (timeEntry.isTangible === true) {
+ timeEntryByPerson[personIdStr].tangibleSeconds += timeEntry.totalSeconds;
+ } else {
+ timeEntryByPerson[personIdStr].intangibleSeconds += timeEntry.totalSeconds;
+ }
+
+ timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds;
+ })
+
+ let leaderBoardData = [];
+ teamMembers.map((teamMember)=>{
+ let 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);
+ })
+
+ let sortedLBData = leaderBoardData.sort((a, b) => {
+ // Sort by totaltangibletime_hrs in descending order
+ if (b.totaltangibletime_hrs !== a.totaltangibletime_hrs) {
+ return b.totaltangibletime_hrs - a.totaltangibletime_hrs;
+ }
+
+ // Then sort by name in ascending order
+ if (a.name !== b.name) {
+ return a.name.localeCompare(b.name);
+ }
+
+ // Finally, sort by role in ascending order
+ return a.role.localeCompare(b.role);
+ });
+ return sortedLBData;
+
+ // return myTeam.aggregate([
+ // {
+ // $match: {
+ // _id: userid,
+ // },
+ // },
+ // {
+ // $unwind: '$myteam',
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // role: 1,
+ // personId: '$myteam._id',
+ // name: '$myteam.fullName',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'userProfiles',
+ // localField: 'personId',
+ // foreignField: '_id',
+ // as: 'persondata',
+ // },
+ // },
+ // {
+ // $match: {
+ // // leaderboard user roles hierarchy
+ // $or: [
+ // {
+ // role: { $in: ['Owner', 'Core Team'] },
+ // },
+ // {
+ // $and: [
+ // {
+ // role: 'Administrator',
+ // },
+ // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ // ],
+ // },
+ // {
+ // $and: [
+ // {
+ // role: { $in: ['Manager', 'Mentor'] },
+ // },
+ // {
+ // 'persondata.0.role': {
+ // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ // },
+ // },
+ // ],
+ // },
+ // { 'persondata.0._id': userId },
+ // { 'persondata.0.role': 'Volunteer' },
+ // { 'persondata.0.isVisible': true },
+ // ],
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: {
+ // $arrayElemAt: ['$persondata.role', 0],
+ // },
+ // isVisible: {
+ // $arrayElemAt: ['$persondata.isVisible', 0],
+ // },
+ // hasSummary: {
+ // $ne: [
+ // {
+ // $arrayElemAt: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
+ // },
+ // 0,
+ // ],
+ // },
+ // '',
+ // ],
+ // },
+ // weeklycommittedHours: {
+ // $sum: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ // },
+ // {
+ // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'timeEntries',
+ // localField: 'personId',
+ // foreignField: 'personId',
+ // as: 'timeEntryData',
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: 1,
+ // isVisible: 1,
+ // hasSummary: 1,
+ // weeklycommittedHours: 1,
+ // timeEntryData: {
+ // $filter: {
+ // input: '$timeEntryData',
+ // as: 'timeentry',
+ // cond: {
+ // $and: [
+ // {
+ // $gte: ['$$timeentry.dateOfWork', pdtstart],
+ // },
+ // {
+ // $lte: ['$$timeentry.dateOfWork', pdtend],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$timeEntryData',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: 1,
+ // isVisible: 1,
+ // hasSummary: 1,
+ // weeklycommittedHours: 1,
+ // totalSeconds: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.totalSeconds',
+ // 0,
+ // ],
+ // },
+ // isTangible: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.isTangible',
+ // false,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // tangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', true],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // intangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', false],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: {
+ // personId: '$personId',
+ // weeklycommittedHours: '$weeklycommittedHours',
+ // name: '$name',
+ // role: '$role',
+ // isVisible: '$isVisible',
+ // hasSummary: '$hasSummary',
+ // },
+ // totalSeconds: {
+ // $sum: '$totalSeconds',
+ // },
+ // tangibletime: {
+ // $sum: '$tangibletime',
+ // },
+ // intangibletime: {
+ // $sum: '$intangibletime',
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$_id.personId',
+ // name: '$_id.name',
+ // role: '$_id.role',
+ // isVisible: '$_id.isVisible',
+ // hasSummary: '$_id.hasSummary',
+ // weeklycommittedHours: '$_id.weeklycommittedHours',
+ // totaltime_hrs: {
+ // $divide: ['$totalSeconds', 3600],
+ // },
+ // totaltangibletime_hrs: {
+ // $divide: ['$tangibletime', 3600],
+ // },
+ // totalintangibletime_hrs: {
+ // $divide: ['$intangibletime', 3600],
+ // },
+ // percentagespentintangible: {
+ // $cond: [
+ // {
+ // $eq: ['$totalSeconds', 0],
+ // },
+ // 0,
+ // {
+ // $multiply: [
+ // {
+ // $divide: ['$tangibletime', '$totalSeconds'],
+ // },
+ // 100,
+ // ],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $sort: {
+ // totaltangibletime_hrs: -1,
+ // name: 1,
+ // role: 1,
+ // },
+ // },
+ // ]);
};
/**
From 2a1ef65af84d0d89eea2d6fb2fcc83fd0cf98810 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 12 Dec 2023 08:51:56 -0800
Subject: [PATCH 201/272] add tool and equipment discriminators
---
.../bmdashboard/buildingInventoryItem.js | 88 +++++++++++++------
1 file changed, 61 insertions(+), 27 deletions(-)
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
index 0d357ae7a..845243331 100644
--- a/src/models/bmdashboard/buildingInventoryItem.js
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -1,8 +1,8 @@
const mongoose = require('mongoose');
-//----------------------
-// BASE INVENTORY SCHEMA
-//----------------------
+//-----------------------
+// BASE INVENTORY SCHEMAS
+//-----------------------
// base schema for all categories of inventory (Consumable, Material, Reusable, Tool, Equipment)
// this schema is extended by the individual schemas for each inventory type
@@ -46,6 +46,28 @@ const buildingMaterial = baseInv.discriminator('material', new mongoose.Schema({
}],
}));
+//-----------------
+// CONSUMABLES SCHEMA
+//-----------------
+
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "consumable" }
+// ex: screws, nails, staples
+
+const buildingConsumable = baseInv.discriminator('consumable', new mongoose.Schema({
+ stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+ stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
+ stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
+ stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
+ updateRecord: [{
+ _id: false,
+ date: { type: Date, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantityUsed: { type: Number, required: true },
+ quantityWasted: { type: Number, required: true },
+ }],
+}));
+
//-----------------
// REUSABLES SCHEMA
//-----------------
@@ -67,54 +89,66 @@ const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
}],
}));
-//-----------------
-// CONSUMABLES SCHEMA
-//-----------------
-
-// inherits all properties of baseInv schema using discriminator
-// each document derived from this schema includes key field { __t: "consumable" }
-// ex: screws, nails, staples
-
//-------------
-// TOOLS SCHEMA
+// TOOL SCHEMAS
//-------------
// inherits all properties of baseInv schema using discriminator
// each document derived from this schema includes key field { __t: "tool" }
-// ex: power drills, wheelbarrows, shovels
+// ex: power drills, wheelbarrows, shovels, jackhammers
+
+// Base Tool Schema:
const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
code: { type: Number, required: true }, // add function to create code for on-site tool tracking
purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
- // add discriminator based on rental or purchase so these fields are required if tool is rented
- rentedOnDate: Date,
- rentalDue: Date,
- userResponsible: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- purchaseRecord: [{ // track purchase/rental requests
- _id: false, // do not add _id field to subdocument
- date: { type: Date, default: Date.now() },
- requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
- brand: String,
- status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
- }],
+ imgUrl: String,
updateRecord: [{ // track tool condition updates
_id: false,
date: { type: Date, default: Date.now() },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
}],
- logRecord: [{ // track tool daily check in/out and use
+ logRecord: [{ // track tool daily check in/out and responsible user
_id: false,
date: { type: Date, default: Date.now() },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- type: { type: String, enum: ['Check In', 'Check Out'] }, // default = opposite of current log status?
+ type: { type: String, enum: ['Check In', 'Check Out'] },
}],
}));
+// Rented Tool Schema:
+// inherits all properties of buildingTool schema using discriminator
+// each document derived from this schema includes key field { __t: "tool_rental" }
+
+// const buildingToolRental = buildingTool.discriminator('tool_rental', new mongoose.Schema({
+// rentedOnDate: { type: Date, required: true },
+// rentalDueDate: { type: Date, required: true },
+// }));
+
+//------------------
+// EQUIPMENT SCHEMAS
+//------------------
+
+// inherits all properties of baseInv schema using discriminator
+// each document derived from this schema includes key field { __t: "equipment" }
+// items in this category are assumed to be rented
+// ex: tractors, excavators, bulldozers
+
+const buildingEquipment = baseInv.discriminator('equipment', new mongoose.Schema({
+ isTracked: { type: Boolean, required: true },
+ assetTracker: String,
+ // add rental record?
+}));
+
+// add purchase varient instead of rental varient?
module.exports = {
buildingMaterial,
+ buildingConsumable,
buildingReusable,
+ buildingTool,
+ // buildingToolRental,
+ buildingEquipment,
};
From ef31db0d43ac6f8c2c6f79b6b9d859502776547a Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 12 Dec 2023 10:12:45 -0800
Subject: [PATCH 202/272] delete redundant files. add basic equipment schema
---
src/models/bmdashboard/baseInvSchema.js | 23 -----------
.../bmdashboard/buildingInventoryItem.js | 41 ++++++++++++-------
src/models/bmdashboard/buildingReusable.js | 21 ----------
3 files changed, 26 insertions(+), 59 deletions(-)
delete mode 100644 src/models/bmdashboard/baseInvSchema.js
delete mode 100644 src/models/bmdashboard/buildingReusable.js
diff --git a/src/models/bmdashboard/baseInvSchema.js b/src/models/bmdashboard/baseInvSchema.js
deleted file mode 100644
index 7eff943e7..000000000
--- a/src/models/bmdashboard/baseInvSchema.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const mongoose = require('mongoose');
-
-// base schema for all categories of inventory (Consumable, Material, Reusable, Tool, Equipment)
-// this schema is extended by the individual schemas for each inventory type
-// all documents derived from this schema are saved to the collection 'buildingInventoryItems'
-
-const baseInvSchema = mongoose.Schema({
- itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
- project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
- purchaseRecord: [{
- _id: false, // do not add _id field to subdocument
- date: { type: Date, default: Date.now() },
- requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantity: { type: Number, required: true },
- priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
- brandPref: String,
- status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
- }],
-});
-
-const baseInv = mongoose.model('buildingInventory', baseInvSchema, 'buildingInventoryItems');
-
-module.exports = baseInv;
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
index 845243331..ed9c52ebc 100644
--- a/src/models/bmdashboard/buildingInventoryItem.js
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -15,7 +15,7 @@ const baseInvSchema = mongoose.Schema({
_id: false, // do not add _id field to subdocument
date: { type: Date, default: Date.now() },
requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantity: { type: Number, required: true },
+ quantity: { type: Number, required: true, default: 1 }, // default 1 for tool or equipment purchases
priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
brandPref: String,
status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
@@ -100,8 +100,11 @@ const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
// Base Tool Schema:
const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
- code: { type: Number, required: true }, // add function to create code for on-site tool tracking
+ code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
+ // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
+ rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+ rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
imgUrl: String,
updateRecord: [{ // track tool condition updates
_id: false,
@@ -118,15 +121,6 @@ const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
}],
}));
-// Rented Tool Schema:
-// inherits all properties of buildingTool schema using discriminator
-// each document derived from this schema includes key field { __t: "tool_rental" }
-
-// const buildingToolRental = buildingTool.discriminator('tool_rental', new mongoose.Schema({
-// rentedOnDate: { type: Date, required: true },
-// rentalDueDate: { type: Date, required: true },
-// }));
-
//------------------
// EQUIPMENT SCHEMAS
//------------------
@@ -137,9 +131,27 @@ const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
// ex: tractors, excavators, bulldozers
const buildingEquipment = baseInv.discriminator('equipment', new mongoose.Schema({
- isTracked: { type: Boolean, required: true },
- assetTracker: String,
- // add rental record?
+ isTracked: { type: Boolean, required: true }, // has asset tracker
+ assetTracker: { type: String, required: () => this.isTracked }, // required if isTracked = true (syntax?)
+ code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
+ purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
+ // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
+ rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+ rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+ imgUrl: String,
+ updateRecord: [{ // track equipment condition updates
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
+ }],
+ logRecord: [{ // track tool daily check in/out and responsible user
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ type: { type: String, enum: ['Check In', 'Check Out'] },
+ }],
}));
// add purchase varient instead of rental varient?
@@ -149,6 +161,5 @@ module.exports = {
buildingConsumable,
buildingReusable,
buildingTool,
- // buildingToolRental,
buildingEquipment,
};
diff --git a/src/models/bmdashboard/buildingReusable.js b/src/models/bmdashboard/buildingReusable.js
deleted file mode 100644
index 1f2ceaa48..000000000
--- a/src/models/bmdashboard/buildingReusable.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const mongoose = require('mongoose');
-
-const baseInv = require('./baseInvSchema');
-
-// inherits all properties of baseInv schema using discriminator
-// each document derived from this schema includes key field { __t: "buildingReusable" }
-
-const buildingReusable = baseInv.discriminator('buildingReusable', new mongoose.Schema({
- stockBought: { type: Number, default: 0 },
- stockDestroyed: { type: Number, default: 0 },
- stockAvailable: { type: Number, default: 0 },
- updateRecord: [{
- _id: false,
- date: { type: Date, required: true },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantityUsed: { type: Number, required: true },
- quantityDestroyed: { type: Number, required: true },
- }],
-}));
-
-module.exports = buildingReusable;
From 6cc5807680d68381b3446d49eaca951f51b33ea3 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 12 Dec 2023 12:03:57 -0800
Subject: [PATCH 203/272] experimenting with new schema varient
---
.../bmdashboard/buildingInventoryItem.js | 217 ++++++++++++------
1 file changed, 146 insertions(+), 71 deletions(-)
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
index ed9c52ebc..a9559a45d 100644
--- a/src/models/bmdashboard/buildingInventoryItem.js
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -8,9 +8,28 @@ const mongoose = require('mongoose');
// this schema is extended by the individual schemas for each inventory type
// all documents derived from this schema are saved to the collection 'buildingInventoryItems'
-const baseInvSchema = mongoose.Schema({
+// const baseInvSchema = mongoose.Schema({
+// itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+// project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+// purchaseRecord: [{
+// _id: false, // do not add _id field to subdocument
+// date: { type: Date, default: Date.now() },
+// requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// quantity: { type: Number, required: true, default: 1 }, // default 1 for tool or equipment purchases
+// priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+// brandPref: String,
+// status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+// }],
+// });
+
+// const baseInv = mongoose.model('buildingInventory', baseInvSchema, 'buildingInventoryItems');
+
+const baseSchemaForMaterialReusableConsumable = mongoose.Schema({
itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+ stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+ // TODO: can stockAvailable default be a function?
+ stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
purchaseRecord: [{
_id: false, // do not add _id field to subdocument
date: { type: Date, default: Date.now() },
@@ -20,9 +39,41 @@ const baseInvSchema = mongoose.Schema({
brandPref: String,
status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
}],
+ updateRecord: [{
+ _id: false,
+ date: { type: Date, required: true },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantityUsed: { type: Number, required: true },
+ quantityWasted: { type: Number, required: true },
+ }],
});
-const baseInv = mongoose.model('buildingInventory', baseInvSchema, 'buildingInventoryItems');
+const baseInvSmallItems = mongoose.model('buildingInvSmallItems', baseSchemaForMaterialReusableConsumable, 'buildingInventoryItems');
+
+const baseSchemaForToolEquipment = mongoose.Schema({
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
+ purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
+ // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
+ rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+ rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+ imgUrl: String,
+ updateRecord: [{ // track tool condition updates
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
+ }],
+ logRecord: [{ // track tool daily check in/out and responsible user
+ _id: false,
+ date: { type: Date, default: Date.now() },
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ type: { type: String, enum: ['Check In', 'Check Out'] },
+ }],
+});
+
+const baseInvLargeItems = mongoose.model('buildingInvLargeItems', baseSchemaForToolEquipment, 'buildingInventoryItems');
//-----------------
// MATERIALS SCHEMA
@@ -32,18 +83,23 @@ const baseInv = mongoose.model('buildingInventory', baseInvSchema, 'buildingInve
// each document derived from this schema includes key field { __t: "material" }
// ex: sand, stone, bricks, lumber, insulation
-const buildingMaterial = baseInv.discriminator('material', new mongoose.Schema({
- stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+// const buildingMaterial = baseInv.discriminator('material', new mongoose.Schema({
+// stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+// stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
+// stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
+// stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
+// updateRecord: [{
+// _id: false,
+// date: { type: Date, required: true },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// quantityUsed: { type: Number, required: true },
+// quantityWasted: { type: Number, required: true },
+// }],
+// }));
+
+const buildingMaterial = baseInvSmallItems.discriminator('material', new mongoose.Schema({
stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
- stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
- updateRecord: [{
- _id: false,
- date: { type: Date, required: true },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantityUsed: { type: Number, required: true },
- quantityWasted: { type: Number, required: true },
- }],
}));
//-----------------
@@ -54,18 +110,23 @@ const buildingMaterial = baseInv.discriminator('material', new mongoose.Schema({
// each document derived from this schema includes key field { __t: "consumable" }
// ex: screws, nails, staples
-const buildingConsumable = baseInv.discriminator('consumable', new mongoose.Schema({
- stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+// const buildingConsumable = baseInv.discriminator('consumable', new mongoose.Schema({
+// stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
+// stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
+// stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
+// stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
+// updateRecord: [{
+// _id: false,
+// date: { type: Date, required: true },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// quantityUsed: { type: Number, required: true },
+// quantityWasted: { type: Number, required: true },
+// }],
+// }));
+
+const buildingConsumable = baseInvSmallItems.discriminator('consumable', new mongoose.Schema({
stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
- stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
- updateRecord: [{
- _id: false,
- date: { type: Date, required: true },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantityUsed: { type: Number, required: true },
- quantityWasted: { type: Number, required: true },
- }],
}));
//-----------------
@@ -76,17 +137,21 @@ const buildingConsumable = baseInv.discriminator('consumable', new mongoose.Sche
// each document derived from this schema includes key field { __t: "reusable" }
// ex: hammers, screwdrivers, mallets, brushes, gloves
-const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
- stockBought: { type: Number, default: 0 },
+// const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
+// stockBought: { type: Number, default: 0 },
+// stockDestroyed: { type: Number, default: 0 },
+// stockAvailable: { type: Number, default: 0 },
+// updateRecord: [{
+// _id: false,
+// date: { type: Date, required: true },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// quantityUsed: { type: Number, required: true },
+// quantityDestroyed: { type: Number, required: true },
+// }],
+// }));
+
+const buildingReusable = baseInvSmallItems.discriminator('reusable', new mongoose.Schema({
stockDestroyed: { type: Number, default: 0 },
- stockAvailable: { type: Number, default: 0 },
- updateRecord: [{
- _id: false,
- date: { type: Date, required: true },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- quantityUsed: { type: Number, required: true },
- quantityDestroyed: { type: Number, required: true },
- }],
}));
//-------------
@@ -99,28 +164,33 @@ const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
// Base Tool Schema:
-const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
+// const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
+// code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
+// purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
+// // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
+// rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+// rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+// imgUrl: String,
+// updateRecord: [{ // track tool condition updates
+// _id: false,
+// date: { type: Date, default: Date.now() },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
+// }],
+// logRecord: [{ // track tool daily check in/out and responsible user
+// _id: false,
+// date: { type: Date, default: Date.now() },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// type: { type: String, enum: ['Check In', 'Check Out'] },
+// }],
+// }));
+
+const buildingTool = baseInvLargeItems.discriminator('tool', new mongoose.Schema({
code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
- purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
- // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
- rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
- rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
- imgUrl: String,
- updateRecord: [{ // track tool condition updates
- _id: false,
- date: { type: Date, default: Date.now() },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
- }],
- logRecord: [{ // track tool daily check in/out and responsible user
- _id: false,
- date: { type: Date, default: Date.now() },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- type: { type: String, enum: ['Check In', 'Check Out'] },
- }],
}));
+
//------------------
// EQUIPMENT SCHEMAS
//------------------
@@ -130,28 +200,33 @@ const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
// items in this category are assumed to be rented
// ex: tractors, excavators, bulldozers
-const buildingEquipment = baseInv.discriminator('equipment', new mongoose.Schema({
+// const buildingEquipment = baseInv.discriminator('equipment', new mongoose.Schema({
+// isTracked: { type: Boolean, required: true }, // has asset tracker
+// assetTracker: { type: String, required: () => this.isTracked }, // required if isTracked = true (syntax?)
+// code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
+// purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
+// // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
+// rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+// rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
+// imgUrl: String,
+// updateRecord: [{ // track equipment condition updates
+// _id: false,
+// date: { type: Date, default: Date.now() },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
+// }],
+// logRecord: [{ // track tool daily check in/out and responsible user
+// _id: false,
+// date: { type: Date, default: Date.now() },
+// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+// type: { type: String, enum: ['Check In', 'Check Out'] },
+// }],
+// }));
+
+const buildingEquipment = baseInvLargeItems.discriminator('equipment', new mongoose.Schema({
isTracked: { type: Boolean, required: true }, // has asset tracker
assetTracker: { type: String, required: () => this.isTracked }, // required if isTracked = true (syntax?)
- code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
- purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
- // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
- rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
- rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
- imgUrl: String,
- updateRecord: [{ // track equipment condition updates
- _id: false,
- date: { type: Date, default: Date.now() },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
- }],
- logRecord: [{ // track tool daily check in/out and responsible user
- _id: false,
- date: { type: Date, default: Date.now() },
- createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
- type: { type: String, enum: ['Check In', 'Check Out'] },
- }],
}));
// add purchase varient instead of rental varient?
From f92d83360f7cca247068b393d576c2cf3baec0dc Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 12 Dec 2023 12:29:45 -0800
Subject: [PATCH 204/272] refactor file
---
.../bmdashboard/buildingInventoryItem.js | 184 +++++-------------
1 file changed, 46 insertions(+), 138 deletions(-)
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
index a9559a45d..5e8b24916 100644
--- a/src/models/bmdashboard/buildingInventoryItem.js
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -4,27 +4,13 @@ const mongoose = require('mongoose');
// BASE INVENTORY SCHEMAS
//-----------------------
-// base schema for all categories of inventory (Consumable, Material, Reusable, Tool, Equipment)
-// this schema is extended by the individual schemas for each inventory type
-// all documents derived from this schema are saved to the collection 'buildingInventoryItems'
-
-// const baseInvSchema = mongoose.Schema({
-// itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
-// project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
-// purchaseRecord: [{
-// _id: false, // do not add _id field to subdocument
-// date: { type: Date, default: Date.now() },
-// requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// quantity: { type: Number, required: true, default: 1 }, // default 1 for tool or equipment purchases
-// priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
-// brandPref: String,
-// status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
-// }],
-// });
-
-// const baseInv = mongoose.model('buildingInventory', baseInvSchema, 'buildingInventoryItems');
-
-const baseSchemaForMaterialReusableConsumable = mongoose.Schema({
+// TODO: purchaseRecord subdocs may be changed to purchaseRequests. A new purchaseRecord subdoc may be added to track purchases and costs for the item.
+
+// SMALL ITEMS BASE
+// base schema for Consumable, Material, Reusable
+// documents stored in 'buildingInventoryItems' collection
+
+const smallItemBaseSchema = mongoose.Schema({
itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
@@ -48,16 +34,29 @@ const baseSchemaForMaterialReusableConsumable = mongoose.Schema({
}],
});
-const baseInvSmallItems = mongoose.model('buildingInvSmallItems', baseSchemaForMaterialReusableConsumable, 'buildingInventoryItems');
+const smallItemBase = mongoose.model('smallItemBase', smallItemBaseSchema, 'buildingInventoryItems');
+
+// LARGE ITEMS BASE
+// base schema for Tool, Equipment
+// documents stored in 'buildingInventoryItems' collection
-const baseSchemaForToolEquipment = mongoose.Schema({
+const largeItemBaseSchema = mongoose.Schema({
itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
// rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
- imgUrl: String,
+ imageUrl: String,
+ purchaseRecord: [{
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ makeModelPref: String,
+ estTimeRequired: { type: Number, required: true }, // estimated time required on site
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+ }],
updateRecord: [{ // track tool condition updates
_id: false,
date: { type: Date, default: Date.now() },
@@ -73,164 +72,73 @@ const baseSchemaForToolEquipment = mongoose.Schema({
}],
});
-const baseInvLargeItems = mongoose.model('buildingInvLargeItems', baseSchemaForToolEquipment, 'buildingInventoryItems');
+const largeItemBase = mongoose.model('largeItemBase', largeItemBaseSchema, 'buildingInventoryItems');
//-----------------
// MATERIALS SCHEMA
//-----------------
-// inherits all properties of baseInv schema using discriminator
+// inherits all properties of smallItemBaseSchema
// each document derived from this schema includes key field { __t: "material" }
// ex: sand, stone, bricks, lumber, insulation
-// const buildingMaterial = baseInv.discriminator('material', new mongoose.Schema({
-// stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
-// stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
-// stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
-// stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
-// updateRecord: [{
-// _id: false,
-// date: { type: Date, required: true },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// quantityUsed: { type: Number, required: true },
-// quantityWasted: { type: Number, required: true },
-// }],
-// }));
-
-const buildingMaterial = baseInvSmallItems.discriminator('material', new mongoose.Schema({
+const buildingMaterial = smallItemBase.discriminator('material', new mongoose.Schema({
stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
}));
-//-----------------
-// CONSUMABLES SCHEMA
-//-----------------
+//------------------
+// CONSUMABLE SCHEMA
+//------------------
-// inherits all properties of baseInv schema using discriminator
+// inherits all properties of smallItemBaseSchema
// each document derived from this schema includes key field { __t: "consumable" }
// ex: screws, nails, staples
-// const buildingConsumable = baseInv.discriminator('consumable', new mongoose.Schema({
-// stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
-// stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
-// stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
-// stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
-// updateRecord: [{
-// _id: false,
-// date: { type: Date, required: true },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// quantityUsed: { type: Number, required: true },
-// quantityWasted: { type: Number, required: true },
-// }],
-// }));
-
-const buildingConsumable = baseInvSmallItems.discriminator('consumable', new mongoose.Schema({
+const buildingConsumable = smallItemBase.discriminator('consumable', new mongoose.Schema({
stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
}));
-//-----------------
-// REUSABLES SCHEMA
-//-----------------
+//----------------
+// REUSABLE SCHEMA
+//----------------
-// inherits all properties of baseInv schema using discriminator
+// inherits all properties of smallItemBaseSchema
// each document derived from this schema includes key field { __t: "reusable" }
// ex: hammers, screwdrivers, mallets, brushes, gloves
-// const buildingReusable = baseInv.discriminator('reusable', new mongoose.Schema({
-// stockBought: { type: Number, default: 0 },
-// stockDestroyed: { type: Number, default: 0 },
-// stockAvailable: { type: Number, default: 0 },
-// updateRecord: [{
-// _id: false,
-// date: { type: Date, required: true },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// quantityUsed: { type: Number, required: true },
-// quantityDestroyed: { type: Number, required: true },
-// }],
-// }));
-
-const buildingReusable = baseInvSmallItems.discriminator('reusable', new mongoose.Schema({
+const buildingReusable = smallItemBase.discriminator('reusable', new mongoose.Schema({
stockDestroyed: { type: Number, default: 0 },
}));
-//-------------
-// TOOL SCHEMAS
-//-------------
+//------------
+// TOOL SCHEMA
+//------------
-// inherits all properties of baseInv schema using discriminator
+// inherits all properties of largeItemBaseSchema
// each document derived from this schema includes key field { __t: "tool" }
// ex: power drills, wheelbarrows, shovels, jackhammers
-// Base Tool Schema:
-
-// const buildingTool = baseInv.discriminator('tool', new mongoose.Schema({
-// code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
-// purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
-// // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
-// rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
-// rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
-// imgUrl: String,
-// updateRecord: [{ // track tool condition updates
-// _id: false,
-// date: { type: Date, default: Date.now() },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
-// }],
-// logRecord: [{ // track tool daily check in/out and responsible user
-// _id: false,
-// date: { type: Date, default: Date.now() },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// type: { type: String, enum: ['Check In', 'Check Out'] },
-// }],
-// }));
-
-const buildingTool = baseInvLargeItems.discriminator('tool', new mongoose.Schema({
+const buildingTool = largeItemBase.discriminator('tool', new mongoose.Schema({
code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
}));
-//------------------
-// EQUIPMENT SCHEMAS
-//------------------
+//-----------------
+// EQUIPMENT SCHEMA
+//-----------------
-// inherits all properties of baseInv schema using discriminator
+// inherits all properties of largeItemBaseSchema
// each document derived from this schema includes key field { __t: "equipment" }
// items in this category are assumed to be rented
// ex: tractors, excavators, bulldozers
-// const buildingEquipment = baseInv.discriminator('equipment', new mongoose.Schema({
-// isTracked: { type: Boolean, required: true }, // has asset tracker
-// assetTracker: { type: String, required: () => this.isTracked }, // required if isTracked = true (syntax?)
-// code: { type: Number, required: true }, // TODO: add function to create simple numeric code for on-site tool tracking
-// purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
-// // rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
-// rentedOnDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
-// rentalDueDate: { type: Date, required: () => this.purchaseStatus === 'Rental' },
-// imgUrl: String,
-// updateRecord: [{ // track equipment condition updates
-// _id: false,
-// date: { type: Date, default: Date.now() },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// condition: { type: String, enum: ['Good', 'Needs Repair', 'Out of Order'] },
-// }],
-// logRecord: [{ // track tool daily check in/out and responsible user
-// _id: false,
-// date: { type: Date, default: Date.now() },
-// createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// responsibleUser: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
-// type: { type: String, enum: ['Check In', 'Check Out'] },
-// }],
-// }));
-
-const buildingEquipment = baseInvLargeItems.discriminator('equipment', new mongoose.Schema({
+const buildingEquipment = largeItemBase.discriminator('equipment', new mongoose.Schema({
isTracked: { type: Boolean, required: true }, // has asset tracker
assetTracker: { type: String, required: () => this.isTracked }, // required if isTracked = true (syntax?)
}));
-// add purchase varient instead of rental varient?
-
module.exports = {
buildingMaterial,
buildingConsumable,
From bae46b1c69333910a54d0d914a5faaec6ed31246 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 12 Dec 2023 12:43:52 -0800
Subject: [PATCH 205/272] undo changes to current material routes to avoid
breaking things
---
.../bmdashboard/bmMaterialsController.js | 2 +-
src/models/bmdashboard/buildingMaterial.js | 30 +++++++++++--------
src/startup/routes.js | 2 +-
3 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 2c79bd9b9..911ca0b55 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -48,7 +48,7 @@ const bmMaterialsController = function (ItemMaterial,BuildingMaterial) {
const newPurchaseRecord = {
quantity,
priority,
- brandPref: brand,
+ brand,
requestedBy: requestorId,
};
try {
diff --git a/src/models/bmdashboard/buildingMaterial.js b/src/models/bmdashboard/buildingMaterial.js
index caf61e4c0..bc86884ed 100644
--- a/src/models/bmdashboard/buildingMaterial.js
+++ b/src/models/bmdashboard/buildingMaterial.js
@@ -1,23 +1,29 @@
const mongoose = require('mongoose');
-const baseInv = require('./baseInvSchema');
+const { Schema } = mongoose;
-// inherits all properties of baseInv schema using discriminator
-// each document derived from this schema includes key field { __t: "buildingMaterial" }
-
-const buildingMaterial = baseInv.discriminator('buildingMaterial', new mongoose.Schema({
+const buildingMaterial = new Schema({
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
- stockUsed: { type: Number, default: 0 }, // stock that has been used up and cannot be reused
- stockWasted: { type: Number, default: 0 }, // ruined or destroyed stock
- stockAvailable: { type: Number, default: 0 }, // available = bought - (used + wasted/destroyed)
+ stockUsed: { type: Number, default: 0 }, // total amount of item used successfully in the project
+ stockWasted: { type: Number, default: 0 }, // total amount of item wasted/ruined/lost in the project
+ stockAvailable: { type: Number, default: 0 }, // bought - (used + wasted)
+ purchaseRecord: [{
+ _id: false, // do not add _id field to subdocument
+ date: { type: Date, default: Date.now() },
+ requestedBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
+ quantity: { type: Number, required: true },
+ priority: { type: String, enum: ['Low', 'Medium', 'High'], required: true },
+ brand: String,
+ status: { type: String, default: 'Pending', enum: ['Approved', 'Pending', 'Rejected'] },
+ }],
updateRecord: [{
_id: false,
date: { type: Date, required: true },
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' },
quantityUsed: { type: Number, required: true },
quantityWasted: { type: Number, required: true },
- test: { type: String, default: 'testing this field' },
}],
-}));
-
-module.exports = buildingMaterial;
+});
+module.exports = mongoose.model('buildingMaterial', buildingMaterial, 'buildingMaterials');
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 37832c199..ff5d01b2b 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -23,7 +23,7 @@ const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const mapLocations = require('../models/mapLocation');
const buildingProject = require('../models/bmdashboard/buildingProject');
const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
-const { buildingMaterial } = require('../models/bmdashboard/buildingInventoryItem');
+const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
From 18da208bce004ec9c8eb85052d65d899c91e3aef Mon Sep 17 00:00:00 2001
From: Olga Yudkin
Date: Wed, 13 Dec 2023 14:55:32 -0500
Subject: [PATCH 206/272] updated toolcontroller query
---
.../bmdashboard/bmToolController.js | 45 ++++++++++++++-----
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/src/controllers/bmdashboard/bmToolController.js b/src/controllers/bmdashboard/bmToolController.js
index 2b29101f3..0feec256c 100644
--- a/src/controllers/bmdashboard/bmToolController.js
+++ b/src/controllers/bmdashboard/bmToolController.js
@@ -4,16 +4,41 @@ const bmToolController = (BuildingTool) => {
try {
BuildingTool
.findById(toolId)
- // .populate([
- // {
- // path: 'itemType',
- // select: '_id name description unit imageURL',
- // },
- // {
- // path: 'userResponsible',
- // select: '_id firstName lastName',
- // },
- // ])
+ .populate([
+ {
+ path: 'itemType',
+ select: '_id name description unit imageUrl category',
+ },
+ {
+ path: 'userResponsible',
+ select: '_id firstName lastName',
+ },
+ {
+ path: 'purchaseRecord',
+ populate: {
+ path: 'requestedBy',
+ select: '_id firstName lastName',
+ },
+ },
+ {
+ path: 'updateRecord',
+ populate: {
+ path: 'createdBy',
+ select: '_id firstName lastName',
+ },
+ },
+ {
+ path: 'logRecord',
+ populate: [{
+ path: 'createdBy',
+ select: '_id firstName lastName',
+ },
+ {
+ path: 'responsibleUser',
+ select: '_id firstName lastName',
+ }],
+ },
+ ])
.exec()
.then(tool => res.status(200).send(tool))
.catch(error => res.status(500).send(error));
From 230cedc459088655359f75cc7a1752be24a4ed40 Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Fri, 15 Dec 2023 15:41:22 +0000
Subject: [PATCH 207/272] added the replyTo feature
---
src/controllers/timeEntryController.js | 366 +++++++++++++++----------
src/helpers/userHelper.js | 4 +-
2 files changed, 228 insertions(+), 142 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index 962f30170..9c4d7c5e3 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -1,17 +1,17 @@
-const moment = require('moment-timezone');
-const mongoose = require('mongoose');
-const { getInfringementEmailBody } = require('../helpers/userHelper')();
-const userProfile = require('../models/userProfile');
-const task = require('../models/task');
-const emailSender = require('../utilities/emailSender');
-const { hasPermission } = require('../utilities/permissions');
+const moment = require("moment-timezone");
+const mongoose = require("mongoose");
+const { getInfringementEmailBody } = require("../helpers/userHelper")();
+const userProfile = require("../models/userProfile");
+const task = require("../models/task");
+const emailSender = require("../utilities/emailSender");
+const { hasPermission } = require("../utilities/permissions");
const formatSeconds = function (seconds) {
const formattedseconds = parseInt(seconds, 10);
const values = `${Math.floor(
- moment.duration(formattedseconds, 'seconds').asHours(),
- )}:${moment.duration(formattedseconds, 'seconds').minutes()}`;
- return values.split(':');
+ moment.duration(formattedseconds, "seconds").asHours()
+ )}:${moment.duration(formattedseconds, "seconds").minutes()}`;
+ return values.split(":");
};
/**
@@ -24,9 +24,20 @@ const formatSeconds = function (seconds) {
* @param {*} requestor The userProfile object of the person that modified the time entry
* @returns {String}
*/
-const getEditedTimeEntryEmailBody = (firstName, lastName, email, originalTime, finalTime, requestor) => {
- const formattedOriginal = moment.utc(originalTime * 1000).format('HH[ hours ]mm[ minutes]');
- const formattedFinal = moment.utc(finalTime * 1000).format('HH[ hours ]mm[ minutes]');
+const getEditedTimeEntryEmailBody = (
+ firstName,
+ lastName,
+ email,
+ originalTime,
+ finalTime,
+ requestor
+) => {
+ const formattedOriginal = moment
+ .utc(originalTime * 1000)
+ .format("HH[ hours ]mm[ minutes]");
+ const formattedFinal = moment
+ .utc(finalTime * 1000)
+ .format("HH[ hours ]mm[ minutes]");
return `
A time entry belonging to ${firstName} ${lastName} (${email}) was modified by ${requestor.firstName} ${requestor.lastName} (${requestor.email}).
The entry's duration was changed from [${formattedOriginal}] to [${formattedFinal}]
@@ -45,18 +56,39 @@ const notifyEditByEmail = async (personId, original, finalTime, final) => {
try {
const originalTime = original.totalSeconds;
const record = await userProfile.findById(personId);
- const requestor = (personId !== final.requestor.requestorId) ? await userProfile.findById(final.requestor.requestorId) : record;
- const emailBody = getEditedTimeEntryEmailBody(record.firstName, record.lastName, record.email, originalTime, finalTime, requestor);
- emailSender('onecommunityglobal@gmail.com', `A Time Entry was Edited for ${record.firstName} ${record.lastName}`, emailBody);
+ const requestor =
+ personId !== final.requestor.requestorId
+ ? await userProfile.findById(final.requestor.requestorId)
+ : record;
+ const emailBody = getEditedTimeEntryEmailBody(
+ record.firstName,
+ record.lastName,
+ record.email,
+ originalTime,
+ finalTime,
+ requestor
+ );
+ emailSender(
+ "onecommunityglobal@gmail.com",
+ `A Time Entry was Edited for ${record.firstName} ${record.lastName}`,
+ emailBody
+ );
} catch (error) {
- throw new Error(`Failed to send email notification about the modification of time entry belonging to user with id ${personId}`);
+ throw new Error(
+ `Failed to send email notification about the modification of time entry belonging to user with id ${personId}`
+ );
}
};
-const notifyTaskOvertimeEmailBody = async (personId, taskName, estimatedHours, hoursLogged) => {
+const notifyTaskOvertimeEmailBody = async (
+ personId,
+ taskName,
+ estimatedHours,
+ hoursLogged
+) => {
try {
- const record = await userProfile.findById(personId);
- const text = `Dear ${record.firstName}${record.lastName},
+ const record = await userProfile.findById(personId);
+ const text = `Dear ${record.firstName}${record.lastName},
Oops, it looks like you have logged more hours than estimated for a task
Task Name : ${taskName}
Time Estimated : ${estimatedHours}
@@ -64,24 +96,37 @@ const notifyTaskOvertimeEmailBody = async (personId, taskName, estimatedHours, h
Please connect with your manager to explain what happened and submit a new hours estimation for completion.
Thank you,
One Community
`;
- emailSender(
- record.email,
- 'Logged more hours than estimated for a task',
- text,
- 'onecommunityglobal@gmail.com',
- null,
+ emailSender(
+ record.email,
+ "Logged more hours than estimated for a task",
+ text,
+ "onecommunityglobal@gmail.com",
+ null,
+ record.email,
+ null
);
} catch (error) {
- console.log(`Failed to send email notification about the overtime for a task belonging to user with id ${personId}`);
+ console.log(
+ `Failed to send email notification about the overtime for a task belonging to user with id ${personId}`
+ );
}
};
const checkTaskOvertime = async (timeentry, record, currentTask) => {
try {
// send email notification if logged in hours exceeds estiamted hours for a task
- if (currentTask.hoursLogged > currentTask.estimatedHours) { notifyTaskOvertimeEmailBody(timeentry.personId.toString(), currentTask.taskName, currentTask.estimatedHours, currentTask.hoursLogged); }
+ if (currentTask.hoursLogged > currentTask.estimatedHours) {
+ notifyTaskOvertimeEmailBody(
+ timeentry.personId.toString(),
+ currentTask.taskName,
+ currentTask.estimatedHours,
+ currentTask.hoursLogged
+ );
+ }
} catch (error) {
- console.log(`Failed to find task whose logged-in hours are more than estimated hours ${record.email}`);
+ console.log(
+ `Failed to find task whose logged-in hours are more than estimated hours ${record.email}`
+ );
}
};
@@ -92,31 +137,58 @@ const timeEntrycontroller = function (TimeEntry) {
try {
if (!req.params.timeEntryId) {
- return res.status(400).send({ error: 'ObjectId in request param is not in correct format' });
+ return res
+ .status(400)
+ .send({
+ error: "ObjectId in request param is not in correct format",
+ });
}
- if (!mongoose.Types.ObjectId.isValid(req.params.timeEntryId) || !mongoose.Types.ObjectId.isValid(req.body.projectId)) {
- return res.status(400).send({ error: 'ObjectIds are not correctly formed' });
+ if (
+ !mongoose.Types.ObjectId.isValid(req.params.timeEntryId) ||
+ !mongoose.Types.ObjectId.isValid(req.body.projectId)
+ ) {
+ return res
+ .status(400)
+ .send({ error: "ObjectIds are not correctly formed" });
}
// Get initial timeEntry by timeEntryId
const timeEntry = await TimeEntry.findById(req.params.timeEntryId);
if (!timeEntry) {
- return res.status(400).send({ error: `No valid records found for ${req.params.timeEntryId}` });
+ return res
+ .status(400)
+ .send({
+ error: `No valid records found for ${req.params.timeEntryId}`,
+ });
}
- if (!(await hasPermission(req.body.requestor, 'editTimeEntry') || timeEntry.personId.toString() === req.body.requestor.requestorId.toString())) {
- return res.status(403).send({ error: 'Unauthorized request' });
+ if (
+ !(
+ (await hasPermission(req.body.requestor, "editTimeEntry")) ||
+ timeEntry.personId.toString() ===
+ req.body.requestor.requestorId.toString()
+ )
+ ) {
+ return res.status(403).send({ error: "Unauthorized request" });
}
- const hours = req.body.hours ? req.body.hours : '00';
- const minutes = req.body.minutes ? req.body.minutes : '00';
+ const hours = req.body.hours ? req.body.hours : "00";
+ const minutes = req.body.minutes ? req.body.minutes : "00";
const totalSeconds = moment.duration(`${hours}:${minutes}`).asSeconds();
- if (timeEntry.isTangible === true && totalSeconds !== timeEntry.totalSeconds) {
- notifyEditByEmail(timeEntry.personId.toString(), timeEntry, totalSeconds, req.body);
+ if (
+ timeEntry.isTangible === true &&
+ totalSeconds !== timeEntry.totalSeconds
+ ) {
+ notifyEditByEmail(
+ timeEntry.personId.toString(),
+ timeEntry,
+ totalSeconds,
+ req.body
+ );
}
const initialSeconds = timeEntry.totalSeconds;
@@ -130,7 +202,7 @@ const timeEntrycontroller = function (TimeEntry) {
timeEntry.isTangible = req.body.isTangible;
timeEntry.lastModifiedDateTime = moment().utc().toISOString();
timeEntry.projectId = mongoose.Types.ObjectId(req.body.projectId);
- timeEntry.dateOfWork = moment(req.body.dateOfWork).format('YYYY-MM-DD');
+ timeEntry.dateOfWork = moment(req.body.dateOfWork).format("YYYY-MM-DD");
// Update the hoursLogged field of related tasks based on before and after timeEntries
// initialIsTangible is a bealoon value, req.body.isTangible is a string
@@ -138,11 +210,11 @@ const timeEntrycontroller = function (TimeEntry) {
try {
if (findTask) {
if (initialIsTangible === true) {
- findTask.hoursLogged -= (initialSeconds / 3600);
+ findTask.hoursLogged -= initialSeconds / 3600;
}
if (req.body.isTangible === true) {
- findTask.hoursLogged += (totalSeconds / 3600);
+ findTask.hoursLogged += totalSeconds / 3600;
}
await findTask.save();
@@ -152,14 +224,17 @@ const timeEntrycontroller = function (TimeEntry) {
}
// Update edit history
- if (initialSeconds !== totalSeconds
- && timeEntry.isTangible
- && req.body.requestor.requestorId === timeEntry.personId.toString()
- && !await hasPermission(req.body.requestor, 'editTimeEntry')
- ) {
- const requestor = await userProfile.findById(req.body.requestor.requestorId);
+ if (
+ initialSeconds !== totalSeconds &&
+ timeEntry.isTangible &&
+ req.body.requestor.requestorId === timeEntry.personId.toString() &&
+ !(await hasPermission(req.body.requestor, "editTimeEntry"))
+ ) {
+ const requestor = await userProfile.findById(
+ req.body.requestor.requestorId
+ );
requestor.timeEntryEditHistory.push({
- date: moment().tz('America/Los_Angeles').toDate(),
+ date: moment().tz("America/Los_Angeles").toDate(),
initialSeconds,
newSeconds: totalSeconds,
});
@@ -168,18 +243,23 @@ const timeEntrycontroller = function (TimeEntry) {
let totalRecentEdits = 0;
requestor.timeEntryEditHistory.forEach((edit) => {
- if (moment().tz('America/Los_Angeles').diff(edit.date, 'days') <= 365) {
+ if (
+ moment().tz("America/Los_Angeles").diff(edit.date, "days") <= 365
+ ) {
totalRecentEdits += 1;
}
});
if (totalRecentEdits >= 5) {
requestor.infringements.push({
- date: moment().tz('America/Los_Angeles'),
+ date: moment().tz("America/Los_Angeles"),
description: `${totalRecentEdits} time entry edits in the last calendar year`,
});
- emailSender('onecommunityglobal@gmail.com', `${requestor.firstName} ${requestor.lastName} was issued a blue square for for editing a time entry ${totalRecentEdits} times`, `
+ emailSender(
+ "onecommunityglobal@gmail.com",
+ `${requestor.firstName} ${requestor.lastName} was issued a blue square for for editing a time entry ${totalRecentEdits} times`,
+ `
${requestor.firstName} ${requestor.lastName} (${requestor.email}) was issued a blue square for editing their time entries ${totalRecentEdits} times
within the last calendar year.
@@ -187,28 +267,39 @@ const timeEntrycontroller = function (TimeEntry) {
This is the ${totalRecentEdits}th edit within the past 365 days.
- `);
+ `
+ );
const emailInfringement = {
- date: moment().tz('America/Los_Angeles').format('MMMM-DD-YY'),
+ date: moment().tz("America/Los_Angeles").format("MMMM-DD-YY"),
description: `You edited your time entries ${totalRecentEdits} times within the last 365 days, exceeding the limit of 4 times per year you can edit them without penalty.`,
};
- emailSender(requestor.email, 'You\'ve been issued a blue square for editing your time entry', getInfringementEmailBody(requestor.firstName, requestor.lastName, emailInfringement, requestor.infringements.length));
+ emailSender(
+ requestor.email,
+ "You've been issued a blue square for editing your time entry",
+ getInfringementEmailBody(
+ requestor.firstName,
+ requestor.lastName,
+ emailInfringement,
+ requestor.infringements.length
+ )
+ );
}
await requestor.save();
}
-
await timeEntry.save();
- res.status(200).send({ message: 'Successfully updated time entry' });
+ res.status(200).send({ message: "Successfully updated time entry" });
// If the time entry isn't related to a task (i.e. it's a project), then don't check for overtime (Most likely pr team)
if (findTask) {
// checking if logged in hours exceed estimated time after timeentry edit for a task
- const record = await userProfile.findById(timeEntry.personId.toString());
+ const record = await userProfile.findById(
+ timeEntry.personId.toString()
+ );
const currentTask = await task.findById(req.body.projectId);
checkTaskOvertime(timeEntry, record, currentTask);
}
@@ -233,9 +324,9 @@ const timeEntrycontroller = function (TimeEntry) {
timeentry.personId = element.personId;
timeentry.projectId = element.projectId;
timeentry.dateOfWork = element.dateOfWork;
- timeentry.timeSpent = moment('1900-01-01 00:00:00')
- .add(element.totalSeconds, 'seconds')
- .format('HH:mm:ss');
+ timeentry.timeSpent = moment("1900-01-01 00:00:00")
+ .add(element.totalSeconds, "seconds")
+ .format("HH:mm:ss");
timeentry.notes = element.notes;
timeentry.isTangible = element.isTangible;
items.push(timeentry);
@@ -246,21 +337,21 @@ const timeEntrycontroller = function (TimeEntry) {
const postTimeEntry = async function (req, res) {
if (
- !mongoose.Types.ObjectId.isValid(req.body.personId)
- || !mongoose.Types.ObjectId.isValid(req.body.projectId)
- || !req.body.dateOfWork
- || !moment(req.body.dateOfWork).isValid()
- || !req.body.timeSpent
- || !req.body.isTangible
+ !mongoose.Types.ObjectId.isValid(req.body.personId) ||
+ !mongoose.Types.ObjectId.isValid(req.body.projectId) ||
+ !req.body.dateOfWork ||
+ !moment(req.body.dateOfWork).isValid() ||
+ !req.body.timeSpent ||
+ !req.body.isTangible
) {
- res.status(400).send({ error: 'Bad request' });
+ res.status(400).send({ error: "Bad request" });
return;
}
const timeentry = new TimeEntry();
const { dateOfWork, timeSpent } = req.body;
timeentry.personId = req.body.personId;
timeentry.projectId = req.body.projectId;
- timeentry.dateOfWork = moment(dateOfWork).format('YYYY-MM-DD');
+ timeentry.dateOfWork = moment(dateOfWork).format("YYYY-MM-DD");
timeentry.totalSeconds = moment.duration(timeSpent).asSeconds();
timeentry.notes = req.body.notes;
timeentry.isTangible = req.body.isTangible;
@@ -274,12 +365,14 @@ const timeEntrycontroller = function (TimeEntry) {
.status(200)
.send({ message: `Time Entry saved with id as ${results._id}` });
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => res.status(400).send(error));
- // Get the task related to this time entry, if not found, then it's a project sets to null
- const currentTask = await task.findById(req.body.projectId).catch(() => null);
+ // Get the task related to this time entry, if not found, then it's a project sets to null
+ const currentTask = await task
+ .findById(req.body.projectId)
+ .catch(() => null);
- // Add this tangbile time entry to related task's hoursLogged and checks if timeEntry is related to a task
+ // Add this tangbile time entry to related task's hoursLogged and checks if timeEntry is related to a task
if (timeentry.isTangible === true && currentTask) {
try {
currentTask.hoursLogged += timeentry.totalSeconds / 3600;
@@ -292,7 +385,9 @@ const timeEntrycontroller = function (TimeEntry) {
// checking if logged in hours exceed estimated time after timeentry for a task, only if the time entry is related to a task (It might not be, if it's a project)
if (currentTask) {
try {
- const record = await userProfile.findById(timeentry.personId.toString());
+ const record = await userProfile.findById(
+ timeentry.personId.toString()
+ );
checkTaskOvertime(timeentry, record, currentTask);
} catch (error) {
throw new Error(error);
@@ -302,19 +397,23 @@ const timeEntrycontroller = function (TimeEntry) {
const getTimeEntriesForSpecifiedPeriod = function (req, res) {
if (
- !req.params
- || !req.params.fromdate
- || !req.params.todate
- || !req.params.userId
- || !moment(req.params.fromdate).isValid()
- || !moment(req.params.toDate).isValid()
+ !req.params ||
+ !req.params.fromdate ||
+ !req.params.todate ||
+ !req.params.userId ||
+ !moment(req.params.fromdate).isValid() ||
+ !moment(req.params.toDate).isValid()
) {
- res.status(400).send({ error: 'Invalid request' });
+ res.status(400).send({ error: "Invalid request" });
return;
}
- const fromdate = moment(req.params.fromdate).tz('America/Los_Angeles').format('YYYY-MM-DD');
- const todate = moment(req.params.todate).tz('America/Los_Angeles').format('YYYY-MM-DD');
+ const fromdate = moment(req.params.fromdate)
+ .tz("America/Los_Angeles")
+ .format("YYYY-MM-DD");
+ const todate = moment(req.params.todate)
+ .tz("America/Los_Angeles")
+ .format("YYYY-MM-DD");
const { userId } = req.params;
TimeEntry.aggregate([
@@ -326,18 +425,18 @@ const timeEntrycontroller = function (TimeEntry) {
},
{
$lookup: {
- from: 'projects',
- localField: 'projectId',
- foreignField: '_id',
- as: 'project',
+ from: "projects",
+ localField: "projectId",
+ foreignField: "_id",
+ as: "project",
},
},
{
$lookup: {
- from: 'tasks',
- localField: 'projectId',
- foreignField: '_id',
- as: 'task',
+ from: "tasks",
+ localField: "projectId",
+ foreignField: "_id",
+ as: "task",
},
},
{
@@ -349,41 +448,26 @@ const timeEntrycontroller = function (TimeEntry) {
projectId: 1,
lastModifiedDateTime: 1,
projectName: {
- $arrayElemAt: [
- '$project.projectName',
- 0,
- ],
+ $arrayElemAt: ["$project.projectName", 0],
},
taskName: {
- $arrayElemAt: [
- '$task.taskName',
- 0,
- ],
+ $arrayElemAt: ["$task.taskName", 0],
},
category: {
- $arrayElemAt: [
- '$project.category',
- 0,
- ],
+ $arrayElemAt: ["$project.category", 0],
},
classification: {
- $arrayElemAt: [
- '$task.classification',
- 0,
- ],
+ $arrayElemAt: ["$task.classification", 0],
},
dateOfWork: 1,
hours: {
$floor: {
- $divide: ['$totalSeconds', 3600],
+ $divide: ["$totalSeconds", 3600],
},
},
minutes: {
$floor: {
- $divide: [
- { $mod: ['$totalSeconds', 3600] },
- 60,
- ],
+ $divide: [{ $mod: ["$totalSeconds", 3600] }, 60],
},
},
},
@@ -393,9 +477,11 @@ const timeEntrycontroller = function (TimeEntry) {
lastModifiedDateTime: -1,
},
},
- ]).then((results) => {
- res.status(200).send(results);
- }).catch(error => res.status(400).send(error));
+ ])
+ .then((results) => {
+ res.status(200).send(results);
+ })
+ .catch((error) => res.status(400).send(error));
};
const getTimeEntriesForUsersList = function (req, res) {
@@ -406,9 +492,9 @@ const timeEntrycontroller = function (TimeEntry) {
personId: { $in: users },
dateOfWork: { $gte: fromDate, $lte: toDate },
},
- ' -createdDateTime',
+ " -createdDateTime"
)
- .populate('projectId')
+ .populate("projectId")
.sort({ lastModifiedDateTime: -1 })
.then((results) => {
const data = [];
@@ -419,72 +505,73 @@ const timeEntrycontroller = function (TimeEntry) {
record.notes = element.notes;
record.isTangible = element.isTangible;
record.personId = element.personId;
- record.projectId = element.projectId ? element.projectId._id : '';
+ record.projectId = element.projectId ? element.projectId._id : "";
record.projectName = element.projectId
? element.projectId.projectName
- : '';
+ : "";
record.dateOfWork = element.dateOfWork;
[record.hours, record.minutes] = formatSeconds(element.totalSeconds);
data.push(record);
});
res.status(200).send(data);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => res.status(400).send(error));
};
const getTimeEntriesForSpecifiedProject = function (req, res) {
if (
- !req.params
- || !req.params.fromDate
- || !req.params.toDate
- || !req.params.projectId
+ !req.params ||
+ !req.params.fromDate ||
+ !req.params.toDate ||
+ !req.params.projectId
) {
- res.status(400).send({ error: 'Invalid request' });
+ res.status(400).send({ error: "Invalid request" });
return;
}
- const todate = moment(req.params.toDate).format('YYYY-MM-DD');
- const fromDate = moment(req.params.fromDate).format('YYYY-MM-DD');
+ const todate = moment(req.params.toDate).format("YYYY-MM-DD");
+ const fromDate = moment(req.params.fromDate).format("YYYY-MM-DD");
const { projectId } = req.params;
TimeEntry.find(
{
projectId,
dateOfWork: { $gte: fromDate, $lte: todate },
},
- '-createdDateTime -lastModifiedDateTime',
+ "-createdDateTime -lastModifiedDateTime"
)
- .populate('userId')
+ .populate("userId")
.sort({ dateOfWork: -1 })
.then((results) => {
res.status(200).send(results);
})
- .catch(error => res.status(400).send(error));
+ .catch((error) => res.status(400).send(error));
};
const deleteTimeEntry = async function (req, res) {
if (!req.params.timeEntryId) {
- res.status(400).send({ error: 'Bad request' });
+ res.status(400).send({ error: "Bad request" });
return;
}
TimeEntry.findById(req.params.timeEntryId)
.then(async (record) => {
if (!record) {
- res.status(400).send({ message: 'No valid record found' });
+ res.status(400).send({ message: "No valid record found" });
return;
}
if (
- record.personId.toString()
- === req.body.requestor.requestorId.toString()
- || await hasPermission(req.body.requestor, 'deleteTimeEntry')
+ record.personId.toString() ===
+ req.body.requestor.requestorId.toString() ||
+ (await hasPermission(req.body.requestor, "deleteTimeEntry"))
) {
// Revert this tangible timeEntry of related task's hoursLogged
if (record.isTangible === true) {
- task.findById(record.projectId)
+ task
+ .findById(record.projectId)
.then((currentTask) => {
// If the time entry isn't related to a task (i.e. it's a project), then don't revert hours (Most likely pr team)
if (currentTask) {
- currentTask.hoursLogged -= (record.totalSeconds / 3600);
+ currentTask.hoursLogged -= record.totalSeconds / 3600;
currentTask.save();
}
})
@@ -496,13 +583,13 @@ const timeEntrycontroller = function (TimeEntry) {
record
.remove()
.then(() => {
- res.status(200).send({ message: 'Successfully deleted' });
+ res.status(200).send({ message: "Successfully deleted" });
})
.catch((error) => {
res.status(500).send(error);
});
} else {
- res.status(403).send({ error: 'Unauthorized request' });
+ res.status(403).send({ error: "Unauthorized request" });
}
})
.catch((error) => {
@@ -510,7 +597,6 @@ const timeEntrycontroller = function (TimeEntry) {
});
};
-
return {
getAllTimeEnteries,
postTimeEntry,
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 8bf04eb5f..42422a02d 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -492,8 +492,8 @@ const userHelper = function () {
emailBody,
null,
"onecommunityglobal@gmail.com",
- null,
- status.email
+ status.email,
+ null
);
const categories = await dashboardHelper.laborThisWeekByCategory(
From 2df386581e81c2227d51c0d99a49770c43d34a30 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Sat, 16 Dec 2023 19:25:31 -0500
Subject: [PATCH 208/272] added TimeOffFrom and TimeOffTill to dashboardhelper
leaderboard pipeline
---
src/helpers/dashboardhelper.js | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 64c867f71..1eaf9b723 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -259,6 +259,12 @@ const dashboardhelper = function () {
},
],
},
+ timeOffFrom: {
+ $ifNull: ["$persondata.timeOffFrom", null],
+ },
+ timeOffTill: {
+ $ifNull: ["$persondata.timeOffTill", null],
+ },
},
},
{
@@ -277,6 +283,8 @@ const dashboardhelper = function () {
isVisible: 1,
hasSummary: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
timeEntryData: {
$filter: {
input: "$timeEntryData",
@@ -309,6 +317,8 @@ const dashboardhelper = function () {
isVisible: 1,
hasSummary: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
totalSeconds: {
$cond: [
{
@@ -356,6 +366,8 @@ const dashboardhelper = function () {
_id: {
personId: "$personId",
weeklycommittedHours: "$weeklycommittedHours",
+ timeOffFrom: "$timeOffFrom",
+ timeOffTill: "$timeOffTill",
name: "$name",
role: "$role",
isVisible: "$isVisible",
@@ -406,12 +418,8 @@ const dashboardhelper = function () {
},
],
},
- timeOffFrom: {
- $ifNull: ["$persondata.timeOffFrom", null],
- },
- timeOffTill: {
- $ifNull: ["$persondata.timeOffTill", null],
- },
+ timeOffFrom: "$_id.timeOffFrom",
+ timeOffTill: "$_id.timeOffTill",
currentDate: { $toDate: new Date() },
},
},
From 2ecf74d07810c42d71038fd1656ba632984b7dda Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Sat, 16 Dec 2023 23:16:19 -0500
Subject: [PATCH 209/272] added pst time instead of est for current date
---
src/helpers/dashboardhelper.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 1eaf9b723..0e3c71e9b 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -420,7 +420,9 @@ const dashboardhelper = function () {
},
timeOffFrom: "$_id.timeOffFrom",
timeOffTill: "$_id.timeOffTill",
- currentDate: { $toDate: new Date() },
+ currentDate: {
+ $toDate: moment.tz("America/Los_Angeles").startOf("day"),
+ },
},
},
{
From 511062fd75c0cb619eea39b06d9def6e6a7bc6d7 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Sun, 17 Dec 2023 11:55:54 -0500
Subject: [PATCH 210/272] removed current date from leaderboard aggregation
pipeline
---
src/helpers/dashboardhelper.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 0e3c71e9b..5efeae4f7 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -420,9 +420,6 @@ const dashboardhelper = function () {
},
timeOffFrom: "$_id.timeOffFrom",
timeOffTill: "$_id.timeOffTill",
- currentDate: {
- $toDate: moment.tz("America/Los_Angeles").startOf("day"),
- },
},
},
{
From ecc27d33cc008ba26d694d6613ff33a5fac09f48 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Sun, 17 Dec 2023 14:16:00 -0500
Subject: [PATCH 211/272] added timeOffFrom and timeOffTill to taskHelper
---
src/helpers/taskHelper.js | 316 ++++++++++++++++++++------------------
1 file changed, 166 insertions(+), 150 deletions(-)
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index a94aaee94..937702e05 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,17 +1,17 @@
-const moment = require('moment-timezone');
-const userProfile = require('../models/userProfile');
-const myteam = require('../helpers/helperModels/myTeam');
+const moment = require("moment-timezone");
+const userProfile = require("../models/userProfile");
+const myteam = require("../helpers/helperModels/myTeam");
const taskHelper = function () {
const getTasksForTeams = 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 myteam.aggregate([
{
$match: {
@@ -19,23 +19,23 @@ const taskHelper = function () {
},
},
{
- $unwind: '$myteam',
+ $unwind: "$myteam",
},
{
$project: {
_id: 0,
- personId: '$myteam._id',
- name: '$myteam.fullName',
+ personId: "$myteam._id",
+ name: "$myteam.fullName",
role: 1,
},
},
// have personId, name, role
{
$lookup: {
- from: 'userProfiles',
- localField: 'personId',
- foreignField: '_id',
- as: 'persondata',
+ from: "userProfiles",
+ localField: "personId",
+ foreignField: "_id",
+ as: "persondata",
},
},
{
@@ -43,31 +43,37 @@ const taskHelper = function () {
// dashboard tasks user roles hierarchy
$or: [
{
- role: { $in: ['Owner', 'Core Team'] },
+ role: { $in: ["Owner", "Core Team"] },
},
{
$and: [
{
- role: 'Administrator',
+ role: "Administrator",
},
- { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ]
+ { "persondata.0.role": { $nin: ["Owner", "Administrator"] } },
+ ],
},
{
$and: [
{
- role: { $in: ['Manager', 'Mentor'] },
+ role: { $in: ["Manager", "Mentor"] },
},
{
- 'persondata.0.role': {
- $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ "persondata.0.role": {
+ $nin: [
+ "Manager",
+ "Mentor",
+ "Core Team",
+ "Administrator",
+ "Owner",
+ ],
},
},
],
},
- { 'persondata.0._id': userId },
- { 'persondata.0.role': 'Volunteer' },
- { 'persondata.0.isVisible': true },
+ { "persondata.0._id": userId },
+ { "persondata.0.role": "Volunteer" },
+ { "persondata.0.isVisible": true },
],
},
},
@@ -78,22 +84,28 @@ const taskHelper = function () {
weeklycommittedHours: {
$sum: [
{
- $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ $arrayElemAt: ["$persondata.weeklycommittedHours", 0],
},
{
- $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0],
},
],
},
+ timeOffFrom: {
+ $ifNull: ["$persondata.timeOffFrom", null],
+ },
+ timeOffTill: {
+ $ifNull: ["$persondata.timeOffTill", null],
+ },
role: 1,
},
},
{
$lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "personId",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -101,17 +113,19 @@ const taskHelper = function () {
personId: 1,
name: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 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],
},
],
},
@@ -122,7 +136,7 @@ const taskHelper = function () {
},
{
$unwind: {
- path: '$timeEntryData',
+ path: "$timeEntryData",
preserveNullAndEmptyArrays: true,
},
},
@@ -131,21 +145,23 @@ const taskHelper = function () {
personId: 1,
name: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 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,
],
},
@@ -157,9 +173,9 @@ const taskHelper = function () {
tangibletime: {
$cond: [
{
- $eq: ['$isTangible', true],
+ $eq: ["$isTangible", true],
},
- '$totalSeconds',
+ "$totalSeconds",
0,
],
},
@@ -168,40 +184,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',
+ personId: "$_id.personId",
+ name: "$_id.name",
+ weeklycommittedHours: "$_id.weeklycommittedHours",
+ timeOffFrom: "$_id.timeOffFrom",
+ timeOffTill: "$_id.timeOffTill",
totaltime_hrs: {
- $divide: ['$totalSeconds', 3600],
+ $divide: ["$totalSeconds", 3600],
},
totaltangibletime_hrs: {
- $divide: ['$tangibletime', 3600],
+ $divide: ["$tangibletime", 3600],
},
- role: '$_id.role',
+ role: "$_id.role",
},
},
{
$lookup: {
- from: 'tasks',
- localField: 'personId',
- foreignField: 'resources.userID',
- as: 'tasks',
+ from: "tasks",
+ localField: "personId",
+ foreignField: "resources.userID",
+ as: "tasks",
},
},
{
@@ -215,25 +235,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",
],
},
},
@@ -255,55 +275,55 @@ 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',
+ _id: "$personId",
tasks: {
- $push: '$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",
},
},
]);
};
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: {
@@ -312,20 +332,16 @@ 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],
},
],
},
@@ -333,10 +349,10 @@ const taskHelper = function () {
},
{
$lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "personId",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -347,15 +363,15 @@ const taskHelper = function () {
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],
},
],
},
@@ -365,7 +381,7 @@ const taskHelper = function () {
},
{
$unwind: {
- path: '$timeEntryData',
+ path: "$timeEntryData",
preserveNullAndEmptyArrays: true,
},
},
@@ -378,18 +394,18 @@ const taskHelper = function () {
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,
],
},
@@ -400,9 +416,9 @@ const taskHelper = function () {
tangibletime: {
$cond: [
{
- $eq: ['$isTangible', true],
+ $eq: ["$isTangible", true],
},
- '$totalSeconds',
+ "$totalSeconds",
0,
],
},
@@ -411,40 +427,40 @@ const taskHelper = function () {
{
$group: {
_id: {
- personId: '$personId',
- weeklycommittedHours: '$weeklycommittedHours',
- name: '$name',
- role: '$role',
+ personId: "$personId",
+ weeklycommittedHours: "$weeklycommittedHours",
+ 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",
+ 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",
},
},
{
@@ -458,25 +474,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",
],
},
},
@@ -498,40 +514,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",
},
},
]);
@@ -539,7 +555,7 @@ const taskHelper = function () {
const getUserProfileFirstAndLastName = function (userId) {
return userProfile.findById(userId).then((results) => {
if (!results) {
- return ' ';
+ return " ";
}
return `${results.firstName} ${results.lastName}`;
});
From 7de89472272d1c058c4c6f4f730cbe35697be5f4 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Sun, 17 Dec 2023 14:55:58 -0500
Subject: [PATCH 212/272] added timeOffFrom and timeOffTill to reportHelper
---
src/helpers/reporthelper.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js
index 0c2a8104d..2614a37f6 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: {
From 33a0546451f5f90acf74fc91fe3e49b28cb41e57 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 18 Dec 2023 14:32:17 -0500
Subject: [PATCH 213/272] updated dashboardhelper and taskHelper to add
timeOffFrom anf timeOffTill for individual task and leaderboard data
---
src/helpers/dashboardhelper.js | 2 ++
src/helpers/taskHelper.js | 14 ++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 5efeae4f7..b8c0f8293 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -485,6 +485,8 @@ const dashboardhelper = function () {
totalintangibletime_hrs: intangibleSeconds / 3600,
percentagespentintangible:
(intangibleSeconds / tangibleSeconds) * 100,
+ timeOffFrom: user.timeOffFrom,
+ timeOffTill: user.timeOffTill,
},
];
} catch (err) {
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 937702e05..f9353f89b 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -345,6 +345,12 @@ const taskHelper = function () {
},
],
},
+ timeOffFrom: {
+ $ifNull: ["$timeOffFrom", null],
+ },
+ timeOffTill: {
+ $ifNull: ["$timeOffTill", null],
+ },
},
},
{
@@ -360,6 +366,8 @@ const taskHelper = function () {
personId: 1,
name: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
role: 1,
timeEntryData: {
$filter: {
@@ -390,6 +398,8 @@ const taskHelper = function () {
personId: 1,
name: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
role: 1,
totalSeconds: {
$cond: [
@@ -429,6 +439,8 @@ const taskHelper = function () {
_id: {
personId: "$personId",
weeklycommittedHours: "$weeklycommittedHours",
+ timeOffFrom: "$timeOffFrom",
+ timeOffTill: "$timeOffTill",
name: "$name",
role: "$role",
},
@@ -446,6 +458,8 @@ const taskHelper = function () {
personId: "$_id.personId",
name: "$_id.name",
weeklycommittedHours: "$_id.weeklycommittedHours",
+ timeOffFrom: "$_id.timeOffFrom",
+ timeOffTill: "$_id.timeOffTill",
role: "$_id.role",
totaltime_hrs: {
$divide: ["$totalSeconds", 3600],
From 367abce5a2300d6ef666c92d6d43ef0028f4c8c9 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 18 Dec 2023 17:50:04 -0500
Subject: [PATCH 214/272] modified the array representation for timeOffFrom and
TimeOffTill to a value instead of array
---
src/helpers/dashboardhelper.js | 4 ++--
src/helpers/taskHelper.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index b8c0f8293..48f9047da 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -260,10 +260,10 @@ const dashboardhelper = function () {
],
},
timeOffFrom: {
- $ifNull: ["$persondata.timeOffFrom", null],
+ $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null],
},
timeOffTill: {
- $ifNull: ["$persondata.timeOffTill", null],
+ $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null],
},
},
},
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index f9353f89b..b5268734e 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -92,10 +92,10 @@ const taskHelper = function () {
],
},
timeOffFrom: {
- $ifNull: ["$persondata.timeOffFrom", null],
+ $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null],
},
timeOffTill: {
- $ifNull: ["$persondata.timeOffTill", null],
+ $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null],
},
role: 1,
},
From 676ab6dd93e725a65995edd07be28b2ee8a18d54 Mon Sep 17 00:00:00 2001
From: Shiwani99 <78906820+Shiwani99@users.noreply.github.com>
Date: Mon, 18 Dec 2023 18:53:26 -0500
Subject: [PATCH 215/272] Added comments to reasonSchedulingController.js
---
src/controllers/reasonSchedulingController.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 89b312bc2..3c6334051 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -55,12 +55,13 @@ const postReason = async (req, res) => {
});
}
- // new changes
+ // 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(
{
@@ -74,6 +75,7 @@ const postReason = async (req, res) => {
}
);
} else {
+ // else only timeOffTill will be updated
await UserModel.findOneAndUpdate(
{
_id: userId,
@@ -86,6 +88,7 @@ const postReason = async (req, res) => {
);
}
} else {
+ // if both the fields are not present then these fields will be added to mongoDB for that user
await UserModel.findOneAndUpdate(
{
_id: userId,
From 775265b4716a32e39624a1cd5516a57675bbfe40 Mon Sep 17 00:00:00 2001
From: Ruike Qiu <114443664+StrawberryCalpico@users.noreply.github.com>
Date: Tue, 19 Dec 2023 20:55:06 -0800
Subject: [PATCH 216/272] added sanitizer
---
package-lock.json | 127 +++++++++++++++++---------------
package.json | 1 +
src/routes/userProfileRouter.js | 71 +++++++++++++-----
3 files changed, 121 insertions(+), 78 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 0c8f3ee0b..ff66994e8 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": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"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": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"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": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
+ "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
},
"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": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"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": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
},
"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": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"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": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"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": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"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": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"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": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"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": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"event-target-shim": {
"version": "5.0.1",
@@ -4409,6 +4409,22 @@
}
}
},
+ "express-validator": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz",
+ "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==",
+ "requires": {
+ "lodash": "^4.17.21",
+ "validator": "^13.9.0"
+ },
+ "dependencies": {
+ "validator": {
+ "version": "13.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz",
+ "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ=="
+ }
+ }
+ },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -4429,7 +4445,7 @@
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
"fast-text-encoding": {
@@ -4559,7 +4575,7 @@
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs-readdir-recursive": {
"version": "1.1.0",
@@ -4569,7 +4585,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.3.2",
@@ -4952,7 +4968,7 @@
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
},
"indent-string": {
@@ -4964,7 +4980,7 @@
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -5069,7 +5085,7 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-glob": {
"version": "4.0.3",
@@ -5171,13 +5187,13 @@
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
"js-tokens": {
"version": "4.0.0",
@@ -5215,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": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
"json5": {
@@ -5536,7 +5552,7 @@
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"lodash.merge": {
"version": "4.6.2",
@@ -5713,7 +5729,7 @@
"lru_map": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
- "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="
+ "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
},
"make-dir": {
"version": "2.1.0",
@@ -5727,7 +5743,7 @@
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"memory-pager": {
"version": "1.5.0",
@@ -5738,7 +5754,7 @@
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"merge-stream": {
"version": "2.0.0",
@@ -5749,7 +5765,7 @@
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"micromatch": {
"version": "4.0.5",
@@ -5806,11 +5822,6 @@
"moment": ">= 2.9.0"
}
},
- "mongo-round": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/mongo-round/-/mongo-round-1.0.0.tgz",
- "integrity": "sha512-lwvLJv827Uks+3HnTOt1I/Qr78Avke3du1oMaFqFpTwtRKtOposNOKkfpGXQN4ZGpRN3XAS8fEppIJ4TUj0xQw=="
- },
"mongodb": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
@@ -5934,7 +5945,7 @@
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true
},
"negotiator": {
@@ -6074,7 +6085,7 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"object-inspect": {
"version": "1.12.0",
@@ -6793,7 +6804,7 @@
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
@@ -6823,7 +6834,7 @@
"os-shim": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
- "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==",
+ "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=",
"dev": true
},
"p-limit": {
@@ -6868,7 +6879,7 @@
"parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
- "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q=="
+ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY="
},
"parseurl": {
"version": "1.3.3",
@@ -6883,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": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-key": {
"version": "3.1.1",
@@ -6899,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": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"picocolors": {
"version": "1.0.0",
@@ -6946,7 +6957,7 @@
"pre-commit": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz",
- "integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==",
+ "integrity": "sha1-287g7p3nI15X95xW186UZBpp7sY=",
"dev": true,
"requires": {
"cross-spawn": "^5.0.1",
@@ -6957,7 +6968,7 @@
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
- "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"dev": true,
"requires": {
"lru-cache": "^4.0.1",
@@ -6968,7 +6979,7 @@
"which": {
"version": "1.2.14",
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
- "integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==",
+ "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
"dev": true,
"requires": {
"isexe": "^2.0.0"
@@ -7010,7 +7021,7 @@
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"dev": true
},
"pstree.remy": {
@@ -7488,7 +7499,7 @@
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
- "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+ "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
@@ -7497,7 +7508,7 @@
"spawn-sync": {
"version": "1.0.15",
"resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
- "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==",
+ "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=",
"dev": true,
"requires": {
"concat-stream": "^1.4.7",
@@ -7892,7 +7903,7 @@
"strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
"dev": true
},
"strip-final-newline": {
@@ -7923,19 +7934,19 @@
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"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": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"to-regex-range": {
"version": "5.0.1",
@@ -7962,7 +7973,7 @@
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"tsconfig-paths": {
"version": "3.14.2",
@@ -8080,7 +8091,7 @@
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
"unbox-primitive": {
@@ -8127,7 +8138,7 @@
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"uri-js": {
"version": "4.4.1",
@@ -8141,17 +8152,17 @@
"url-template": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
- "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="
+ "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "3.4.0",
@@ -8174,17 +8185,17 @@
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@@ -8302,7 +8313,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "8.8.1",
diff --git a/package.json b/package.json
index 1c6b8a5d4..e7fbd6307 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"cron": "^1.8.2",
"dotenv": "^5.0.1",
"express": "^4.17.1",
+ "express-validator": "^7.0.1",
"googleapis": "^100.0.0",
"jsonwebtoken": "^9.0.0",
"lodash": "^4.17.21",
diff --git a/src/routes/userProfileRouter.js b/src/routes/userProfileRouter.js
index 9032359a8..8d7807514 100644
--- a/src/routes/userProfileRouter.js
+++ b/src/routes/userProfileRouter.js
@@ -1,53 +1,84 @@
-const express = require('express');
-
+const express = require("express");
+import { body } from "express-validator";
const routes = function (userProfile) {
- const controller = require('../controllers/userProfileController')(userProfile);
+ const controller = require("../controllers/userProfileController")(
+ userProfile
+ );
const userProfileRouter = express.Router();
- userProfileRouter.route('/userProfile')
+ userProfileRouter
+ .route("/userProfile")
.get(controller.getUserProfiles)
- .post(controller.postUserProfile);
-
- userProfileRouter.route('/userProfile/:userId')
+ .post(
+ body("firstName").customSanitizer((value) => value.trim()),
+ body("lastName").customSanitizer((value) => value.trim()),
+ controller.postUserProfile
+ );
+
+ userProfileRouter
+ .route("/userProfile/:userId")
.get(controller.getUserById)
- .put(controller.putUserProfile)
+ .put(
+ body("firstName").customSanitizer((value) => value.trim()),
+ body("lastName").customSanitizer((value) => value.trim()),
+ body("personalLinks").customSanitizer((value) =>
+ value.map((link) => {
+ if (link.Name.replace(/\s/g, "") || link.Link.replace(/\s/g, "")) {
+ return {
+ ...link,
+ Name: link.Name.trim(),
+ Link: link.Link.replace(/\s/g, ""),
+ };
+ }
+ throw new Error("Url not valid");
+ })
+ ),
+ controller.putUserProfile
+ )
.delete(controller.deleteUserProfile)
.patch(controller.changeUserStatus);
- userProfileRouter.route('/userProfile/name/:name')
+ userProfileRouter
+ .route("/userProfile/name/:name")
.get(controller.getUserByName);
- userProfileRouter.route('/refreshToken/:userId')
- .get(controller.refreshToken);
+ userProfileRouter.route("/refreshToken/:userId").get(controller.refreshToken);
- userProfileRouter.route('/userProfile/reportees/:userId')
+ userProfileRouter
+ .route("/userProfile/reportees/:userId")
.get(controller.getreportees);
- userProfileRouter.route('/userProfile/teammembers/:userId')
+ userProfileRouter
+ .route("/userProfile/teammembers/:userId")
.get(controller.getTeamMembersofUser);
- userProfileRouter.route('/userProfile/:userId/property')
+ userProfileRouter
+ .route("/userProfile/:userId/property")
.patch(controller.updateOneProperty);
- userProfileRouter.route('/userProfile/:userId/updatePassword')
+ userProfileRouter
+ .route("/userProfile/:userId/updatePassword")
.patch(controller.updatepassword);
- userProfileRouter.route('/userProfile/:userId/resetPassword')
+ userProfileRouter
+ .route("/userProfile/:userId/resetPassword")
.patch(controller.resetPassword);
- userProfileRouter.route('/userProfile/name/:userId')
+ userProfileRouter
+ .route("/userProfile/name/:userId")
.get(controller.getUserName);
- userProfileRouter.route('/userProfile/project/:projectId')
+ userProfileRouter
+ .route("/userProfile/project/:projectId")
.get(controller.getProjectMembers);
- userProfileRouter.route('/userProfile/socials/facebook')
+ userProfileRouter
+ .route("/userProfile/socials/facebook")
.get(controller.getAllUsersWithFacebookLink);
return userProfileRouter;
};
-
module.exports = routes;
From 5c7cc8cdc7c5fcf7563008e31af9e08443b723c3 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Wed, 20 Dec 2023 12:35:10 -0800
Subject: [PATCH 217/272] Refactor of timeentry controller, wbs controller,
task controller and their router
---
src/controllers/taskController.js | 58 ++-
src/controllers/timeEntryController.js | 472 +++++++++++------------
src/controllers/wbsController.js | 23 ++
src/helpers/helperModels/userProjects.js | 1 +
src/models/timeentry.js | 6 +
src/routes/taskRouter.js | 4 +-
src/routes/timeentryRouter.js | 4 +-
src/routes/wbsRouter.js | 3 +
8 files changed, 284 insertions(+), 287 deletions(-)
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index 9bcf071de..5b087db4d 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -1,10 +1,10 @@
const mongoose = require('mongoose');
-const wbs = require('../models/wbs');
+const WBS = require('../models/wbs');
+const UserProfile = require('../models/userProfile');
const timeEntryHelper = require('../helpers/timeEntryHelper')();
const taskHelper = require('../helpers/taskHelper')();
const { hasPermission } = require('../utilities/permissions');
const emailSender = require('../utilities/emailSender');
-const userProfile = require('../models/userProfile');
const taskController = function (Task) {
const getTasks = (req, res) => {
@@ -33,7 +33,7 @@ const taskController = function (Task) {
const getWBSId = (req, res) => {
const { wbsId } = req.params;
- wbs.findById(wbsId)
+ WBS.findById(wbsId)
.then(results => res.status(200).send(results))
.catch(error => res.status(404).send(error));
};
@@ -446,7 +446,7 @@ const taskController = function (Task) {
});
const saveTask = _task.save();
- const saveWbs = wbs.findById(wbsId).then((currentwbs) => {
+ const saveWbs = WBS.findById(wbsId).then((currentwbs) => {
currentwbs.modifiedDatetime = Date.now();
return currentwbs.save();
});
@@ -803,31 +803,28 @@ const taskController = function (Task) {
res.status(200).send('done');
};
- const getTasksByUserList = async (req, res) => {
- const { members } = req.query;
- const membersArr = members.split(',');
+ const getTasksByUserId = async (req, res) => {
+ const { userId } = req.params;
try {
- Task.find(
- { 'resources.userID': { $in: membersArr } },
- '-resources.profilePic',
- ).then((results) => {
- wbs
- .find({
- _id: { $in: results.map(item => item.wbsId) },
- })
- .then((projectIds) => {
- const resultsWithProjectsIds = results.map((item) => {
- item.set(
- 'projectId',
- projectIds?.find(
- projectId => projectId._id.toString() === item.wbsId.toString(),
- )?.projectId,
- { strict: false },
- );
- return item;
- });
- res.status(200).send(resultsWithProjectsIds);
+ Task.find({
+ 'resources.userID': mongoose.Types.ObjectId(userId),
+ }, '-resources.profilePic')
+ .then((results) => {
+ WBS.find({
+ _id: { $in: results.map(item => item.wbsId) },
+ }).then((WBSs) => {
+ const resultsWithProjectsIds = results.map((item) => {
+ item.set(
+ 'projectId',
+ WBSs?.find(
+ wbs => wbs._id.toString() === item.wbsId.toString(),
+ )?.projectId,
+ { strict: false },
+ );
+ return item;
});
+ res.status(200).send(resultsWithProjectsIds);
+ });
});
} catch (error) {
res.status(400).send(error);
@@ -845,6 +842,7 @@ const taskController = function (Task) {
res.status(200).send(singleUserData);
}
} catch (error) {
+ console.log(error);
res.status(400).send(error);
}
};
@@ -872,8 +870,8 @@ const taskController = function (Task) {
const getRecipients = async function (myUserId) {
const recipients = [];
- const user = await userProfile.findById(myUserId);
- const membership = await userProfile.find({ role: { $in: ['Administrator', 'Manager', 'Mentor'] } });
+ const user = await UserProfile.findById(myUserId);
+ const membership = await UserProfile.find({ role: { $in: ['Administrator', 'Manager', 'Mentor'] } });
membership.forEach((member) => {
if (member.teams.some(team => user.teams.includes(team))) {
recipients.push(member.email);
@@ -917,7 +915,7 @@ const taskController = function (Task) {
updateAllParents,
deleteTaskByWBS,
moveTask,
- getTasksByUserList,
+ getTasksByUserId,
getTasksForTeamsByUser,
updateTaskStatus,
sendReviewReq,
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index 9c4d7c5e3..5edd3a095 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -1,17 +1,18 @@
-const moment = require("moment-timezone");
-const mongoose = require("mongoose");
-const { getInfringementEmailBody } = require("../helpers/userHelper")();
-const userProfile = require("../models/userProfile");
-const task = require("../models/task");
-const emailSender = require("../utilities/emailSender");
-const { hasPermission } = require("../utilities/permissions");
+const moment = require('moment-timezone');
+const mongoose = require('mongoose');
+const { getInfringementEmailBody } = require('../helpers/userHelper')();
+const UserProfile = require('../models/userProfile');
+const Task = require('../models/task');
+const WBS = require('../models/wbs');
+const emailSender = require('../utilities/emailSender');
+const { hasPermission } = require('../utilities/permissions');
const formatSeconds = function (seconds) {
const formattedseconds = parseInt(seconds, 10);
const values = `${Math.floor(
- moment.duration(formattedseconds, "seconds").asHours()
- )}:${moment.duration(formattedseconds, "seconds").minutes()}`;
- return values.split(":");
+ moment.duration(formattedseconds, 'seconds').asHours(),
+ )}:${moment.duration(formattedseconds, 'seconds').minutes()}`;
+ return values.split(':');
};
/**
@@ -30,14 +31,14 @@ const getEditedTimeEntryEmailBody = (
email,
originalTime,
finalTime,
- requestor
+ requestor,
) => {
const formattedOriginal = moment
.utc(originalTime * 1000)
- .format("HH[ hours ]mm[ minutes]");
+ .format('HH[ hours ]mm[ minutes]');
const formattedFinal = moment
.utc(finalTime * 1000)
- .format("HH[ hours ]mm[ minutes]");
+ .format('HH[ hours ]mm[ minutes]');
return `
A time entry belonging to ${firstName} ${lastName} (${email}) was modified by ${requestor.firstName} ${requestor.lastName} (${requestor.email}).
The entry's duration was changed from [${formattedOriginal}] to [${formattedFinal}]
@@ -55,10 +56,9 @@ const getEditedTimeEntryEmailBody = (
const notifyEditByEmail = async (personId, original, finalTime, final) => {
try {
const originalTime = original.totalSeconds;
- const record = await userProfile.findById(personId);
- const requestor =
- personId !== final.requestor.requestorId
- ? await userProfile.findById(final.requestor.requestorId)
+ const record = await UserProfile.findById(personId);
+ const requestor = personId !== final.requestor.requestorId
+ ? await UserProfile.findById(final.requestor.requestorId)
: record;
const emailBody = getEditedTimeEntryEmailBody(
record.firstName,
@@ -66,16 +66,16 @@ const notifyEditByEmail = async (personId, original, finalTime, final) => {
record.email,
originalTime,
finalTime,
- requestor
+ requestor,
);
emailSender(
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
`A Time Entry was Edited for ${record.firstName} ${record.lastName}`,
- emailBody
+ emailBody,
);
} catch (error) {
throw new Error(
- `Failed to send email notification about the modification of time entry belonging to user with id ${personId}`
+ `Failed to send email notification about the modification of time entry belonging to user with id ${personId}`,
);
}
};
@@ -84,10 +84,10 @@ const notifyTaskOvertimeEmailBody = async (
personId,
taskName,
estimatedHours,
- hoursLogged
+ hoursLogged,
) => {
try {
- const record = await userProfile.findById(personId);
+ const record = await UserProfile.findById(personId);
const text = `Dear ${record.firstName}${record.lastName},
Oops, it looks like you have logged more hours than estimated for a task
Task Name : ${taskName}
@@ -98,16 +98,16 @@ const notifyTaskOvertimeEmailBody = async (
One Community
`;
emailSender(
record.email,
- "Logged more hours than estimated for a task",
+ 'Logged more hours than estimated for a task',
text,
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
null,
record.email,
- null
+ null,
);
} catch (error) {
console.log(
- `Failed to send email notification about the overtime for a task belonging to user with id ${personId}`
+ `Failed to send email notification about the overtime for a task belonging to user with id ${personId}`,
);
}
};
@@ -120,122 +120,132 @@ const checkTaskOvertime = async (timeentry, record, currentTask) => {
timeentry.personId.toString(),
currentTask.taskName,
currentTask.estimatedHours,
- currentTask.hoursLogged
+ currentTask.hoursLogged,
);
}
} catch (error) {
console.log(
- `Failed to find task whose logged-in hours are more than estimated hours ${record.email}`
+ `Failed to find task whose logged-in hours are more than estimated hours ${record.email}`,
);
}
};
+// update timeentry with wbsId and taskId if projectId in the old timeentry is actually a taskId
+const updateTaskIdInTimeEntry = async (id, timeEntry) => {
+ // if id is a taskId, then timeentry should have the parent wbsId and projectId for that task;
+ // if id is not a taskId, then it is a projectId, timeentry should have both wbsId and taskId to be null;
+ let taskId = null;
+ let wbsId = null;
+ let projectId = id;
+ const task = await Task.findById(id);
+ if (task) {
+ taskId = id;
+ ({ wbsId } = task);
+ const wbs = await WBS.findById(wbsId);
+ ({ projectId } = wbs);
+ }
+ Object.assign(timeEntry, { taskId, wbsId, projectId });
+};
+
const timeEntrycontroller = function (TimeEntry) {
const editTimeEntry = async (req, res) => {
+ const { timeEntryId } = req.params;
+
+ if (!timeEntryId) {
+ const error = 'ObjectId in request param is not in correct format';
+ return res.status(400).send({ error });
+ }
+
+ if (!mongoose.Types.ObjectId.isValid(timeEntryId)) {
+ const error = 'ObjectIds are not correctly formed';
+ return res.status(400).send({ error });
+ }
+
+ const {
+ personId,
+ hours = '00',
+ minutes = '00',
+ notes,
+ isTangible,
+ projectId,
+ wbsId,
+ taskId,
+ dateOfWork,
+ } = req.body;
+
+ const isForAuthUser = personId === req.body.requestor.requestorId;
+ const isSameDayTimeEntry = moment().tz('America/Los_Angeles').format('YYYY-MM-DD') === dateOfWork;
+ const canEdit = (await hasPermission(req.body.requestor, 'editTimeEntry')) || (isForAuthUser && isSameDayTimeEntry);
+
+ if (!canEdit) {
+ const error = 'Unauthorized request';
+ return res.status(403).send({ error });
+ }
+
const session = await mongoose.startSession();
session.startTransaction();
try {
- if (!req.params.timeEntryId) {
- return res
- .status(400)
- .send({
- error: "ObjectId in request param is not in correct format",
- });
- }
-
- if (
- !mongoose.Types.ObjectId.isValid(req.params.timeEntryId) ||
- !mongoose.Types.ObjectId.isValid(req.body.projectId)
- ) {
- return res
- .status(400)
- .send({ error: "ObjectIds are not correctly formed" });
- }
-
// Get initial timeEntry by timeEntryId
- const timeEntry = await TimeEntry.findById(req.params.timeEntryId);
-
+ const timeEntry = await TimeEntry.findById(timeEntryId);
if (!timeEntry) {
- return res
- .status(400)
- .send({
- error: `No valid records found for ${req.params.timeEntryId}`,
- });
+ const error = `No valid records found for ${timeEntryId}`;
+ return res.status(400).send({ error });
}
- if (
- !(
- (await hasPermission(req.body.requestor, "editTimeEntry")) ||
- timeEntry.personId.toString() ===
- req.body.requestor.requestorId.toString()
- )
- ) {
- return res.status(403).send({ error: "Unauthorized request" });
- }
-
- const hours = req.body.hours ? req.body.hours : "00";
- const minutes = req.body.minutes ? req.body.minutes : "00";
+ const totalSeconds = moment.duration({ hours, minutes }).asSeconds();
+ const {
+ totalSeconds: initialTotalSeconds,
+ projectId: initialProjectId,
+ wbsId: initialWBSId,
+ taskId: initialTaskId,
+ isTangible: initialIsTangible,
+ } = timeEntry;
- const totalSeconds = moment.duration(`${hours}:${minutes}`).asSeconds();
-
- if (
- timeEntry.isTangible === true &&
- totalSeconds !== timeEntry.totalSeconds
- ) {
+ if (initialIsTangible && totalSeconds !== initialTotalSeconds) {
notifyEditByEmail(
timeEntry.personId.toString(),
timeEntry,
totalSeconds,
- req.body
+ req.body,
);
}
- const initialSeconds = timeEntry.totalSeconds;
- const initialProjectId = timeEntry.projectId;
- const initialIsTangible = timeEntry.isTangible;
- // Get the task related to this time entry, if not found, then it's a project and will be null
- const findTask = await task.findById(initialProjectId);
-
- timeEntry.notes = req.body.notes;
- timeEntry.totalSeconds = totalSeconds;
- timeEntry.isTangible = req.body.isTangible;
- timeEntry.lastModifiedDateTime = moment().utc().toISOString();
- timeEntry.projectId = mongoose.Types.ObjectId(req.body.projectId);
- timeEntry.dateOfWork = moment(req.body.dateOfWork).format("YYYY-MM-DD");
-
- // Update the hoursLogged field of related tasks based on before and after timeEntries
- // initialIsTangible is a bealoon value, req.body.isTangible is a string
- // initialProjectId may be a task id or project id, so do not throw error.
- try {
- if (findTask) {
- if (initialIsTangible === true) {
- findTask.hoursLogged -= initialSeconds / 3600;
- }
-
- if (req.body.isTangible === true) {
- findTask.hoursLogged += totalSeconds / 3600;
- }
+ updateTaskIdInTimeEntry(projectId, timeEntry);
- await findTask.save();
+ if (timeEntry.taskId) {
+ const findTask = await Task.findById(initialProjectId);
+ if (initialIsTangible) {
+ findTask.hoursLogged -= initialTotalSeconds / 3600;
}
- } catch (error) {
- throw new Error(error);
+ if (req.body.isTangible === true) {
+ findTask.hoursLogged += totalSeconds / 3600;
+ }
+ await findTask.save();
}
+ timeEntry.notes = notes;
+ timeEntry.totalSeconds = totalSeconds;
+ timeEntry.isTangible = isTangible;
+ timeEntry.lastModifiedDateTime = moment().utc().toISOString();
+ timeEntry.projectId = mongoose.Types.ObjectId(projectId);
+ timeEntry.wbsId = wbsId ? mongoose.Types.ObjectId(wbsId) : null;
+ timeEntry.taskId = taskId ? mongoose.Types.ObjectId(taskId) : null;
+ timeEntry.dateOfWork = moment(dateOfWork).format('YYYY-MM-DD');
+
// Update edit history
if (
- initialSeconds !== totalSeconds &&
- timeEntry.isTangible &&
- req.body.requestor.requestorId === timeEntry.personId.toString() &&
- !(await hasPermission(req.body.requestor, "editTimeEntry"))
+ initialTotalSeconds !== totalSeconds
+ && timeEntry.isTangible
+ && req.body.requestor.requestorId === timeEntry.personId.toString()
+ && !(await hasPermission(req.body.requestor, 'editTimeEntry'))
) {
- const requestor = await userProfile.findById(
- req.body.requestor.requestorId
+ const requestor = await UserProfile.findById(
+ req.body.requestor.requestorId,
);
requestor.timeEntryEditHistory.push({
- date: moment().tz("America/Los_Angeles").toDate(),
- initialSeconds,
+ date: moment().tz('America/Los_Angeles').toDate(),
+ initialSeconds: initialTotalSeconds,
newSeconds: totalSeconds,
});
@@ -244,7 +254,7 @@ const timeEntrycontroller = function (TimeEntry) {
requestor.timeEntryEditHistory.forEach((edit) => {
if (
- moment().tz("America/Los_Angeles").diff(edit.date, "days") <= 365
+ moment().tz('America/Los_Angeles').diff(edit.date, 'days') <= 365
) {
totalRecentEdits += 1;
}
@@ -252,12 +262,12 @@ const timeEntrycontroller = function (TimeEntry) {
if (totalRecentEdits >= 5) {
requestor.infringements.push({
- date: moment().tz("America/Los_Angeles"),
+ date: moment().tz('America/Los_Angeles'),
description: `${totalRecentEdits} time entry edits in the last calendar year`,
});
emailSender(
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
`${requestor.firstName} ${requestor.lastName} was issued a blue square for for editing a time entry ${totalRecentEdits} times`,
`
@@ -267,11 +277,11 @@ const timeEntrycontroller = function (TimeEntry) {
This is the ${totalRecentEdits}th edit within the past 365 days.
- `
+ `,
);
const emailInfringement = {
- date: moment().tz("America/Los_Angeles").format("MMMM-DD-YY"),
+ date: moment().tz('America/Los_Angeles').format('MMMM-DD-YY'),
description: `You edited your time entries ${totalRecentEdits} times within the last 365 days, exceeding the limit of 4 times per year you can edit them without penalty.`,
};
@@ -282,8 +292,8 @@ const timeEntrycontroller = function (TimeEntry) {
requestor.firstName,
requestor.lastName,
emailInfringement,
- requestor.infringements.length
- )
+ requestor.infringements.length,
+ ),
);
}
@@ -292,15 +302,15 @@ const timeEntrycontroller = function (TimeEntry) {
await timeEntry.save();
- res.status(200).send({ message: "Successfully updated time entry" });
+ res.status(200).send({ message: 'Successfully updated time entry' });
// If the time entry isn't related to a task (i.e. it's a project), then don't check for overtime (Most likely pr team)
if (findTask) {
// checking if logged in hours exceed estimated time after timeentry edit for a task
- const record = await userProfile.findById(
- timeEntry.personId.toString()
+ const record = await UserProfile.findById(
+ timeEntry.personId.toString(),
);
- const currentTask = await task.findById(req.body.projectId);
+ const currentTask = await Task.findById(req.body.projectId);
checkTaskOvertime(timeEntry, record, currentTask);
}
} catch (err) {
@@ -324,9 +334,9 @@ const timeEntrycontroller = function (TimeEntry) {
timeentry.personId = element.personId;
timeentry.projectId = element.projectId;
timeentry.dateOfWork = element.dateOfWork;
- timeentry.timeSpent = moment("1900-01-01 00:00:00")
- .add(element.totalSeconds, "seconds")
- .format("HH:mm:ss");
+ timeentry.timeSpent = moment('1900-01-01 00:00:00')
+ .add(element.totalSeconds, 'seconds')
+ .format('HH:mm:ss');
timeentry.notes = element.notes;
timeentry.isTangible = element.isTangible;
items.push(timeentry);
@@ -337,21 +347,23 @@ const timeEntrycontroller = function (TimeEntry) {
const postTimeEntry = async function (req, res) {
if (
- !mongoose.Types.ObjectId.isValid(req.body.personId) ||
- !mongoose.Types.ObjectId.isValid(req.body.projectId) ||
- !req.body.dateOfWork ||
- !moment(req.body.dateOfWork).isValid() ||
- !req.body.timeSpent ||
- !req.body.isTangible
+ !mongoose.Types.ObjectId.isValid(req.body.personId)
+ || !mongoose.Types.ObjectId.isValid(req.body.projectId)
+ || !req.body.dateOfWork
+ || !moment(req.body.dateOfWork).isValid()
+ || !req.body.timeSpent
+ || !req.body.isTangible
) {
- res.status(400).send({ error: "Bad request" });
+ res.status(400).send({ error: 'Bad request' });
return;
}
const timeentry = new TimeEntry();
const { dateOfWork, timeSpent } = req.body;
timeentry.personId = req.body.personId;
timeentry.projectId = req.body.projectId;
- timeentry.dateOfWork = moment(dateOfWork).format("YYYY-MM-DD");
+ timeentry.wbsId = req.body.wbsId;
+ timeentry.taskId = req.body.taskId;
+ timeentry.dateOfWork = moment(dateOfWork).format('YYYY-MM-DD');
timeentry.totalSeconds = moment.duration(timeSpent).asSeconds();
timeentry.notes = req.body.notes;
timeentry.isTangible = req.body.isTangible;
@@ -365,10 +377,10 @@ const timeEntrycontroller = function (TimeEntry) {
.status(200)
.send({ message: `Time Entry saved with id as ${results._id}` });
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
// Get the task related to this time entry, if not found, then it's a project sets to null
- const currentTask = await task
+ const currentTask = await Task
.findById(req.body.projectId)
.catch(() => null);
@@ -385,8 +397,8 @@ const timeEntrycontroller = function (TimeEntry) {
// checking if logged in hours exceed estimated time after timeentry for a task, only if the time entry is related to a task (It might not be, if it's a project)
if (currentTask) {
try {
- const record = await userProfile.findById(
- timeentry.personId.toString()
+ const record = await UserProfile.findById(
+ timeentry.personId.toString(),
);
checkTaskOvertime(timeentry, record, currentTask);
} catch (error) {
@@ -395,93 +407,47 @@ const timeEntrycontroller = function (TimeEntry) {
}
};
- const getTimeEntriesForSpecifiedPeriod = function (req, res) {
+ const getTimeEntriesForSpecifiedPeriod = async function (req, res) {
if (
- !req.params ||
- !req.params.fromdate ||
- !req.params.todate ||
- !req.params.userId ||
- !moment(req.params.fromdate).isValid() ||
- !moment(req.params.toDate).isValid()
+ !req.params
+ || !req.params.fromdate
+ || !req.params.todate
+ || !req.params.userId
+ || !moment(req.params.fromdate).isValid()
+ || !moment(req.params.toDate).isValid()
) {
- res.status(400).send({ error: "Invalid request" });
+ res.status(400).send({ error: 'Invalid request' });
return;
}
const fromdate = moment(req.params.fromdate)
- .tz("America/Los_Angeles")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .format('YYYY-MM-DD');
const todate = moment(req.params.todate)
- .tz("America/Los_Angeles")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .format('YYYY-MM-DD');
const { userId } = req.params;
- TimeEntry.aggregate([
- {
- $match: {
- personId: mongoose.Types.ObjectId(userId),
- dateOfWork: { $gte: fromdate, $lte: todate },
- },
- },
- {
- $lookup: {
- from: "projects",
- localField: "projectId",
- foreignField: "_id",
- as: "project",
- },
- },
- {
- $lookup: {
- from: "tasks",
- localField: "projectId",
- foreignField: "_id",
- as: "task",
- },
- },
- {
- $project: {
- _id: 1,
- notes: 1,
- isTangible: 1,
- personId: 1,
- projectId: 1,
- lastModifiedDateTime: 1,
- projectName: {
- $arrayElemAt: ["$project.projectName", 0],
- },
- taskName: {
- $arrayElemAt: ["$task.taskName", 0],
- },
- category: {
- $arrayElemAt: ["$project.category", 0],
- },
- classification: {
- $arrayElemAt: ["$task.classification", 0],
- },
- dateOfWork: 1,
- hours: {
- $floor: {
- $divide: ["$totalSeconds", 3600],
- },
- },
- minutes: {
- $floor: {
- $divide: [{ $mod: ["$totalSeconds", 3600] }, 60],
- },
- },
- },
- },
- {
- $sort: {
- lastModifiedDateTime: -1,
- },
- },
- ])
- .then((results) => {
- res.status(200).send(results);
- })
- .catch((error) => res.status(400).send(error));
+ try {
+ const timeEntries = await TimeEntry.find({
+ personId: userId,
+ dateOfWork: { $gte: fromdate, $lte: todate },
+ }).sort('-lastModifiedDateTime');
+
+ const results = await Promise.all(timeEntries.map(async (timeEntry) => {
+ timeEntry = { ...timeEntry.toObject() };
+ const { projectId } = timeEntry;
+ await updateTaskIdInTimeEntry(projectId, timeEntry);
+ const hours = Math.floor(timeEntry.totalSeconds / 3600);
+ const minutes = Math.floor((timeEntry.totalSeconds % 3600) / 60);
+ Object.assign(timeEntry, { hours, minutes, totalSeconds: undefined });
+ return timeEntry;
+ }));
+
+ res.status(200).send(results);
+ } catch (err) {
+ res.status(400).send({ error: err });
+ }
};
const getTimeEntriesForUsersList = function (req, res) {
@@ -492,9 +458,9 @@ const timeEntrycontroller = function (TimeEntry) {
personId: { $in: users },
dateOfWork: { $gte: fromDate, $lte: toDate },
},
- " -createdDateTime"
+ ' -createdDateTime',
)
- .populate("projectId")
+ .populate('projectId')
.sort({ lastModifiedDateTime: -1 })
.then((results) => {
const data = [];
@@ -505,68 +471,68 @@ const timeEntrycontroller = function (TimeEntry) {
record.notes = element.notes;
record.isTangible = element.isTangible;
record.personId = element.personId;
- record.projectId = element.projectId ? element.projectId._id : "";
+ record.projectId = element.projectId ? element.projectId._id : '';
record.projectName = element.projectId
? element.projectId.projectName
- : "";
+ : '';
record.dateOfWork = element.dateOfWork;
[record.hours, record.minutes] = formatSeconds(element.totalSeconds);
data.push(record);
});
res.status(200).send(data);
})
- .catch((error) => res.status(400).send(error));
+ .catch(error => res.status(400).send(error));
};
- const getTimeEntriesForSpecifiedProject = function (req, res) {
- if (
- !req.params ||
- !req.params.fromDate ||
- !req.params.toDate ||
- !req.params.projectId
- ) {
- res.status(400).send({ error: "Invalid request" });
- return;
- }
- const todate = moment(req.params.toDate).format("YYYY-MM-DD");
- const fromDate = moment(req.params.fromDate).format("YYYY-MM-DD");
- const { projectId } = req.params;
- TimeEntry.find(
- {
- projectId,
- dateOfWork: { $gte: fromDate, $lte: todate },
- },
- "-createdDateTime -lastModifiedDateTime"
- )
- .populate("userId")
- .sort({ dateOfWork: -1 })
- .then((results) => {
- res.status(200).send(results);
- })
- .catch((error) => res.status(400).send(error));
- };
+ // const getTimeEntriesForSpecifiedProject = function (req, res) {
+ // if (
+ // !req.params
+ // || !req.params.fromDate
+ // || !req.params.toDate
+ // || !req.params.projectId
+ // ) {
+ // res.status(400).send({ error: 'Invalid request' });
+ // return;
+ // }
+ // const todate = moment(req.params.toDate).format('YYYY-MM-DD');
+ // const fromDate = moment(req.params.fromDate).format('YYYY-MM-DD');
+ // const { projectId } = req.params;
+ // TimeEntry.find(
+ // {
+ // projectId,
+ // dateOfWork: { $gte: fromDate, $lte: todate },
+ // },
+ // '-createdDateTime -lastModifiedDateTime',
+ // )
+ // .populate('userId')
+ // .sort({ dateOfWork: -1 })
+ // .then((results) => {
+ // res.status(200).send(results);
+ // })
+ // .catch(error => res.status(400).send(error));
+ // };
const deleteTimeEntry = async function (req, res) {
if (!req.params.timeEntryId) {
- res.status(400).send({ error: "Bad request" });
+ res.status(400).send({ error: 'Bad request' });
return;
}
TimeEntry.findById(req.params.timeEntryId)
.then(async (record) => {
if (!record) {
- res.status(400).send({ message: "No valid record found" });
+ res.status(400).send({ message: 'No valid record found' });
return;
}
if (
- record.personId.toString() ===
- req.body.requestor.requestorId.toString() ||
- (await hasPermission(req.body.requestor, "deleteTimeEntry"))
+ record.personId.toString()
+ === req.body.requestor.requestorId.toString()
+ || (await hasPermission(req.body.requestor, 'deleteTimeEntry'))
) {
// Revert this tangible timeEntry of related task's hoursLogged
if (record.isTangible === true) {
- task
+ Task
.findById(record.projectId)
.then((currentTask) => {
// If the time entry isn't related to a task (i.e. it's a project), then don't revert hours (Most likely pr team)
@@ -583,13 +549,13 @@ const timeEntrycontroller = function (TimeEntry) {
record
.remove()
.then(() => {
- res.status(200).send({ message: "Successfully deleted" });
+ res.status(200).send({ message: 'Successfully deleted' });
})
.catch((error) => {
res.status(500).send(error);
});
} else {
- res.status(403).send({ error: "Unauthorized request" });
+ res.status(403).send({ error: 'Unauthorized request' });
}
})
.catch((error) => {
@@ -604,7 +570,7 @@ const timeEntrycontroller = function (TimeEntry) {
getTimeEntriesForUsersList,
editTimeEntry,
deleteTimeEntry,
- getTimeEntriesForSpecifiedProject,
+ // getTimeEntriesForSpecifiedProject,
checkTaskOvertime,
};
};
diff --git a/src/controllers/wbsController.js b/src/controllers/wbsController.js
index fa7f4427f..04070eaf9 100644
--- a/src/controllers/wbsController.js
+++ b/src/controllers/wbsController.js
@@ -1,4 +1,7 @@
+const mongoose = require('mongoose');
const { hasPermission } = require('../utilities/permissions');
+const Project = require('../models/project');
+const Task = require('../models/task');
const wbsController = function (WBS) {
const getAllWBS = function (req, res) {
@@ -68,12 +71,32 @@ const wbsController = function (WBS) {
.catch(error => res.status(404).send(error));
};
+ const getWBSByUserId = async function (req, res) {
+ const { userId } = req.params;
+ try {
+ const result = await Task.aggregate()
+ .match({ 'resources.userID': mongoose.Types.ObjectId(userId) })
+ .project('wbsId -_id')
+ .group({ _id: '$wbsId' })
+ .lookup({
+ from: 'wbs', localField: '_id', foreignField: '_id', as: 'wbs',
+ })
+ .unwind('wbs')
+ .replaceRoot('wbs');
+
+ res.status(200).send(result);
+ } catch (error) {
+ res.status(404).send(error);
+ }
+ };
+
return {
postWBS,
deleteWBS,
getAllWBS,
getWBS,
getWBSById,
+ getWBSByUserId,
};
};
diff --git a/src/helpers/helperModels/userProjects.js b/src/helpers/helperModels/userProjects.js
index 108ec345b..e325a0e39 100644
--- a/src/helpers/helperModels/userProjects.js
+++ b/src/helpers/helperModels/userProjects.js
@@ -5,6 +5,7 @@ const { Schema } = mongoose;
const ProjectSchema = new Schema({
projectId: { type: mongoose.SchemaTypes.ObjectId, ref: 'projects' },
projectName: { type: String },
+ category: { type: String },
});
diff --git a/src/models/timeentry.js b/src/models/timeentry.js
index aeef5fdc7..3876cfcc7 100644
--- a/src/models/timeentry.js
+++ b/src/models/timeentry.js
@@ -6,6 +6,12 @@ const { Schema } = mongoose;
const TimeEntry = new Schema({
personId: { type: Schema.Types.ObjectId, required: [true, 'Resource is a required field'], ref: 'userProfile' },
projectId: { type: Schema.Types.ObjectId, required: [true, 'Project is a required field'], ref: 'project' },
+ wbsId: {
+ type: Schema.Types.ObjectId, required: false, default: null, ref: 'wbs',
+ },
+ taskId: {
+ type: Schema.Types.ObjectId, required: false, default: null, ref: 'task',
+ },
dateOfWork: { type: String, required: true },
totalSeconds: { type: Number },
notes: { type: String },
diff --git a/src/routes/taskRouter.js b/src/routes/taskRouter.js
index 46e467c9d..e04b499eb 100644
--- a/src/routes/taskRouter.js
+++ b/src/routes/taskRouter.js
@@ -43,8 +43,8 @@ const routes = function (task, userProfile) {
wbsRouter.route('/tasks/moveTasks/:wbsId')
.put(controller.moveTask);
- wbsRouter.route('/tasks/userProfile')
- .get(controller.getTasksByUserList);
+ wbsRouter.route('/tasks/user/:userId')
+ .get(controller.getTasksByUserId);
wbsRouter.route('/user/:userId/teams/tasks')
.get(controller.getTasksForTeamsByUser);
diff --git a/src/routes/timeentryRouter.js b/src/routes/timeentryRouter.js
index b319aa595..f5a89e351 100644
--- a/src/routes/timeentryRouter.js
+++ b/src/routes/timeentryRouter.js
@@ -19,8 +19,8 @@ const routes = function (TimeEntry) {
TimeEntryRouter.route('/TimeEntry/users')
.post(controller.getTimeEntriesForUsersList);
- TimeEntryRouter.route('/TimeEntry/projects/:projectId/:fromDate/:toDate')
- .get(controller.getTimeEntriesForSpecifiedProject);
+ // TimeEntryRouter.route('/TimeEntry/projects/:projectId/:fromDate/:toDate')
+ // .get(controller.getTimeEntriesForSpecifiedProject);
return TimeEntryRouter;
};
diff --git a/src/routes/wbsRouter.js b/src/routes/wbsRouter.js
index b78ada5b9..08bfdc7b5 100644
--- a/src/routes/wbsRouter.js
+++ b/src/routes/wbsRouter.js
@@ -14,6 +14,9 @@ const routes = function (wbs) {
wbsRouter.route('/wbsId/:id')
.get(controller.getWBSById);
+ wbsRouter.route('/wbs/user/:userId')
+ .get(controller.getWBSByUserId);
+
wbsRouter.route('/wbs').get(controller.getWBS);
return wbsRouter;
From 1f2d4bec21da660d2f943f14adb098d5c9aa71c5 Mon Sep 17 00:00:00 2001
From: Ruike Qiu <114443664+StrawberryCalpico@users.noreply.github.com>
Date: Wed, 20 Dec 2023 17:16:31 -0800
Subject: [PATCH 218/272] Update for adminLinks
---
src/routes/userProfileRouter.js | 78 +++++++++++++++++++--------------
1 file changed, 44 insertions(+), 34 deletions(-)
diff --git a/src/routes/userProfileRouter.js b/src/routes/userProfileRouter.js
index 8d7807514..ac567ebe8 100644
--- a/src/routes/userProfileRouter.js
+++ b/src/routes/userProfileRouter.js
@@ -1,81 +1,91 @@
-const express = require("express");
-import { body } from "express-validator";
+import { body } from 'express-validator';
+
+const express = require('express');
+
const routes = function (userProfile) {
- const controller = require("../controllers/userProfileController")(
- userProfile
+ const controller = require('../controllers/userProfileController')(
+ userProfile,
);
const userProfileRouter = express.Router();
userProfileRouter
- .route("/userProfile")
+ .route('/userProfile')
.get(controller.getUserProfiles)
.post(
- body("firstName").customSanitizer((value) => value.trim()),
- body("lastName").customSanitizer((value) => value.trim()),
- controller.postUserProfile
+ body('firstName').customSanitizer(value => value.trim()),
+ body('lastName').customSanitizer(value => value.trim()),
+ controller.postUserProfile,
);
userProfileRouter
- .route("/userProfile/:userId")
+ .route('/userProfile/:userId')
.get(controller.getUserById)
.put(
- body("firstName").customSanitizer((value) => value.trim()),
- body("lastName").customSanitizer((value) => value.trim()),
- body("personalLinks").customSanitizer((value) =>
- value.map((link) => {
- if (link.Name.replace(/\s/g, "") || link.Link.replace(/\s/g, "")) {
- return {
- ...link,
- Name: link.Name.trim(),
- Link: link.Link.replace(/\s/g, ""),
- };
- }
- throw new Error("Url not valid");
- })
- ),
- controller.putUserProfile
+ body('firstName').customSanitizer(value => value.trim()),
+ body('lastName').customSanitizer(value => value.trim()),
+ body('personalLinks').customSanitizer(value => value.map((link) => {
+ if (link.Name.replace(/\s/g, '') || link.Link.replace(/\s/g, '')) {
+ return {
+ ...link,
+ Name: link.Name.trim(),
+ Link: link.Link.replace(/\s/g, ''),
+ };
+ }
+ throw new Error('Url not valid');
+ })),
+ body('adminLinks').customSanitizer(value => value.map((link) => {
+ if (link.Name.replace(/\s/g, '') || link.Link.replace(/\s/g, '')) {
+ return {
+ ...link,
+ Name: link.Name.trim(),
+ Link: link.Link.replace(/\s/g, ''),
+ };
+ }
+ throw new Error('Url not valid');
+ })),
+ controller.putUserProfile,
)
.delete(controller.deleteUserProfile)
.patch(controller.changeUserStatus);
userProfileRouter
- .route("/userProfile/name/:name")
+ .route('/userProfile/name/:name')
.get(controller.getUserByName);
- userProfileRouter.route("/refreshToken/:userId").get(controller.refreshToken);
+ userProfileRouter.route('/refreshToken/:userId').get(controller.refreshToken);
userProfileRouter
- .route("/userProfile/reportees/:userId")
+ .route('/userProfile/reportees/:userId')
.get(controller.getreportees);
userProfileRouter
- .route("/userProfile/teammembers/:userId")
+ .route('/userProfile/teammembers/:userId')
.get(controller.getTeamMembersofUser);
userProfileRouter
- .route("/userProfile/:userId/property")
+ .route('/userProfile/:userId/property')
.patch(controller.updateOneProperty);
userProfileRouter
- .route("/userProfile/:userId/updatePassword")
+ .route('/userProfile/:userId/updatePassword')
.patch(controller.updatepassword);
userProfileRouter
- .route("/userProfile/:userId/resetPassword")
+ .route('/userProfile/:userId/resetPassword')
.patch(controller.resetPassword);
userProfileRouter
- .route("/userProfile/name/:userId")
+ .route('/userProfile/name/:userId')
.get(controller.getUserName);
userProfileRouter
- .route("/userProfile/project/:projectId")
+ .route('/userProfile/project/:projectId')
.get(controller.getProjectMembers);
userProfileRouter
- .route("/userProfile/socials/facebook")
+ .route('/userProfile/socials/facebook')
.get(controller.getAllUsersWithFacebookLink);
return userProfileRouter;
From 01e386b2030049c95e73e961aa6af661dba5b2eb Mon Sep 17 00:00:00 2001
From: AriaYu927
Date: Wed, 20 Dec 2023 20:59:34 -0800
Subject: [PATCH 219/272] fix issue that logged time reset on leaderboard
---
src/controllers/timeEntryController.js | 29 +++++++++++++++++---------
src/helpers/dashboardhelper.js | 29 ++++++++++++++++++++------
2 files changed, 42 insertions(+), 16 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index 3516517cc..effe61a3b 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -14,6 +14,13 @@ const formatSeconds = function (seconds) {
return values.split(':');
};
+const isGeneralTimeEntry = function (type) {
+ if (type === undefined || type === 'default') {
+ return true;
+ }
+ return false;
+};
+
/**
*
* @param {*} firstName First name of the owner of the time entry that was modified
@@ -135,6 +142,7 @@ const timeEntrycontroller = function (TimeEntry) {
session.startTransaction();
const type = req.body.entryType;
+ const isGeneralEntry = isGeneralTimeEntry(type);
try {
if (!req.params.timeEntryId) {
@@ -147,7 +155,7 @@ const timeEntrycontroller = function (TimeEntry) {
if (
!mongoose.Types.ObjectId.isValid(req.params.timeEntryId)
- || ((type === 'default' || type === 'project')
+ || ((isGeneralEntry || type === 'project')
&& !mongoose.Types.ObjectId.isValid(req.body.projectId)
)) {
return res
@@ -169,7 +177,7 @@ const timeEntrycontroller = function (TimeEntry) {
if (
!(
(await hasPermission(req.body.requestor, 'editTimeEntry'))
- || (type === 'default'
+ || (isGeneralEntry
&& timeEntry.personId.toString()
=== req.body.requestor.requestorId.toString()
)
@@ -183,7 +191,7 @@ const timeEntrycontroller = function (TimeEntry) {
const totalSeconds = moment.duration(`${hours}:${minutes}`).asSeconds();
if (
- type === 'default'
+ isGeneralEntry
&& timeEntry.isTangible === true
&& totalSeconds !== timeEntry.totalSeconds
) {
@@ -207,13 +215,13 @@ const timeEntrycontroller = function (TimeEntry) {
timeEntry.lastModifiedDateTime = moment().utc().toISOString();
timeEntry.projectId = mongoose.Types.ObjectId(req.body.projectId);
timeEntry.dateOfWork = moment(req.body.dateOfWork).format('YYYY-MM-DD');
- timeEntry.entryType = req.body.entryType;
+ timeEntry.entryType = req.body.entryType === undefined ? 'default' : req.body.entryType;
// Update the hoursLogged field of related tasks based on before and after timeEntries
// initialIsTangible is a bealoon value, req.body.isTangible is a string
// initialProjectId may be a task id or project id, so do not throw error.
try {
- if (type === 'default' && findTask) {
+ if (isGeneralEntry && findTask) {
if (initialIsTangible === true) {
findTask.hoursLogged -= initialSeconds / 3600;
}
@@ -230,7 +238,7 @@ const timeEntrycontroller = function (TimeEntry) {
// Update edit history
if (
- (type === 'default' || type === 'person')
+ (isGeneralEntry || type === 'person')
&& initialSeconds !== totalSeconds
&& timeEntry.isTangible
&& req.body.requestor.requestorId === timeEntry.personId.toString()
@@ -245,7 +253,7 @@ const timeEntrycontroller = function (TimeEntry) {
newSeconds: totalSeconds,
});
- if (type === 'default') {
+ if (isGeneralEntry) {
// Issue infraction if edit history contains more than 5 edits in the last year
let totalRecentEdits = 0;
@@ -303,7 +311,7 @@ const timeEntrycontroller = function (TimeEntry) {
res.status(200).send({ message: 'Successfully updated time entry' });
// If the time entry isn't related to a task (i.e. it's a project), then don't check for overtime (Most likely pr team)
- if (type === 'default' && findTask) {
+ if (isGeneralEntry && findTask) {
// checking if logged in hours exceed estimated time after timeentry edit for a task
const record = await userProfile.findById(
timeEntry.personId.toString(),
@@ -328,7 +336,8 @@ const timeEntrycontroller = function (TimeEntry) {
}
const items = [];
records.forEach((element) => {
- if (element.entryType === 'default' || element.entryType === undefined) {
+ const isGeneralEntry = isGeneralTimeEntry(element.entryType);
+ if (isGeneralEntry) {
const timeentry = new TimeEntry();
timeentry.personId = element.personId;
timeentry.projectId = element.projectId;
@@ -400,7 +409,7 @@ const timeEntrycontroller = function (TimeEntry) {
timeentry.isTangible = req.body.isTangible;
timeentry.createdDateTime = moment().utc().toISOString();
timeentry.lastModifiedDateTime = moment().utc().toISOString();
- timeentry.entryType = req.body.entryType;
+ timeentry.entryType = req.body.entryType === undefined ? 'default' : req.body.entryType;
timeentry
.save()
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index bc56fc5c6..b7ca2f131 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -70,7 +70,11 @@ const dashboardhelper = function () {
$lte: ['$$timeentry.dateOfWork', pdtend],
},
{
- $in: ['$$timeentry.entryType', ['default', null]],
+ $not: [
+ {
+ $in: ['$$timeentry.entryType', ['person', 'team', 'project']],
+ },
+ ],
},
],
},
@@ -155,7 +159,7 @@ const dashboardhelper = function () {
return output;
};
- const getLeaderboard = function (userId) {
+ const getLeaderboard = async function (userId) {
const userid = mongoose.Types.ObjectId(userId);
const pdtstart = moment()
.tz('America/Los_Angeles')
@@ -165,7 +169,7 @@ const dashboardhelper = function () {
.tz('America/Los_Angeles')
.endOf('week')
.format('YYYY-MM-DD');
- return myTeam.aggregate([
+ const output = await myTeam.aggregate([
{
$match: {
_id: userid,
@@ -287,7 +291,11 @@ const dashboardhelper = function () {
$lte: ['$$timeentry.dateOfWork', pdtend],
},
{
- $in: ['$$timeentry.entryType', ['default', null]],
+ $not: [
+ {
+ $in: ['$$timeentry.entryType', ['person', 'team', 'project']],
+ },
+ ],
},
],
},
@@ -416,6 +424,7 @@ const dashboardhelper = function () {
},
},
]);
+ return output;
};
/**
@@ -583,7 +592,11 @@ const dashboardhelper = function () {
$lte: ['$$timeentry.dateOfWork', todate],
},
{
- $in: ['$$timeentry.entryType', ['default', null]],
+ $not: [
+ {
+ $in: ['$$timeentry.entryType', ['person', 'team', 'project']],
+ },
+ ],
},
],
},
@@ -663,7 +676,11 @@ const dashboardhelper = function () {
$lte: ['$$timeentry.dateOfWork', todate],
},
{
- $in: ['$$timeentry.entryType', ['default', null]],
+ $not: [
+ {
+ $in: ['$$timeentry.entryType', ['person', 'team', 'project']],
+ },
+ ],
},
],
},
From 62b4ff352f874123aef9726cd044f3c942f90a52 Mon Sep 17 00:00:00 2001
From: abdelmounaim lallouache
Date: Thu, 21 Dec 2023 02:58:10 -0600
Subject: [PATCH 220/272] fixed error
---
.../profileInitialSetupController.js | 22 ++++++++++---------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index df1f5adfb..12776442e 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -101,6 +101,18 @@ const profileInitialSetupController = function (
) {
const { JWT_SECRET } = config;
+ const setMapLocation = async (locationData) => {
+
+ const location = new MapLocation(locationData);
+
+ try {
+ const response = await location.save()
+ return response
+ } catch (err) {
+ return {type: "Error", message: err.message || 'An error occurred while saving the location'}
+ }
+ }
+
/*
Function to handle token generation and email process:
- Generates a new token and saves it to the database.
@@ -319,17 +331,7 @@ const profileInitialSetupController = function (
}
};
- const setMapLocation = async (locationData) => {
- const location = new MapLocation(locationData);
-
- try {
- const response = await location.save()
- return response
- } catch (err) {
- return {type: "Error", message: err.message || 'An error occurred while saving the location'}
- }
- }
return {
getSetupToken,
From 5b8c91b7120baaca0c4b4ef15e1702749271256f Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 21 Dec 2023 13:52:14 -0800
Subject: [PATCH 221/272] add equip controller, add equip func, update
package-lock
---
package-lock.json | 109 +++++++++---------
.../bmdashboard/bmEquipmentController.js | 17 +++
2 files changed, 69 insertions(+), 57 deletions(-)
create mode 100644 src/controllers/bmdashboard/bmEquipmentController.js
diff --git a/package-lock.json b/package-lock.json
index 0c8f3ee0b..97de1f352 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": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"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": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"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": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
+ "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
},
"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": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"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": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
},
"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": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"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": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"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": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"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": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"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": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"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": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"event-target-shim": {
"version": "5.0.1",
@@ -4429,7 +4429,7 @@
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
"fast-text-encoding": {
@@ -4559,7 +4559,7 @@
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs-readdir-recursive": {
"version": "1.1.0",
@@ -4569,7 +4569,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.3.2",
@@ -4952,7 +4952,7 @@
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
},
"indent-string": {
@@ -4964,7 +4964,7 @@
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -5069,7 +5069,7 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-glob": {
"version": "4.0.3",
@@ -5171,13 +5171,13 @@
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
"js-tokens": {
"version": "4.0.0",
@@ -5215,7 +5215,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": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
"json5": {
@@ -5713,7 +5713,7 @@
"lru_map": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
- "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="
+ "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
},
"make-dir": {
"version": "2.1.0",
@@ -5727,7 +5727,7 @@
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"memory-pager": {
"version": "1.5.0",
@@ -5738,7 +5738,7 @@
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"merge-stream": {
"version": "2.0.0",
@@ -5749,7 +5749,7 @@
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"micromatch": {
"version": "4.0.5",
@@ -5806,11 +5806,6 @@
"moment": ">= 2.9.0"
}
},
- "mongo-round": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/mongo-round/-/mongo-round-1.0.0.tgz",
- "integrity": "sha512-lwvLJv827Uks+3HnTOt1I/Qr78Avke3du1oMaFqFpTwtRKtOposNOKkfpGXQN4ZGpRN3XAS8fEppIJ4TUj0xQw=="
- },
"mongodb": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
@@ -5934,7 +5929,7 @@
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true
},
"negotiator": {
@@ -6074,7 +6069,7 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"object-inspect": {
"version": "1.12.0",
@@ -6793,7 +6788,7 @@
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
@@ -6823,7 +6818,7 @@
"os-shim": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
- "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==",
+ "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=",
"dev": true
},
"p-limit": {
@@ -6868,7 +6863,7 @@
"parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
- "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q=="
+ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY="
},
"parseurl": {
"version": "1.3.3",
@@ -6883,7 +6878,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-key": {
"version": "3.1.1",
@@ -6899,7 +6894,7 @@
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"picocolors": {
"version": "1.0.0",
@@ -6946,7 +6941,7 @@
"pre-commit": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz",
- "integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==",
+ "integrity": "sha1-287g7p3nI15X95xW186UZBpp7sY=",
"dev": true,
"requires": {
"cross-spawn": "^5.0.1",
@@ -6957,7 +6952,7 @@
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
- "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"dev": true,
"requires": {
"lru-cache": "^4.0.1",
@@ -6968,7 +6963,7 @@
"which": {
"version": "1.2.14",
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
- "integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==",
+ "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
"dev": true,
"requires": {
"isexe": "^2.0.0"
@@ -7010,7 +7005,7 @@
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"dev": true
},
"pstree.remy": {
@@ -7488,7 +7483,7 @@
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
- "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+ "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
@@ -7497,7 +7492,7 @@
"spawn-sync": {
"version": "1.0.15",
"resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
- "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==",
+ "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=",
"dev": true,
"requires": {
"concat-stream": "^1.4.7",
@@ -7892,7 +7887,7 @@
"strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
"dev": true
},
"strip-final-newline": {
@@ -7923,19 +7918,19 @@
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"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": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"to-regex-range": {
"version": "5.0.1",
@@ -7962,7 +7957,7 @@
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"tsconfig-paths": {
"version": "3.14.2",
@@ -8080,7 +8075,7 @@
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
"unbox-primitive": {
@@ -8127,7 +8122,7 @@
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"uri-js": {
"version": "4.4.1",
@@ -8141,17 +8136,17 @@
"url-template": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
- "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="
+ "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "3.4.0",
@@ -8174,17 +8169,17 @@
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@@ -8302,7 +8297,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "8.8.1",
diff --git a/src/controllers/bmdashboard/bmEquipmentController.js b/src/controllers/bmdashboard/bmEquipmentController.js
new file mode 100644
index 000000000..57d73359d
--- /dev/null
+++ b/src/controllers/bmdashboard/bmEquipmentController.js
@@ -0,0 +1,17 @@
+// const mongoose = require('mongoose');
+
+function bmEquipmentController() {
+ async function addEquipmentType(req, res) {
+ console.log(req.body);
+ try {
+ res.status(201).send({ message: 'Hello world!' });
+ } catch (error) {
+ res.status(500).send(error);
+ }
+ }
+ return {
+ addEquipmentType,
+ };
+}
+
+module.exports = bmEquipmentController;
From b8996e949b5c6e944c189207ea2894bcb7775adc Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 21 Dec 2023 13:57:26 -0800
Subject: [PATCH 222/272] add equipment router
---
src/routes/bmdashboard/bmEquipmentRouter.js | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 src/routes/bmdashboard/bmEquipmentRouter.js
diff --git a/src/routes/bmdashboard/bmEquipmentRouter.js b/src/routes/bmdashboard/bmEquipmentRouter.js
new file mode 100644
index 000000000..e4cc6972f
--- /dev/null
+++ b/src/routes/bmdashboard/bmEquipmentRouter.js
@@ -0,0 +1,12 @@
+const express = require('express');
+
+const routes = function () {
+ const equipmentRouter = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmEquipmentController')();
+ equipmentRouter.route('/equipment/add')
+ .post(controller.addEquipmentType);
+
+ return equipmentRouter;
+};
+
+module.exports = routes;
From 08c45bb09da422533acc78fc0e84a103f2f1f55f Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 21 Dec 2023 13:59:40 -0800
Subject: [PATCH 223/272] add equipment endpoint to routes
---
src/startup/routes.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/startup/routes.js b/src/startup/routes.js
index ff5d01b2b..80b51fa9a 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -65,6 +65,7 @@ const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, buildingMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(buildingInventoryType);
+const bmEquipmentRouter = require('../routes/bmdashboard/bmEquipmentRouter')();
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -101,4 +102,5 @@ module.exports = function (app) {
app.use('/api/bm', bmMaterialsRouter);
app.use('/api/bm', bmProjectRouter);
app.use('/api/bm', bmInventoryTypeRouter);
+ app.use('/api/bm', bmEquipmentRouter);
};
From d911d14b77f1d70e7f6f941517c77b005198a0fa Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 21 Dec 2023 15:47:24 -0800
Subject: [PATCH 224/272] move api to invtype. delete redundant files.
---
.../bmdashboard/bmEquipmentController.js | 17 -----------------
.../bmdashboard/bmInventoryTypeController.js | 19 +++++++++++++++----
src/routes/bmdashboard/bmEquipmentRouter.js | 12 ------------
.../bmdashboard/bmInventoryTypeRouter.js | 3 +++
src/startup/routes.js | 2 --
5 files changed, 18 insertions(+), 35 deletions(-)
delete mode 100644 src/controllers/bmdashboard/bmEquipmentController.js
delete mode 100644 src/routes/bmdashboard/bmEquipmentRouter.js
diff --git a/src/controllers/bmdashboard/bmEquipmentController.js b/src/controllers/bmdashboard/bmEquipmentController.js
deleted file mode 100644
index 57d73359d..000000000
--- a/src/controllers/bmdashboard/bmEquipmentController.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// const mongoose = require('mongoose');
-
-function bmEquipmentController() {
- async function addEquipmentType(req, res) {
- console.log(req.body);
- try {
- res.status(201).send({ message: 'Hello world!' });
- } catch (error) {
- res.status(500).send(error);
- }
- }
- return {
- addEquipmentType,
- };
-}
-
-module.exports = bmEquipmentController;
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index b9ced243e..48264d81b 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -1,5 +1,5 @@
-const bmInventoryTypeController = function (InvType) {
- const fetchMaterialTypes = async (req, res) => {
+function bmInventoryTypeController(InvType) {
+ async function fetchMaterialTypes(req, res) {
try {
InvType
.find()
@@ -9,11 +9,22 @@ const bmInventoryTypeController = function (InvType) {
} catch (err) {
res.json(err);
}
- };
+ }
+ async function addEquipmentType(req, res) {
+ const { name, desc } = req.body;
+ console.log(name, desc);
+ try {
+ res.status(201).send({ message: 'Hello world!' });
+ } catch (error) {
+ res.status(500).send(error);
+ }
+ }
return {
fetchMaterialTypes,
+ addEquipmentType,
};
-};
+}
+
module.exports = bmInventoryTypeController;
diff --git a/src/routes/bmdashboard/bmEquipmentRouter.js b/src/routes/bmdashboard/bmEquipmentRouter.js
deleted file mode 100644
index e4cc6972f..000000000
--- a/src/routes/bmdashboard/bmEquipmentRouter.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const express = require('express');
-
-const routes = function () {
- const equipmentRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmEquipmentController')();
- equipmentRouter.route('/equipment/add')
- .post(controller.addEquipmentType);
-
- return equipmentRouter;
-};
-
-module.exports = routes;
diff --git a/src/routes/bmdashboard/bmInventoryTypeRouter.js b/src/routes/bmdashboard/bmInventoryTypeRouter.js
index ceae439dc..5155fa52a 100644
--- a/src/routes/bmdashboard/bmInventoryTypeRouter.js
+++ b/src/routes/bmdashboard/bmInventoryTypeRouter.js
@@ -7,6 +7,9 @@ const routes = function (invType) {
inventoryTypeRouter.route('/invtypes/materials')
.get(controller.fetchMaterialTypes);
+ inventoryTypeRouter.route('/invtypes/equipment')
+ .post(controller.addEquipmentType);
+
return inventoryTypeRouter;
};
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 80b51fa9a..ff5d01b2b 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -65,7 +65,6 @@ const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, buildingMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(buildingInventoryType);
-const bmEquipmentRouter = require('../routes/bmdashboard/bmEquipmentRouter')();
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -102,5 +101,4 @@ module.exports = function (app) {
app.use('/api/bm', bmMaterialsRouter);
app.use('/api/bm', bmProjectRouter);
app.use('/api/bm', bmInventoryTypeRouter);
- app.use('/api/bm', bmEquipmentRouter);
};
From a5039719ec206e9fa74407f0856cb5ceef8d37b3 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Thu, 21 Dec 2023 16:01:46 -0800
Subject: [PATCH 225/272] add invtype create method
---
.../bmdashboard/bmInventoryTypeController.js | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index 48264d81b..7914066dc 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -12,10 +12,19 @@ function bmInventoryTypeController(InvType) {
}
async function addEquipmentType(req, res) {
- const { name, desc } = req.body;
- console.log(name, desc);
+ const { name, desc: description } = req.body;
+ const newDoc = {
+ category: 'Equipment',
+ name,
+ description,
+ unit: 'irrelevant',
+ imageUrl: 'test string',
+ };
try {
- res.status(201).send({ message: 'Hello world!' });
+ InvType
+ .create(newDoc)
+ .then(() => res.status(201).send())
+ .catch(error => res.status(500).send(error));
} catch (error) {
res.status(500).send(error);
}
From 80d45f1077e553e494c63a38c16b16edc16331ed Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Thu, 21 Dec 2023 21:56:36 -0600
Subject: [PATCH 226/272] Update modifiedDatetime when team member added or
removed from a team
---
src/controllers/teamController.js | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index 5c8cb5cc2..d625d6a93 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -157,11 +157,17 @@ const teamcontroller = function (Team) {
.exec();
const addUserToTeam = Team.updateOne(
{ _id: team._id },
- { $addToSet: { members: { $each: assignlist.map(userId => ({ userId })) } } },
+ {
+ $addToSet: { members: { $each: assignlist.map(userId => ({ userId })) } },
+ $set: { modifiedDatetime: Date.now() },
+ },
).exec();
const removeUserFromTeam = Team.updateOne(
{ _id: team._id },
- { $pull: { members: { userId: { $in: unassignlist } } } },
+ {
+ $pull: { members: { userId: { $in: unassignlist } } },
+ $set: { modifiedDatetime: Date.now() },
+ },
).exec();
Promise.all([addTeamToUserProfile, removeTeamFromUserProfile, addUserToTeam, removeUserFromTeam])
From 4acbedb9a58e65adc36917c6ac5d2257ee18d206 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 22 Dec 2023 15:04:45 -0800
Subject: [PATCH 227/272] add discriminators to inv type model
---
.../bmdashboard/buildingInventoryType.js | 76 ++++++++++++++++++-
1 file changed, 72 insertions(+), 4 deletions(-)
diff --git a/src/models/bmdashboard/buildingInventoryType.js b/src/models/bmdashboard/buildingInventoryType.js
index 8d2364c64..562dddf91 100644
--- a/src/models/bmdashboard/buildingInventoryType.js
+++ b/src/models/bmdashboard/buildingInventoryType.js
@@ -2,12 +2,80 @@ const mongoose = require('mongoose');
const { Schema } = mongoose;
-const buildingInventoryType = new Schema({
- category: { type: String, enum: ['Consumable', 'Material', 'Tool', 'Equipment'], required: true },
+//---------------------------
+// BASE INVENTORY TYPE SCHEMA
+//---------------------------
+
+// all schemas will inherit these properties
+// all documents will live in buildingInventoryTypes collection
+
+const invTypeBaseSchema = new Schema({
name: { type: String, required: true },
description: { type: String, required: true },
- unit: { type: String, required: true }, // unit of measurement
imageUrl: String,
});
-module.exports = mongoose.model('buildingInventoryType', buildingInventoryType, 'buildingInventoryTypes');
+const invTypeBase = mongoose.model('invTypeBase', invTypeBaseSchema, 'buildingInventoryTypes');
+
+//---------------------------
+// MATERIAL TYPE
+//---------------------------
+
+// ex: sand, stone, brick, lumber
+
+const materialType = invTypeBase.discriminator('material', new mongoose.Schema({
+ category: { type: String, enum: ['Material'] },
+ unit: { type: String, required: true }, // unit of measurement
+}));
+
+//---------------------------
+// CONSUMABLE TYPE
+//---------------------------
+
+// ex: screws, nails, staples
+
+const consumableType = invTypeBase.discriminator('consumable', new mongoose.Schema({
+ category: { type: String, enum: ['Consumable'] },
+ size: { type: String, required: true },
+}));
+
+//---------------------------
+// REUSABLE TYPE
+//---------------------------
+
+// ex: gloves, brushes, hammers, screwdrivers
+
+const reusableType = invTypeBase.discriminator('reusable', new mongoose.Schema({
+ category: { type: String, enum: ['Reusable'] },
+}));
+
+//---------------------------
+// TOOL TYPE
+//---------------------------
+
+// ex: shovels, wheelbarrows, power drills, jackhammers
+
+const toolType = invTypeBase.discriminator('tool', new mongoose.Schema({
+ category: { type: String, enum: ['Tool'] },
+ isPowered: { type: Boolean, required: true },
+ powerSource: { type: String, required: () => this.isPowered }, // required if isPowered = true (syntax?)
+}));
+
+//---------------------------
+// EQUIPMENT TYPE
+//---------------------------
+
+// ex: tractors, excavators
+
+const equipmentType = invTypeBase.discriminator('equipment', new mongoose.Schema({
+ category: { type: String, enum: ['Equipment'] },
+ fuelType: { type: String, required: true },
+}));
+
+module.exports = {
+ materialType,
+ consumableType,
+ reusableType,
+ toolType,
+ equipmentType,
+};
From b4e05848163567749bc88352994f587ff87976cd Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 22 Dec 2023 16:43:28 -0800
Subject: [PATCH 228/272] add inv type models to routing. update controller
func for new model.
---
.../bmdashboard/bmInventoryTypeController.js | 14 ++++++++------
src/models/bmdashboard/buildingInventoryType.js | 2 +-
src/routes/bmdashboard/bmInventoryTypeRouter.js | 4 ++--
src/startup/routes.js | 11 +++++++++--
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index 7914066dc..d52be6d68 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -1,7 +1,7 @@
-function bmInventoryTypeController(InvType) {
+function bmInventoryTypeController(MatType, ConsType, ReusType, ToolType, EquipType) {
async function fetchMaterialTypes(req, res) {
try {
- InvType
+ MatType
.find()
.exec()
.then(result => res.status(200).send(result))
@@ -11,17 +11,19 @@ function bmInventoryTypeController(InvType) {
}
}
+ // TODO: validate request body
+ // TODO: update model
+ // TODO: Mongo error handling
async function addEquipmentType(req, res) {
- const { name, desc: description } = req.body;
+ const { name, desc: description, fuel: fuelType } = req.body;
const newDoc = {
category: 'Equipment',
name,
description,
- unit: 'irrelevant',
- imageUrl: 'test string',
+ fuelType,
};
try {
- InvType
+ EquipType
.create(newDoc)
.then(() => res.status(201).send())
.catch(error => res.status(500).send(error));
diff --git a/src/models/bmdashboard/buildingInventoryType.js b/src/models/bmdashboard/buildingInventoryType.js
index 562dddf91..2972db3ab 100644
--- a/src/models/bmdashboard/buildingInventoryType.js
+++ b/src/models/bmdashboard/buildingInventoryType.js
@@ -69,7 +69,7 @@ const toolType = invTypeBase.discriminator('tool', new mongoose.Schema({
const equipmentType = invTypeBase.discriminator('equipment', new mongoose.Schema({
category: { type: String, enum: ['Equipment'] },
- fuelType: { type: String, required: true },
+ fuelType: { type: String, enum: ['Diesel', 'Biodiesel', 'Gasoline', 'Natural Gas', 'Ethanol'], required: true },
}));
module.exports = {
diff --git a/src/routes/bmdashboard/bmInventoryTypeRouter.js b/src/routes/bmdashboard/bmInventoryTypeRouter.js
index 5155fa52a..13c8c5200 100644
--- a/src/routes/bmdashboard/bmInventoryTypeRouter.js
+++ b/src/routes/bmdashboard/bmInventoryTypeRouter.js
@@ -1,8 +1,8 @@
const express = require('express');
-const routes = function (invType) {
+const routes = function (matType, consType, reusType, toolType, equipType) {
const inventoryTypeRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmInventoryTypeController')(invType);
+ const controller = require('../../controllers/bmdashboard/bmInventoryTypeController')(matType, consType, reusType, toolType, equipType);
inventoryTypeRouter.route('/invtypes/materials')
.get(controller.fetchMaterialTypes);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index ff5d01b2b..8a44ac338 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -22,8 +22,15 @@ const mouseoverText = require('../models/mouseoverText');
const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const mapLocations = require('../models/mapLocation');
const buildingProject = require('../models/bmdashboard/buildingProject');
-const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
+// const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
+const {
+ materialType,
+ consumableType,
+ reusableType,
+ toolType,
+ equipmentType,
+} = require('../models/bmdashboard/buildingInventoryType');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -64,7 +71,7 @@ const mapLocationRouter = require('../routes/mapLocationsRouter')(mapLocations);
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, buildingMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
-const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(buildingInventoryType);
+const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(materialType, consumableType, reusableType, toolType, equipmentType);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
From e812126c668115c7eb625c4ca473ed3c30920c9e Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 22 Dec 2023 17:16:42 -0800
Subject: [PATCH 229/272] add validation error handling to create op
---
.../bmdashboard/bmInventoryTypeController.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index d52be6d68..a2cae4d01 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -11,9 +11,6 @@ function bmInventoryTypeController(MatType, ConsType, ReusType, ToolType, EquipT
}
}
- // TODO: validate request body
- // TODO: update model
- // TODO: Mongo error handling
async function addEquipmentType(req, res) {
const { name, desc: description, fuel: fuelType } = req.body;
const newDoc = {
@@ -26,7 +23,12 @@ function bmInventoryTypeController(MatType, ConsType, ReusType, ToolType, EquipT
EquipType
.create(newDoc)
.then(() => res.status(201).send())
- .catch(error => res.status(500).send(error));
+ .catch((error) => {
+ if (error._message.includes('validation failed')) {
+ res.status(400).send(error);
+ }
+ res.status(500).send(error);
+ });
} catch (error) {
res.status(500).send(error);
}
From 9d3dda9b4792a9e62d6a548503217deab4194ce3 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sat, 23 Dec 2023 03:11:18 -0800
Subject: [PATCH 230/272] finish TimeEntryForm, TimeLog, TimeEntry refactor
---
src/controllers/timeEntryController.js | 256 ++++++++++---------------
src/models/timeentry.js | 2 +-
src/models/userProfile.js | 2 +-
3 files changed, 103 insertions(+), 157 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index bc7763705..6c2269a1d 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -53,9 +53,8 @@ const getEditedTimeEntryEmailBody = (
* @param {*} final Final time entry object
* @returns {Void}
*/
-const notifyEditByEmail = async (personId, original, finalTime, final) => {
+const notifyEditByEmail = async (personId, originalTime, finalTime, final) => {
try {
- const originalTime = original.totalSeconds;
const record = await UserProfile.findById(personId);
const requestor = personId !== final.requestor.requestorId
? await UserProfile.findById(final.requestor.requestorId)
@@ -112,7 +111,7 @@ const notifyTaskOvertimeEmailBody = async (
}
};
-const checkTaskOvertime = async (timeentry, record, currentTask) => {
+const checkTaskOvertime = async (timeentry, currentUser, currentTask) => {
try {
// send email notification if logged in hours exceeds estiamted hours for a task
if (currentTask.hoursLogged > currentTask.estimatedHours) {
@@ -125,7 +124,7 @@ const checkTaskOvertime = async (timeentry, record, currentTask) => {
}
} catch (error) {
console.log(
- `Failed to find task whose logged-in hours are more than estimated hours ${record.email}`,
+ `Failed to find task whose logged-in hours are more than estimated hours for ${currentUser.email}`,
);
}
};
@@ -163,18 +162,18 @@ const timeEntrycontroller = function (TimeEntry) {
const {
personId,
- hours = '00',
- minutes = '00',
- notes,
- isTangible,
- projectId,
- wbsId,
- taskId,
- dateOfWork,
+ hours: newHours = '00',
+ minutes: newMinutes = '00',
+ notes: newNotes,
+ isTangible: newIsTangible,
+ projectId: newProjectId,
+ wbsId: newWbsId,
+ taskId: newTaskId,
+ dateOfWork: newDateOfWork,
} = req.body;
const isForAuthUser = personId === req.body.requestor.requestorId;
- const isSameDayTimeEntry = moment().tz('America/Los_Angeles').format('YYYY-MM-DD') === dateOfWork;
+ const isSameDayTimeEntry = moment().tz('America/Los_Angeles').format('YYYY-MM-DD') === newDateOfWork;
const canEdit = (await hasPermission(req.body.requestor, 'editTimeEntry')) || (isForAuthUser && isSameDayTimeEntry);
if (!canEdit) {
@@ -189,130 +188,98 @@ const timeEntrycontroller = function (TimeEntry) {
try {
if (!req.params.timeEntryId) {
- return res
- .status(400)
- .send({
- error: 'ObjectId in request param is not in correct format',
- });
+ const error = 'ObjectId in request param is not in correct format';
+ return res.status(400).send({ error });
}
- if (
- !mongoose.Types.ObjectId.isValid(req.params.timeEntryId)
+ if (!mongoose.Types.ObjectId.isValid(req.params.timeEntryId)
|| ((type === 'default' || type === 'project')
&& !mongoose.Types.ObjectId.isValid(req.body.projectId)
)) {
- return res
- .status(400)
- .send({ error: 'ObjectIds are not correctly formed' });
+ const error = 'ObjectIds are not correctly formed';
+ return res.status(400).send({ error });
}
// Get initial timeEntry by timeEntryId
const timeEntry = await TimeEntry.findById(timeEntryId);
+
if (!timeEntry) {
const error = `No valid records found for ${timeEntryId}`;
return res.status(400).send({ error });
}
- const totalSeconds = moment.duration({ hours, minutes }).asSeconds();
- const {
- totalSeconds: initialTotalSeconds,
- projectId: initialProjectId,
- wbsId: initialWBSId,
- taskId: initialTaskId,
- isTangible: initialIsTangible,
- } = timeEntry;
+ const newTotalSeconds = moment.duration({ hours: newHours, minutes: newMinutes }).asSeconds();
- if (initialIsTangible && totalSeconds !== initialTotalSeconds) {
+ if (timeEntry.isTangible && newIsTangible && newTotalSeconds !== timeEntry.totalSeconds) {
notifyEditByEmail(
timeEntry.personId.toString(),
- timeEntry,
- totalSeconds,
+ timeEntry.totalSeconds,
+ newTotalSeconds,
req.body,
);
}
- updateTaskIdInTimeEntry(projectId, timeEntry);
-
- if (timeEntry.taskId) {
- const findTask = await Task.findById(initialProjectId);
- if (initialIsTangible) {
- findTask.hoursLogged -= initialTotalSeconds / 3600;
+ if (newTaskId) {
+ const timeEntryTask = await Task.findById(newTaskId);
+ const timeEntryUser = await UserProfile.findById(personId);
+ if (timeEntry.isTangible) {
+ timeEntryTask.hoursLogged -= timeEntry.totalSeconds / 3600;
}
- if (req.body.isTangible === true) {
- findTask.hoursLogged += totalSeconds / 3600;
+ if (newIsTangible) {
+ timeEntryTask.hoursLogged += newTotalSeconds / 3600;
}
- await findTask.save();
+ checkTaskOvertime(timeEntry, timeEntryUser, timeEntryTask);
+ await timeEntryTask.save();
}
- timeEntry.notes = notes;
- timeEntry.totalSeconds = totalSeconds;
- timeEntry.isTangible = isTangible;
- timeEntry.lastModifiedDateTime = moment().utc().toISOString();
- timeEntry.projectId = mongoose.Types.ObjectId(projectId);
- timeEntry.wbsId = wbsId ? mongoose.Types.ObjectId(wbsId) : null;
- timeEntry.taskId = taskId ? mongoose.Types.ObjectId(taskId) : null;
- timeEntry.dateOfWork = moment(dateOfWork).format('YYYY-MM-DD');
-
// Update edit history
- if (
- (type === 'default' || type === 'person')
- && initialSeconds !== totalSeconds
+ if ((type === 'default' || type === 'person')
+ && timeEntry.totalSeconds !== newTotalSeconds
&& timeEntry.isTangible
- && req.body.requestor.requestorId === timeEntry.personId.toString()
+ && isForAuthUser
&& !(await hasPermission(req.body.requestor, 'editTimeEntry'))
) {
const requestor = await UserProfile.findById(
req.body.requestor.requestorId,
);
+
requestor.timeEntryEditHistory.push({
date: moment().tz('America/Los_Angeles').toDate(),
- initialSeconds: initialTotalSeconds,
- newSeconds: totalSeconds,
+ initialSeconds: timeEntry.totalSeconds,
+ newSeconds: newTotalSeconds,
});
if (type === 'default') {
// Issue infraction if edit history contains more than 5 edits in the last year
let totalRecentEdits = 0;
- requestor.timeEntryEditHistory.forEach((edit) => {
- if (
- moment().tz('America/Los_Angeles').diff(edit.date, 'days') <= 365
- ) {
- totalRecentEdits += 1;
- }
- });
requestor.timeEntryEditHistory.forEach((edit) => {
if (
- moment().tz('America/Los_Angeles').diff(edit.date, 'days') <= 365
- ) {
- totalRecentEdits += 1;
- }
+ moment()
+ .tz('America/Los_Angeles')
+ .diff(edit.date, 'days') <= 365
+ ) totalRecentEdits += 1;
});
- if (totalRecentEdits >= 5) {
- requestor.infringements.push({
- date: moment().tz('America/Los_Angeles'),
- description: `${totalRecentEdits} time entry edits in the last calendar year`,
- });
if (totalRecentEdits >= 5) {
requestor.infringements.push({
date: moment().tz('America/Los_Angeles'),
description: `${totalRecentEdits} time entry edits in the last calendar year`,
});
- emailSender(
- "onecommunityglobal@gmail.com",
- `${requestor.firstName} ${requestor.lastName} was issued a blue square for for editing a time entry ${totalRecentEdits} times`,
- `
-
- ${requestor.firstName} ${requestor.lastName} (${requestor.email}) was issued a blue square for editing their time entries ${totalRecentEdits} times
- within the last calendar year.
-
-
- This is the ${totalRecentEdits}th edit within the past 365 days.
-
- `
- );
+ emailSender(
+ 'onecommunityglobal@gmail.com',
+ `${requestor.firstName} ${requestor.lastName} was issued a blue square for for editing a time entry ${totalRecentEdits} times`,
+ `
+
+ ${requestor.firstName} ${requestor.lastName} (${requestor.email}) was issued a blue square for editing their time entries ${totalRecentEdits} times
+ within the last calendar year.
+
+
+ This is the ${totalRecentEdits}th edit within the past 365 days.
+
+ `,
+ );
const emailInfringement = {
date: moment().tz('America/Los_Angeles').format('MMMM-DD-YY'),
@@ -331,31 +298,26 @@ const timeEntrycontroller = function (TimeEntry) {
);
}
}
-
await requestor.save();
}
+ timeEntry.notes = newNotes;
+ timeEntry.totalSeconds = newTotalSeconds;
+ timeEntry.isTangible = newIsTangible;
+ timeEntry.lastModifiedDateTime = moment().utc().toISOString();
+ timeEntry.projectId = mongoose.Types.ObjectId(newProjectId);
+ timeEntry.wbsId = newWbsId ? mongoose.Types.ObjectId(newWbsId) : null;
+ timeEntry.taskId = newTaskId ? mongoose.Types.ObjectId(newTaskId) : null;
+ timeEntry.dateOfWork = moment(newDateOfWork).format('YYYY-MM-DD');
await timeEntry.save();
- res.status(200).send({ message: 'Successfully updated time entry' });
-
- // If the time entry isn't related to a task (i.e. it's a project), then don't check for overtime (Most likely pr team)
- if (type === 'default' && findTask) {
- // checking if logged in hours exceed estimated time after timeentry edit for a task
- const record = await UserProfile.findById(
- timeEntry.personId.toString(),
- );
- const currentTask = await Task.findById(req.body.projectId);
- checkTaskOvertime(timeEntry, record, currentTask);
- }
+ return res.status(200).send({ message: 'Successfully updated time entry' });
} catch (err) {
await session.abortTransaction();
return res.status(400).send({ error: err.toString() });
} finally {
session.endSession();
}
-
- return res.status(200).send();
};
const getAllTimeEnteries = function (req, res) {
@@ -369,6 +331,8 @@ const timeEntrycontroller = function (TimeEntry) {
const timeentry = new TimeEntry();
timeentry.personId = element.personId;
timeentry.projectId = element.projectId;
+ timeentry.wbsId = element.wbsId;
+ timeentry.taskId = element.taskId;
timeentry.dateOfWork = element.dateOfWork;
timeentry.timeSpent = moment('1900-01-01 00:00:00')
.add(element.totalSeconds, 'seconds')
@@ -386,8 +350,7 @@ const timeEntrycontroller = function (TimeEntry) {
const postTimeEntry = async function (req, res) {
const isInvalid = !req.body.dateOfWork
|| !moment(req.body.dateOfWork).isValid()
- || !req.body.timeSpent
- || !req.body.isTangible;
+ || !req.body.timeSpent;
const returnErr = (result) => {
result.status(400).send({ error: 'Bad request' });
@@ -426,57 +389,40 @@ const timeEntrycontroller = function (TimeEntry) {
break;
}
- const timeentry = new TimeEntry();
+ const timeEntry = new TimeEntry();
const { dateOfWork, timeSpent } = req.body;
- timeentry.personId = req.body.personId;
- timeentry.projectId = req.body.projectId;
- timeentry.wbsId = req.body.wbsId;
- timeentry.taskId = req.body.taskId;
- timeentry.teamId = req.body.teamId;
- timeentry.dateOfWork = moment(dateOfWork).format('YYYY-MM-DD');
- timeentry.totalSeconds = moment.duration(timeSpent).asSeconds();
- timeentry.notes = req.body.notes;
- timeentry.isTangible = req.body.isTangible;
- timeentry.createdDateTime = moment().utc().toISOString();
- timeentry.lastModifiedDateTime = moment().utc().toISOString();
- timeentry.entryType = req.body.entryType;
-
- timeentry
- .save()
- .then((results) => {
- res
- .status(200)
- .send({ message: `Time Entry saved with id as ${results._id}` });
- })
- .catch((error) => {
- res.status(400).send(error);
- });
-
- if (timeentry.entryType === 'default') {
- // Get the task related to this time entry, if not found, then it's a project sets to null
- const currentTask = await task
- .findById(req.body.projectId)
- .catch(() => null);
-
- // Add this tangbile time entry to related task's hoursLogged and checks if timeEntry is related to a task
- if (timeentry.isTangible === true && currentTask) {
- try {
- currentTask.hoursLogged += timeentry.totalSeconds / 3600;
- await currentTask.save();
- } catch (error) {
- throw new Error(error);
- }
+ timeEntry.personId = req.body.personId;
+ timeEntry.projectId = req.body.projectId;
+ timeEntry.wbsId = req.body.wbsId;
+ timeEntry.taskId = req.body.taskId;
+ timeEntry.teamId = req.body.teamId;
+ timeEntry.dateOfWork = moment(dateOfWork).format('YYYY-MM-DD');
+ timeEntry.totalSeconds = moment.duration(timeSpent).asSeconds();
+ timeEntry.notes = req.body.notes;
+ timeEntry.isTangible = req.body.isTangible;
+ timeEntry.createdDateTime = moment().utc().toISOString();
+ timeEntry.lastModifiedDateTime = moment().utc().toISOString();
+ timeEntry.entryType = req.body.entryType;
+
+ if (timeEntry.taskId) {
+ const timeEntryTask = await Task.findById(timeEntry.taskId);
+ const timeEntryUser = await UserProfile.findById(timeEntry.personId);
+ if (timeEntry.isTangible) {
+ timeEntryTask.hoursLogged += timeEntry.totalSeconds / 3600;
}
+ checkTaskOvertime(timeEntry, timeEntryUser, timeEntryTask);
+ await timeEntryTask.save();
+ }
- // checking if logged in hours exceed estimated time after timeentry for a task, only if the time entry is related to a task (It might not be, if it's a project)
- if (currentTask) {
- try {
- const record = await UserProfile.findById(timeentry.personId.toString());
- checkTaskOvertime(timeentry, record, currentTask);
- } catch (error) {
- throw new Error(error);
- }
- }
+ try {
+ return timeEntry
+ .save()
+ .then(results => res.status(200).send({
+ message: `Time Entry saved with id as ${results._id}`,
+ }))
+ .catch(error => res.status(400).send(error));
+ } catch (error) {
+ return res.status(500).send(error);
}
};
@@ -510,8 +456,8 @@ const timeEntrycontroller = function (TimeEntry) {
const results = await Promise.all(timeEntries.map(async (timeEntry) => {
timeEntry = { ...timeEntry.toObject() };
- const { projectId } = timeEntry;
- await updateTaskIdInTimeEntry(projectId, timeEntry);
+ const { projectId, taskId } = timeEntry;
+ if (!taskId) await updateTaskIdInTimeEntry(projectId, timeEntry); // if no taskId, then it might be old time entry data that didn't separate projectId with taskId
const hours = Math.floor(timeEntry.totalSeconds / 3600);
const minutes = Math.floor((timeEntry.totalSeconds % 3600) / 60);
Object.assign(timeEntry, { hours, minutes, totalSeconds: undefined });
@@ -520,7 +466,7 @@ const timeEntrycontroller = function (TimeEntry) {
res.status(200).send(results);
} catch (error) {
- res.status(400).send({ error});
+ res.status(400).send({ error });
}
};
@@ -773,7 +719,7 @@ const timeEntrycontroller = function (TimeEntry) {
getTimeEntriesForUsersList,
editTimeEntry,
deleteTimeEntry,
- // getTimeEntriesForSpecifiedProject,
+ getTimeEntriesForSpecifiedProject,
checkTaskOvertime,
getLostTimeEntriesForUserList,
getLostTimeEntriesForProjectList,
diff --git a/src/models/timeentry.js b/src/models/timeentry.js
index 5343e9758..79504cc20 100644
--- a/src/models/timeentry.js
+++ b/src/models/timeentry.js
@@ -8,7 +8,7 @@ const TimeEntry = new Schema({
personId: { type: Schema.Types.ObjectId, ref: 'userProfile' },
projectId: { type: Schema.Types.ObjectId, ref: 'project' },
wbsId: { type: Schema.Types.ObjectId, ref: 'project' },
- taskId: { type: Schema.Types.ObjectId, ref: 'wbs' },
+ taskId: { type: Schema.Types.ObjectId, default: null, ref: 'wbs' },
teamId: { type: Schema.Types.ObjectId, ref: 'task' },
dateOfWork: { type: String, required: true },
totalSeconds: { type: Number },
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index e3f8d4a48..8a8de2e18 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -88,7 +88,7 @@ const userProfileSchema = new Schema({
lng: { type: Number, default: '' },
},
country: { type: String, default: '' },
- city: { type: String, default: '' }
+ city: { type: String, default: '' },
},
oldInfringements: [
From c1328bbe8fd64e668c5524aa58a8c66e77143e01 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sat, 23 Dec 2023 15:16:53 -0800
Subject: [PATCH 231/272] add task handle for project or task change when
editing time entry
---
src/controllers/timeEntryController.js | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index 9aef95ddb..c8ef3d464 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -211,7 +211,6 @@ const timeEntrycontroller = function (TimeEntry) {
// Get initial timeEntry by timeEntryId
const timeEntry = await TimeEntry.findById(timeEntryId);
-
if (!timeEntry) {
const error = `No valid records found for ${timeEntryId}`;
return res.status(400).send({ error });
@@ -228,7 +227,8 @@ const timeEntrycontroller = function (TimeEntry) {
);
}
- if (newTaskId) {
+ // update task data if project/task is changed
+ if (newTaskId === timeEntry.taskId) {
const timeEntryTask = await Task.findById(newTaskId);
const timeEntryUser = await UserProfile.findById(personId);
if (timeEntry.isTangible) {
@@ -239,6 +239,19 @@ const timeEntrycontroller = function (TimeEntry) {
}
checkTaskOvertime(timeEntry, timeEntryUser, timeEntryTask);
await timeEntryTask.save();
+ } else {
+ const oldTimeEntryTask = await Task.findById(timeEntry.taskId);
+ const newTimeEntryTask = await Task.findById(newTaskId);
+ const timeEntryUser = await UserProfile.findById(personId);
+ if (timeEntry.isTangible) {
+ oldTimeEntryTask.hoursLogged -= timeEntry.totalSeconds / 3600;
+ }
+ if (newIsTangible) {
+ newTimeEntryTask.hoursLogged += newTotalSeconds / 3600;
+ }
+ checkTaskOvertime(timeEntry, timeEntryUser, newTimeEntryTask);
+ await oldTimeEntryTask.save();
+ await newTimeEntryTask.save();
}
// Update edit history
From 6953ec3a2e3b1b741d9ca725f38bdf6e7a29bb81 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Fri, 29 Dec 2023 16:32:00 -0800
Subject: [PATCH 232/272] add createdBy field to base inv type model
---
src/controllers/bmdashboard/bmInventoryTypeController.js | 8 +++++++-
src/models/bmdashboard/buildingInventoryType.js | 1 +
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index a2cae4d01..ea2cba730 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -12,12 +12,18 @@ function bmInventoryTypeController(MatType, ConsType, ReusType, ToolType, EquipT
}
async function addEquipmentType(req, res) {
- const { name, desc: description, fuel: fuelType } = req.body;
+ const {
+ name,
+ desc: description,
+ fuel: fuelType,
+ requestor: { requestorId },
+ } = req.body;
const newDoc = {
category: 'Equipment',
name,
description,
fuelType,
+ createdBy: requestorId,
};
try {
EquipType
diff --git a/src/models/bmdashboard/buildingInventoryType.js b/src/models/bmdashboard/buildingInventoryType.js
index 2972db3ab..b1512dca2 100644
--- a/src/models/bmdashboard/buildingInventoryType.js
+++ b/src/models/bmdashboard/buildingInventoryType.js
@@ -13,6 +13,7 @@ const invTypeBaseSchema = new Schema({
name: { type: String, required: true },
description: { type: String, required: true },
imageUrl: String,
+ createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfiles' },
});
const invTypeBase = mongoose.model('invTypeBase', invTypeBaseSchema, 'buildingInventoryTypes');
From 0888853ab93d3d122d670b72e1d59ff2ad22497f Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Fri, 29 Dec 2023 17:16:45 -0800
Subject: [PATCH 233/272] Consumables first commit
---
.../bmdashboard/bmConsumableController.js | 46 +++++++++++++++++++
src/routes/bmdashboard/bmConsumablesRouter.js | 13 ++++++
src/startup/routes.js | 4 ++
3 files changed, 63 insertions(+)
create mode 100644 src/controllers/bmdashboard/bmConsumableController.js
create mode 100644 src/routes/bmdashboard/bmConsumablesRouter.js
diff --git a/src/controllers/bmdashboard/bmConsumableController.js b/src/controllers/bmdashboard/bmConsumableController.js
new file mode 100644
index 000000000..23ea6e5cd
--- /dev/null
+++ b/src/controllers/bmdashboard/bmConsumableController.js
@@ -0,0 +1,46 @@
+const bmConsumableController = function (BuildingConsumable) {
+ const fetchBMConsumables = async (req, res) => {
+ try {
+ BuildingConsumable
+ .find()
+ .populate([
+ {
+ path: 'project',
+ select: '_id name',
+ },
+ {
+ path: 'itemType',
+ select: '_id name unit',
+ },
+ {
+ path: 'updateRecord',
+ populate: {
+ path: 'createdBy',
+ select: '_id firstName lastName',
+ },
+ },
+ {
+ path: 'purchaseRecord',
+ populate: {
+ path: 'requestedBy',
+ select: '_id firstName lastName',
+ },
+ },
+ ])
+ .exec()
+ .then(result => {
+ res.status(200).send(result);
+ })
+ .catch(error => res.status(500).send(error));
+ } catch (err) {
+ res.json(err);
+ }
+ };
+
+ return {
+ fetchBMConsumables,
+ };
+ };
+
+module.exports = bmConsumableController;
+
\ No newline at end of file
diff --git a/src/routes/bmdashboard/bmConsumablesRouter.js b/src/routes/bmdashboard/bmConsumablesRouter.js
new file mode 100644
index 000000000..51126e3a3
--- /dev/null
+++ b/src/routes/bmdashboard/bmConsumablesRouter.js
@@ -0,0 +1,13 @@
+const express = require('express');
+
+const routes = function (BuildingConsumable) {
+ const BuildingConsumableController = express.Router();
+ const controller = require('../../controllers/bmdashboard/bmConsumableController')(BuildingConsumable);
+
+ BuildingConsumableController.route('/consumables')
+ .get(controller.fetchBMConsumables);
+
+ return BuildingConsumableController;
+};
+
+module.exports = routes;
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 620e8c9f8..963531627 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -24,6 +24,7 @@ const mapLocations = require('../models/mapLocation');
const buildingProject = require('../models/bmdashboard/buildingProject');
const buildingInventoryType = require('../models/bmdashboard/buildingInventoryType');
const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
+const buildingInventoryItem = require('../models/bmdashboard/buildingInventoryItem');
const userProfileRouter = require('../routes/userProfileRouter')(userProfile);
const badgeRouter = require('../routes/badgeRouter')(badge);
@@ -65,6 +66,7 @@ const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, buildingMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(buildingInventoryType);
+const bmConsumablesRouter = require('../routes/bmdashboard/bmConsumablesRouter')(buildingInventoryItem.buildingConsumable);
module.exports = function (app) {
app.use('/api', forgotPwdRouter);
@@ -101,4 +103,6 @@ module.exports = function (app) {
app.use('/api/bm', bmMaterialsRouter);
app.use('/api/bm', bmProjectRouter);
app.use('/api/bm', bmInventoryTypeRouter);
+ app.use('/api/bm', bmConsumablesRouter);
+
};
From 25595a567d1f5a909b26609c18d1ddf05692f394 Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Sat, 30 Dec 2023 10:01:56 -0500
Subject: [PATCH 234/272] Fix badge update feature - Add code to update badge
earned date when badge count changes
---
src/helpers/userHelper.js | 655 +++++++++++++++++++-------------------
1 file changed, 331 insertions(+), 324 deletions(-)
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 1033bab2f..97beafc17 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -1,71 +1,68 @@
/* eslint-disable no-continue */
/* eslint-disable no-await-in-loop */
-const mongoose = require("mongoose");
-const moment = require("moment-timezone");
-const _ = require("lodash");
-const userProfile = require("../models/userProfile");
-const timeEntries = require("../models/timeentry");
-const badge = require("../models/badge");
-const myTeam = require("./helperModels/myTeam");
-const dashboardHelper = require("./dashboardhelper")();
-const reportHelper = require("./reporthelper")();
-const emailSender = require("../utilities/emailSender");
-const logger = require("../startup/logger");
-const hasPermission = require("../utilities/permissions");
-const Reason = require("../models/reason");
-const token = require("../models/profileInitialSetupToken");
+const mongoose = require('mongoose');
+const moment = require('moment-timezone');
+const _ = require('lodash');
+const userProfile = require('../models/userProfile');
+const timeEntries = require('../models/timeentry');
+const badge = require('../models/badge');
+const myTeam = require('./helperModels/myTeam');
+const dashboardHelper = require('./dashboardhelper')();
+const reportHelper = require('./reporthelper')();
+const emailSender = require('../utilities/emailSender');
+const logger = require('../startup/logger');
+const Reason = require('../models/reason');
+const token = require('../models/profileInitialSetupToken');
const userHelper = function () {
+ // Update format to "MMM-DD-YY" from "YYYY-MMM-DD" (Confirmed with Jae)
+ const earnedDateBadge = () => {
+ const currentDate = new Date(Date.now());
+ return moment(currentDate).tz('America/Los_Angeles').format('MMM-DD-YY');
+ };
+
+
const getTeamMembers = function (user) {
const userId = mongoose.Types.ObjectId(user._id);
// var teamid = userdetails.teamId;
return myTeam.findById(userId).select({
- "myTeam._id": 0,
- "myTeam.role": 0,
- "myTeam.fullName": 0,
+ 'myTeam._id': 0,
+ 'myTeam.role': 0,
+ 'myTeam.fullName': 0,
_id: 0,
});
};
- // Updated By: Shengwei
- // Updated Date: 12/08/2023
- // Update format to "MMM-DD-YY" from "YYYY-MMM-DD" (Confirmed with Jae)
- const earnedDateBadge = () => {
- const currentDate = new Date(Date.now());
- return moment(currentDate).tz('America/Los_Angeles').format('MMM-DD-YY');
- };
-
const getUserName = async function (userId) {
const userid = mongoose.Types.ObjectId(userId);
- return userProfile.findById(userid, "firstName lastName");
+ return userProfile.findById(userid, 'firstName lastName');
};
const validateProfilePic = function (profilePic) {
- const picParts = profilePic.split("base64");
+ const picParts = profilePic.split('base64');
let result = true;
const errors = [];
if (picParts.length < 2) {
return {
result: false,
- errors: "Invalid image",
+ errors: 'Invalid image',
};
}
// validate size
const imageSize = picParts[1].length;
- const sizeInBytes =
- (4 * Math.ceil(imageSize / 3) * 0.5624896334383812) / 1024;
+ const sizeInBytes = (4 * Math.ceil(imageSize / 3) * 0.5624896334383812) / 1024;
if (sizeInBytes > 50) {
- errors.push("Image size should not exceed 50KB");
+ errors.push('Image size should not exceed 50KB');
result = false;
}
- const imageType = picParts[0].split("/")[1];
- if (imageType !== "jpeg;" && imageType !== "png;") {
- errors.push("Image type shoud be either jpeg or png.");
+ const imageType = picParts[0].split('/')[1];
+ if (imageType !== 'jpeg;' && imageType !== 'png;') {
+ errors.push('Image type shoud be either jpeg or png.');
result = false;
}
@@ -80,13 +77,12 @@ const userHelper = function () {
lastName,
infringement,
totalInfringements,
- timeRemaining
+ timeRemaining,
) {
- let final_paragraph = "";
+ let final_paragraph = '';
if (timeRemaining == undefined) {
- final_paragraph =
- "Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
";
+ final_paragraph = 'Life happens and we understand that. That’s why we allow 5 of them before taking action. This action usually includes removal from our team though, so please let your direct supervisor know what happened and do your best to avoid future blue squares if you are getting close to 5 and wish to avoid termination. Each blue square drops off after a year.
';
} else {
final_paragraph = `Life happens and we understand that. Please make up the missed hours this following week though to avoid getting another blue square. So you know what’s needed, the missing/incomplete hours (${timeRemaining} hours) have been added to your current week and this new weekly total can be seen at the top of your dashboard.
Reminder also that each blue square is removed from your profile 1 year after it was issued.
`;
@@ -117,10 +113,10 @@ const userHelper = function () {
* @return {void}
*/
const emailWeeklySummariesForAllUsers = async (weekIndex = 1) => {
- const currentFormattedDate = moment().tz("America/Los_Angeles").format();
+ const currentFormattedDate = moment().tz('America/Los_Angeles').format();
logger.logInfo(
- `Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`
+ `Job for emailing all users' weekly summaries starting at ${currentFormattedDate}`,
);
const emails = [];
@@ -128,19 +124,15 @@ const userHelper = function () {
try {
const results = await reportHelper.weeklySummaries(weekIndex, weekIndex);
- let emailBody = "Weekly Summaries for all active users:
";
+ let emailBody = 'Weekly Summaries for all active users:
';
- const weeklySummaryNotProvidedMessage =
- 'Weekly Summary: Not provided!
';
+ const weeklySummaryNotProvidedMessage = 'Weekly Summary: Not provided!
';
- const weeklySummaryNotRequiredMessage =
- 'Weekly Summary: Not required for this user
';
+ const weeklySummaryNotRequiredMessage = 'Weekly Summary: Not required for this user
';
- results.sort((a, b) =>
- `${a.firstName} ${a.lastName}`.localeCompare(
- `${b.firstName} ${b.lastname}`
- )
- );
+ results.sort((a, b) => `${a.firstName} ${a.lastName}`.localeCompare(
+ `${b.firstName} ${b.lastname}`,
+ ));
for (let i = 0; i < results.length; i += 1) {
const result = results[i];
@@ -166,19 +158,19 @@ const userHelper = function () {
const mediaUrlLink = mediaUrl
? `${mediaUrl}`
- : "Not provided!";
+ : 'Not provided!';
let weeklySummaryMessage = weeklySummaryNotProvidedMessage;
const colorStyle = (() => {
switch (weeklySummaryOption) {
- case "Team":
+ case 'Team':
return 'style="color: magenta;"';
- case "Not Required":
+ case 'Not Required':
return 'style="color: green"';
- case "Required":
- return "";
+ case 'Required':
+ return '';
default:
- return result.weeklySummaryNotReq ? 'style="color: green"' : "";
+ return result.weeklySummaryNotReq ? 'style="color: green"' : '';
}
})();
// weeklySummaries array should only have one item if any, hence weeklySummaries[0] needs be used to access it.
@@ -189,16 +181,16 @@ const userHelper = function () {
Weekly Summary
(for the week ending on ${moment(dueDate)
- .tz("America/Los_Angeles")
- .format("YYYY-MMM-DD")}):
+ .tz('America/Los_Angeles')
+ .format('YYYY-MMM-DD')}):
${summary}
`;
} else if (
- weeklySummaryOption === "Not Required" ||
- (!weeklySummaryOption && result.weeklySummaryNotReq)
+ weeklySummaryOption === 'Not Required'
+ || (!weeklySummaryOption && result.weeklySummaryNotReq)
) {
weeklySummaryMessage = weeklySummaryNotRequiredMessage;
}
@@ -219,16 +211,16 @@ const userHelper = function () {
weeklySummariesCount === 8
? `Total Valid Weekly Summaries: ${weeklySummariesCount}
`
: `Total Valid Weekly Summaries: ${
- weeklySummariesCount || "No valid submissions yet!"
+ weeklySummariesCount || 'No valid submissions yet!'
}
`
}
${
hoursLogged >= weeklycommittedHours
? `Hours logged: ${hoursLogged.toFixed(
- 2
+ 2,
)} / ${weeklycommittedHours}
`
: `Hours logged: ${hoursLogged.toFixed(
- 2
+ 2,
)} / ${weeklycommittedHours}
`
}
${weeklySummaryMessage}
@@ -238,10 +230,8 @@ const userHelper = function () {
// Necessary because our version of node is outdated
// and doesn't have String.prototype.replaceAll
let emailString = [...new Set(emails)].toString();
- while (emailString.includes(","))
- emailString = emailString.replace(",", "\n");
- while (emailString.includes("\n"))
- emailString = emailString.replace("\n", ", ");
+ while (emailString.includes(',')) { emailString = emailString.replace(',', '\n'); }
+ while (emailString.includes('\n')) { emailString = emailString.replace('\n', ', '); }
emailBody += `\n
@@ -253,12 +243,12 @@ const userHelper = function () {
`;
emailSender(
- "onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com",
- "Weekly Summaries for all active users...",
+ 'onecommunityglobal@gmail.com, sangam.pravah@gmail.com, onecommunityhospitality@gmail.com',
+ 'Weekly Summaries for all active users...',
emailBody,
null,
null,
- emailString
+ emailString,
);
} catch (err) {
logger.logException(err);
@@ -279,8 +269,8 @@ const userHelper = function () {
weeklySummaries: {
$each: [
{
- dueDate: moment().tz("America/Los_Angeles").endOf("week"),
- summary: "",
+ dueDate: moment().tz('America/Los_Angeles').endOf('week'),
+ summary: '',
},
],
$position: 0,
@@ -288,7 +278,7 @@ const userHelper = function () {
},
},
})
- .catch((error) => logger.logException(error));
+ .catch(error => logger.logException(error));
};
/**
@@ -299,34 +289,34 @@ const userHelper = function () {
*/
const assignBlueSquareForTimeNotMet = async () => {
try {
- const currentFormattedDate = moment().tz("America/Los_Angeles").format();
+ const currentFormattedDate = moment().tz('America/Los_Angeles').format();
const currentUTCDate = moment
- .tz("America/Los_Angeles")
- .startOf("day")
+ .tz('America/Los_Angeles')
+ .startOf('day')
.toISOString();
logger.logInfo(
- `Job for assigning blue square for commitment not met starting at ${currentFormattedDate}`
+ `Job for assigning blue square for commitment not met starting at ${currentFormattedDate}`,
);
const pdtStartOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .startOf("week")
- .subtract(1, "week");
+ .tz('America/Los_Angeles')
+ .startOf('week')
+ .subtract(1, 'week');
const pdtEndOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .endOf("week")
- .subtract(1, "week");
+ .tz('America/Los_Angeles')
+ .endOf('week')
+ .subtract(1, 'week');
const users = await userProfile.find(
{ isActive: true },
- "_id weeklycommittedHours weeklySummaries missedHours"
+ '_id weeklycommittedHours weeklySummaries missedHours',
);
- //this part is supposed to be a for, so it'll be slower when sending emails, so the emails will not be
- //targeted as spam
- //There's no need to put Promise.all here
+ // this part is supposed to be a for, so it'll be slower when sending emails, so the emails will not be
+ // targeted as spam
+ // There's no need to put Promise.all here
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -342,8 +332,8 @@ const userHelper = function () {
let hasWeeklySummary = false;
if (
- Array.isArray(user.weeklySummaries) &&
- user.weeklySummaries.length
+ Array.isArray(user.weeklySummaries)
+ && user.weeklySummaries.length
) {
const { summary } = user.weeklySummaries[0];
if (summary) {
@@ -357,13 +347,12 @@ const userHelper = function () {
const results = await dashboardHelper.laborthisweek(
personId,
pdtStartOfLastWeek,
- pdtEndOfLastWeek
+ pdtEndOfLastWeek,
);
const { timeSpent_hrs: timeSpent } = results[0];
- const weeklycommittedHours =
- user.weeklycommittedHours + (user.missedHours ?? 0);
+ const weeklycommittedHours = user.weeklycommittedHours + (user.missedHours ?? 0);
const timeNotMet = timeSpent < weeklycommittedHours;
let description;
@@ -386,23 +375,23 @@ const userHelper = function () {
lastWeekTangibleHrs: timeSpent || 0,
},
},
- { new: true }
+ { new: true },
);
if (
- updateResult?.weeklySummaryOption === "Not Required" ||
- updateResult?.weeklySummaryNotReq
+ updateResult?.weeklySummaryOption === 'Not Required'
+ || updateResult?.weeklySummaryNotReq
) {
hasWeeklySummary = true;
}
- const cutOffDate = moment().subtract(1, "year");
+ const cutOffDate = moment().subtract(1, 'year');
const oldInfringements = [];
for (let k = 0; k < updateResult?.infringements.length; k += 1) {
if (
- updateResult?.infringements &&
- moment(updateResult?.infringements[k].date).diff(cutOffDate) >= 0
+ updateResult?.infringements
+ && moment(updateResult?.infringements[k].date).diff(cutOffDate) >= 0
) {
oldInfringements.push(updateResult.infringements[k]);
} else {
@@ -418,35 +407,33 @@ const userHelper = function () {
oldInfringements: { $each: oldInfringements, $slice: -10 },
},
},
- { new: true }
+ { new: true },
);
}
if (timeNotMet || !hasWeeklySummary) {
if (foundReason) {
description = foundReason.reason;
- } else {
- if (timeNotMet && !hasWeeklySummary) {
+ } else if (timeNotMet && !hasWeeklySummary) {
description = `System auto-assigned infringement for two reasons: not meeting weekly volunteer time commitment as well as not submitting a weekly summary. For the hours portion, you logged ${timeSpent.toFixed(
- 2
+ 2,
)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
- "dddd YYYY-MM-DD"
- )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
+ 'dddd YYYY-MM-DD',
+ )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
} else if (timeNotMet) {
description = `System auto-assigned infringement for not meeting weekly volunteer time commitment. You logged ${timeSpent.toFixed(
- 2
+ 2,
)} hours against committed effort of ${weeklycommittedHours} hours in the week starting ${pdtStartOfLastWeek.format(
- "dddd YYYY-MM-DD"
- )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
+ 'dddd YYYY-MM-DD',
+ )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
} else {
description = `System auto-assigned infringement for not submitting a weekly summary for the week starting ${pdtStartOfLastWeek.format(
- "dddd YYYY-MM-DD"
- )} and ending ${pdtEndOfLastWeek.format("dddd YYYY-MM-DD")}.`;
+ 'dddd YYYY-MM-DD',
+ )} and ending ${pdtEndOfLastWeek.format('dddd YYYY-MM-DD')}.`;
}
- }
const infringement = {
- date: moment().utc().format("YYYY-MM-DD"),
+ date: moment().utc().format('YYYY-MM-DD'),
description,
};
@@ -457,47 +444,47 @@ const userHelper = function () {
infringements: infringement,
},
},
- { new: true }
+ { new: true },
);
- let emailBody = "";
- if (person.role == "Core Team" && timeRemaining > 0) {
+ let emailBody = '';
+ if (person.role === 'Core Team' && timeRemaining > 0) {
emailBody = getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
status.infringements.length,
- timeRemaining
+ timeRemaining,
);
} else {
emailBody = getInfringementEmailBody(
status.firstName,
status.lastName,
infringement,
- status.infringements.length
+ status.infringements.length,
);
}
emailSender(
status.email,
- "New Infringement Assigned",
+ 'New Infringement Assigned',
emailBody,
null,
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
status.email,
- null
+ null,
);
const categories = await dashboardHelper.laborThisWeekByCategory(
personId,
pdtStartOfLastWeek,
- pdtEndOfLastWeek
+ pdtEndOfLastWeek,
);
if (Array.isArray(categories) && categories.length > 0) {
await userProfile.findOneAndUpdate(
{ _id: personId, categoryTangibleHrs: { $exists: false } },
- { $set: { categoryTangibleHrs: [] } }
+ { $set: { categoryTangibleHrs: [] } },
);
} else {
continue;
@@ -507,20 +494,20 @@ const userHelper = function () {
const elem = categories[j];
if (elem._id == null) {
- elem._id = "Other";
+ elem._id = 'Other';
}
const updateResult2 = await userProfile.findOneAndUpdate(
- { _id: personId, "categoryTangibleHrs.category": elem._id },
- { $inc: { "categoryTangibleHrs.$.hrs": elem.timeSpent_hrs } },
- { new: true }
+ { _id: personId, 'categoryTangibleHrs.category': elem._id },
+ { $inc: { 'categoryTangibleHrs.$.hrs': elem.timeSpent_hrs } },
+ { new: true },
);
if (!updateResult2) {
await userProfile.findOneAndUpdate(
{
_id: personId,
- "categoryTangibleHrs.category": { $ne: elem._id },
+ 'categoryTangibleHrs.category': { $ne: elem._id },
},
{
$addToSet: {
@@ -529,7 +516,7 @@ const userHelper = function () {
hrs: elem.timeSpent_hrs,
},
},
- }
+ },
);
}
}
@@ -541,13 +528,13 @@ const userHelper = function () {
// processWeeklySummaries for nonActive users
try {
- const inactiveUsers = await userProfile.find({ isActive: false }, "_id");
+ const inactiveUsers = await userProfile.find({ isActive: false }, '_id');
for (let i = 0; i < inactiveUsers.length; i += 1) {
const user = inactiveUsers[i];
await processWeeklySummariesByUserId(
mongoose.Types.ObjectId(user._id),
- false
+ false,
);
}
} catch (err) {
@@ -557,28 +544,28 @@ const userHelper = function () {
const applyMissedHourForCoreTeam = async () => {
try {
- const currentDate = moment().tz("America/Los_Angeles").format();
+ const currentDate = moment().tz('America/Los_Angeles').format();
logger.logInfo(
- `Job for applying missed hours for Core Team members starting at ${currentDate}`
+ `Job for applying missed hours for Core Team members starting at ${currentDate}`,
);
const startOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .startOf("week")
- .subtract(1, "week")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .startOf('week')
+ .subtract(1, 'week')
+ .format('YYYY-MM-DD');
const endOfLastWeek = moment()
- .tz("America/Los_Angeles")
- .endOf("week")
- .subtract(1, "week")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .endOf('week')
+ .subtract(1, 'week')
+ .format('YYYY-MM-DD');
const missedHours = await userProfile.aggregate([
{
$match: {
- role: "Core Team",
+ role: 'Core Team',
isActive: true,
},
},
@@ -592,16 +579,15 @@ const userHelper = function () {
$match: {
$expr: {
$and: [
- { $eq: ["$isTangible", true] },
- { $gte: ["$dateOfWork", startOfLastWeek] },
- { $lte: ["$dateOfWork", endOfLastWeek] },
- { $in: ["$entryType", 'default', null] },
+ { $eq: ['$isTangible', true] },
+ { $gte: ['$dateOfWork', startOfLastWeek] },
+ { $lte: ['$dateOfWork', endOfLastWeek] },
],
},
},
},
],
- as: "timeEntries",
+ as: 'timeEntries',
},
},
{
@@ -613,8 +599,8 @@ const userHelper = function () {
$subtract: [
{
$sum: [
- { $ifNull: ["$missedHours", 0] },
- "$weeklycommittedHours",
+ { $ifNull: ['$missedHours', 0] },
+ '$weeklycommittedHours',
],
},
{
@@ -622,8 +608,8 @@ const userHelper = function () {
{
$sum: {
$map: {
- input: "$timeEntries",
- in: "$$this.totalSeconds",
+ input: '$timeEntries',
+ in: '$$this.totalSeconds',
},
},
},
@@ -657,13 +643,13 @@ const userHelper = function () {
};
const deleteBlueSquareAfterYear = async () => {
- const currentFormattedDate = moment().tz("America/Los_Angeles").format();
+ const currentFormattedDate = moment().tz('America/Los_Angeles').format();
logger.logInfo(
- `Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`
+ `Job for deleting blue squares older than 1 year starting at ${currentFormattedDate}`,
);
- const cutOffDate = moment().subtract(1, "year").format("YYYY-MM-DD");
+ const cutOffDate = moment().subtract(1, 'year').format('YYYY-MM-DD');
try {
const results = await userProfile.updateMany(
@@ -676,7 +662,7 @@ const userHelper = function () {
},
},
},
- }
+ },
);
logger.logInfo(results);
@@ -686,16 +672,16 @@ const userHelper = function () {
};
const reActivateUser = async () => {
- const currentFormattedDate = moment().tz("America/Los_Angeles").format();
+ const currentFormattedDate = moment().tz('America/Los_Angeles').format();
logger.logInfo(
- `Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`
+ `Job for activating users based on scheduled re-activation date starting at ${currentFormattedDate}`,
);
try {
const users = await userProfile.find(
{ isActive: false, reactivationDate: { $exists: true } },
- "_id isActive reactivationDate"
+ '_id isActive reactivationDate',
);
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -710,21 +696,21 @@ const userHelper = function () {
endDate: user.endDate,
},
},
- { new: true }
+ { new: true },
);
logger.logInfo(
`User with id: ${user._id} was re-acticated at ${moment()
- .tz("America/Los_Angeles")
- .format()}.`
+ .tz('America/Los_Angeles')
+ .format()}.`,
);
const id = user._id;
const person = await userProfile.findById(id);
- const endDate = moment(person.endDate).format("YYYY-MM-DD");
+ const endDate = moment(person.endDate).format('YYYY-MM-DD');
logger.logInfo(
`User with id: ${
user._id
- } was re-acticated at ${moment().format()}.`
+ } was re-acticated at ${moment().format()}.`,
);
const subject = `IMPORTANT:${person.firstName} ${person.lastName} has been RE-activated in the Highest Good Network`;
@@ -740,12 +726,12 @@ const userHelper = function () {
The HGN A.I. (and One Community)
`;
emailSender(
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
subject,
emailBody,
null,
null,
- person.email
+ person.email,
);
}
}
@@ -759,7 +745,7 @@ const userHelper = function () {
current,
firstName,
lastName,
- emailAddress
+ emailAddress,
) {
if (!current) return;
const newOriginal = original.toObject();
@@ -770,58 +756,58 @@ const userHelper = function () {
newInfringements = _.differenceWith(
newCurrent,
newOriginal,
- (arrVal, othVal) => arrVal._id.equals(othVal._id)
+ (arrVal, othVal) => arrVal._id.equals(othVal._id),
);
newInfringements.forEach((element) => {
emailSender(
emailAddress,
- "New Infringement Assigned",
+ 'New Infringement Assigned',
getInfringementEmailBody(
firstName,
lastName,
element,
- totalInfringements
+ totalInfringements,
),
null,
- "onecommunityglobal@gmail.com",
- emailAddress
+ 'onecommunityglobal@gmail.com',
+ emailAddress,
);
});
};
const replaceBadge = async function (personId, oldBadgeId, newBadgeId) {
userProfile.updateOne(
- { _id: personId, "badgeCollection.badge": oldBadgeId },
+ { _id: personId, 'badgeCollection.badge': oldBadgeId },
{
$set: {
- "badgeCollection.$.badge": newBadgeId,
- "badgeCollection.$.lastModified": Date.now().toString(),
- "badgeCollection.$.count": 1,
+ 'badgeCollection.$.badge': newBadgeId,
+ 'badgeCollection.$.lastModified': Date.now().toString(),
+ 'badgeCollection.$.count': 1,
+ 'badgeCollection.$.earnedDate': [earnedDateBadge()],
},
},
(err) => {
if (err) {
throw new Error(err);
}
- }
+ },
);
};
const increaseBadgeCount = async function (personId, badgeId) {
- console.log("Increase Badge Count", personId, badgeId);
userProfile.updateOne(
- { _id: personId, "badgeCollection.badge": badgeId },
+ { _id: personId, 'badgeCollection.badge': badgeId },
{
- $inc: { "badgeCollection.$.count": 1 },
- $set: { "badgeCollection.$.lastModified": Date.now().toString() },
- $push: { "badgeCollection.$.earnedDate": earnedDateBadge() },
+ $inc: { 'badgeCollection.$.count': 1 },
+ $set: { 'badgeCollection.$.lastModified': Date.now().toString() },
+ $push: { 'badgeCollection.$.earnedDate': earnedDateBadge() },
},
(err) => {
if (err) {
console.log(err);
}
- }
+ },
);
};
@@ -829,9 +815,8 @@ const userHelper = function () {
personId,
badgeId,
count = 1,
- featured = false
+ featured = false,
) {
- console.log("Adding Badge");
userProfile.findByIdAndUpdate(
personId,
{
@@ -849,7 +834,7 @@ const userHelper = function () {
if (err) {
throw new Error(err);
}
- }
+ },
);
};
@@ -865,27 +850,49 @@ const userHelper = function () {
if (err) {
throw new Error(err);
}
- }
+ },
);
};
- const changeBadgeCount = async function (personId, badgeId, count) {
+const changeBadgeCount = async function (personId, badgeId, count) {
if (count === 0) {
removeDupBadge(personId, badgeId);
} else if (count) {
+ // Process exisiting earned date to match the new count
+ const userInfo = await userProfile.findById(personId);
+ let newEarnedDate = [];
+ const recordToUpdate = userInfo.badgeCollection.find(item => item.badge._id.toString() === badgeId.toString());
+ if (!recordToUpdate) {
+ throw new Error('Badge not found');
+ }
+ const copyOfEarnedDate = recordToUpdate.earnedDate;
+ if (copyOfEarnedDate.length < count) {
+ // if the EarnedDate count is less than the new count, add a earned date to the end of the collection
+ while (copyOfEarnedDate.length < count) {
+ copyOfEarnedDate.push(earnedDateBadge());
+ }
+ } else {
+ // if the EarnedDate count is greater than the new count, remove the oldest earned date of the collection until it matches the new count - 1
+ while (copyOfEarnedDate.length >= count) {
+ copyOfEarnedDate.shift();
+ }
+ copyOfEarnedDate.push(earnedDateBadge());
+ }
+ newEarnedDate = [...copyOfEarnedDate];
userProfile.updateOne(
- { _id: personId, "badgeCollection.badge": badgeId },
+ { _id: personId, 'badgeCollection.badge': badgeId },
{
$set: {
- "badgeCollection.$.count": count,
- "badgeCollection.$.lastModified": Date.now().toString(),
+ 'badgeCollection.$.count': count,
+ 'badgeCollection.$.lastModified': Date.now().toString(),
+ 'badgeCollection.$.earnedDate': newEarnedDate,
},
},
(err) => {
if (err) {
throw new Error(err);
}
- }
+ },
);
}
};
@@ -897,7 +904,7 @@ const userHelper = function () {
user,
badgeCollection,
hrs,
- weeks
+ weeks,
) {
// Check each Streak Greater than One to check if it works
if (weeks < 3) {
@@ -908,7 +915,7 @@ const userHelper = function () {
.aggregate([
{
$match: {
- type: "X Hours for X Week Streak",
+ type: 'X Hours for X Week Streak',
weeks: { $gt: 1, $lt: weeks },
totalHrs: hrs,
},
@@ -916,9 +923,9 @@ const userHelper = function () {
{ $sort: { weeks: -1, totalHrs: -1 } },
{
$group: {
- _id: "$weeks",
+ _id: '$weeks',
badges: {
- $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" },
+ $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' },
},
},
},
@@ -928,16 +935,16 @@ const userHelper = function () {
streak.badges.every((bdge) => {
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
- badgeCollection[i].badge?.type ===
- "X Hours for X Week Streak" &&
- badgeCollection[i].badge?.weeks === bdge.weeks &&
- bdge.hrs === hrs &&
- !removed
+ badgeCollection[i].badge?.type
+ === 'X Hours for X Week Streak'
+ && badgeCollection[i].badge?.weeks === bdge.weeks
+ && bdge.hrs === hrs
+ && !removed
) {
changeBadgeCount(
personId,
badgeCollection[i].badge._id,
- badgeCollection[i].badge.count - 1
+ badgeCollection[i].badge.count - 1,
);
removed = true;
return false;
@@ -950,24 +957,23 @@ const userHelper = function () {
};
// 'No Infringement Streak',
-
const checkNoInfringementStreak = async function (
personId,
user,
- badgeCollection
+ badgeCollection,
) {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === "No Infringement Streak") {
+ if (badgeCollection[i].badge?.type === 'No Infringement Streak') {
if (
- badgeOfType &&
- badgeOfType.months <= badgeCollection[i].badge.months
+ badgeOfType
+ && badgeOfType.months <= badgeCollection[i].badge.months
) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType &&
- badgeOfType.months > badgeCollection[i].badge.months
+ badgeOfType
+ && badgeOfType.months > badgeCollection[i].badge.months
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -976,7 +982,7 @@ const userHelper = function () {
}
}
await badge
- .find({ type: "No Infringement Streak" })
+ .find({ type: 'No Infringement Streak' })
.sort({ months: -1 })
.then((results) => {
if (!Array.isArray(results) || !results.length) {
@@ -988,19 +994,19 @@ const userHelper = function () {
if (elem.months <= 12) {
if (
- moment().diff(moment(user.createdDate), "months", true) >=
- elem.months
+ moment().diff(moment(user.createdDate), 'months', true)
+ >= elem.months
) {
if (
- user.infringements.length === 0 ||
- Math.abs(
+ user.infringements.length === 0
+ || Math.abs(
moment().diff(
moment(
- user.infringements[user.infringements?.length - 1].date
+ user.infringements[user.infringements?.length - 1].date,
),
- "months",
- true
- )
+ 'months',
+ true,
+ ),
) >= elem.months
) {
if (badgeOfType) {
@@ -1008,7 +1014,7 @@ const userHelper = function () {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id)
+ mongoose.Types.ObjectId(elem._id),
);
}
return false;
@@ -1019,29 +1025,29 @@ const userHelper = function () {
}
} else if (user?.infringements?.length === 0) {
if (
- moment().diff(moment(user.createdDate), "months", true) >=
- elem.months
+ moment().diff(moment(user.createdDate), 'months', true)
+ >= elem.months
) {
if (
- user.oldInfringements.length === 0 ||
- Math.abs(
+ user.oldInfringements.length === 0
+ || Math.abs(
moment().diff(
moment(
user.oldInfringements[user.oldInfringements?.length - 1]
- .date
+ .date,
),
- "months",
- true
- )
- ) >=
- elem.months - 12
+ 'months',
+ true,
+ ),
+ )
+ >= elem.months - 12
) {
if (badgeOfType) {
if (badgeOfType._id.toString() !== elem._id.toString()) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id)
+ mongoose.Types.ObjectId(elem._id),
);
}
return false;
@@ -1060,13 +1066,13 @@ const userHelper = function () {
const checkMinHoursMultiple = async function (
personId,
user,
- badgeCollection
+ badgeCollection,
) {
const badgesOfType = badgeCollection
- .map((obj) => obj.badge)
- .filter((badge) => badge.type === "Minimum Hours Multiple");
+ .map(obj => obj.badge)
+ .filter(badgeItem => badgeItem.type === 'Minimum Hours Multiple');
await badge
- .find({ type: "Minimum Hours Multiple" })
+ .find({ type: 'Minimum Hours Multiple' })
.sort({ multiple: -1 })
.then((results) => {
if (!Array.isArray(results) || !results.length) {
@@ -1077,16 +1083,16 @@ const userHelper = function () {
const elem = results[i]; // making variable elem accessible for below code
if (
- user.lastWeekTangibleHrs / user.weeklycommittedHours >=
- elem.multiple
+ user.lastWeekTangibleHrs / user.weeklycommittedHours
+ >= elem.multiple
) {
const theBadge = badgesOfType.find(
- (badge) => badge._id.toString() === elem._id.toString()
+ badgeItem => badgeItem._id.toString() === elem._id.toString(),
);
return theBadge
? increaseBadgeCount(
personId,
- mongoose.Types.ObjectId(theBadge._id)
+ mongoose.Types.ObjectId(theBadge._id),
)
: addBadge(personId, mongoose.Types.ObjectId(elem._id));
}
@@ -1098,29 +1104,29 @@ const userHelper = function () {
const checkPersonalMax = async function (personId, user, badgeCollection) {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === "Personal Max") {
+ if (badgeCollection[i].badge?.type === 'Personal Max') {
if (badgeOfType) {
removeDupBadge(personId, badgeOfType._id);
}
}
}
- await badge.findOne({ type: "Personal Max" }).then((results) => {
+ await badge.findOne({ type: 'Personal Max' }).then((results) => {
if (
- user.lastWeekTangibleHrs &&
- user.lastWeekTangibleHrs >= 1 &&
- user.lastWeekTangibleHrs === user.personalBestMaxHrs
+ user.lastWeekTangibleHrs
+ && user.lastWeekTangibleHrs >= 1
+ && user.lastWeekTangibleHrs === user.personalBestMaxHrs
) {
if (badgeOfType) {
changeBadgeCount(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- user.personalBestMaxHrs
+ user.personalBestMaxHrs,
);
} else {
addBadge(
personId,
mongoose.Types.ObjectId(results._id),
- user.personalBestMaxHrs
+ user.personalBestMaxHrs,
);
}
}
@@ -1131,17 +1137,17 @@ const userHelper = function () {
const checkMostHrsWeek = async function (personId, user, badgeCollection) {
if (
- user.weeklycommittedHours > 0 &&
- user.lastWeekTangibleHrs > user.weeklycommittedHours
+ user.weeklycommittedHours > 0
+ && user.lastWeekTangibleHrs > user.weeklycommittedHours
) {
const badgeOfType = badgeCollection
- .filter((object) => object.badge.type === "Most Hrs in Week")
- .map((object) => object.badge);
- await badge.findOne({ type: "Most Hrs in Week" }).then((results) => {
+ .filter(object => object.badge.type === 'Most Hrs in Week')
+ .map(object => object.badge);
+ await badge.findOne({ type: 'Most Hrs in Week' }).then((results) => {
userProfile
.aggregate([
{ $match: { isActive: true } },
- { $group: { _id: 1, maxHours: { $max: "$lastWeekTangibleHrs" } } },
+ { $group: { _id: 1, maxHours: { $max: '$lastWeekTangibleHrs' } } },
])
.then((userResults) => {
if (badgeOfType.length > 1) {
@@ -1149,13 +1155,13 @@ const userHelper = function () {
}
if (
- user.lastWeekTangibleHrs &&
- user.lastWeekTangibleHrs >= userResults[0].maxHours
+ user.lastWeekTangibleHrs
+ && user.lastWeekTangibleHrs >= userResults[0].maxHours
) {
if (badgeOfType.length) {
increaseBadgeCount(
personId,
- mongoose.Types.ObjectId(badgeOfType[0]._id)
+ mongoose.Types.ObjectId(badgeOfType[0]._id),
);
} else {
addBadge(personId, mongoose.Types.ObjectId(results._id));
@@ -1171,12 +1177,12 @@ const userHelper = function () {
// Handle Increasing the 1 week streak badges
const badgesOfType = [];
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === "X Hours for X Week Streak") {
+ if (badgeCollection[i].badge?.type === 'X Hours for X Week Streak') {
badgesOfType.push(badgeCollection[i].badge);
}
}
await badge
- .find({ type: "X Hours for X Week Streak", weeks: 1 })
+ .find({ type: 'X Hours for X Week Streak', weeks: 1 })
.sort({ totalHrs: -1 })
.then((results) => {
results.every((elem) => {
@@ -1201,13 +1207,13 @@ const userHelper = function () {
// Check each Streak Greater than One to check if it works
await badge
.aggregate([
- { $match: { type: "X Hours for X Week Streak", weeks: { $gt: 1 } } },
+ { $match: { type: 'X Hours for X Week Streak', weeks: { $gt: 1 } } },
{ $sort: { weeks: -1, totalHrs: -1 } },
{
$group: {
- _id: "$weeks",
+ _id: '$weeks',
badges: {
- $push: { _id: "$_id", hrs: "$totalHrs", weeks: "$weeks" },
+ $push: { _id: '$_id', hrs: '$totalHrs', weeks: '$weeks' },
},
},
},
@@ -1219,19 +1225,19 @@ const userHelper = function () {
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
- badgeCollection[i].badge?.type ===
- "X Hours for X Week Streak" &&
- badgeCollection[i].badge?.weeks === bdge.weeks
+ badgeCollection[i].badge?.type
+ === 'X Hours for X Week Streak'
+ && badgeCollection[i].badge?.weeks === bdge.weeks
) {
if (
- badgeOfType &&
- badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
+ badgeOfType
+ && badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType &&
- badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
+ badgeOfType
+ && badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -1256,7 +1262,7 @@ const userHelper = function () {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(bdge._id)
+ mongoose.Types.ObjectId(bdge._id),
);
removePrevHrBadge(
@@ -1264,7 +1270,7 @@ const userHelper = function () {
user,
badgeCollection,
bdge.hrs,
- bdge.weeks
+ bdge.weeks,
);
} else if (!badgeOfType) {
addBadge(personId, mongoose.Types.ObjectId(bdge._id));
@@ -1273,19 +1279,19 @@ const userHelper = function () {
user,
badgeCollection,
bdge.hrs,
- bdge.weeks
+ bdge.weeks,
);
} else if (badgeOfType && badgeOfType.totalHrs === bdge.hrs) {
increaseBadgeCount(
personId,
- mongoose.Types.ObjectId(badgeOfType._id)
+ mongoose.Types.ObjectId(badgeOfType._id),
);
removePrevHrBadge(
personId,
user,
badgeCollection,
bdge.hrs,
- bdge.weeks
+ bdge.weeks,
);
}
return false;
@@ -1302,16 +1308,16 @@ const userHelper = function () {
const checkLeadTeamOfXplus = async function (
personId,
user,
- badgeCollection
+ badgeCollection,
) {
const leaderRoles = [
- "Mentor",
- "Manager",
- "Administrator",
- "Owner",
- "Core Team",
+ 'Mentor',
+ 'Manager',
+ 'Administrator',
+ 'Owner',
+ 'Core Team',
];
- const approvedRoles = ["Mentor", "Manager"];
+ const approvedRoles = ['Mentor', 'Manager'];
if (!approvedRoles.includes(user.role)) return;
let teamMembers;
@@ -1336,16 +1342,16 @@ const userHelper = function () {
});
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
- if (badgeCollection[i].badge?.type === "Lead a team of X+") {
+ if (badgeCollection[i].badge?.type === 'Lead a team of X+') {
if (
- badgeOfType &&
- badgeOfType.people <= badgeCollection[i].badge.people
+ badgeOfType
+ && badgeOfType.people <= badgeCollection[i].badge.people
) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType &&
- badgeOfType.people > badgeCollection[i].badge.people
+ badgeOfType
+ && badgeOfType.people > badgeCollection[i].badge.people
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -1354,7 +1360,7 @@ const userHelper = function () {
}
}
await badge
- .find({ type: "Lead a team of X+" })
+ .find({ type: 'Lead a team of X+' })
.sort({ people: -1 })
.then((results) => {
if (!Array.isArray(results) || !results.length) {
@@ -1364,14 +1370,14 @@ const userHelper = function () {
if (teamMembers && teamMembers.length >= badge.people) {
if (badgeOfType) {
if (
- badgeOfType._id.toString() !== badge._id.toString() &&
- badgeOfType.people < badge.people
+ badgeOfType._id.toString() !== badge._id.toString()
+ && badgeOfType.people < badge.people
) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(badge._id)
+ mongoose.Types.ObjectId(badge._id),
);
}
return false;
@@ -1388,39 +1394,39 @@ const userHelper = function () {
const checkTotalHrsInCat = async function (personId, user, badgeCollection) {
const hoursByCategory = user.hoursByCategory || {};
const categories = [
- "food",
- "energy",
- "housing",
- "education",
- "society",
- "economics",
- "stewardship",
+ 'food',
+ 'energy',
+ 'housing',
+ 'education',
+ 'society',
+ 'economics',
+ 'stewardship',
];
const badgesOfType = badgeCollection
- .filter((object) => object.badge.type === "Total Hrs in Category")
- .map((object) => object.badge);
+ .filter(object => object.badge.type === 'Total Hrs in Category')
+ .map(object => object.badge);
categories.forEach(async (category) => {
const categoryHrs = Object.keys(hoursByCategory).find(
- (elem) => elem === category
+ elem => elem === category,
);
let badgeOfType;
for (let i = 0; i < badgeCollection.length; i += 1) {
if (
- badgeCollection[i].badge?.type === "Total Hrs in Category" &&
- badgeCollection[i].badge?.category === category
+ badgeCollection[i].badge?.type === 'Total Hrs in Category'
+ && badgeCollection[i].badge?.category === category
) {
if (
- badgeOfType &&
- badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
+ badgeOfType
+ && badgeOfType.totalHrs <= badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeOfType._id);
badgeOfType = badgeCollection[i].badge;
} else if (
- badgeOfType &&
- badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
+ badgeOfType
+ && badgeOfType.totalHrs > badgeCollection[i].badge.totalHrs
) {
removeDupBadge(personId, badgeCollection[i].badge._id);
} else if (!badgeOfType) {
@@ -1432,7 +1438,7 @@ const userHelper = function () {
const newCatg = category.charAt(0).toUpperCase() + category.slice(1);
await badge
- .find({ type: "Total Hrs in Category", category: newCatg })
+ .find({ type: 'Total Hrs in Category', category: newCatg })
.sort({ totalHrs: -1 })
.then((results) => {
@@ -1442,8 +1448,8 @@ const userHelper = function () {
results.every((elem) => {
if (
- hoursByCategory[categoryHrs] >= 100 &&
- hoursByCategory[categoryHrs] >= elem.totalHrs
+ hoursByCategory[categoryHrs] >= 100
+ && hoursByCategory[categoryHrs] >= elem.totalHrs
) {
let theBadge;
for (let i = 0; i < badgesOfType.length; i += 1) {
@@ -1458,13 +1464,13 @@ const userHelper = function () {
}
if (badgeOfType) {
if (
- badgeOfType._id.toString() !== elem._id.toString() &&
- badgeOfType.totalHrs < elem.totalHrs
+ badgeOfType._id.toString() !== elem._id.toString()
+ && badgeOfType.totalHrs < elem.totalHrs
) {
replaceBadge(
personId,
mongoose.Types.ObjectId(badgeOfType._id),
- mongoose.Types.ObjectId(elem._id)
+ mongoose.Types.ObjectId(elem._id),
);
}
return false;
@@ -1479,11 +1485,11 @@ const userHelper = function () {
};
const awardNewBadges = async () => {
- console.log("Awarding");
+ console.log('Awarding');
try {
const users = await userProfile
.find({ isActive: true })
- .populate("badgeCollection.badge");
+ .populate('badgeCollection.badge');
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
@@ -1506,13 +1512,13 @@ const userHelper = function () {
const userId = mongoose.Types.ObjectId(personId);
const pdtstart = moment()
- .tz("America/Los_Angeles")
- .startOf("week")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .startOf('week')
+ .format('YYYY-MM-DD');
const pdtend = moment()
- .tz("America/Los_Angeles")
- .endOf("week")
- .format("YYYY-MM-DD");
+ .tz('America/Los_Angeles')
+ .endOf('week')
+ .format('YYYY-MM-DD');
return timeEntries
.find(
@@ -1521,12 +1527,12 @@ const userHelper = function () {
dateOfWork: { $gte: pdtstart, $lte: pdtend },
isTangible: true,
},
- "totalSeconds"
+ 'totalSeconds',
)
.then((results) => {
const totalTangibleWeeklySeconds = results.reduce(
(acc, { totalSeconds }) => acc + totalSeconds,
- 0
+ 0,
);
return (totalTangibleWeeklySeconds / 3600).toFixed(2);
});
@@ -1536,28 +1542,28 @@ const userHelper = function () {
try {
const users = await userProfile.find(
{ isActive: true, endDate: { $exists: true } },
- "_id isActive endDate"
+ '_id isActive endDate',
);
for (let i = 0; i < users.length; i += 1) {
const user = users[i];
const { endDate } = user;
endDate.setHours(endDate.getHours() + 7);
- if (moment().isAfter(moment(endDate).add(1, "days"))) {
+ if (moment().isAfter(moment(endDate).add(1, 'days'))) {
await userProfile.findByIdAndUpdate(
user._id,
user.set({
isActive: false,
}),
- { new: true }
+ { new: true },
);
const id = user._id;
const person = await userProfile.findById(id);
- const lastDay = moment(person.endDate).format("YYYY-MM-DD");
+ const lastDay = moment(person.endDate).format('YYYY-MM-DD');
logger.logInfo(
`User with id: ${
user._id
- } was de-acticated at ${moment().format()}.`
+ } was de-acticated at ${moment().format()}.`,
);
const subject = `IMPORTANT:${person.firstName} ${person.lastName} has been deactivated in the Highest Good Network`;
@@ -1573,12 +1579,12 @@ const userHelper = function () {
The HGN A.I. (and One Community)
`;
emailSender(
- "onecommunityglobal@gmail.com",
+ 'onecommunityglobal@gmail.com',
subject,
emailBody,
null,
null,
- person.email
+ person.email,
);
}
}
@@ -1598,6 +1604,7 @@ const userHelper = function () {
};
return {
+ changeBadgeCount,
getUserName,
getTeamMembers,
validateProfilePic,
@@ -1615,4 +1622,4 @@ const userHelper = function () {
};
};
-module.exports = userHelper;
\ No newline at end of file
+module.exports = userHelper;
From a538fd14b032d998f0f33c1d0f5aaf116ddb38fe Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Sat, 30 Dec 2023 12:41:56 -0500
Subject: [PATCH 235/272] fix bug in changeBadgeCount
---
src/helpers/userHelper.js | 78 +++++++++++++++++++++++----------------
1 file changed, 46 insertions(+), 32 deletions(-)
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 97beafc17..4026b1462 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -859,41 +859,45 @@ const changeBadgeCount = async function (personId, badgeId, count) {
removeDupBadge(personId, badgeId);
} else if (count) {
// Process exisiting earned date to match the new count
- const userInfo = await userProfile.findById(personId);
- let newEarnedDate = [];
- const recordToUpdate = userInfo.badgeCollection.find(item => item.badge._id.toString() === badgeId.toString());
- if (!recordToUpdate) {
- throw new Error('Badge not found');
- }
- const copyOfEarnedDate = recordToUpdate.earnedDate;
- if (copyOfEarnedDate.length < count) {
- // if the EarnedDate count is less than the new count, add a earned date to the end of the collection
- while (copyOfEarnedDate.length < count) {
- copyOfEarnedDate.push(earnedDateBadge());
+ try {
+ const userInfo = await userProfile.findById(personId);
+ let newEarnedDate = [];
+ const recordToUpdate = userInfo.badgeCollection.find(item => item.badge._id.toString() === badgeId.toString());
+ if (!recordToUpdate) {
+ throw new Error('Badge not found');
}
- } else {
- // if the EarnedDate count is greater than the new count, remove the oldest earned date of the collection until it matches the new count - 1
- while (copyOfEarnedDate.length >= count) {
- copyOfEarnedDate.shift();
+ const copyOfEarnedDate = recordToUpdate.earnedDate;
+ if (copyOfEarnedDate.length < count) {
+ // if the EarnedDate count is less than the new count, add a earned date to the end of the collection
+ while (copyOfEarnedDate.length < count) {
+ copyOfEarnedDate.push(earnedDateBadge());
+ }
+ } else {
+ // if the EarnedDate count is greater than the new count, remove the oldest earned date of the collection until it matches the new count - 1
+ while (copyOfEarnedDate.length >= count) {
+ copyOfEarnedDate.shift();
+ }
+ copyOfEarnedDate.push(earnedDateBadge());
}
- copyOfEarnedDate.push(earnedDateBadge());
- }
- newEarnedDate = [...copyOfEarnedDate];
- userProfile.updateOne(
- { _id: personId, 'badgeCollection.badge': badgeId },
- {
- $set: {
- 'badgeCollection.$.count': count,
- 'badgeCollection.$.lastModified': Date.now().toString(),
- 'badgeCollection.$.earnedDate': newEarnedDate,
+ newEarnedDate = [...copyOfEarnedDate];
+ userProfile.updateOne(
+ { _id: personId, 'badgeCollection.badge': badgeId },
+ {
+ $set: {
+ 'badgeCollection.$.count': count,
+ 'badgeCollection.$.lastModified': Date.now().toString(),
+ 'badgeCollection.$.earnedDate': newEarnedDate,
+ },
},
- },
- (err) => {
- if (err) {
- throw new Error(err);
- }
- },
- );
+ (err) => {
+ if (err) {
+ throw new Error(err);
+ }
+ },
+ );
+ } catch (err) {
+ logger.logException(err);
+ }
}
};
@@ -1487,6 +1491,7 @@ const changeBadgeCount = async function (personId, badgeId, count) {
const awardNewBadges = async () => {
console.log('Awarding');
try {
+ // This will be used in production to run task on all users
const users = await userProfile
.find({ isActive: true })
.populate('badgeCollection.badge');
@@ -1503,6 +1508,15 @@ const changeBadgeCount = async function (personId, badgeId, count) {
await checkXHrsForXWeeks(personId, user, badgeCollection);
await checkNoInfringementStreak(personId, user, badgeCollection);
}
+
+ // Testing purpose only
+ // You can lookup your user id in view profile and get the id from the url
+ // const user = await userProfile
+ // .findOne({ _id: '65500b658e0b2922b80d5f9f' })
+ // .populate('badgeCollection.badge');
+ // for (let badgeItem of user.badgeCollection){
+ // await changeBadgeCount('65500b658e0b2922b80d5f9f', badgeItem.badge._id, badgeItem.count + 1);
+ // }
} catch (err) {
logger.logException(err);
}
From af91cadfe4f95f412980e5a6d8302440cc727956 Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Sat, 30 Dec 2023 12:42:58 -0500
Subject: [PATCH 236/272] Remove testing code
---
src/helpers/userHelper.js | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 4026b1462..dba1369f3 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -1508,15 +1508,6 @@ const changeBadgeCount = async function (personId, badgeId, count) {
await checkXHrsForXWeeks(personId, user, badgeCollection);
await checkNoInfringementStreak(personId, user, badgeCollection);
}
-
- // Testing purpose only
- // You can lookup your user id in view profile and get the id from the url
- // const user = await userProfile
- // .findOne({ _id: '65500b658e0b2922b80d5f9f' })
- // .populate('badgeCollection.badge');
- // for (let badgeItem of user.badgeCollection){
- // await changeBadgeCount('65500b658e0b2922b80d5f9f', badgeItem.badge._id, badgeItem.count + 1);
- // }
} catch (err) {
logger.logException(err);
}
From 04cbd643091cae073f58477efde6a9a6d218e206 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Sat, 30 Dec 2023 21:24:15 -0800
Subject: [PATCH 237/272] fix editTimeEntry
---
src/controllers/timeEntryController.js | 43 ++++++++++++++------------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js
index c8ef3d464..1cbab61c4 100644
--- a/src/controllers/timeEntryController.js
+++ b/src/controllers/timeEntryController.js
@@ -195,15 +195,15 @@ const timeEntrycontroller = function (TimeEntry) {
const isGeneralEntry = isGeneralTimeEntry(type);
try {
- if (!req.params.timeEntryId) {
+ if (!timeEntryId) {
const error = 'ObjectId in request param is not in correct format';
return res.status(400).send({ error });
}
if (
- !mongoose.Types.ObjectId.isValid(req.params.timeEntryId)
+ !mongoose.Types.ObjectId.isValid(timeEntryId)
|| ((isGeneralEntry || type === 'project')
- && !mongoose.Types.ObjectId.isValid(req.body.projectId)
+ && !mongoose.Types.ObjectId.isValid(newProjectId)
)) {
const error = 'ObjectIds are not correctly formed';
return res.status(400).send({ error });
@@ -228,30 +228,35 @@ const timeEntrycontroller = function (TimeEntry) {
}
// update task data if project/task is changed
- if (newTaskId === timeEntry.taskId) {
+ if (newTaskId === timeEntry.taskId && newProjectId === timeEntry.projectId) {
+ // when project/task is the same
const timeEntryTask = await Task.findById(newTaskId);
- const timeEntryUser = await UserProfile.findById(personId);
- if (timeEntry.isTangible) {
- timeEntryTask.hoursLogged -= timeEntry.totalSeconds / 3600;
- }
- if (newIsTangible) {
- timeEntryTask.hoursLogged += newTotalSeconds / 3600;
+ if (timeEntryTask) {
+ const timeEntryUser = await UserProfile.findById(personId);
+ if (timeEntry.isTangible) {
+ timeEntryTask.hoursLogged -= timeEntry.totalSeconds / 3600;
+ }
+ if (newIsTangible) {
+ timeEntryTask.hoursLogged += newTotalSeconds / 3600;
+ }
+ checkTaskOvertime(timeEntry, timeEntryUser, timeEntryTask);
+ await timeEntryTask.save();
}
- checkTaskOvertime(timeEntry, timeEntryUser, timeEntryTask);
- await timeEntryTask.save();
} else {
+ // update oldtTimeEntryTask
const oldTimeEntryTask = await Task.findById(timeEntry.taskId);
- const newTimeEntryTask = await Task.findById(newTaskId);
- const timeEntryUser = await UserProfile.findById(personId);
- if (timeEntry.isTangible) {
+ if (oldTimeEntryTask && timeEntry.isTangible) {
oldTimeEntryTask.hoursLogged -= timeEntry.totalSeconds / 3600;
+ oldTimeEntryTask.save();
}
- if (newIsTangible) {
+ // update newtTimeEntryTask
+ const newTimeEntryTask = await Task.findById(newTaskId);
+ if (newTimeEntryTask && newIsTangible) {
+ const timeEntryUser = await UserProfile.findById(personId);
newTimeEntryTask.hoursLogged += newTotalSeconds / 3600;
+ checkTaskOvertime(timeEntry, timeEntryUser, newTimeEntryTask);
+ await newTimeEntryTask.save();
}
- checkTaskOvertime(timeEntry, timeEntryUser, newTimeEntryTask);
- await oldTimeEntryTask.save();
- await newTimeEntryTask.save();
}
// Update edit history
From 57c0267b2d1a04da276a20d57f3806d70f56336e Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Tue, 2 Jan 2024 15:42:54 -0500
Subject: [PATCH 238/272] Update the scheduler to run every Sunday at midnight
---
src/cronjobs/userProfileJobs.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/cronjobs/userProfileJobs.js b/src/cronjobs/userProfileJobs.js
index f3903c057..8ca6ff95c 100644
--- a/src/cronjobs/userProfileJobs.js
+++ b/src/cronjobs/userProfileJobs.js
@@ -5,7 +5,8 @@ const userhelper = require('../helpers/userHelper')();
const userProfileJobs = () => {
const allUserProfileJobs = new CronJob(
- '1 0 * * *', // Every day, 1 minute past midnight (PST).
+ // '* * * * *', // Comment out for testing. Run Every minute.
+ '0 0 * * 0', // Every Sunday, at midnight.
async () => {
const SUNDAY = 0;
if (moment().tz('America/Los_Angeles').day() === SUNDAY) {
From 0d805bc24041186ac9bb95d5b5e22ddd10ba7e9a Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Tue, 2 Jan 2024 15:52:18 -0500
Subject: [PATCH 239/272] Update cron config to run at 1 minute past midnight
every Sunday in PST
---
src/cronjobs/userProfileJobs.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cronjobs/userProfileJobs.js b/src/cronjobs/userProfileJobs.js
index 8ca6ff95c..8bc94c0f1 100644
--- a/src/cronjobs/userProfileJobs.js
+++ b/src/cronjobs/userProfileJobs.js
@@ -6,7 +6,7 @@ const userhelper = require('../helpers/userHelper')();
const userProfileJobs = () => {
const allUserProfileJobs = new CronJob(
// '* * * * *', // Comment out for testing. Run Every minute.
- '0 0 * * 0', // Every Sunday, at midnight.
+ '1 0 * * 0', // Every Sunday, 1 minute past midnight.
async () => {
const SUNDAY = 0;
if (moment().tz('America/Los_Angeles').day() === SUNDAY) {
From e587b6a4ad2083f18abc5b047cf4d609ca1c7a70 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 2 Jan 2024 15:44:40 -0800
Subject: [PATCH 240/272] add char limit to desc
---
src/models/bmdashboard/buildingInventoryType.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/models/bmdashboard/buildingInventoryType.js b/src/models/bmdashboard/buildingInventoryType.js
index b1512dca2..b130c6ae9 100644
--- a/src/models/bmdashboard/buildingInventoryType.js
+++ b/src/models/bmdashboard/buildingInventoryType.js
@@ -11,7 +11,7 @@ const { Schema } = mongoose;
const invTypeBaseSchema = new Schema({
name: { type: String, required: true },
- description: { type: String, required: true },
+ description: { type: String, required: true, maxLength: 150 },
imageUrl: String,
createdBy: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfiles' },
});
From bda1712e367d2b7d1b5e64846a4ed13bac3c6682 Mon Sep 17 00:00:00 2001
From: wang9hu
Date: Tue, 2 Jan 2024 16:59:35 -0800
Subject: [PATCH 241/272] change request body format for adding and deleting
team member, refactor request handler
---
src/controllers/teamController.js | 82 +++++++++++--------------------
1 file changed, 28 insertions(+), 54 deletions(-)
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index 5c8cb5cc2..0570afc00 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -115,66 +115,40 @@ const teamcontroller = function (Team) {
return;
}
- if (
- !req.params.teamId
- || !mongoose.Types.ObjectId.isValid(req.params.teamId)
- || !req.body.users
- || req.body.users.length === 0
- ) {
- res.status(400).send({ error: 'Invalid request' });
+ const { teamId } = req.params;
+
+ if (!teamId || !mongoose.Types.ObjectId.isValid(teamId)) {
+ res.status(400).send({ error: 'Invalid teamId' });
return;
}
// verify team exists
+ const targetTeam = await Team.findById(teamId);
- Team.findById(req.params.teamId)
- .then((team) => {
- if (!team || team.length === 0) {
- res.status(400).send({ error: 'Invalid team' });
- return;
- }
- const { users } = req.body;
- const assignlist = [];
- const unassignlist = [];
-
- users.forEach((element) => {
- const { userId, operation } = element;
- // if user's profile is stored in cache, clear it so when you visit their profile page it will be up to date
- if (cache.hasCache(`user-${userId}`)) cache.removeCache(`user-${userId}`);
-
- if (operation === 'Assign') {
- assignlist.push(userId);
- } else {
- unassignlist.push(userId);
- }
- });
+ if (!targetTeam || targetTeam.length === 0) {
+ res.status(400).send({ error: 'Invalid team' });
+ return;
+ }
- const addTeamToUserProfile = userProfile
- .updateMany({ _id: { $in: assignlist } }, { $addToSet: { teams: team._id } })
- .exec();
- const removeTeamFromUserProfile = userProfile
- .updateMany({ _id: { $in: unassignlist } }, { $pull: { teams: team._id } })
- .exec();
- const addUserToTeam = Team.updateOne(
- { _id: team._id },
- { $addToSet: { members: { $each: assignlist.map(userId => ({ userId })) } } },
- ).exec();
- const removeUserFromTeam = Team.updateOne(
- { _id: team._id },
- { $pull: { members: { userId: { $in: unassignlist } } } },
- ).exec();
-
- Promise.all([addTeamToUserProfile, removeTeamFromUserProfile, addUserToTeam, removeUserFromTeam])
- .then(() => {
- res.status(200).send({ result: 'Done' });
- })
- .catch((error) => {
- res.status(500).send({ error });
- });
- })
- .catch((error) => {
- res.status(500).send({ error });
- });
+ try {
+ const { userId, operation } = req.body;
+
+ // if user's profile is stored in cache, clear it so when you visit their profile page it will be up to date
+ if (cache.hasCache(`user-${userId}`)) cache.removeCache(`user-${userId}`);
+
+
+ if (operation === 'Assign') {
+ await Team.findOneAndUpdate({ _id: teamId }, { $addToSet: { members: { userId } } }, { new: true });
+ const newMember = await userProfile.findOneAndUpdate({ _id: userId }, { $addToSet: { teams: teamId } }, { new: true });
+ res.status(200).send({ newMember });
+ } else {
+ await Team.findOneAndUpdate({ _id: teamId }, { $pull: { members: { userId } } });
+ await userProfile.findOneAndUpdate({ _id: userId }, { $pull: { teams: teamId } }, { new: true });
+ res.status(200).send({ result: 'Delete Success' });
+ }
+ } catch (error) {
+ res.status(500).send({ error });
+ }
};
const getTeamMembership = function (req, res) {
From b83b1b54b94df722b249dde96aff9eeb48153249 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Tue, 2 Jan 2024 17:33:50 -0800
Subject: [PATCH 242/272] add duplicate name check
---
.../bmdashboard/bmInventoryTypeController.js | 43 +++++++++++--------
1 file changed, 26 insertions(+), 17 deletions(-)
diff --git a/src/controllers/bmdashboard/bmInventoryTypeController.js b/src/controllers/bmdashboard/bmInventoryTypeController.js
index ea2cba730..bab55c386 100644
--- a/src/controllers/bmdashboard/bmInventoryTypeController.js
+++ b/src/controllers/bmdashboard/bmInventoryTypeController.js
@@ -18,32 +18,41 @@ function bmInventoryTypeController(MatType, ConsType, ReusType, ToolType, EquipT
fuel: fuelType,
requestor: { requestorId },
} = req.body;
- const newDoc = {
- category: 'Equipment',
- name,
- description,
- fuelType,
- createdBy: requestorId,
- };
try {
EquipType
- .create(newDoc)
- .then(() => res.status(201).send())
- .catch((error) => {
- if (error._message.includes('validation failed')) {
- res.status(400).send(error);
+ .find({ name })
+ .then((result) => {
+ if (result.length) {
+ res.status(409).send();
+ } else {
+ const newDoc = {
+ category: 'Equipment',
+ name,
+ description,
+ fuelType,
+ createdBy: requestorId,
+ };
+ EquipType
+ .create(newDoc)
+ .then(() => res.status(201).send())
+ .catch((error) => {
+ if (error._message.includes('validation failed')) {
+ res.status(400).send(error);
+ } else {
+ res.status(500).send(error);
+ }
+ });
}
- res.status(500).send(error);
- });
- } catch (error) {
+ })
+ .catch(error => res.status(500).send(error));
+ } catch (error) {
res.status(500).send(error);
+ }
}
- }
return {
fetchMaterialTypes,
addEquipmentType,
};
}
-
module.exports = bmInventoryTypeController;
From 3dd167170b4d5945821ed64fb9e1e256cca27628 Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Wed, 3 Jan 2024 12:41:46 -0500
Subject: [PATCH 243/272] Update cache removal after badge awarding
---
src/helpers/userHelper.js | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index dba1369f3..5e6b0870b 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -13,7 +13,7 @@ const emailSender = require('../utilities/emailSender');
const logger = require('../startup/logger');
const Reason = require('../models/reason');
const token = require('../models/profileInitialSetupToken');
-
+const cache = require('../utilities/nodeCache')();
const userHelper = function () {
// Update format to "MMM-DD-YY" from "YYYY-MMM-DD" (Confirmed with Jae)
@@ -860,6 +860,7 @@ const changeBadgeCount = async function (personId, badgeId, count) {
} else if (count) {
// Process exisiting earned date to match the new count
try {
+ console.log('changeBadgeCount');
const userInfo = await userProfile.findById(personId);
let newEarnedDate = [];
const recordToUpdate = userInfo.badgeCollection.find(item => item.badge._id.toString() === badgeId.toString());
@@ -1507,6 +1508,10 @@ const changeBadgeCount = async function (personId, badgeId, count) {
await checkLeadTeamOfXplus(personId, user, badgeCollection);
await checkXHrsForXWeeks(personId, user, badgeCollection);
await checkNoInfringementStreak(personId, user, badgeCollection);
+ // remove cache after badge asssignment.
+ if (cache.hasCache(`user-${_id}`)) {
+ cache.removeCache(`user-${_id}`);
+ }
}
} catch (err) {
logger.logException(err);
From fdbbd1d76c981b6c8c04f6c32d81134b47bcfd9a Mon Sep 17 00:00:00 2001
From: Shengwei Peng
Date: Wed, 3 Jan 2024 15:38:48 -0500
Subject: [PATCH 244/272] Remove log statement from changeBadgeCount
---
src/helpers/userHelper.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 5e6b0870b..b4b2acb46 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -860,7 +860,6 @@ const changeBadgeCount = async function (personId, badgeId, count) {
} else if (count) {
// Process exisiting earned date to match the new count
try {
- console.log('changeBadgeCount');
const userInfo = await userProfile.findById(personId);
let newEarnedDate = [];
const recordToUpdate = userInfo.badgeCollection.find(item => item.badge._id.toString() === badgeId.toString());
From 8c077b0f71365cab26348f075578d021dfda9d3a Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 3 Jan 2024 14:10:42 -0800
Subject: [PATCH 245/272] Leaderboard api and task api fix
---
src/controllers/taskController.js | 2 +-
src/helpers/dashboardhelper.js | 11 +-
src/helpers/taskHelper.js | 705 ++++++++++++++++++------------
3 files changed, 430 insertions(+), 288 deletions(-)
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index 9bcf071de..8d1559ebc 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -837,7 +837,7 @@ const taskController = function (Task) {
const getTasksForTeamsByUser = async (req, res) => {
try {
const userId = mongoose.Types.ObjectId(req.params.userId);
- const teamsData = await taskHelper.getTasksForTeams(userId).exec();
+ const teamsData = await taskHelper.getTasksForTeams(userId);
if (teamsData.length > 0) {
res.status(200).send(teamsData);
} else {
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 59b1d7f51..76c0e8554 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -171,19 +171,20 @@ const dashboardhelper = function () {
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)=>{ return res; }).catch((e)=>{})
-
+
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,isVisible:1,weeklycommittedHours:1,weeklySummaries:1})
.then((res)=>{ return res; }).catch((e)=>{})
@@ -202,9 +203,9 @@ const dashboardhelper = function () {
.then((res)=>{ return res; }).catch((e)=>{})
}
-
+
}
-
+
teamMemberIds = teamMembers.map(member => member._id);
const timeEntries = await timeentry.find({
@@ -231,6 +232,7 @@ const dashboardhelper = function () {
timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds;
})
+
let leaderBoardData = [];
teamMembers.map((teamMember)=>{
@@ -267,6 +269,7 @@ const dashboardhelper = function () {
// Finally, sort by role in ascending order
return a.role.localeCompare(b.role);
});
+
return sortedLBData;
// return myTeam.aggregate([
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index f59dedcbc..2a49439f8 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,9 +1,23 @@
const moment = require('moment-timezone');
const userProfile = require('../models/userProfile');
-const myteam = require('../helpers/helperModels/myTeam');
+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 mongoose = require('mongoose');
const taskHelper = function () {
- const getTasksForTeams = function (userId) {
+ 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)=>{ return res; }).catch((e)=>{});
+
+ if(userById==null) return null;
+ const userRole = userById.role;
+
const pdtstart = moment()
.tz('America/Los_Angeles')
.startOf('week')
@@ -12,288 +26,413 @@ const taskHelper = function () {
.tz('America/Los_Angeles')
.endOf('week')
.format('YYYY-MM-DD');
- return myteam.aggregate([
- {
- $match: {
- _id: userId,
- },
- },
- {
- $unwind: '$myteam',
- },
- {
- $project: {
- _id: 0,
- personId: '$myteam._id',
- name: '$myteam.fullName',
- role: 1,
- },
- },
- // have personId, name, role
- {
- $lookup: {
- from: 'userProfiles',
- localField: 'personId',
- foreignField: '_id',
- as: 'persondata',
- },
- },
- {
- $match: {
- // dashboard tasks user roles hierarchy
- $or: [
- {
- role: { $in: ['Owner', 'Core Team'] },
- },
- {
- $and: [
- {
- role: 'Administrator',
- },
- { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ],
- },
- {
- $and: [
- {
- role: { $in: ['Manager', 'Mentor'] },
- },
- {
- 'persondata.0.role': {
- $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
- },
- },
- ],
- },
- { 'persondata.0._id': userId },
- { 'persondata.0.role': 'Volunteer' },
- { 'persondata.0.isVisible': true },
- ],
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: {
- $sum: [
- {
- $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
- },
- {
- $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
- },
- ],
- },
- role: 1,
- },
- },
- {
- $lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: 1,
- timeEntryData: {
- $filter: {
- input: '$timeEntryData',
- as: 'timeentry',
- cond: {
- $and: [
- {
- $gte: ['$$timeentry.dateOfWork', pdtstart],
- },
- {
- $lte: ['$$timeentry.dateOfWork', pdtend],
- },
- ],
- },
- },
- },
- role: 1,
- },
- },
- {
- $unwind: {
- path: '$timeEntryData',
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: 1,
- totalSeconds: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.totalSeconds',
- 0,
- ],
- },
- isTangible: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.isTangible',
- false,
- ],
- },
- role: 1,
- },
- },
- {
- $addFields: {
- tangibletime: {
- $cond: [
- {
- $eq: ['$isTangible', true],
- },
- '$totalSeconds',
- 0,
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- personId: '$personId',
- weeklycommittedHours: '$weeklycommittedHours',
- name: '$name',
- role: '$role',
- },
- totalSeconds: {
- $sum: '$totalSeconds',
- },
- tangibletime: {
- $sum: '$tangibletime',
- },
- },
- },
- {
- $project: {
- _id: 0,
- personId: '$_id.personId',
- name: '$_id.name',
- weeklycommittedHours: '$_id.weeklycommittedHours',
- totaltime_hrs: {
- $divide: ['$totalSeconds', 3600],
- },
- totaltangibletime_hrs: {
- $divide: ['$tangibletime', 3600],
- },
- role: '$_id.role',
- },
- },
- {
- $lookup: {
- from: 'tasks',
- localField: 'personId',
- foreignField: 'resources.userID',
- as: 'tasks',
- },
- },
- {
- $project: {
- tasks: {
- resources: {
- profilePic: 0,
- },
- },
- },
- },
- {
- $unwind: {
- path: '$tasks',
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $lookup: {
- from: 'wbs',
- localField: 'tasks.wbsId',
- foreignField: '_id',
- as: 'projectId',
- },
- },
- {
- $addFields: {
- 'tasks.projectId': {
- $cond: [
- { $ne: ['$projectId', []] },
- { $arrayElemAt: ['$projectId', 0] },
- '$tasks.projectId',
- ],
- },
- },
- },
- {
- $project: {
- projectId: 0,
- tasks: {
- projectId: {
- _id: 0,
- isActive: 0,
- modifiedDatetime: 0,
- wbsName: 0,
- createdDatetime: 0,
- __v: 0,
- },
- },
- },
- },
- {
- $addFields: {
- 'tasks.projectId': '$tasks.projectId.projectId',
- },
- },
- {
- $lookup: {
- from: 'taskNotifications',
- localField: 'tasks._id',
- foreignField: 'taskId',
- as: 'tasks.taskNotifications',
- },
- },
- {
- $group: {
- _id: '$personId',
- tasks: {
- $push: '$tasks',
- },
- data: {
- $first: '$$ROOT',
- },
- },
- },
- {
- $addFields: {
- 'data.tasks': {
- $filter: {
- input: '$tasks',
- as: 'task',
- cond: { $ne: ['$$task', {}] },
- },
- },
- },
- },
+
+ let teamMemberIds = [userid]
+ let teamMembers = [];
+
+ if(userRole!='Administrator' && userRole!='Owner' && userRole!='Core Team') //Manager , Mentor , Volunteer ... , Show only team members
{
- $replaceRoot: {
- newRoot: '$data',
- },
- },
- ]);
+
+ const teamsResult = await team.find( { "members.userId": { $in: [userid] } }, {members:1} )
+ .then((res)=>{ return res; }).catch((e)=>{})
+
+ 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)=>{ return 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)=>{ return 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)=>{ return res; }).catch((e)=>{})
+ }
+ }
+
+ teamMemberIds = teamMembers.map(member => member._id);
+
+ const timeEntries = await timeentry.find({
+ dateOfWork: {
+ $gte: pdtstart,
+ $lte: pdtend,
+ },
+ personId: { $in: teamMemberIds }
+ });
+
+ let timeEntryByPerson = {}
+ timeEntries.map((timeEntry)=>{
+
+ let personIdStr = timeEntry.personId.toString();
+
+ 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;
+ })
+
+ 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 => {
+
+ let taskIdStr = teamMemberTaskNotification.taskId.toString();
+ let userIdStr = teamMemberTaskNotification.userId.toString();
+ let taskNdUserID = taskIdStr+","+userIdStr;
+
+ if(taskNotificationByTaskNdUser[taskNdUserID]) {
+ taskNotificationByTaskNdUser[taskNdUserID].push(teamMemberTaskNotification)
+ }
+ else{
+ taskNotificationByTaskNdUser[taskNdUserID] = [teamMemberTaskNotification]
+ }
+
+ })
+
+ const taskByPerson = []
+
+ teamMemberTasks.map(teamMemberTask => {
+
+ let projId = teamMemberTask.wbsId?.projectId;
+ let _teamMemberTask = {...teamMemberTask._doc}
+ _teamMemberTask.projectId = projId;
+ let taskIdStr = _teamMemberTask._id.toString();
+
+ teamMemberTask.resources.map(resource => {
+
+ let resourceIdStr = resource.userID.toString();
+ let taskNdUserID = taskIdStr+","+resourceIdStr;
+ _teamMemberTask.taskNotifications = taskNotificationByTaskNdUser[taskNdUserID] || []
+ if(taskByPerson[resourceIdStr]) {
+ taskByPerson[resourceIdStr].push(_teamMemberTask)
+ }
+ else{
+ taskByPerson[resourceIdStr] = [_teamMemberTask]
+ }
+ })
+ })
+
+
+ let teamMemberTasksData = [];
+ teamMembers.map((teamMember)=>{
+ let 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);
+ })
+
+
+ return teamMemberTasksData;
+
+
+ // return myteam.aggregate([
+ // {
+ // $match: {
+ // _id: userId,
+ // },
+ // },
+ // {
+ // $unwind: '$myteam',
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$myteam._id',
+ // name: '$myteam.fullName',
+ // role: 1,
+ // },
+ // },
+ // // have personId, name, role
+ // {
+ // $lookup: {
+ // from: 'userProfiles',
+ // localField: 'personId',
+ // foreignField: '_id',
+ // as: 'persondata',
+ // },
+ // },
+ // {
+ // $match: {
+ // // dashboard tasks user roles hierarchy
+ // $or: [
+ // {
+ // role: { $in: ['Owner', 'Core Team'] },
+ // },
+ // {
+ // $and: [
+ // {
+ // role: 'Administrator',
+ // },
+ // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ // ],
+ // },
+ // {
+ // $and: [
+ // {
+ // role: { $in: ['Manager', 'Mentor'] },
+ // },
+ // {
+ // 'persondata.0.role': {
+ // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ // },
+ // },
+ // ],
+ // },
+ // { 'persondata.0._id': userId },
+ // { 'persondata.0.role': 'Volunteer' },
+ // { 'persondata.0.isVisible': true },
+ // ],
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: {
+ // $sum: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ // },
+ // {
+ // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ // },
+ // ],
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'timeEntries',
+ // localField: 'personId',
+ // foreignField: 'personId',
+ // as: 'timeEntryData',
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: 1,
+ // timeEntryData: {
+ // $filter: {
+ // input: '$timeEntryData',
+ // as: 'timeentry',
+ // cond: {
+ // $and: [
+ // {
+ // $gte: ['$$timeentry.dateOfWork', pdtstart],
+ // },
+ // {
+ // $lte: ['$$timeentry.dateOfWork', pdtend],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$timeEntryData',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: 1,
+ // totalSeconds: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.totalSeconds',
+ // 0,
+ // ],
+ // },
+ // isTangible: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.isTangible',
+ // false,
+ // ],
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $addFields: {
+ // tangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', true],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: {
+ // personId: '$personId',
+ // weeklycommittedHours: '$weeklycommittedHours',
+ // name: '$name',
+ // role: '$role',
+ // },
+ // totalSeconds: {
+ // $sum: '$totalSeconds',
+ // },
+ // tangibletime: {
+ // $sum: '$tangibletime',
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$_id.personId',
+ // name: '$_id.name',
+ // weeklycommittedHours: '$_id.weeklycommittedHours',
+ // totaltime_hrs: {
+ // $divide: ['$totalSeconds', 3600],
+ // },
+ // totaltangibletime_hrs: {
+ // $divide: ['$tangibletime', 3600],
+ // },
+ // role: '$_id.role',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'tasks',
+ // localField: 'personId',
+ // foreignField: 'resources.userID',
+ // as: 'tasks',
+ // },
+ // },
+ // {
+ // $project: {
+ // tasks: {
+ // resources: {
+ // profilePic: 0,
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$tasks',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'wbs',
+ // localField: 'tasks.wbsId',
+ // foreignField: '_id',
+ // as: 'projectId',
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'tasks.projectId': {
+ // $cond: [
+ // { $ne: ['$projectId', []] },
+ // { $arrayElemAt: ['$projectId', 0] },
+ // '$tasks.projectId',
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // projectId: 0,
+ // tasks: {
+ // projectId: {
+ // _id: 0,
+ // isActive: 0,
+ // modifiedDatetime: 0,
+ // wbsName: 0,
+ // createdDatetime: 0,
+ // __v: 0,
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'tasks.projectId': '$tasks.projectId.projectId',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'taskNotifications',
+ // localField: 'tasks._id',
+ // foreignField: 'taskId',
+ // as: 'tasks.taskNotifications',
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: '$personId',
+ // tasks: {
+ // $push: '$tasks',
+ // },
+ // data: {
+ // $first: '$$ROOT',
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'data.tasks': {
+ // $filter: {
+ // input: '$tasks',
+ // as: 'task',
+ // cond: { $ne: ['$$task', {}] },
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $replaceRoot: {
+ // newRoot: '$data',
+ // },
+ // },
+ // ]);
};
const getTasksForSingleUser = function (userId) {
const pdtstart = moment()
From 9e6589608a82300e4d9d4f024df09198b9f3957d Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 3 Jan 2024 16:10:55 -0800
Subject: [PATCH 246/272] merged with dev bracnh
---
src/helpers/taskHelper.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 19551b0ed..e1e2acb13 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -15,6 +15,7 @@ const taskHelper = function () {
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)=>{ return res; }).catch((e)=>{});
+
if(userById==null) return null;
const userRole = userById.role;
From d3c2daebe1a1fa8eaafd0556a2bf0b21754fee27 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 3 Jan 2024 16:21:53 -0800
Subject: [PATCH 247/272] api fix
---
src/helpers/dashboardhelper.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 0b85cb004..ca534b894 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -176,7 +176,6 @@ const dashboardhelper = function () {
.endOf('week')
.format('YYYY-MM-DD');
-
let teamMemberIds = [userid]
let teamMembers = [];
@@ -211,7 +210,6 @@ const dashboardhelper = function () {
.then((res)=>{ return res; }).catch((e)=>{})
}
-
}
teamMemberIds = teamMembers.map(member => member._id);
From 1e8f5e46f27d7e9418b0a0a5445599cf186850a8 Mon Sep 17 00:00:00 2001
From: Vishala09 <65274029+Vishala09@users.noreply.github.com>
Date: Wed, 3 Jan 2024 16:49:49 -0800
Subject: [PATCH 248/272] Revert "Vishala LB and Task api fix"
---
src/helpers/dashboardhelper.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index ca534b894..0b85cb004 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -176,6 +176,7 @@ const dashboardhelper = function () {
.endOf('week')
.format('YYYY-MM-DD');
+
let teamMemberIds = [userid]
let teamMembers = [];
@@ -210,6 +211,7 @@ const dashboardhelper = function () {
.then((res)=>{ return res; }).catch((e)=>{})
}
+
}
teamMemberIds = teamMembers.map(member => member._id);
From 9c913c709d714af5f3901262112245f051770916 Mon Sep 17 00:00:00 2001
From: Vishala09 <65274029+Vishala09@users.noreply.github.com>
Date: Wed, 3 Jan 2024 16:53:22 -0800
Subject: [PATCH 249/272] Revert "Vishala Leaderboard and Team Member Tasks Api
Fix"
---
src/controllers/taskController.js | 2 +-
src/helpers/dashboardhelper.js | 614 +++++++++++---------------
src/helpers/taskHelper.js | 708 ++++++++++++------------------
3 files changed, 542 insertions(+), 782 deletions(-)
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index 753dbba11..5b087db4d 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -834,7 +834,7 @@ const taskController = function (Task) {
const getTasksForTeamsByUser = async (req, res) => {
try {
const userId = mongoose.Types.ObjectId(req.params.userId);
- const teamsData = await taskHelper.getTasksForTeams(userId);
+ const teamsData = await taskHelper.getTasksForTeams(userId).exec();
if (teamsData.length > 0) {
res.status(200).send(teamsData);
} else {
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 0b85cb004..b7ca2f131 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -3,7 +3,6 @@ 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) {
@@ -162,11 +161,6 @@ 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)=>{ return res; }).catch((e)=>{});
-
- if(userById==null) return null;
- const userRole = userById.role;
const pdtstart = moment()
.tz('America/Los_Angeles')
.startOf('week')
@@ -175,360 +169,262 @@ const dashboardhelper = function () {
.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)=>{ return res; }).catch((e)=>{})
-
- 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,isVisible:1,weeklycommittedHours:1,weeklySummaries:1})
- .then((res)=>{ return 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)=>{ return 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})
- .then((res)=>{ return res; }).catch((e)=>{})
- }
-
-
- }
-
- teamMemberIds = teamMembers.map(member => member._id);
-
- const timeEntries = await timeentry.find({
- dateOfWork: {
- $gte: pdtstart,
- $lte: pdtend,
+ const output = await myTeam.aggregate([
+ {
+ $match: {
+ _id: userid,
+ },
},
- personId: { $in: teamMemberIds }
- });
-
- let timeEntryByPerson = {}
- timeEntries.map((timeEntry)=>{
-
- let personIdStr = timeEntry.personId.toString();
-
- if(timeEntryByPerson[personIdStr]==null)
- timeEntryByPerson[personIdStr] = {tangibleSeconds:0,intangibleSeconds:0,totalSeconds:0};
-
- if (timeEntry.isTangible === true) {
- timeEntryByPerson[personIdStr].tangibleSeconds += timeEntry.totalSeconds;
- } else {
- timeEntryByPerson[personIdStr].intangibleSeconds += timeEntry.totalSeconds;
- }
-
- timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds;
- })
-
-
- let leaderBoardData = [];
- teamMembers.map((teamMember)=>{
- let 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);
- })
-
- let sortedLBData = leaderBoardData.sort((a, b) => {
- // Sort by totaltangibletime_hrs in descending order
- if (b.totaltangibletime_hrs !== a.totaltangibletime_hrs) {
- return b.totaltangibletime_hrs - a.totaltangibletime_hrs;
- }
-
- // Then sort by name in ascending order
- if (a.name !== b.name) {
- return a.name.localeCompare(b.name);
- }
-
- // Finally, sort by role in ascending order
- return a.role.localeCompare(b.role);
- });
-
- return sortedLBData;
-
- // return myTeam.aggregate([
- // {
- // $match: {
- // _id: userid,
- // },
- // },
- // {
- // $unwind: '$myteam',
- // },
- // {
- // $project: {
- // _id: 0,
- // role: 1,
- // personId: '$myteam._id',
- // name: '$myteam.fullName',
- // },
- // },
- // {
- // $lookup: {
- // from: 'userProfiles',
- // localField: 'personId',
- // foreignField: '_id',
- // as: 'persondata',
- // },
- // },
- // {
- // $match: {
- // // leaderboard user roles hierarchy
- // $or: [
- // {
- // role: { $in: ['Owner', 'Core Team'] },
- // },
- // {
- // $and: [
- // {
- // role: 'Administrator',
- // },
- // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- // ],
- // },
- // {
- // $and: [
- // {
- // role: { $in: ['Manager', 'Mentor'] },
- // },
- // {
- // 'persondata.0.role': {
- // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
- // },
- // },
- // ],
- // },
- // { 'persondata.0._id': userId },
- // { 'persondata.0.role': 'Volunteer' },
- // { 'persondata.0.isVisible': true },
- // ],
- // },
- // },
- // {
- // $project: {
- // personId: 1,
- // name: 1,
- // role: {
- // $arrayElemAt: ['$persondata.role', 0],
- // },
- // isVisible: {
- // $arrayElemAt: ['$persondata.isVisible', 0],
- // },
- // hasSummary: {
- // $ne: [
- // {
- // $arrayElemAt: [
- // {
- // $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
- // },
- // 0,
- // ],
- // },
- // '',
- // ],
- // },
- // weeklycommittedHours: {
- // $sum: [
- // {
- // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
- // },
- // {
- // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
- // },
- // ],
- // },
- // },
- // },
- // {
- // $lookup: {
- // from: 'timeEntries',
- // localField: 'personId',
- // foreignField: 'personId',
- // as: 'timeEntryData',
- // },
- // },
- // {
- // $project: {
- // personId: 1,
- // name: 1,
- // role: 1,
- // isVisible: 1,
- // hasSummary: 1,
- // weeklycommittedHours: 1,
- // timeEntryData: {
- // $filter: {
- // input: '$timeEntryData',
- // as: 'timeentry',
- // cond: {
- // $and: [
- // {
- // $gte: ['$$timeentry.dateOfWork', pdtstart],
- // },
- // {
- // $lte: ['$$timeentry.dateOfWork', pdtend],
- // },
- // ],
- // },
- // },
- // },
- // },
- // },
- // {
- // $unwind: {
- // path: '$timeEntryData',
- // preserveNullAndEmptyArrays: true,
- // },
- // },
- // {
- // $project: {
- // personId: 1,
- // name: 1,
- // role: 1,
- // isVisible: 1,
- // hasSummary: 1,
- // weeklycommittedHours: 1,
- // totalSeconds: {
- // $cond: [
- // {
- // $gte: ['$timeEntryData.totalSeconds', 0],
- // },
- // '$timeEntryData.totalSeconds',
- // 0,
- // ],
- // },
- // isTangible: {
- // $cond: [
- // {
- // $gte: ['$timeEntryData.totalSeconds', 0],
- // },
- // '$timeEntryData.isTangible',
- // false,
- // ],
- // },
- // },
- // },
- // {
- // $addFields: {
- // tangibletime: {
- // $cond: [
- // {
- // $eq: ['$isTangible', true],
- // },
- // '$totalSeconds',
- // 0,
- // ],
- // },
- // intangibletime: {
- // $cond: [
- // {
- // $eq: ['$isTangible', false],
- // },
- // '$totalSeconds',
- // 0,
- // ],
- // },
- // },
- // },
- // {
- // $group: {
- // _id: {
- // personId: '$personId',
- // weeklycommittedHours: '$weeklycommittedHours',
- // name: '$name',
- // role: '$role',
- // isVisible: '$isVisible',
- // hasSummary: '$hasSummary',
- // },
- // totalSeconds: {
- // $sum: '$totalSeconds',
- // },
- // tangibletime: {
- // $sum: '$tangibletime',
- // },
- // intangibletime: {
- // $sum: '$intangibletime',
- // },
- // },
- // },
- // {
- // $project: {
- // _id: 0,
- // personId: '$_id.personId',
- // name: '$_id.name',
- // role: '$_id.role',
- // isVisible: '$_id.isVisible',
- // hasSummary: '$_id.hasSummary',
- // weeklycommittedHours: '$_id.weeklycommittedHours',
- // totaltime_hrs: {
- // $divide: ['$totalSeconds', 3600],
- // },
- // totaltangibletime_hrs: {
- // $divide: ['$tangibletime', 3600],
- // },
- // totalintangibletime_hrs: {
- // $divide: ['$intangibletime', 3600],
- // },
- // percentagespentintangible: {
- // $cond: [
- // {
- // $eq: ['$totalSeconds', 0],
- // },
- // 0,
- // {
- // $multiply: [
- // {
- // $divide: ['$tangibletime', '$totalSeconds'],
- // },
- // 100,
- // ],
- // },
- // ],
- // },
- // },
- // },
- // {
- // $sort: {
- // totaltangibletime_hrs: -1,
- // name: 1,
- // role: 1,
- // },
- // },
- // ]);
-
+ {
+ $unwind: '$myteam',
+ },
+ {
+ $project: {
+ _id: 0,
+ role: 1,
+ personId: '$myteam._id',
+ name: '$myteam.fullName',
+ },
+ },
+ {
+ $lookup: {
+ from: 'userProfiles',
+ localField: 'personId',
+ foreignField: '_id',
+ as: 'persondata',
+ },
+ },
+ {
+ $match: {
+ // leaderboard user roles hierarchy
+ $or: [
+ {
+ role: { $in: ['Owner', 'Core Team'] },
+ },
+ {
+ $and: [
+ {
+ role: 'Administrator',
+ },
+ { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ ],
+ },
+ {
+ $and: [
+ {
+ role: { $in: ['Manager', 'Mentor'] },
+ },
+ {
+ 'persondata.0.role': {
+ $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ },
+ },
+ ],
+ },
+ { 'persondata.0._id': userId },
+ { 'persondata.0.role': 'Volunteer' },
+ { 'persondata.0.isVisible': true },
+ ],
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ role: {
+ $arrayElemAt: ['$persondata.role', 0],
+ },
+ isVisible: {
+ $arrayElemAt: ['$persondata.isVisible', 0],
+ },
+ hasSummary: {
+ $ne: [
+ {
+ $arrayElemAt: [
+ {
+ $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
+ },
+ 0,
+ ],
+ },
+ '',
+ ],
+ },
+ weeklycommittedHours: {
+ $sum: [
+ {
+ $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ },
+ {
+ $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ },
+ ],
+ },
+ },
+ },
+ {
+ $lookup: {
+ from: 'timeEntries',
+ localField: 'personId',
+ foreignField: 'personId',
+ as: 'timeEntryData',
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ role: 1,
+ isVisible: 1,
+ hasSummary: 1,
+ weeklycommittedHours: 1,
+ timeEntryData: {
+ $filter: {
+ input: '$timeEntryData',
+ as: 'timeentry',
+ cond: {
+ $and: [
+ {
+ $gte: ['$$timeentry.dateOfWork', pdtstart],
+ },
+ {
+ $lte: ['$$timeentry.dateOfWork', pdtend],
+ },
+ {
+ $not: [
+ {
+ $in: ['$$timeentry.entryType', ['person', 'team', 'project']],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ {
+ $unwind: {
+ path: '$timeEntryData',
+ preserveNullAndEmptyArrays: true,
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ role: 1,
+ isVisible: 1,
+ hasSummary: 1,
+ weeklycommittedHours: 1,
+ totalSeconds: {
+ $cond: [
+ {
+ $gte: ['$timeEntryData.totalSeconds', 0],
+ },
+ '$timeEntryData.totalSeconds',
+ 0,
+ ],
+ },
+ isTangible: {
+ $cond: [
+ {
+ $gte: ['$timeEntryData.totalSeconds', 0],
+ },
+ '$timeEntryData.isTangible',
+ false,
+ ],
+ },
+ },
+ },
+ {
+ $addFields: {
+ tangibletime: {
+ $cond: [
+ {
+ $eq: ['$isTangible', true],
+ },
+ '$totalSeconds',
+ 0,
+ ],
+ },
+ intangibletime: {
+ $cond: [
+ {
+ $eq: ['$isTangible', false],
+ },
+ '$totalSeconds',
+ 0,
+ ],
+ },
+ },
+ },
+ {
+ $group: {
+ _id: {
+ personId: '$personId',
+ weeklycommittedHours: '$weeklycommittedHours',
+ name: '$name',
+ role: '$role',
+ isVisible: '$isVisible',
+ hasSummary: '$hasSummary',
+ },
+ totalSeconds: {
+ $sum: '$totalSeconds',
+ },
+ tangibletime: {
+ $sum: '$tangibletime',
+ },
+ intangibletime: {
+ $sum: '$intangibletime',
+ },
+ },
+ },
+ {
+ $project: {
+ _id: 0,
+ personId: '$_id.personId',
+ name: '$_id.name',
+ role: '$_id.role',
+ isVisible: '$_id.isVisible',
+ hasSummary: '$_id.hasSummary',
+ weeklycommittedHours: '$_id.weeklycommittedHours',
+ totaltime_hrs: {
+ $divide: ['$totalSeconds', 3600],
+ },
+ totaltangibletime_hrs: {
+ $divide: ['$tangibletime', 3600],
+ },
+ totalintangibletime_hrs: {
+ $divide: ['$intangibletime', 3600],
+ },
+ percentagespentintangible: {
+ $cond: [
+ {
+ $eq: ['$totalSeconds', 0],
+ },
+ 0,
+ {
+ $multiply: [
+ {
+ $divide: ['$tangibletime', '$totalSeconds'],
+ },
+ 100,
+ ],
+ },
+ ],
+ },
+ },
+ },
+ {
+ $sort: {
+ totaltangibletime_hrs: -1,
+ name: 1,
+ role: 1,
+ },
+ },
+ ]);
+ return output;
};
/**
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 19551b0ed..cfb1235fd 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,23 +1,9 @@
const moment = require('moment-timezone');
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 mongoose = require('mongoose');
+const myteam = require('../helpers/helperModels/myTeam');
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)=>{ return res; }).catch((e)=>{});
-
- if(userById==null) return null;
- const userRole = userById.role;
-
+ const getTasksForTeams = function (userId) {
const pdtstart = moment()
.tz('America/Los_Angeles')
.startOf('week')
@@ -26,413 +12,291 @@ const taskHelper = function () {
.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
+ return myteam.aggregate([
{
-
- const teamsResult = await team.find( { "members.userId": { $in: [userid] } }, {members:1} )
- .then((res)=>{ return res; }).catch((e)=>{})
-
- 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)=>{ return 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)=>{ return 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)=>{ return res; }).catch((e)=>{})
- }
- }
-
- teamMemberIds = teamMembers.map(member => member._id);
-
- const timeEntries = await timeentry.find({
- dateOfWork: {
- $gte: pdtstart,
- $lte: pdtend,
- },
- personId: { $in: teamMemberIds }
- });
-
- let timeEntryByPerson = {}
- timeEntries.map((timeEntry)=>{
-
- let personIdStr = timeEntry.personId.toString();
-
- 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;
- })
-
- 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 => {
-
- let taskIdStr = teamMemberTaskNotification.taskId.toString();
- let userIdStr = teamMemberTaskNotification.userId.toString();
- let taskNdUserID = taskIdStr+","+userIdStr;
-
- if(taskNotificationByTaskNdUser[taskNdUserID]) {
- taskNotificationByTaskNdUser[taskNdUserID].push(teamMemberTaskNotification)
- }
- else{
- taskNotificationByTaskNdUser[taskNdUserID] = [teamMemberTaskNotification]
- }
-
- })
-
- const taskByPerson = []
-
- teamMemberTasks.map(teamMemberTask => {
-
- let projId = teamMemberTask.wbsId?.projectId;
- let _teamMemberTask = {...teamMemberTask._doc}
- _teamMemberTask.projectId = projId;
- let taskIdStr = _teamMemberTask._id.toString();
-
- teamMemberTask.resources.map(resource => {
-
- let resourceIdStr = resource.userID.toString();
- let taskNdUserID = taskIdStr+","+resourceIdStr;
- _teamMemberTask.taskNotifications = taskNotificationByTaskNdUser[taskNdUserID] || []
- if(taskByPerson[resourceIdStr]) {
- taskByPerson[resourceIdStr].push(_teamMemberTask)
- }
- else{
- taskByPerson[resourceIdStr] = [_teamMemberTask]
- }
- })
- })
-
-
- let teamMemberTasksData = [];
- teamMembers.map((teamMember)=>{
- let 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);
- })
-
-
- return teamMemberTasksData;
-
-
- // return myteam.aggregate([
- // {
- // $match: {
- // _id: userId,
- // },
- // },
- // {
- // $unwind: '$myteam',
- // },
- // {
- // $project: {
- // _id: 0,
- // personId: '$myteam._id',
- // name: '$myteam.fullName',
- // role: 1,
- // },
- // },
- // // have personId, name, role
- // {
- // $lookup: {
- // from: 'userProfiles',
- // localField: 'personId',
- // foreignField: '_id',
- // as: 'persondata',
- // },
- // },
- // {
- // $match: {
- // // dashboard tasks user roles hierarchy
- // $or: [
- // {
- // role: { $in: ['Owner', 'Core Team'] },
- // },
- // {
- // $and: [
- // {
- // role: 'Administrator',
- // },
- // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- // ],
- // },
- // {
- // $and: [
- // {
- // role: { $in: ['Manager', 'Mentor'] },
- // },
- // {
- // 'persondata.0.role': {
- // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
- // },
- // },
- // ],
- // },
- // { 'persondata.0._id': userId },
- // { 'persondata.0.role': 'Volunteer' },
- // { 'persondata.0.isVisible': true },
- // ],
- // },
- // },
- // {
- // $project: {
- // personId: 1,
- // name: 1,
- // weeklycommittedHours: {
- // $sum: [
- // {
- // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
- // },
- // {
- // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
- // },
- // ],
- // },
- // role: 1,
- // },
- // },
- // {
- // $lookup: {
- // from: 'timeEntries',
- // localField: 'personId',
- // foreignField: 'personId',
- // as: 'timeEntryData',
- // },
- // },
- // {
- // $project: {
- // personId: 1,
- // name: 1,
- // weeklycommittedHours: 1,
- // timeEntryData: {
- // $filter: {
- // input: '$timeEntryData',
- // as: 'timeentry',
- // cond: {
- // $and: [
- // {
- // $gte: ['$$timeentry.dateOfWork', pdtstart],
- // },
- // {
- // $lte: ['$$timeentry.dateOfWork', pdtend],
- // },
- // ],
- // },
- // },
- // },
- // role: 1,
- // },
- // },
- // {
- // $unwind: {
- // path: '$timeEntryData',
- // preserveNullAndEmptyArrays: true,
- // },
- // },
- // {
- // $project: {
- // personId: 1,
- // name: 1,
- // weeklycommittedHours: 1,
- // totalSeconds: {
- // $cond: [
- // {
- // $gte: ['$timeEntryData.totalSeconds', 0],
- // },
- // '$timeEntryData.totalSeconds',
- // 0,
- // ],
- // },
- // isTangible: {
- // $cond: [
- // {
- // $gte: ['$timeEntryData.totalSeconds', 0],
- // },
- // '$timeEntryData.isTangible',
- // false,
- // ],
- // },
- // role: 1,
- // },
- // },
- // {
- // $addFields: {
- // tangibletime: {
- // $cond: [
- // {
- // $eq: ['$isTangible', true],
- // },
- // '$totalSeconds',
- // 0,
- // ],
- // },
- // },
- // },
- // {
- // $group: {
- // _id: {
- // personId: '$personId',
- // weeklycommittedHours: '$weeklycommittedHours',
- // name: '$name',
- // role: '$role',
- // },
- // totalSeconds: {
- // $sum: '$totalSeconds',
- // },
- // tangibletime: {
- // $sum: '$tangibletime',
- // },
- // },
- // },
- // {
- // $project: {
- // _id: 0,
- // personId: '$_id.personId',
- // name: '$_id.name',
- // weeklycommittedHours: '$_id.weeklycommittedHours',
- // totaltime_hrs: {
- // $divide: ['$totalSeconds', 3600],
- // },
- // totaltangibletime_hrs: {
- // $divide: ['$tangibletime', 3600],
- // },
- // role: '$_id.role',
- // },
- // },
- // {
- // $lookup: {
- // from: 'tasks',
- // localField: 'personId',
- // foreignField: 'resources.userID',
- // as: 'tasks',
- // },
- // },
- // {
- // $project: {
- // tasks: {
- // resources: {
- // profilePic: 0,
- // },
- // },
- // },
- // },
- // {
- // $unwind: {
- // path: '$tasks',
- // preserveNullAndEmptyArrays: true,
- // },
- // },
- // {
- // $lookup: {
- // from: 'wbs',
- // localField: 'tasks.wbsId',
- // foreignField: '_id',
- // as: 'projectId',
- // },
- // },
- // {
- // $addFields: {
- // 'tasks.projectId': {
- // $cond: [
- // { $ne: ['$projectId', []] },
- // { $arrayElemAt: ['$projectId', 0] },
- // '$tasks.projectId',
- // ],
- // },
- // },
- // },
- // {
- // $project: {
- // projectId: 0,
- // tasks: {
- // projectId: {
- // _id: 0,
- // isActive: 0,
- // modifiedDatetime: 0,
- // wbsName: 0,
- // createdDatetime: 0,
- // __v: 0,
- // },
- // },
- // },
- // },
- // {
- // $addFields: {
- // 'tasks.projectId': '$tasks.projectId.projectId',
- // },
- // },
- // {
- // $lookup: {
- // from: 'taskNotifications',
- // localField: 'tasks._id',
- // foreignField: 'taskId',
- // as: 'tasks.taskNotifications',
- // },
- // },
- // {
- // $group: {
- // _id: '$personId',
- // tasks: {
- // $push: '$tasks',
- // },
- // data: {
- // $first: '$$ROOT',
- // },
- // },
- // },
- // {
- // $addFields: {
- // 'data.tasks': {
- // $filter: {
- // input: '$tasks',
- // as: 'task',
- // cond: { $ne: ['$$task', {}] },
- // },
- // },
- // },
- // },
- // {
- // $replaceRoot: {
- // newRoot: '$data',
- // },
- // },
- // ]);
+ $match: {
+ _id: userId,
+ },
+ },
+ {
+ $unwind: '$myteam',
+ },
+ {
+ $project: {
+ _id: 0,
+ personId: '$myteam._id',
+ name: '$myteam.fullName',
+ role: 1,
+ },
+ },
+ // have personId, name, role
+ {
+ $lookup: {
+ from: 'userProfiles',
+ localField: 'personId',
+ foreignField: '_id',
+ as: 'persondata',
+ },
+ },
+ {
+ $match: {
+ // dashboard tasks user roles hierarchy
+ $or: [
+ {
+ role: { $in: ['Owner', 'Core Team'] },
+ },
+ {
+ $and: [
+ {
+ role: 'Administrator',
+ },
+ { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ ],
+ },
+ {
+ $and: [
+ {
+ role: { $in: ['Manager', 'Mentor'] },
+ },
+ {
+ 'persondata.0.role': {
+ $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ },
+ },
+ ],
+ },
+ { 'persondata.0._id': userId },
+ { 'persondata.0.role': 'Volunteer' },
+ { 'persondata.0.isVisible': true },
+ ],
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ weeklycommittedHours: {
+ $sum: [
+ {
+ $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ },
+ {
+ $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ },
+ ],
+ },
+ role: 1,
+ },
+ },
+ {
+ $lookup: {
+ from: 'timeEntries',
+ localField: 'personId',
+ foreignField: 'personId',
+ as: 'timeEntryData',
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ weeklycommittedHours: 1,
+ timeEntryData: {
+ $filter: {
+ input: '$timeEntryData',
+ as: 'timeentry',
+ cond: {
+ $and: [
+ {
+ $gte: ['$$timeentry.dateOfWork', pdtstart],
+ },
+ {
+ $lte: ['$$timeentry.dateOfWork', pdtend],
+ },
+ {
+ $in: ['$$timeentry.entryType', ['default', null]],
+ },
+ ],
+ },
+ },
+ },
+ role: 1,
+ },
+ },
+ {
+ $unwind: {
+ path: '$timeEntryData',
+ preserveNullAndEmptyArrays: true,
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ weeklycommittedHours: 1,
+ totalSeconds: {
+ $cond: [
+ {
+ $gte: ['$timeEntryData.totalSeconds', 0],
+ },
+ '$timeEntryData.totalSeconds',
+ 0,
+ ],
+ },
+ isTangible: {
+ $cond: [
+ {
+ $gte: ['$timeEntryData.totalSeconds', 0],
+ },
+ '$timeEntryData.isTangible',
+ false,
+ ],
+ },
+ role: 1,
+ },
+ },
+ {
+ $addFields: {
+ tangibletime: {
+ $cond: [
+ {
+ $eq: ['$isTangible', true],
+ },
+ '$totalSeconds',
+ 0,
+ ],
+ },
+ },
+ },
+ {
+ $group: {
+ _id: {
+ personId: '$personId',
+ weeklycommittedHours: '$weeklycommittedHours',
+ name: '$name',
+ role: '$role',
+ },
+ totalSeconds: {
+ $sum: '$totalSeconds',
+ },
+ tangibletime: {
+ $sum: '$tangibletime',
+ },
+ },
+ },
+ {
+ $project: {
+ _id: 0,
+ personId: '$_id.personId',
+ name: '$_id.name',
+ weeklycommittedHours: '$_id.weeklycommittedHours',
+ totaltime_hrs: {
+ $divide: ['$totalSeconds', 3600],
+ },
+ totaltangibletime_hrs: {
+ $divide: ['$tangibletime', 3600],
+ },
+ role: '$_id.role',
+ },
+ },
+ {
+ $lookup: {
+ from: 'tasks',
+ localField: 'personId',
+ foreignField: 'resources.userID',
+ as: 'tasks',
+ },
+ },
+ {
+ $project: {
+ tasks: {
+ resources: {
+ profilePic: 0,
+ },
+ },
+ },
+ },
+ {
+ $unwind: {
+ path: '$tasks',
+ preserveNullAndEmptyArrays: true,
+ },
+ },
+ {
+ $lookup: {
+ from: 'wbs',
+ localField: 'tasks.wbsId',
+ foreignField: '_id',
+ as: 'projectId',
+ },
+ },
+ {
+ $addFields: {
+ 'tasks.projectId': {
+ $cond: [
+ { $ne: ['$projectId', []] },
+ { $arrayElemAt: ['$projectId', 0] },
+ '$tasks.projectId',
+ ],
+ },
+ },
+ },
+ {
+ $project: {
+ projectId: 0,
+ tasks: {
+ projectId: {
+ _id: 0,
+ isActive: 0,
+ modifiedDatetime: 0,
+ wbsName: 0,
+ createdDatetime: 0,
+ __v: 0,
+ },
+ },
+ },
+ },
+ {
+ $addFields: {
+ 'tasks.projectId': '$tasks.projectId.projectId',
+ },
+ },
+ {
+ $lookup: {
+ from: 'taskNotifications',
+ localField: 'tasks._id',
+ foreignField: 'taskId',
+ as: 'tasks.taskNotifications',
+ },
+ },
+ {
+ $group: {
+ _id: '$personId',
+ tasks: {
+ $push: '$tasks',
+ },
+ data: {
+ $first: '$$ROOT',
+ },
+ },
+ },
+ {
+ $addFields: {
+ 'data.tasks': {
+ $filter: {
+ input: '$tasks',
+ as: 'task',
+ cond: { $ne: ['$$task', {}] },
+ },
+ },
+ },
+ },
+ {
+ $replaceRoot: {
+ newRoot: '$data',
+ },
+ },
+ ]);
};
const getTasksForSingleUser = function (userId) {
const pdtstart = moment()
From e214e9cc7e1c9df313b42c5258c93720f7e07504 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 3 Jan 2024 17:13:02 -0800
Subject: [PATCH 250/272] task api
---
src/helpers/taskHelper.js | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index e1e2acb13..5a17f8b20 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,12 +1,6 @@
const moment = require('moment-timezone');
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 mongoose = require('mongoose');
+const myteam = require('../helpers/helperModels/myTeam');
const taskHelper = function () {
const getTasksForTeams = async function (userId) {
@@ -15,7 +9,6 @@ const taskHelper = function () {
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)=>{ return res; }).catch((e)=>{});
-
if(userById==null) return null;
const userRole = userById.role;
From 38ffc5f0e3b49f88e8a14046440bc07935c8ce81 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 3 Jan 2024 17:29:41 -0800
Subject: [PATCH 251/272] leaderboard ,task api fix
---
src/controllers/taskController.js | 2 +-
src/helpers/dashboardhelper.js | 611 +++++++++++++++-----------
src/helpers/taskHelper.js | 699 ++++++++++++++++++------------
3 files changed, 771 insertions(+), 541 deletions(-)
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index 5b087db4d..753dbba11 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -834,7 +834,7 @@ const taskController = function (Task) {
const getTasksForTeamsByUser = async (req, res) => {
try {
const userId = mongoose.Types.ObjectId(req.params.userId);
- const teamsData = await taskHelper.getTasksForTeams(userId).exec();
+ const teamsData = await taskHelper.getTasksForTeams(userId);
if (teamsData.length > 0) {
res.status(200).send(teamsData);
} else {
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index b7ca2f131..dea392e4f 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -161,6 +161,11 @@ 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)=>{ return res; }).catch((e)=>{});
+
+ if(userById==null) return null;
+ const userRole = userById.role;
const pdtstart = moment()
.tz('America/Los_Angeles')
.startOf('week')
@@ -169,262 +174,358 @@ const dashboardhelper = function () {
.tz('America/Los_Angeles')
.endOf('week')
.format('YYYY-MM-DD');
- const output = await myTeam.aggregate([
- {
- $match: {
- _id: userid,
- },
- },
- {
- $unwind: '$myteam',
- },
- {
- $project: {
- _id: 0,
- role: 1,
- personId: '$myteam._id',
- name: '$myteam.fullName',
- },
- },
- {
- $lookup: {
- from: 'userProfiles',
- localField: 'personId',
- foreignField: '_id',
- as: 'persondata',
- },
- },
- {
- $match: {
- // leaderboard user roles hierarchy
- $or: [
- {
- role: { $in: ['Owner', 'Core Team'] },
- },
- {
- $and: [
- {
- role: 'Administrator',
- },
- { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ],
- },
- {
- $and: [
- {
- role: { $in: ['Manager', 'Mentor'] },
- },
- {
- 'persondata.0.role': {
- $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
- },
- },
- ],
- },
- { 'persondata.0._id': userId },
- { 'persondata.0.role': 'Volunteer' },
- { 'persondata.0.isVisible': true },
- ],
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: {
- $arrayElemAt: ['$persondata.role', 0],
- },
- isVisible: {
- $arrayElemAt: ['$persondata.isVisible', 0],
- },
- hasSummary: {
- $ne: [
- {
- $arrayElemAt: [
- {
- $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
- },
- 0,
- ],
- },
- '',
- ],
- },
- weeklycommittedHours: {
- $sum: [
- {
- $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
- },
- {
- $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
- },
- ],
- },
- },
- },
- {
- $lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- timeEntryData: {
- $filter: {
- input: '$timeEntryData',
- as: 'timeentry',
- cond: {
- $and: [
- {
- $gte: ['$$timeentry.dateOfWork', pdtstart],
- },
- {
- $lte: ['$$timeentry.dateOfWork', pdtend],
- },
- {
- $not: [
- {
- $in: ['$$timeentry.entryType', ['person', 'team', 'project']],
- },
- ],
- },
- ],
- },
- },
- },
- },
- },
- {
- $unwind: {
- path: '$timeEntryData',
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- totalSeconds: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.totalSeconds',
- 0,
- ],
- },
- isTangible: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.isTangible',
- false,
- ],
- },
- },
- },
- {
- $addFields: {
- tangibletime: {
- $cond: [
- {
- $eq: ['$isTangible', true],
- },
- '$totalSeconds',
- 0,
- ],
- },
- intangibletime: {
- $cond: [
- {
- $eq: ['$isTangible', false],
- },
- '$totalSeconds',
- 0,
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- personId: '$personId',
- weeklycommittedHours: '$weeklycommittedHours',
- name: '$name',
- role: '$role',
- isVisible: '$isVisible',
- hasSummary: '$hasSummary',
- },
- totalSeconds: {
- $sum: '$totalSeconds',
- },
- tangibletime: {
- $sum: '$tangibletime',
- },
- intangibletime: {
- $sum: '$intangibletime',
- },
- },
- },
- {
- $project: {
- _id: 0,
- personId: '$_id.personId',
- name: '$_id.name',
- role: '$_id.role',
- isVisible: '$_id.isVisible',
- hasSummary: '$_id.hasSummary',
- weeklycommittedHours: '$_id.weeklycommittedHours',
- totaltime_hrs: {
- $divide: ['$totalSeconds', 3600],
- },
- totaltangibletime_hrs: {
- $divide: ['$tangibletime', 3600],
- },
- totalintangibletime_hrs: {
- $divide: ['$intangibletime', 3600],
- },
- percentagespentintangible: {
- $cond: [
- {
- $eq: ['$totalSeconds', 0],
- },
- 0,
- {
- $multiply: [
- {
- $divide: ['$tangibletime', '$totalSeconds'],
- },
- 100,
- ],
- },
- ],
- },
- },
- },
- {
- $sort: {
- totaltangibletime_hrs: -1,
- name: 1,
- role: 1,
- },
+
+ 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)=>{ return res; }).catch((e)=>{})
+
+ 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,isVisible:1,weeklycommittedHours:1,weeklySummaries:1})
+ .then((res)=>{ return 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)=>{ return 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})
+ .then((res)=>{ return res; }).catch((e)=>{})
+ }
+
+
+ }
+
+ teamMemberIds = teamMembers.map(member => member._id);
+
+ const timeEntries = await timeentry.find({
+ dateOfWork: {
+ $gte: pdtstart,
+ $lte: pdtend,
},
- ]);
- return output;
+ personId: { $in: teamMemberIds }
+ });
+
+ let timeEntryByPerson = {}
+ timeEntries.map((timeEntry)=>{
+
+ let personIdStr = timeEntry.personId.toString();
+
+ if(timeEntryByPerson[personIdStr]==null)
+ timeEntryByPerson[personIdStr] = {tangibleSeconds:0,intangibleSeconds:0,totalSeconds:0};
+
+ if (timeEntry.isTangible === true) {
+ timeEntryByPerson[personIdStr].tangibleSeconds += timeEntry.totalSeconds;
+ } else {
+ timeEntryByPerson[personIdStr].intangibleSeconds += timeEntry.totalSeconds;
+ }
+
+ timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds;
+ })
+
+
+ let leaderBoardData = [];
+ teamMembers.map((teamMember)=>{
+ let 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);
+ })
+
+ let sortedLBData = leaderBoardData.sort((a, b) => {
+ // Sort by totaltangibletime_hrs in descending order
+ if (b.totaltangibletime_hrs !== a.totaltangibletime_hrs) {
+ return b.totaltangibletime_hrs - a.totaltangibletime_hrs;
+ }
+
+ // Then sort by name in ascending order
+ if (a.name !== b.name) {
+ return a.name.localeCompare(b.name);
+ }
+
+ // Finally, sort by role in ascending order
+ return a.role.localeCompare(b.role);
+ });
+
+ return sortedLBData;
+
+ // return myTeam.aggregate([
+ // {
+ // $match: {
+ // _id: userid,
+ // },
+ // },
+ // {
+ // $unwind: '$myteam',
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // role: 1,
+ // personId: '$myteam._id',
+ // name: '$myteam.fullName',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'userProfiles',
+ // localField: 'personId',
+ // foreignField: '_id',
+ // as: 'persondata',
+ // },
+ // },
+ // {
+ // $match: {
+ // // leaderboard user roles hierarchy
+ // $or: [
+ // {
+ // role: { $in: ['Owner', 'Core Team'] },
+ // },
+ // {
+ // $and: [
+ // {
+ // role: 'Administrator',
+ // },
+ // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ // ],
+ // },
+ // {
+ // $and: [
+ // {
+ // role: { $in: ['Manager', 'Mentor'] },
+ // },
+ // {
+ // 'persondata.0.role': {
+ // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ // },
+ // },
+ // ],
+ // },
+ // { 'persondata.0._id': userId },
+ // { 'persondata.0.role': 'Volunteer' },
+ // { 'persondata.0.isVisible': true },
+ // ],
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: {
+ // $arrayElemAt: ['$persondata.role', 0],
+ // },
+ // isVisible: {
+ // $arrayElemAt: ['$persondata.isVisible', 0],
+ // },
+ // hasSummary: {
+ // $ne: [
+ // {
+ // $arrayElemAt: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
+ // },
+ // 0,
+ // ],
+ // },
+ // '',
+ // ],
+ // },
+ // weeklycommittedHours: {
+ // $sum: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ // },
+ // {
+ // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'timeEntries',
+ // localField: 'personId',
+ // foreignField: 'personId',
+ // as: 'timeEntryData',
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: 1,
+ // isVisible: 1,
+ // hasSummary: 1,
+ // weeklycommittedHours: 1,
+ // timeEntryData: {
+ // $filter: {
+ // input: '$timeEntryData',
+ // as: 'timeentry',
+ // cond: {
+ // $and: [
+ // {
+ // $gte: ['$$timeentry.dateOfWork', pdtstart],
+ // },
+ // {
+ // $lte: ['$$timeentry.dateOfWork', pdtend],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$timeEntryData',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: 1,
+ // isVisible: 1,
+ // hasSummary: 1,
+ // weeklycommittedHours: 1,
+ // totalSeconds: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.totalSeconds',
+ // 0,
+ // ],
+ // },
+ // isTangible: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.isTangible',
+ // false,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // tangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', true],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // intangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', false],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: {
+ // personId: '$personId',
+ // weeklycommittedHours: '$weeklycommittedHours',
+ // name: '$name',
+ // role: '$role',
+ // isVisible: '$isVisible',
+ // hasSummary: '$hasSummary',
+ // },
+ // totalSeconds: {
+ // $sum: '$totalSeconds',
+ // },
+ // tangibletime: {
+ // $sum: '$tangibletime',
+ // },
+ // intangibletime: {
+ // $sum: '$intangibletime',
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$_id.personId',
+ // name: '$_id.name',
+ // role: '$_id.role',
+ // isVisible: '$_id.isVisible',
+ // hasSummary: '$_id.hasSummary',
+ // weeklycommittedHours: '$_id.weeklycommittedHours',
+ // totaltime_hrs: {
+ // $divide: ['$totalSeconds', 3600],
+ // },
+ // totaltangibletime_hrs: {
+ // $divide: ['$tangibletime', 3600],
+ // },
+ // totalintangibletime_hrs: {
+ // $divide: ['$intangibletime', 3600],
+ // },
+ // percentagespentintangible: {
+ // $cond: [
+ // {
+ // $eq: ['$totalSeconds', 0],
+ // },
+ // 0,
+ // {
+ // $multiply: [
+ // {
+ // $divide: ['$tangibletime', '$totalSeconds'],
+ // },
+ // 100,
+ // ],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $sort: {
+ // totaltangibletime_hrs: -1,
+ // name: 1,
+ // role: 1,
+ // },
+ // },
+ // ]);
};
/**
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index cfb1235fd..9135f7573 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -3,7 +3,14 @@ const userProfile = require('../models/userProfile');
const myteam = require('../helpers/helperModels/myTeam');
const taskHelper = function () {
- const getTasksForTeams = function (userId) {
+ 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)=>{ return res; }).catch((e)=>{});
+
+ if(userById==null) return null;
+ const userRole = userById.role;
+
const pdtstart = moment()
.tz('America/Los_Angeles')
.startOf('week')
@@ -12,291 +19,413 @@ const taskHelper = function () {
.tz('America/Los_Angeles')
.endOf('week')
.format('YYYY-MM-DD');
- return myteam.aggregate([
- {
- $match: {
- _id: userId,
- },
- },
- {
- $unwind: '$myteam',
- },
- {
- $project: {
- _id: 0,
- personId: '$myteam._id',
- name: '$myteam.fullName',
- role: 1,
- },
- },
- // have personId, name, role
- {
- $lookup: {
- from: 'userProfiles',
- localField: 'personId',
- foreignField: '_id',
- as: 'persondata',
- },
- },
- {
- $match: {
- // dashboard tasks user roles hierarchy
- $or: [
- {
- role: { $in: ['Owner', 'Core Team'] },
- },
- {
- $and: [
- {
- role: 'Administrator',
- },
- { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
- ],
- },
- {
- $and: [
- {
- role: { $in: ['Manager', 'Mentor'] },
- },
- {
- 'persondata.0.role': {
- $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
- },
- },
- ],
- },
- { 'persondata.0._id': userId },
- { 'persondata.0.role': 'Volunteer' },
- { 'persondata.0.isVisible': true },
- ],
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: {
- $sum: [
- {
- $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
- },
- {
- $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
- },
- ],
- },
- role: 1,
- },
- },
- {
- $lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: 1,
- timeEntryData: {
- $filter: {
- input: '$timeEntryData',
- as: 'timeentry',
- cond: {
- $and: [
- {
- $gte: ['$$timeentry.dateOfWork', pdtstart],
- },
- {
- $lte: ['$$timeentry.dateOfWork', pdtend],
- },
- {
- $in: ['$$timeentry.entryType', ['default', null]],
- },
- ],
- },
- },
- },
- role: 1,
- },
- },
- {
- $unwind: {
- path: '$timeEntryData',
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: 1,
- totalSeconds: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.totalSeconds',
- 0,
- ],
- },
- isTangible: {
- $cond: [
- {
- $gte: ['$timeEntryData.totalSeconds', 0],
- },
- '$timeEntryData.isTangible',
- false,
- ],
- },
- role: 1,
- },
- },
- {
- $addFields: {
- tangibletime: {
- $cond: [
- {
- $eq: ['$isTangible', true],
- },
- '$totalSeconds',
- 0,
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- personId: '$personId',
- weeklycommittedHours: '$weeklycommittedHours',
- name: '$name',
- role: '$role',
- },
- totalSeconds: {
- $sum: '$totalSeconds',
- },
- tangibletime: {
- $sum: '$tangibletime',
- },
- },
- },
- {
- $project: {
- _id: 0,
- personId: '$_id.personId',
- name: '$_id.name',
- weeklycommittedHours: '$_id.weeklycommittedHours',
- totaltime_hrs: {
- $divide: ['$totalSeconds', 3600],
- },
- totaltangibletime_hrs: {
- $divide: ['$tangibletime', 3600],
- },
- role: '$_id.role',
- },
- },
- {
- $lookup: {
- from: 'tasks',
- localField: 'personId',
- foreignField: 'resources.userID',
- as: 'tasks',
- },
- },
- {
- $project: {
- tasks: {
- resources: {
- profilePic: 0,
- },
- },
- },
- },
- {
- $unwind: {
- path: '$tasks',
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $lookup: {
- from: 'wbs',
- localField: 'tasks.wbsId',
- foreignField: '_id',
- as: 'projectId',
- },
- },
- {
- $addFields: {
- 'tasks.projectId': {
- $cond: [
- { $ne: ['$projectId', []] },
- { $arrayElemAt: ['$projectId', 0] },
- '$tasks.projectId',
- ],
- },
- },
- },
- {
- $project: {
- projectId: 0,
- tasks: {
- projectId: {
- _id: 0,
- isActive: 0,
- modifiedDatetime: 0,
- wbsName: 0,
- createdDatetime: 0,
- __v: 0,
- },
- },
- },
- },
- {
- $addFields: {
- 'tasks.projectId': '$tasks.projectId.projectId',
- },
- },
- {
- $lookup: {
- from: 'taskNotifications',
- localField: 'tasks._id',
- foreignField: 'taskId',
- as: 'tasks.taskNotifications',
- },
- },
- {
- $group: {
- _id: '$personId',
- tasks: {
- $push: '$tasks',
- },
- data: {
- $first: '$$ROOT',
- },
- },
- },
- {
- $addFields: {
- 'data.tasks': {
- $filter: {
- input: '$tasks',
- as: 'task',
- cond: { $ne: ['$$task', {}] },
- },
- },
- },
- },
+
+ let teamMemberIds = [userid]
+ let teamMembers = [];
+
+ if(userRole!='Administrator' && userRole!='Owner' && userRole!='Core Team') //Manager , Mentor , Volunteer ... , Show only team members
{
- $replaceRoot: {
- newRoot: '$data',
- },
- },
- ]);
+
+ const teamsResult = await team.find( { "members.userId": { $in: [userid] } }, {members:1} )
+ .then((res)=>{ return res; }).catch((e)=>{})
+
+ 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)=>{ return 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)=>{ return 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)=>{ return res; }).catch((e)=>{})
+ }
+ }
+
+ teamMemberIds = teamMembers.map(member => member._id);
+
+ const timeEntries = await timeentry.find({
+ dateOfWork: {
+ $gte: pdtstart,
+ $lte: pdtend,
+ },
+ personId: { $in: teamMemberIds }
+ });
+
+ let timeEntryByPerson = {}
+ timeEntries.map((timeEntry)=>{
+
+ let personIdStr = timeEntry.personId.toString();
+
+ 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;
+ })
+
+ 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 => {
+
+ let taskIdStr = teamMemberTaskNotification.taskId.toString();
+ let userIdStr = teamMemberTaskNotification.userId.toString();
+ let taskNdUserID = taskIdStr+","+userIdStr;
+
+ if(taskNotificationByTaskNdUser[taskNdUserID]) {
+ taskNotificationByTaskNdUser[taskNdUserID].push(teamMemberTaskNotification)
+ }
+ else{
+ taskNotificationByTaskNdUser[taskNdUserID] = [teamMemberTaskNotification]
+ }
+
+ })
+
+ const taskByPerson = []
+
+ teamMemberTasks.map(teamMemberTask => {
+
+ let projId = teamMemberTask.wbsId?.projectId;
+ let _teamMemberTask = {...teamMemberTask._doc}
+ _teamMemberTask.projectId = projId;
+ let taskIdStr = _teamMemberTask._id.toString();
+
+ teamMemberTask.resources.map(resource => {
+
+ let resourceIdStr = resource.userID.toString();
+ let taskNdUserID = taskIdStr+","+resourceIdStr;
+ _teamMemberTask.taskNotifications = taskNotificationByTaskNdUser[taskNdUserID] || []
+ if(taskByPerson[resourceIdStr]) {
+ taskByPerson[resourceIdStr].push(_teamMemberTask)
+ }
+ else{
+ taskByPerson[resourceIdStr] = [_teamMemberTask]
+ }
+ })
+ })
+
+
+ let teamMemberTasksData = [];
+ teamMembers.map((teamMember)=>{
+ let 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);
+ })
+
+
+ return teamMemberTasksData;
+
+
+ // return myteam.aggregate([
+ // {
+ // $match: {
+ // _id: userId,
+ // },
+ // },
+ // {
+ // $unwind: '$myteam',
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$myteam._id',
+ // name: '$myteam.fullName',
+ // role: 1,
+ // },
+ // },
+ // // have personId, name, role
+ // {
+ // $lookup: {
+ // from: 'userProfiles',
+ // localField: 'personId',
+ // foreignField: '_id',
+ // as: 'persondata',
+ // },
+ // },
+ // {
+ // $match: {
+ // // dashboard tasks user roles hierarchy
+ // $or: [
+ // {
+ // role: { $in: ['Owner', 'Core Team'] },
+ // },
+ // {
+ // $and: [
+ // {
+ // role: 'Administrator',
+ // },
+ // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ // ],
+ // },
+ // {
+ // $and: [
+ // {
+ // role: { $in: ['Manager', 'Mentor'] },
+ // },
+ // {
+ // 'persondata.0.role': {
+ // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ // },
+ // },
+ // ],
+ // },
+ // { 'persondata.0._id': userId },
+ // { 'persondata.0.role': 'Volunteer' },
+ // { 'persondata.0.isVisible': true },
+ // ],
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: {
+ // $sum: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ // },
+ // {
+ // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ // },
+ // ],
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'timeEntries',
+ // localField: 'personId',
+ // foreignField: 'personId',
+ // as: 'timeEntryData',
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: 1,
+ // timeEntryData: {
+ // $filter: {
+ // input: '$timeEntryData',
+ // as: 'timeentry',
+ // cond: {
+ // $and: [
+ // {
+ // $gte: ['$$timeentry.dateOfWork', pdtstart],
+ // },
+ // {
+ // $lte: ['$$timeentry.dateOfWork', pdtend],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$timeEntryData',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: 1,
+ // totalSeconds: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.totalSeconds',
+ // 0,
+ // ],
+ // },
+ // isTangible: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.isTangible',
+ // false,
+ // ],
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $addFields: {
+ // tangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', true],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: {
+ // personId: '$personId',
+ // weeklycommittedHours: '$weeklycommittedHours',
+ // name: '$name',
+ // role: '$role',
+ // },
+ // totalSeconds: {
+ // $sum: '$totalSeconds',
+ // },
+ // tangibletime: {
+ // $sum: '$tangibletime',
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$_id.personId',
+ // name: '$_id.name',
+ // weeklycommittedHours: '$_id.weeklycommittedHours',
+ // totaltime_hrs: {
+ // $divide: ['$totalSeconds', 3600],
+ // },
+ // totaltangibletime_hrs: {
+ // $divide: ['$tangibletime', 3600],
+ // },
+ // role: '$_id.role',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'tasks',
+ // localField: 'personId',
+ // foreignField: 'resources.userID',
+ // as: 'tasks',
+ // },
+ // },
+ // {
+ // $project: {
+ // tasks: {
+ // resources: {
+ // profilePic: 0,
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$tasks',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'wbs',
+ // localField: 'tasks.wbsId',
+ // foreignField: '_id',
+ // as: 'projectId',
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'tasks.projectId': {
+ // $cond: [
+ // { $ne: ['$projectId', []] },
+ // { $arrayElemAt: ['$projectId', 0] },
+ // '$tasks.projectId',
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // projectId: 0,
+ // tasks: {
+ // projectId: {
+ // _id: 0,
+ // isActive: 0,
+ // modifiedDatetime: 0,
+ // wbsName: 0,
+ // createdDatetime: 0,
+ // __v: 0,
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'tasks.projectId': '$tasks.projectId.projectId',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'taskNotifications',
+ // localField: 'tasks._id',
+ // foreignField: 'taskId',
+ // as: 'tasks.taskNotifications',
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: '$personId',
+ // tasks: {
+ // $push: '$tasks',
+ // },
+ // data: {
+ // $first: '$$ROOT',
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'data.tasks': {
+ // $filter: {
+ // input: '$tasks',
+ // as: 'task',
+ // cond: { $ne: ['$$task', {}] },
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $replaceRoot: {
+ // newRoot: '$data',
+ // },
+ // },
+ // ]);
};
const getTasksForSingleUser = function (userId) {
const pdtstart = moment()
From 3784309815e64465d8210ec6e08ec5b6ef1d4256 Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 3 Jan 2024 17:37:23 -0800
Subject: [PATCH 252/272] fix imports
---
src/helpers/dashboardhelper.js | 2 ++
src/helpers/taskHelper.js | 8 +++++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index dea392e4f..929b5781b 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -3,6 +3,8 @@ 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) {
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 9135f7573..8c45df737 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,6 +1,12 @@
const moment = require('moment-timezone');
const userProfile = require('../models/userProfile');
-const myteam = require('../helpers/helperModels/myTeam');
+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 mongoose = require('mongoose');
const taskHelper = function () {
const getTasksForTeams = async function (userId) {
From 037cc6f1b28407af489643e7a65bd6449001473c Mon Sep 17 00:00:00 2001
From: Carl Bebli
Date: Thu, 4 Jan 2024 13:11:23 +0000
Subject: [PATCH 253/272] took out the cc for review requests
---
src/controllers/taskController.js | 460 +++++++++++++++++-------------
1 file changed, 263 insertions(+), 197 deletions(-)
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index 753dbba11..126d17914 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -1,10 +1,10 @@
-const mongoose = require('mongoose');
-const WBS = require('../models/wbs');
-const UserProfile = require('../models/userProfile');
-const timeEntryHelper = require('../helpers/timeEntryHelper')();
-const taskHelper = require('../helpers/taskHelper')();
-const { hasPermission } = require('../utilities/permissions');
-const emailSender = require('../utilities/emailSender');
+const mongoose = require("mongoose");
+const WBS = require("../models/wbs");
+const UserProfile = require("../models/userProfile");
+const timeEntryHelper = require("../helpers/timeEntryHelper")();
+const taskHelper = require("../helpers/taskHelper")();
+const { hasPermission } = require("../utilities/permissions");
+const emailSender = require("../utilities/emailSender");
const taskController = function (Task) {
const getTasks = (req, res) => {
@@ -17,7 +17,7 @@ const taskController = function (Task) {
const { mother } = req.params;
- if (mother !== '0') {
+ if (mother !== "0") {
query = {
wbsId: { $in: [req.params.wbsId] },
level: { $in: [level] },
@@ -26,16 +26,16 @@ const taskController = function (Task) {
}
Task.find(query)
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
+ .then((results) => res.status(200).send(results))
+ .catch((error) => res.status(404).send(error));
};
const getWBSId = (req, res) => {
const { wbsId } = req.params;
WBS.findById(wbsId)
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
+ .then((results) => res.status(200).send(results))
+ .catch((error) => res.status(404).send(error));
};
const updateSumUp = (
@@ -45,7 +45,7 @@ const taskController = function (Task) {
hoursMost,
hoursLogged,
estimatedHours,
- resources,
+ resources
) => {
Task.findById(taskId, (error, task) => {
task.hoursBest = hoursBest;
@@ -81,10 +81,10 @@ const taskController = function (Task) {
};
const calculateSubTasks = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let sumHoursBest = 0;
let sumHoursWorst = 0;
@@ -96,14 +96,19 @@ const taskController = function (Task) {
childTasks.forEach((childTask) => {
if (childTask.mother.equals(task.taskId)) {
hasChild = true;
- sumHoursBest = parseFloat(childTask.hoursBest, 10) + parseFloat(sumHoursBest, 10);
- sumHoursWorst = parseFloat(childTask.hoursWorst, 10)
- + parseFloat(sumHoursWorst, 10);
- sumHoursMost = parseFloat(childTask.hoursMost, 10) + parseFloat(sumHoursMost, 10);
- sumHoursLogged = parseFloat(childTask.hoursLogged, 10)
- + parseFloat(sumHoursLogged, 10);
- sumEstimatedHours = parseFloat(childTask.estimatedHours, 10)
- + parseFloat(sumEstimatedHours, 10);
+ sumHoursBest =
+ parseFloat(childTask.hoursBest, 10) + parseFloat(sumHoursBest, 10);
+ sumHoursWorst =
+ parseFloat(childTask.hoursWorst, 10) +
+ parseFloat(sumHoursWorst, 10);
+ sumHoursMost =
+ parseFloat(childTask.hoursMost, 10) + parseFloat(sumHoursMost, 10);
+ sumHoursLogged =
+ parseFloat(childTask.hoursLogged, 10) +
+ parseFloat(sumHoursLogged, 10);
+ sumEstimatedHours =
+ parseFloat(childTask.estimatedHours, 10) +
+ parseFloat(sumEstimatedHours, 10);
childTask.resources.forEach((member) => {
let isInResource = false;
resources.forEach((mem) => {
@@ -136,7 +141,7 @@ const taskController = function (Task) {
sumHoursMost,
sumHoursLogged,
sumEstimatedHours,
- resources,
+ resources
);
}
});
@@ -144,10 +149,10 @@ const taskController = function (Task) {
};
const setDatesSubTasks = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let minStartedDate = task.startedDatetime;
let maxDueDatetime = task.dueDatetime;
@@ -178,10 +183,10 @@ const taskController = function (Task) {
};
const calculatePriority = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let totalNumberPriority = 0;
let totalChild = 0;
@@ -190,11 +195,11 @@ const taskController = function (Task) {
if (childTask.mother.equals(task.taskId)) {
hasChild = true;
totalChild += 1;
- if (childTask.priority === 'Primary') {
+ if (childTask.priority === "Primary") {
totalNumberPriority += 3;
- } else if (childTask.priority === 'Secondary') {
+ } else if (childTask.priority === "Secondary") {
totalNumberPriority += 2;
- } else if (childTask.priority === 'Tertiary') {
+ } else if (childTask.priority === "Tertiary") {
totalNumberPriority += 1;
}
}
@@ -207,11 +212,11 @@ const taskController = function (Task) {
if (mainTask._id.equals(task._id)) {
const avg = totalNumberPriority / totalChild;
if (avg <= 1.6) {
- priority = 'Tertiary';
+ priority = "Tertiary";
} else if (avg > 1.6 && avg < 2.5) {
- priority = 'Secondary';
+ priority = "Secondary";
} else {
- priority = 'Primary';
+ priority = "Primary";
}
}
});
@@ -222,10 +227,10 @@ const taskController = function (Task) {
};
const setAssigned = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let isAssigned = false;
let hasChild = false;
@@ -259,7 +264,7 @@ const taskController = function (Task) {
{ wbsId: { $in: [wbsId] } },
],
}).then((tasks) => {
- tasks = [...new Set(tasks.map(item => item))];
+ tasks = [...new Set(tasks.map((item) => item))];
for (let lv = 3; lv > 0; lv -= 1) {
calculateSubTasks(lv, tasks);
setDatesSubTasks(lv, tasks);
@@ -285,18 +290,20 @@ const taskController = function (Task) {
const tasksWithId = tasks.map((task) => {
const _id = new mongoose.Types.ObjectId();
const resources = task.resources.map((resource) => {
- const [name, userID, profilePic] = resource.split('|');
+ const [name, userID, profilePic] = resource.split("|");
return { name, userID, profilePic };
});
return {
- ...task, _id, resources,
+ ...task,
+ _id,
+ resources,
};
});
// update tasks makes sure its parentIds and mother props are correct assigned,
tasksWithId.forEach((task) => {
- const taskNumArr = task.num.split('.');
+ const taskNumArr = task.num.split(".");
switch (task.level) {
case 1: // task.num is x, no parentId1 or mother
task.parentId1 = null; // no parent so its value is null
@@ -305,21 +312,34 @@ const taskController = function (Task) {
task.mother = null;
break;
case 2: // task.num is x.x, only has one level of parent (x)
- task.parentId1 = tasksWithId.find(pTask => pTask.num === taskNumArr[0])._id; // task of parentId1 has num prop of x
+ task.parentId1 = tasksWithId.find(
+ (pTask) => pTask.num === taskNumArr[0]
+ )._id; // task of parentId1 has num prop of x
task.parentId2 = null;
task.parentId3 = null;
task.mother = task.parentId1; // parent task num prop is x
break;
case 3: // task.num is x.x.x, has two levels of parent (parent: x.x and grandparent: x)
- task.parentId1 = tasksWithId.find(pTask => pTask.num === taskNumArr[0])._id; // task of parentId1 has num prop of x
- task.parentId2 = tasksWithId.find(pTask => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`)._id; // task of parentId2 has num prop of x.x
+ task.parentId1 = tasksWithId.find(
+ (pTask) => pTask.num === taskNumArr[0]
+ )._id; // task of parentId1 has num prop of x
+ task.parentId2 = tasksWithId.find(
+ (pTask) => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`
+ )._id; // task of parentId2 has num prop of x.x
task.parentId3 = null;
task.mother = task.parentId2; // parent task num prop is x.x
break;
case 4: // task.num is x.x.x.x, has three levels of parent (x.x.x, x.x and x)
- task.parentId1 = tasksWithId.find(pTask => pTask.num === taskNumArr[0])._id; // x
- task.parentId2 = tasksWithId.find(pTask => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`)._id; // x.x
- task.parentId3 = tasksWithId.find(pTask => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}.${taskNumArr[2]}`)._id; // x.x.x
+ task.parentId1 = tasksWithId.find(
+ (pTask) => pTask.num === taskNumArr[0]
+ )._id; // x
+ task.parentId2 = tasksWithId.find(
+ (pTask) => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`
+ )._id; // x.x
+ task.parentId3 = tasksWithId.find(
+ (pTask) =>
+ pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}.${taskNumArr[2]}`
+ )._id; // x.x.x
task.mother = task.parentId3; // parent task num prop is x.x.x
break;
default:
@@ -327,7 +347,9 @@ const taskController = function (Task) {
});
// create an array of four empty arrays
- const tasksFromSameLevelArr = Array(4).fill(null).map(() => []);
+ const tasksFromSameLevelArr = Array(4)
+ .fill(null)
+ .map(() => []);
// sort them out into an array of four arrays based on their levels
tasksWithId.forEach((task) => {
@@ -358,18 +380,32 @@ const taskController = function (Task) {
task.hoursMost += childTask.hoursMost;
task.hoursLogged += childTask.hoursLogged;
task.estimatedHours += childTask.estimatedHours;
- task.startedDatetime = Math.min(task.startedDatetime, childTask.startedDatetime);
- task.dueDatetime = Math.max(task.dueDatetime, childTask.dueDatetime);
+ task.startedDatetime = Math.min(
+ task.startedDatetime,
+ childTask.startedDatetime
+ );
+ task.dueDatetime = Math.max(
+ task.dueDatetime,
+ childTask.dueDatetime
+ );
task.childrenQty = (task.childrenQty || 0) + 1;
task.isAssigned = task.isAssigned || childTask.isAssigned;
- task.resources = childTask.resources.reduce((resources, childTaskMember) => {
- if (task.resources.every(member => member.name !== childTaskMember.name)) return [...resources, childTaskMember];
- return resources;
- }, [...task.resources]);
+ task.resources = childTask.resources.reduce(
+ (resources, childTaskMember) => {
+ if (
+ task.resources.every(
+ (member) => member.name !== childTaskMember.name
+ )
+ )
+ return [...resources, childTaskMember];
+ return resources;
+ },
+ [...task.resources]
+ );
// add priority pts for task.priority
- if (childTask.priority === 'Primary') {
+ if (childTask.priority === "Primary") {
priorityPts += 3;
- } else if (childTask.priority === 'Secondary') {
+ } else if (childTask.priority === "Secondary") {
priorityPts += 2;
} else {
priorityPts += 1;
@@ -379,11 +415,11 @@ const taskController = function (Task) {
});
const averagePts = priorityPts / task.childrenQty;
if (averagePts >= 2.5) {
- task.priority = 'Primary';
+ task.priority = "Primary";
} else if (averagePts >= 1.6) {
- task.priority = 'Secondary';
+ task.priority = "Secondary";
} else {
- task.priority = 'Tertiary';
+ task.priority = "Tertiary";
}
});
}
@@ -392,10 +428,10 @@ const taskController = function (Task) {
};
const importTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor, 'importTask')) {
+ if (!(await hasPermission(req.body.requestor, "importTask"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new Task.' });
+ .send({ error: "You are not authorized to create new Task." });
return;
}
@@ -407,7 +443,10 @@ const taskController = function (Task) {
const createdDatetime = Date.now();
const modifiedDatetime = Date.now();
const _task = new Task({
- ...task, wbsId, createdDatetime, modifiedDatetime,
+ ...task,
+ wbsId,
+ createdDatetime,
+ modifiedDatetime,
});
_task
@@ -418,20 +457,20 @@ const taskController = function (Task) {
});
});
- res.status(201).send('done');
+ res.status(201).send("done");
};
const postTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor, 'postTask')) {
+ if (!(await hasPermission(req.body.requestor, "postTask"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new Task.' });
+ .send({ error: "You are not authorized to create new Task." });
return;
}
if (!req.body.taskName || !req.body.isActive) {
res.status(400).send({
- error: 'Task Name, Active status, Task Number are mandatory fields',
+ error: "Task Name, Active status, Task Number are mandatory fields",
});
return;
}
@@ -442,7 +481,10 @@ const taskController = function (Task) {
const modifiedDatetime = Date.now();
const _task = new Task({
- ...task, wbsId, createdDatetime, modifiedDatetime,
+ ...task,
+ wbsId,
+ createdDatetime,
+ modifiedDatetime,
});
const saveTask = _task.save();
@@ -451,22 +493,23 @@ const taskController = function (Task) {
return currentwbs.save();
});
- Promise.all([saveTask, saveWbs]).then(results => res.status(201).send(results[0]))
+ Promise.all([saveTask, saveWbs])
+ .then((results) => res.status(201).send(results[0]))
.catch((errors) => {
res.status(400).send(errors);
});
};
const updateNum = async (req, res) => {
- if (!await hasPermission(req.body.requestor, 'updateNum')) {
+ if (!(await hasPermission(req.body.requestor, "updateNum"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new projects.' });
+ .send({ error: "You are not authorized to create new projects." });
return;
}
if (!req.body.nums) {
- res.status(400).send({ error: 'Num is a mandatory fields' });
+ res.status(400).send({ error: "Num is a mandatory fields" });
return;
}
@@ -477,7 +520,7 @@ const taskController = function (Task) {
task
.save()
.then()
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
});
// level 2
@@ -487,13 +530,13 @@ const taskController = function (Task) {
childTasks1.forEach((childTask1) => {
childTask1.num = childTask1.num.replace(
childTask1.num.substring(0, elm.num.length),
- elm.num,
+ elm.num
);
childTask1
.save()
.then(true)
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
// level 3
Task.find({ parentId: { $in: [childTask1._id] } })
@@ -502,13 +545,13 @@ const taskController = function (Task) {
childTasks2.forEach((childTask2) => {
childTask2.num = childTask2.num.replace(
childTask2.num.substring(0, childTask1.num.length),
- childTask1.num,
+ childTask1.num
);
childTask2
.save()
.then(true)
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
// level 4
Task.find({ parentId: { $in: [childTask2._id] } })
@@ -518,27 +561,29 @@ const taskController = function (Task) {
childTask3.num = childTask3.num.replace(
childTask3.num.substring(
0,
- childTask2.num.length,
+ childTask2.num.length
),
- childTask2.num,
+ childTask2.num
);
childTask3
.save()
.then(true)
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) =>
+ res.status(400).send(errors)
+ );
});
}
})
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
});
}
})
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
});
}
})
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
});
res.status(200).send(true);
@@ -548,106 +593,113 @@ const taskController = function (Task) {
if (!req.body.fromNum || !req.body.toNum) {
res
.status(400)
- .send({ error: 'wbsId, fromNum, toNum are mandatory fields' });
+ .send({ error: "wbsId, fromNum, toNum are mandatory fields" });
return;
}
Task.find({ wbsId: { $in: req.params.wbsId } }).then((tasks) => {
- const fromNumArr = req.body.fromNum.replace(/\.0/g, '').split('.');
- const toNumArr = req.body.toNum.replace(/\.0/g, '').split('.');
+ const fromNumArr = req.body.fromNum.replace(/\.0/g, "").split(".");
+ const toNumArr = req.body.toNum.replace(/\.0/g, "").split(".");
const changedLvl = fromNumArr.length;
const fromLastLvl = parseInt(fromNumArr.pop(), 10);
const toLastLvl = parseInt(toNumArr.pop(), 10);
- const leadingLvls = fromNumArr.length ? fromNumArr.join('.').concat('.') : ''; // in a format of x, x.x, or x.x.x, also could be '' if move level one tasks
+ const leadingLvls = fromNumArr.length
+ ? fromNumArr.join(".").concat(".")
+ : ""; // in a format of x, x.x, or x.x.x, also could be '' if move level one tasks
const changingNums = [];
- for (let i = Math.min(fromLastLvl, toLastLvl); i <= Math.max(fromLastLvl, toLastLvl); i += 1) {
+ for (
+ let i = Math.min(fromLastLvl, toLastLvl);
+ i <= Math.max(fromLastLvl, toLastLvl);
+ i += 1
+ ) {
changingNums.push(leadingLvls.concat(`${i}`));
}
const changingNumTasks = tasks.filter((task) => {
- const taskLeadingNum = task.num.split('.').slice(0, changedLvl).join('.');
+ const taskLeadingNum = task.num
+ .split(".")
+ .slice(0, changedLvl)
+ .join(".");
return changingNums.includes(taskLeadingNum);
});
const queries = [];
changingNumTasks.forEach((task) => {
- const taskNumArr = task.num.split('.');
+ const taskNumArr = task.num.split(".");
const taskChanedLvlNum = parseInt(taskNumArr[changedLvl - 1], 10);
let newTaskLastLvl;
if (fromLastLvl > toLastLvl) {
- newTaskLastLvl = taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum + 1;
+ newTaskLastLvl =
+ taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum + 1;
} else {
- newTaskLastLvl = taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum - 1;
+ newTaskLastLvl =
+ taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum - 1;
}
taskNumArr[changedLvl - 1] = String(newTaskLastLvl);
- task.num = taskNumArr.join('.');
+ task.num = taskNumArr.join(".");
queries.push(task.save());
});
Promise.all(queries)
- .then(() => res.status(200).send('Success!'))
- .catch(err => res.status(400).send(err));
+ .then(() => res.status(200).send("Success!"))
+ .catch((err) => res.status(400).send(err));
});
};
const deleteTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor, 'deleteTask')) {
- res
- .status(403)
- .send({ error: 'You are not authorized to deleteTasks.' });
+ if (!(await hasPermission(req.body.requestor, "deleteTask"))) {
+ res.status(403).send({ error: "You are not authorized to deleteTasks." });
return;
}
const { taskId } = req.params;
const { mother } = req.params;
- const removeChildTasks = Task.find(
- {
- $or: [
- { _id: taskId },
- { parentId1: taskId },
- { parentId2: taskId },
- { parentId3: taskId },
- ],
- },
- )
- .then((record) => {
- if (!record || record === null || record.length === 0) return res.status(400).send({ error: 'No valid records found' });
- const removeTasks = record.map(rec => rec.remove());
- return removeTasks;
+ const removeChildTasks = Task.find({
+ $or: [
+ { _id: taskId },
+ { parentId1: taskId },
+ { parentId2: taskId },
+ { parentId3: taskId },
+ ],
+ }).then((record) => {
+ if (!record || record === null || record.length === 0)
+ return res.status(400).send({ error: "No valid records found" });
+ const removeTasks = record.map((rec) => rec.remove());
+ return removeTasks;
});
- const updateMotherChildrenQty = mother !== 'null'
- ? Task.findById(mother).then((task) => {
- let newQty = 0;
- let child = true;
- if (task.childrenQty > 0) {
- newQty = task.childrenQty - 1;
- if (newQty === 0) {
- child = false;
+ const updateMotherChildrenQty =
+ mother !== "null"
+ ? Task.findById(mother).then((task) => {
+ let newQty = 0;
+ let child = true;
+ if (task.childrenQty > 0) {
+ newQty = task.childrenQty - 1;
+ if (newQty === 0) {
+ child = false;
+ }
}
- }
- task.hasChild = child;
- task.childrenQty = newQty;
- return task.save();
- })
- : Promise.resolve(1);
-
- Promise
- .all([removeChildTasks, updateMotherChildrenQty])
- .then(() => res.status(200).send({ message: 'Task successfully deleted' })) // no need to resetNum(taskId, mother);
- .catch(errors => res.status(400).send(errors));
+ task.hasChild = child;
+ task.childrenQty = newQty;
+ return task.save();
+ })
+ : Promise.resolve(1);
+
+ Promise.all([removeChildTasks, updateMotherChildrenQty])
+ .then(() =>
+ res.status(200).send({ message: "Task successfully deleted" })
+ ) // no need to resetNum(taskId, mother);
+ .catch((errors) => res.status(400).send(errors));
};
const deleteTaskByWBS = async (req, res) => {
- if (!await hasPermission(req.body.requestor, 'deleteTask')) {
- res
- .status(403)
- .send({ error: 'You are not authorized to deleteTasks.' });
+ if (!(await hasPermission(req.body.requestor, "deleteTask"))) {
+ res.status(403).send({ error: "You are not authorized to deleteTasks." });
return;
}
@@ -655,7 +707,7 @@ const taskController = function (Task) {
Task.find({ wbsId: { $in: [wbsId] } }, (error, record) => {
if (error || !record || record === null || record.length === 0) {
- res.status(400).send({ error: 'No valid records found' });
+ res.status(400).send({ error: "No valid records found" });
return;
}
@@ -665,7 +717,9 @@ const taskController = function (Task) {
});
Promise.all([...removeTasks])
- .then(() => res.status(200).send({ message: ' Tasks were successfully deleted' }))
+ .then(() =>
+ res.status(200).send({ message: " Tasks were successfully deleted" })
+ )
.catch((errors) => {
res.status(400).send(errors);
});
@@ -675,8 +729,8 @@ const taskController = function (Task) {
};
const updateTask = async (req, res) => {
- if (!await hasPermission(req.body.requestor, 'updateTask')) {
- res.status(403).send({ error: 'You are not authorized to update Task.' });
+ if (!(await hasPermission(req.body.requestor, "updateTask"))) {
+ res.status(403).send({ error: "You are not authorized to update Task." });
return;
}
@@ -684,46 +738,46 @@ const taskController = function (Task) {
Task.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(taskId) },
- { ...req.body, modifiedDatetime: Date.now() },
+ { ...req.body, modifiedDatetime: Date.now() }
)
.then(() => res.status(201).send())
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
};
const swap = async function (req, res) {
- if (!await hasPermission(req.body.requestor, 'swapTask')) {
+ if (!(await hasPermission(req.body.requestor, "swapTask"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new projects.' });
+ .send({ error: "You are not authorized to create new projects." });
return;
}
if (!req.body.taskId1 || !req.body.taskId2) {
res
.status(400)
- .send({ error: 'taskId1 and taskId2 are mandatory fields' });
+ .send({ error: "taskId1 and taskId2 are mandatory fields" });
return;
}
Task.findById(req.body.taskId1, (error1, task1) => {
if (error1 || task1 === null) {
- res.status(400).send('No valid records found');
+ res.status(400).send("No valid records found");
return;
}
Task.findById(req.body.taskId2, (error2, task2) => {
if (error2 || task2 === null) {
- res.status(400).send('No valid records found');
+ res.status(400).send("No valid records found");
return;
}
if (task1.parentId.toString() === task2.parentId.toString()) {
- let tmpNum = '';
+ let tmpNum = "";
tmpNum = task1.num;
task1.num = task2.num;
task2.num = tmpNum;
} else {
- let tmpName = '';
+ let tmpName = "";
tmpName = task1.taskName;
task1.taskName = task2.taskName;
task2.taskName = tmpName;
@@ -732,53 +786,62 @@ const taskController = function (Task) {
task1
.save()
.then()
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
task2
.save()
.then()
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
Task.find({
wbsId: { $in: [task1.wbsId] },
})
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
+ .then((results) => res.status(200).send(results))
+ .catch((error) => res.status(404).send(error));
});
});
};
const getTaskById = async (req, res) => {
try {
- const taskId = req.params.id;
+ const taskId = req.params.id;
- // Ensure the task ID is provided
- if (!taskId || taskId === 'undefined') {
- return res.status(400).send({ error: 'Task ID is missing' });
- }
+ // Ensure the task ID is provided
+ if (!taskId || taskId === "undefined") {
+ return res.status(400).send({ error: "Task ID is missing" });
+ }
- const task = await Task.findById(taskId, '-__v -createdDatetime -modifiedDatetime');
+ const task = await Task.findById(
+ taskId,
+ "-__v -createdDatetime -modifiedDatetime"
+ );
- if (!task) {
- return res.status(400).send({ error: 'This is not a valid task' });
- }
+ if (!task) {
+ return res.status(400).send({ error: "This is not a valid task" });
+ }
- const hoursLogged = await timeEntryHelper.getAllHoursLoggedForSpecifiedProject(taskId);
- task.set('hoursLogged', hoursLogged, { strict: false });
+ const hoursLogged =
+ await timeEntryHelper.getAllHoursLoggedForSpecifiedProject(taskId);
+ task.set("hoursLogged", hoursLogged, { strict: false });
- // Fetch the resource names for all resources
- const resourceNamesPromises = task.resources.map(resource => taskHelper.getUserProfileFirstAndLastName(resource.userID));
- const resourceNames = await Promise.all(resourceNamesPromises);
+ // Fetch the resource names for all resources
+ const resourceNamesPromises = task.resources.map((resource) =>
+ taskHelper.getUserProfileFirstAndLastName(resource.userID)
+ );
+ const resourceNames = await Promise.all(resourceNamesPromises);
- // Update the task's resources with the fetched names
- task.resources.forEach((resource, index) => {
- resource.name = resourceNames[index] !== ' ' ? resourceNames[index] : resource.name;
- });
+ // Update the task's resources with the fetched names
+ task.resources.forEach((resource, index) => {
+ resource.name =
+ resourceNames[index] !== " " ? resourceNames[index] : resource.name;
+ });
- res.status(200).send(task);
+ res.status(200).send(task);
} catch (error) {
- // Generic error message, you can adjust as needed
- res.status(500).send({ error: 'Internal Server Error', details: error.message });
+ // Generic error message, you can adjust as needed
+ res
+ .status(500)
+ .send({ error: "Internal Server Error", details: error.message });
}
};
@@ -787,39 +850,40 @@ const taskController = function (Task) {
try {
Task.find({ wbsId: { $in: [wbsId] } }).then((tasks) => {
- tasks = tasks.filter(task => task.level === 1);
+ tasks = tasks.filter((task) => task.level === 1);
tasks.forEach((task) => {
updateParents(task.wbsId, task.taskId.toString());
});
- res.status(200).send('done');
+ res.status(200).send("done");
});
- res.status(200).send('done');
+ res.status(200).send("done");
} catch (error) {
res.status(400).send(error);
}
};
const fixTasks = function (req, res) {
- res.status(200).send('done');
+ res.status(200).send("done");
};
const getTasksByUserId = async (req, res) => {
const { userId } = req.params;
try {
- Task.find({
- 'resources.userID': mongoose.Types.ObjectId(userId),
- }, '-resources.profilePic')
- .then((results) => {
+ Task.find(
+ {
+ "resources.userID": mongoose.Types.ObjectId(userId),
+ },
+ "-resources.profilePic"
+ ).then((results) => {
WBS.find({
- _id: { $in: results.map(item => item.wbsId) },
+ _id: { $in: results.map((item) => item.wbsId) },
}).then((WBSs) => {
const resultsWithProjectsIds = results.map((item) => {
item.set(
- 'projectId',
- WBSs?.find(
- wbs => wbs._id.toString() === item.wbsId.toString(),
- )?.projectId,
- { strict: false },
+ "projectId",
+ WBSs?.find((wbs) => wbs._id.toString() === item.wbsId.toString())
+ ?.projectId,
+ { strict: false }
);
return item;
});
@@ -838,7 +902,9 @@ const taskController = function (Task) {
if (teamsData.length > 0) {
res.status(200).send(teamsData);
} else {
- const singleUserData = await taskHelper.getTasksForSingleUser(userId).exec();
+ const singleUserData = await taskHelper
+ .getTasksForSingleUser(userId)
+ .exec();
res.status(200).send(singleUserData);
}
} catch (error) {
@@ -852,10 +918,10 @@ const taskController = function (Task) {
Task.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(taskId) },
- { ...req.body, modifiedDatetime: Date.now() },
+ { ...req.body, modifiedDatetime: Date.now() }
)
.then(() => res.status(201).send())
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
};
const getReviewReqEmailBody = function (name, taskName) {
@@ -871,9 +937,11 @@ const taskController = function (Task) {
const getRecipients = async function (myUserId) {
const recipients = [];
const user = await UserProfile.findById(myUserId);
- const membership = await UserProfile.find({ role: { $in: ['Administrator', 'Manager', 'Mentor'] } });
+ const membership = await UserProfile.find({
+ role: { $in: ["Administrator", "Manager", "Mentor"] },
+ });
membership.forEach((member) => {
- if (member.teams.some(team => user.teams.includes(team))) {
+ if (member.teams.some((team) => user.teams.includes(team))) {
recipients.push(member.email);
}
});
@@ -881,9 +949,7 @@ const taskController = function (Task) {
};
const sendReviewReq = async function (req, res) {
- const {
- myUserId, name, taskName,
- } = req.body;
+ const { myUserId, name, taskName } = req.body;
const emailBody = getReviewReqEmailBody(name, taskName);
const recipients = await getRecipients(myUserId);
@@ -892,12 +958,12 @@ const taskController = function (Task) {
recipients,
`Review Request from ${name}`,
emailBody,
- 'highestgoodnetwork@gmail.com',
null,
+ null
);
- res.status(200).send('Success');
+ res.status(200).send("Success");
} catch (err) {
- res.status(500).send('Failed');
+ res.status(500).send("Failed");
}
};
From ae8bb2bb6119d644aa683ee62eb67881b2b6dcd3 Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Fri, 5 Jan 2024 22:07:22 -0600
Subject: [PATCH 254/272] revert lint
---
.../bmdashboard/bmMaterialsController.js | 90 +++---
src/controllers/dashBoardController.js | 2 +-
src/controllers/mapLocationsController.js | 45 +--
.../profileInitialSetupController.js | 42 +--
src/controllers/reasonSchedulingController.js | 45 +--
src/controllers/taskController.js | 303 ++++++++++--------
src/controllers/teamController.js | 4 +-
src/helpers/dashboardhelper.js | 126 ++++----
src/helpers/taskHelper.js | 176 +++++-----
src/models/mapLocation.js | 4 +-
src/routes/bmdashboard/bmMaterialsRouter.js | 6 +-
src/routes/mapLocationsRouter.js | 2 +-
src/routes/profileInitialSetupRouter.js | 4 +-
src/startup/routes.js | 2 +-
src/utilities/emailSender.js | 12 +-
15 files changed, 461 insertions(+), 402 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index da45aad1d..911ca0b55 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,6 +1,6 @@
const mongoose = require('mongoose');
-const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
+const bmMaterialsController = function (ItemMaterial,BuildingMaterial) {
const bmMaterialsList = async function _matsList(req, res) {
try {
BuildingMaterial.find()
@@ -91,20 +91,25 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
};
const bmPostMaterialUpdateRecord = function (req, res) {
- const payload = req.body;
+ let payload = req.body;
let quantityUsed = +req.body.quantityUsed;
let quantityWasted = +req.body.quantityWasted;
- const { material } = req.body;
- if (payload.QtyUsedLogUnit == 'percent' && quantityWasted >= 0) {
+ let material = req.body.material;
+ if(payload.QtyUsedLogUnit=='percent' && quantityWasted>=0)
+ {
quantityUsed = +((+quantityUsed / 100) * material.stockAvailable).toFixed(4);
}
- if (payload.QtyWastedLogUnit == 'percent' && quantityUsed >= 0) {
+ if(payload.QtyWastedLogUnit=='percent' && quantityUsed>=0)
+ {
quantityWasted = +((+quantityWasted / 100) * material.stockAvailable).toFixed(4);
}
- if (quantityUsed > material.stockAvailable || quantityWasted > material.stockAvailable || (quantityUsed + quantityWasted) > material.stockAvailable) {
- res.status(500).send('Please check the used and wasted stock values. Either individual values or their sum exceeds the total stock available.');
- } else {
+ if(quantityUsed>material.stockAvailable || quantityWasted>material.stockAvailable || (quantityUsed+quantityWasted)>material.stockAvailable)
+ {
+ res.status(500).send('Please check the used and wasted stock values. Either individual values or their sum exceeds the total stock available.')
+ }
+ else
+ {
let newStockUsed = +material.stockUsed + parseFloat(quantityUsed);
let newStockWasted = +material.stockWasted + parseFloat(quantityWasted);
let newAvailable = +material.stockAvailable - parseFloat(quantityUsed) - parseFloat(quantityWasted);
@@ -113,42 +118,45 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
newAvailable = parseFloat(newAvailable.toFixed(4));
BuildingMaterial.updateOne(
{ _id: req.body.material._id },
-
+
{
$set: {
- stockUsed: newStockUsed,
- stockWasted: newStockWasted,
- stockAvailable: newAvailable,
+ 'stockUsed': newStockUsed,
+ 'stockWasted': newStockWasted,
+ 'stockAvailable': newAvailable
},
$push: {
updateRecord: {
date: req.body.date,
createdBy: req.body.requestor.requestorId,
- quantityUsed,
- quantityWasted,
+ quantityUsed: quantityUsed,
+ quantityWasted: quantityWasted
},
- },
- },
-
+ }
+ }
+
)
- .then((results) => { res.status(200).send(results); })
- .catch(error => res.status(500).send({ message: error }));
+ .then(results => {res.status(200).send(results)})
+ .catch(error => res.status(500).send({'message':error}));
}
};
const bmPostMaterialUpdateBulk = function (req, res) {
- const materialUpdates = req.body.upadateMaterials;
+ const materialUpdates= req.body.upadateMaterials;
let errorFlag = false;
const updateRecordsToBeAdded = [];
- for (let i = 0; i < materialUpdates.length; i++) {
- const payload = materialUpdates[i];
+ for(let i=0;i= 0) {
+ let material = payload.material;
+ if(payload.QtyUsedLogUnit=='percent' && quantityWasted>=0)
+ {
quantityUsed = +((+quantityUsed / 100) * material.stockAvailable).toFixed(4);
}
- if (payload.QtyWastedLogUnit == 'percent' && quantityUsed >= 0) {
+ if(payload.QtyWastedLogUnit=='percent' && quantityUsed>=0)
+ {
quantityWasted = +((+quantityWasted / 100) * material.stockAvailable).toFixed(4);
}
@@ -158,36 +166,38 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
newStockUsed = parseFloat(newStockUsed.toFixed(4));
newStockWasted = parseFloat(newStockWasted.toFixed(4));
newAvailable = parseFloat(newAvailable.toFixed(4));
- if (newAvailable < 0) {
+ if(newAvailable<0)
+ {
errorFlag = true;
break;
}
- updateRecordsToBeAdded.push({
+ updateRecordsToBeAdded.push ({
updateId: material._id,
set: {
- stockUsed: newStockUsed,
- stockWasted: newStockWasted,
- stockAvailable: newAvailable,
+ 'stockUsed': newStockUsed,
+ 'stockWasted': newStockWasted,
+ 'stockAvailable': newAvailable
},
updateValue: {
createdBy: req.body.requestor.requestorId,
- quantityUsed,
- quantityWasted,
+ quantityUsed: quantityUsed,
+ quantityWasted: quantityWasted,
date: req.body.date,
- },
-});
+ }});
+
}
try {
- if (errorFlag) {
- res.status(500).send('Stock quantities submitted seems to be invalid');
+ if(errorFlag)
+ {
+ res.status(500).send('Stock quantities submitted seems to be invalid')
return;
}
const updatePromises = updateRecordsToBeAdded.map(updateItem => BuildingMaterial.updateOne(
{ _id: updateItem.updateId },
- {
- $set: updateItem.set,
- $push: { updateRecord: updateItem.updateValue },
+ {
+ $set : updateItem.set,
+ $push: { updateRecord: updateItem.updateValue }
},
).exec());
Promise.all(updatePromises)
@@ -203,7 +213,7 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
bmMaterialsList,
bmPostMaterialUpdateRecord,
bmPostMaterialUpdateBulk,
- bmPurchaseMaterials,
+ bmPurchaseMaterials
};
};
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 1cf730a5a..3fdda9eb7 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -211,7 +211,7 @@ const dashboardcontroller = function () {
null,
null,
email,
- null,
+ null
);
res.status(200).send('Success');
} catch {
diff --git a/src/controllers/mapLocationsController.js b/src/controllers/mapLocationsController.js
index 76fad59f9..29af9e3d6 100644
--- a/src/controllers/mapLocationsController.js
+++ b/src/controllers/mapLocationsController.js
@@ -4,15 +4,17 @@ const cache = require('../utilities/nodeCache')();
const mapLocationsController = function (MapLocation) {
const getAllLocations = async function (req, res) {
+
try {
const users = [];
const results = await UserProfile.find({},
- '_id firstName lastName isActive location jobTitle totalTangibleHrs hoursByCategory');
+ '_id firstName lastName isActive location jobTitle totalTangibleHrs hoursByCategory'
+ );
results.forEach((item) => {
if (
- (item.location?.coords.lat && item.location?.coords.lng && item.totalTangibleHrs >= 10)
- || (item.location?.coords.lat && item.location?.coords.lng && calculateTotalHours(item.hoursByCategory) >= 10)
+ (item.location?.coords.lat && item.location?.coords.lng && item.totalTangibleHrs >= 10) ||
+ (item.location?.coords.lat && item.location?.coords.lng && calculateTotalHours(item.hoursByCategory) >= 10)
) {
users.push(item);
}
@@ -23,7 +25,7 @@ const mapLocationsController = function (MapLocation) {
jobTitle: item.jobTitle[0],
_id: item._id,
firstName: item.firstName,
- lastName: item.lastName,
+ lastName: item.lastName
}));
const mUsers = await MapLocation.find({});
@@ -31,19 +33,22 @@ const mapLocationsController = function (MapLocation) {
} catch (err) {
res.status(404).send(err);
}
+
};
const deleteLocation = async function (req, res) {
+
if (!req.body.requestor.role === 'Administrator' || !req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
}
- const { locationId } = req.params;
+ const locationId = req.params.locationId
MapLocation.findOneAndDelete({ _id: locationId })
- .then(() => res.status(200).send({ message: 'The location was successfully removed!' }))
+ .then(() => res.status(200).send({ message: "The location was successfully removed!" }))
.catch(error => res.status(500).send({ message: error || "Couldn't remove the location" }));
};
const putUserLocation = async function (req, res) {
+
if (!req.body.requestor.role === 'Owner') {
res.status(403).send('You are not authorized to make changes in the teams.');
return;
@@ -53,17 +58,17 @@ const mapLocationsController = function (MapLocation) {
lastName: req.body.lastName,
jobTitle: req.body.jobTitle,
location: req.body.location,
- };
+ }
const location = new MapLocation(locationData);
try {
- const response = await location.save();
+ const response = await location.save()
if (!response) {
- throw new Error('Something went wrong during saving the location...');
+ throw new Error('Something went wrong during saving the location...')
}
res.status(200).send(response);
} catch (err) {
- console.log(err.message);
+ console.log(err.message)
res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
@@ -79,26 +84,26 @@ const mapLocationsController = function (MapLocation) {
lastName: req.body.lastName,
jobTitle: req.body.jobTitle,
location: req.body.location,
- };
+ }
if (req.body.timeZone) {
- updateData.timeZone = req.body.timeZone;
+ updateData.timeZone = req.body.timeZone
}
try {
let response;
if (userType === 'user') {
response = await UserProfile.findOneAndUpdate({ _id: userId }, { $set: { ...updateData, jobTitle: [updateData.jobTitle] } }, { new: true });
- cache.removeCache('allusers');
+ cache.removeCache('allusers')
cache.removeCache(`user-${userId}`);
cache.setCache(`user-${userId}`, JSON.stringify(response));
} else {
- response = await MapLocation.findOneAndUpdate({ _id: userId }, { $set: updateData }, { new: true });
+ response = await MapLocation.findOneAndUpdate({ _id: userId }, { $set: updateData }, { new: true })
}
if (!response) {
- throw new Error('Something went wrong during saving the location...');
+ throw new Error('Something went wrong during saving the location...')
}
const newData = {
firstName: response.firstName,
@@ -106,12 +111,12 @@ const mapLocationsController = function (MapLocation) {
jobTitle: response.jobTitle,
location: response.location,
_id: response._id,
- type: userType,
- };
+ type: userType
+ }
res.status(200).send(newData);
} catch (err) {
- console.log(err.message);
+ console.log(err.message)
res.status(500).json({ message: err.message || 'Something went wrong...' });
}
};
@@ -123,12 +128,12 @@ const mapLocationsController = function (MapLocation) {
});
return hours;
}
-
+
return {
getAllLocations,
deleteLocation,
putUserLocation,
- updateUserLocation,
+ updateUserLocation
};
};
diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js
index 84f801671..12776442e 100644
--- a/src/controllers/profileInitialSetupController.js
+++ b/src/controllers/profileInitialSetupController.js
@@ -76,7 +76,8 @@ function informManagerMessage(user) {
return message;
}
-const sendEmailWithAcknowledgment = (email, subject, message) => new Promise((resolve, reject) => {
+const sendEmailWithAcknowledgment = (email, subject, message) => {
+ return new Promise((resolve, reject) => {
emailSender(
email,
subject,
@@ -84,31 +85,33 @@ const sendEmailWithAcknowledgment = (email, subject, message) => new Promise((re
null,
null,
null,
- (error, result) => {
- if (result) resolve(result);
- if (error) reject(result);
- },
+ (error,result) => {
+ if (result) resolve(result)
+ if (error) reject(result)
+ }
);
});
+};
const profileInitialSetupController = function (
ProfileInitialSetupToken,
userProfile,
Project,
- MapLocation,
+ MapLocation
) {
const { JWT_SECRET } = config;
const setMapLocation = async (locationData) => {
+
const location = new MapLocation(locationData);
try {
- const response = await location.save();
- return response;
+ const response = await location.save()
+ return response
} catch (err) {
- return { type: 'Error', message: err.message || 'An error occurred while saving the location' };
+ return {type: "Error", message: err.message || 'An error occurred while saving the location'}
}
- };
+ }
/*
Function to handle token generation and email process:
@@ -143,10 +146,10 @@ const profileInitialSetupController = function (
const acknowledgment = await sendEmailWithAcknowledgment(
email,
- 'NEEDED: Complete your One Community profile setup',
- sendLinkMessage(link),
+ "NEEDED: Complete your One Community profile setup",
+ sendLinkMessage(link)
);
-
+
res.status(200).send(acknowledgment);
}
} catch (error) {
@@ -275,15 +278,15 @@ const profileInitialSetupController = function (
lastName: req.body.lastName,
jobTitle: req.body.jobTitle,
location: req.body.homeCountry,
- };
+ }
res.send({ token }).status(200);
- const mapEntryResult = await setMapLocation(locationData);
- if (mapEntryResult.type === 'Error') {
- console.log(mapEntryResult.message);
+ const mapEntryResult = await setMapLocation(locationData)
+ if(mapEntryResult.type === "Error"){
+ console.log(mapEntryResult.message)
}
-
+
const NewUserCache = {
permissions: savedUser.permissions,
isActive: true,
@@ -324,10 +327,11 @@ const profileInitialSetupController = function (
if (foundToken) {
res.status(200).send({ userAPIKey: premiumKey });
} else {
- res.status(403).send('Unauthorized Request');
+ res.status(403).send("Unauthorized Request");
}
};
+
return {
getSetupToken,
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 6f872f338..e310049c2 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -2,7 +2,7 @@
const moment = require('moment-timezone');
const UserModel = require('../models/userProfile');
const ReasonModel = require('../models/reason');
-const emailSender = require('../utilities/emailSender');
+const emailSender = require("../utilities/emailSender");
const postReason = async (req, res) => {
@@ -39,7 +39,7 @@ const postReason = async (req, res) => {
});
}
- // 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({
@@ -86,11 +86,13 @@ const postReason = async (req, res) => {
userId,
});
-
- // await newReason.save();
+
+ //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.
+ 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 emailBody = ` Hi !
@@ -102,18 +104,19 @@ const postReason = async (req, res) => {
Thank you,
One Community
`;
-
-
+
+
// 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null);
- // 2 user email -
+ // 2 user email -
emailSender(`${foundUser.email}`, subject, emailBody, null, null);
- // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email)
+ //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({
@@ -256,10 +259,12 @@ const patchReason = async (req, res) => {
}
foundReason.reason = reasonData.message;
-
+
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.
+ 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 emailBody = ` Hi !
@@ -271,15 +276,17 @@ const patchReason = async (req, res) => {
Thank you,
One Community
`;
-
-
+
+
// 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null);
- // 2 user email -
+ // 2 user email -
emailSender(`${foundUser.email}`, subject, emailBody, null, null);
- // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email)
+ //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({
@@ -297,7 +304,7 @@ const deleteReason = async (req, res) => {
const { reasonData, requestor } = req.body;
const { userId } = req.params;
- // error case 1
+ //error case 1
if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') {
return res.status(403).json({
message:
diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js
index a91a2b90d..126d17914 100644
--- a/src/controllers/taskController.js
+++ b/src/controllers/taskController.js
@@ -1,10 +1,10 @@
-const mongoose = require('mongoose');
-const WBS = require('../models/wbs');
-const UserProfile = require('../models/userProfile');
-const timeEntryHelper = require('../helpers/timeEntryHelper')();
-const taskHelper = require('../helpers/taskHelper')();
-const { hasPermission } = require('../utilities/permissions');
-const emailSender = require('../utilities/emailSender');
+const mongoose = require("mongoose");
+const WBS = require("../models/wbs");
+const UserProfile = require("../models/userProfile");
+const timeEntryHelper = require("../helpers/timeEntryHelper")();
+const taskHelper = require("../helpers/taskHelper")();
+const { hasPermission } = require("../utilities/permissions");
+const emailSender = require("../utilities/emailSender");
const taskController = function (Task) {
const getTasks = (req, res) => {
@@ -17,7 +17,7 @@ const taskController = function (Task) {
const { mother } = req.params;
- if (mother !== '0') {
+ if (mother !== "0") {
query = {
wbsId: { $in: [req.params.wbsId] },
level: { $in: [level] },
@@ -26,16 +26,16 @@ const taskController = function (Task) {
}
Task.find(query)
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
+ .then((results) => res.status(200).send(results))
+ .catch((error) => res.status(404).send(error));
};
const getWBSId = (req, res) => {
const { wbsId } = req.params;
WBS.findById(wbsId)
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
+ .then((results) => res.status(200).send(results))
+ .catch((error) => res.status(404).send(error));
};
const updateSumUp = (
@@ -45,7 +45,7 @@ const taskController = function (Task) {
hoursMost,
hoursLogged,
estimatedHours,
- resources,
+ resources
) => {
Task.findById(taskId, (error, task) => {
task.hoursBest = hoursBest;
@@ -81,10 +81,10 @@ const taskController = function (Task) {
};
const calculateSubTasks = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let sumHoursBest = 0;
let sumHoursWorst = 0;
@@ -96,14 +96,19 @@ const taskController = function (Task) {
childTasks.forEach((childTask) => {
if (childTask.mother.equals(task.taskId)) {
hasChild = true;
- sumHoursBest = parseFloat(childTask.hoursBest, 10) + parseFloat(sumHoursBest, 10);
- sumHoursWorst = parseFloat(childTask.hoursWorst, 10)
- + parseFloat(sumHoursWorst, 10);
- sumHoursMost = parseFloat(childTask.hoursMost, 10) + parseFloat(sumHoursMost, 10);
- sumHoursLogged = parseFloat(childTask.hoursLogged, 10)
- + parseFloat(sumHoursLogged, 10);
- sumEstimatedHours = parseFloat(childTask.estimatedHours, 10)
- + parseFloat(sumEstimatedHours, 10);
+ sumHoursBest =
+ parseFloat(childTask.hoursBest, 10) + parseFloat(sumHoursBest, 10);
+ sumHoursWorst =
+ parseFloat(childTask.hoursWorst, 10) +
+ parseFloat(sumHoursWorst, 10);
+ sumHoursMost =
+ parseFloat(childTask.hoursMost, 10) + parseFloat(sumHoursMost, 10);
+ sumHoursLogged =
+ parseFloat(childTask.hoursLogged, 10) +
+ parseFloat(sumHoursLogged, 10);
+ sumEstimatedHours =
+ parseFloat(childTask.estimatedHours, 10) +
+ parseFloat(sumEstimatedHours, 10);
childTask.resources.forEach((member) => {
let isInResource = false;
resources.forEach((mem) => {
@@ -136,7 +141,7 @@ const taskController = function (Task) {
sumHoursMost,
sumHoursLogged,
sumEstimatedHours,
- resources,
+ resources
);
}
});
@@ -144,10 +149,10 @@ const taskController = function (Task) {
};
const setDatesSubTasks = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let minStartedDate = task.startedDatetime;
let maxDueDatetime = task.dueDatetime;
@@ -178,10 +183,10 @@ const taskController = function (Task) {
};
const calculatePriority = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let totalNumberPriority = 0;
let totalChild = 0;
@@ -190,11 +195,11 @@ const taskController = function (Task) {
if (childTask.mother.equals(task.taskId)) {
hasChild = true;
totalChild += 1;
- if (childTask.priority === 'Primary') {
+ if (childTask.priority === "Primary") {
totalNumberPriority += 3;
- } else if (childTask.priority === 'Secondary') {
+ } else if (childTask.priority === "Secondary") {
totalNumberPriority += 2;
- } else if (childTask.priority === 'Tertiary') {
+ } else if (childTask.priority === "Tertiary") {
totalNumberPriority += 1;
}
}
@@ -207,11 +212,11 @@ const taskController = function (Task) {
if (mainTask._id.equals(task._id)) {
const avg = totalNumberPriority / totalChild;
if (avg <= 1.6) {
- priority = 'Tertiary';
+ priority = "Tertiary";
} else if (avg > 1.6 && avg < 2.5) {
- priority = 'Secondary';
+ priority = "Secondary";
} else {
- priority = 'Primary';
+ priority = "Primary";
}
}
});
@@ -222,10 +227,10 @@ const taskController = function (Task) {
};
const setAssigned = (level, tasks) => {
- const parentTasks = tasks.filter(task => task.level === level);
+ const parentTasks = tasks.filter((task) => task.level === level);
parentTasks.forEach((task) => {
const childTasks = tasks.filter(
- taskChild => taskChild.level === level + 1,
+ (taskChild) => taskChild.level === level + 1
);
let isAssigned = false;
let hasChild = false;
@@ -259,7 +264,7 @@ const taskController = function (Task) {
{ wbsId: { $in: [wbsId] } },
],
}).then((tasks) => {
- tasks = [...new Set(tasks.map(item => item))];
+ tasks = [...new Set(tasks.map((item) => item))];
for (let lv = 3; lv > 0; lv -= 1) {
calculateSubTasks(lv, tasks);
setDatesSubTasks(lv, tasks);
@@ -285,7 +290,7 @@ const taskController = function (Task) {
const tasksWithId = tasks.map((task) => {
const _id = new mongoose.Types.ObjectId();
const resources = task.resources.map((resource) => {
- const [name, userID, profilePic] = resource.split('|');
+ const [name, userID, profilePic] = resource.split("|");
return { name, userID, profilePic };
});
@@ -298,7 +303,7 @@ const taskController = function (Task) {
// update tasks makes sure its parentIds and mother props are correct assigned,
tasksWithId.forEach((task) => {
- const taskNumArr = task.num.split('.');
+ const taskNumArr = task.num.split(".");
switch (task.level) {
case 1: // task.num is x, no parentId1 or mother
task.parentId1 = null; // no parent so its value is null
@@ -308,7 +313,7 @@ const taskController = function (Task) {
break;
case 2: // task.num is x.x, only has one level of parent (x)
task.parentId1 = tasksWithId.find(
- pTask => pTask.num === taskNumArr[0],
+ (pTask) => pTask.num === taskNumArr[0]
)._id; // task of parentId1 has num prop of x
task.parentId2 = null;
task.parentId3 = null;
@@ -316,23 +321,24 @@ const taskController = function (Task) {
break;
case 3: // task.num is x.x.x, has two levels of parent (parent: x.x and grandparent: x)
task.parentId1 = tasksWithId.find(
- pTask => pTask.num === taskNumArr[0],
+ (pTask) => pTask.num === taskNumArr[0]
)._id; // task of parentId1 has num prop of x
task.parentId2 = tasksWithId.find(
- pTask => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`,
+ (pTask) => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`
)._id; // task of parentId2 has num prop of x.x
task.parentId3 = null;
task.mother = task.parentId2; // parent task num prop is x.x
break;
case 4: // task.num is x.x.x.x, has three levels of parent (x.x.x, x.x and x)
task.parentId1 = tasksWithId.find(
- pTask => pTask.num === taskNumArr[0],
+ (pTask) => pTask.num === taskNumArr[0]
)._id; // x
task.parentId2 = tasksWithId.find(
- pTask => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`,
+ (pTask) => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}`
)._id; // x.x
task.parentId3 = tasksWithId.find(
- pTask => pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}.${taskNumArr[2]}`,
+ (pTask) =>
+ pTask.num === `${taskNumArr[0]}.${taskNumArr[1]}.${taskNumArr[2]}`
)._id; // x.x.x
task.mother = task.parentId3; // parent task num prop is x.x.x
break;
@@ -376,11 +382,11 @@ const taskController = function (Task) {
task.estimatedHours += childTask.estimatedHours;
task.startedDatetime = Math.min(
task.startedDatetime,
- childTask.startedDatetime,
+ childTask.startedDatetime
);
task.dueDatetime = Math.max(
task.dueDatetime,
- childTask.dueDatetime,
+ childTask.dueDatetime
);
task.childrenQty = (task.childrenQty || 0) + 1;
task.isAssigned = task.isAssigned || childTask.isAssigned;
@@ -388,17 +394,18 @@ const taskController = function (Task) {
(resources, childTaskMember) => {
if (
task.resources.every(
- member => member.name !== childTaskMember.name,
+ (member) => member.name !== childTaskMember.name
)
- ) return [...resources, childTaskMember];
+ )
+ return [...resources, childTaskMember];
return resources;
},
- [...task.resources],
+ [...task.resources]
);
// add priority pts for task.priority
- if (childTask.priority === 'Primary') {
+ if (childTask.priority === "Primary") {
priorityPts += 3;
- } else if (childTask.priority === 'Secondary') {
+ } else if (childTask.priority === "Secondary") {
priorityPts += 2;
} else {
priorityPts += 1;
@@ -408,11 +415,11 @@ const taskController = function (Task) {
});
const averagePts = priorityPts / task.childrenQty;
if (averagePts >= 2.5) {
- task.priority = 'Primary';
+ task.priority = "Primary";
} else if (averagePts >= 1.6) {
- task.priority = 'Secondary';
+ task.priority = "Secondary";
} else {
- task.priority = 'Tertiary';
+ task.priority = "Tertiary";
}
});
}
@@ -421,10 +428,10 @@ const taskController = function (Task) {
};
const importTask = async (req, res) => {
- if (!(await hasPermission(req.body.requestor, 'importTask'))) {
+ if (!(await hasPermission(req.body.requestor, "importTask"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new Task.' });
+ .send({ error: "You are not authorized to create new Task." });
return;
}
@@ -450,20 +457,20 @@ const taskController = function (Task) {
});
});
- res.status(201).send('done');
+ res.status(201).send("done");
};
const postTask = async (req, res) => {
- if (!(await hasPermission(req.body.requestor, 'postTask'))) {
+ if (!(await hasPermission(req.body.requestor, "postTask"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new Task.' });
+ .send({ error: "You are not authorized to create new Task." });
return;
}
if (!req.body.taskName || !req.body.isActive) {
res.status(400).send({
- error: 'Task Name, Active status, Task Number are mandatory fields',
+ error: "Task Name, Active status, Task Number are mandatory fields",
});
return;
}
@@ -487,22 +494,22 @@ const taskController = function (Task) {
});
Promise.all([saveTask, saveWbs])
- .then(results => res.status(201).send(results[0]))
+ .then((results) => res.status(201).send(results[0]))
.catch((errors) => {
res.status(400).send(errors);
});
};
const updateNum = async (req, res) => {
- if (!(await hasPermission(req.body.requestor, 'updateNum'))) {
+ if (!(await hasPermission(req.body.requestor, "updateNum"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new projects.' });
+ .send({ error: "You are not authorized to create new projects." });
return;
}
if (!req.body.nums) {
- res.status(400).send({ error: 'Num is a mandatory fields' });
+ res.status(400).send({ error: "Num is a mandatory fields" });
return;
}
@@ -513,7 +520,7 @@ const taskController = function (Task) {
task
.save()
.then()
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
});
// level 2
@@ -523,13 +530,13 @@ const taskController = function (Task) {
childTasks1.forEach((childTask1) => {
childTask1.num = childTask1.num.replace(
childTask1.num.substring(0, elm.num.length),
- elm.num,
+ elm.num
);
childTask1
.save()
.then(true)
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
// level 3
Task.find({ parentId: { $in: [childTask1._id] } })
@@ -538,13 +545,13 @@ const taskController = function (Task) {
childTasks2.forEach((childTask2) => {
childTask2.num = childTask2.num.replace(
childTask2.num.substring(0, childTask1.num.length),
- childTask1.num,
+ childTask1.num
);
childTask2
.save()
.then(true)
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
// level 4
Task.find({ parentId: { $in: [childTask2._id] } })
@@ -554,27 +561,29 @@ const taskController = function (Task) {
childTask3.num = childTask3.num.replace(
childTask3.num.substring(
0,
- childTask2.num.length,
+ childTask2.num.length
),
- childTask2.num,
+ childTask2.num
);
childTask3
.save()
.then(true)
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) =>
+ res.status(400).send(errors)
+ );
});
}
})
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
});
}
})
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
});
}
})
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
});
res.status(200).send(true);
@@ -584,13 +593,13 @@ const taskController = function (Task) {
if (!req.body.fromNum || !req.body.toNum) {
res
.status(400)
- .send({ error: 'wbsId, fromNum, toNum are mandatory fields' });
+ .send({ error: "wbsId, fromNum, toNum are mandatory fields" });
return;
}
Task.find({ wbsId: { $in: req.params.wbsId } }).then((tasks) => {
- const fromNumArr = req.body.fromNum.replace(/\.0/g, '').split('.');
- const toNumArr = req.body.toNum.replace(/\.0/g, '').split('.');
+ const fromNumArr = req.body.fromNum.replace(/\.0/g, "").split(".");
+ const toNumArr = req.body.toNum.replace(/\.0/g, "").split(".");
const changedLvl = fromNumArr.length;
@@ -598,8 +607,8 @@ const taskController = function (Task) {
const toLastLvl = parseInt(toNumArr.pop(), 10);
const leadingLvls = fromNumArr.length
- ? fromNumArr.join('.').concat('.')
- : ''; // in a format of x, x.x, or x.x.x, also could be '' if move level one tasks
+ ? fromNumArr.join(".").concat(".")
+ : ""; // in a format of x, x.x, or x.x.x, also could be '' if move level one tasks
const changingNums = [];
for (
@@ -611,37 +620,39 @@ const taskController = function (Task) {
}
const changingNumTasks = tasks.filter((task) => {
const taskLeadingNum = task.num
- .split('.')
+ .split(".")
.slice(0, changedLvl)
- .join('.');
+ .join(".");
return changingNums.includes(taskLeadingNum);
});
const queries = [];
changingNumTasks.forEach((task) => {
- const taskNumArr = task.num.split('.');
+ const taskNumArr = task.num.split(".");
const taskChanedLvlNum = parseInt(taskNumArr[changedLvl - 1], 10);
let newTaskLastLvl;
if (fromLastLvl > toLastLvl) {
- newTaskLastLvl = taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum + 1;
+ newTaskLastLvl =
+ taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum + 1;
} else {
- newTaskLastLvl = taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum - 1;
+ newTaskLastLvl =
+ taskChanedLvlNum === fromLastLvl ? toLastLvl : taskChanedLvlNum - 1;
}
taskNumArr[changedLvl - 1] = String(newTaskLastLvl);
- task.num = taskNumArr.join('.');
+ task.num = taskNumArr.join(".");
queries.push(task.save());
});
Promise.all(queries)
- .then(() => res.status(200).send('Success!'))
- .catch(err => res.status(400).send(err));
+ .then(() => res.status(200).send("Success!"))
+ .catch((err) => res.status(400).send(err));
});
};
const deleteTask = async (req, res) => {
- if (!(await hasPermission(req.body.requestor, 'deleteTask'))) {
- res.status(403).send({ error: 'You are not authorized to deleteTasks.' });
+ if (!(await hasPermission(req.body.requestor, "deleteTask"))) {
+ res.status(403).send({ error: "You are not authorized to deleteTasks." });
return;
}
@@ -656,12 +667,14 @@ const taskController = function (Task) {
{ parentId3: taskId },
],
}).then((record) => {
- if (!record || record === null || record.length === 0) return res.status(400).send({ error: 'No valid records found' });
- const removeTasks = record.map(rec => rec.remove());
+ if (!record || record === null || record.length === 0)
+ return res.status(400).send({ error: "No valid records found" });
+ const removeTasks = record.map((rec) => rec.remove());
return removeTasks;
});
- const updateMotherChildrenQty = mother !== 'null'
+ const updateMotherChildrenQty =
+ mother !== "null"
? Task.findById(mother).then((task) => {
let newQty = 0;
let child = true;
@@ -678,13 +691,15 @@ const taskController = function (Task) {
: Promise.resolve(1);
Promise.all([removeChildTasks, updateMotherChildrenQty])
- .then(() => res.status(200).send({ message: 'Task successfully deleted' })) // no need to resetNum(taskId, mother);
- .catch(errors => res.status(400).send(errors));
+ .then(() =>
+ res.status(200).send({ message: "Task successfully deleted" })
+ ) // no need to resetNum(taskId, mother);
+ .catch((errors) => res.status(400).send(errors));
};
const deleteTaskByWBS = async (req, res) => {
- if (!(await hasPermission(req.body.requestor, 'deleteTask'))) {
- res.status(403).send({ error: 'You are not authorized to deleteTasks.' });
+ if (!(await hasPermission(req.body.requestor, "deleteTask"))) {
+ res.status(403).send({ error: "You are not authorized to deleteTasks." });
return;
}
@@ -692,7 +707,7 @@ const taskController = function (Task) {
Task.find({ wbsId: { $in: [wbsId] } }, (error, record) => {
if (error || !record || record === null || record.length === 0) {
- res.status(400).send({ error: 'No valid records found' });
+ res.status(400).send({ error: "No valid records found" });
return;
}
@@ -702,7 +717,9 @@ const taskController = function (Task) {
});
Promise.all([...removeTasks])
- .then(() => res.status(200).send({ message: ' Tasks were successfully deleted' }))
+ .then(() =>
+ res.status(200).send({ message: " Tasks were successfully deleted" })
+ )
.catch((errors) => {
res.status(400).send(errors);
});
@@ -712,8 +729,8 @@ const taskController = function (Task) {
};
const updateTask = async (req, res) => {
- if (!(await hasPermission(req.body.requestor, 'updateTask'))) {
- res.status(403).send({ error: 'You are not authorized to update Task.' });
+ if (!(await hasPermission(req.body.requestor, "updateTask"))) {
+ res.status(403).send({ error: "You are not authorized to update Task." });
return;
}
@@ -721,46 +738,46 @@ const taskController = function (Task) {
Task.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(taskId) },
- { ...req.body, modifiedDatetime: Date.now() },
+ { ...req.body, modifiedDatetime: Date.now() }
)
.then(() => res.status(201).send())
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
};
const swap = async function (req, res) {
- if (!(await hasPermission(req.body.requestor, 'swapTask'))) {
+ if (!(await hasPermission(req.body.requestor, "swapTask"))) {
res
.status(403)
- .send({ error: 'You are not authorized to create new projects.' });
+ .send({ error: "You are not authorized to create new projects." });
return;
}
if (!req.body.taskId1 || !req.body.taskId2) {
res
.status(400)
- .send({ error: 'taskId1 and taskId2 are mandatory fields' });
+ .send({ error: "taskId1 and taskId2 are mandatory fields" });
return;
}
Task.findById(req.body.taskId1, (error1, task1) => {
if (error1 || task1 === null) {
- res.status(400).send('No valid records found');
+ res.status(400).send("No valid records found");
return;
}
Task.findById(req.body.taskId2, (error2, task2) => {
if (error2 || task2 === null) {
- res.status(400).send('No valid records found');
+ res.status(400).send("No valid records found");
return;
}
if (task1.parentId.toString() === task2.parentId.toString()) {
- let tmpNum = '';
+ let tmpNum = "";
tmpNum = task1.num;
task1.num = task2.num;
task2.num = tmpNum;
} else {
- let tmpName = '';
+ let tmpName = "";
tmpName = task1.taskName;
task1.taskName = task2.taskName;
task2.taskName = tmpName;
@@ -769,18 +786,18 @@ const taskController = function (Task) {
task1
.save()
.then()
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
task2
.save()
.then()
- .catch(errors => res.status(400).send(errors));
+ .catch((errors) => res.status(400).send(errors));
Task.find({
wbsId: { $in: [task1.wbsId] },
})
- .then(results => res.status(200).send(results))
- .catch(error => res.status(404).send(error));
+ .then((results) => res.status(200).send(results))
+ .catch((error) => res.status(404).send(error));
});
});
};
@@ -790,29 +807,33 @@ const taskController = function (Task) {
const taskId = req.params.id;
// Ensure the task ID is provided
- if (!taskId || taskId === 'undefined') {
- return res.status(400).send({ error: 'Task ID is missing' });
+ if (!taskId || taskId === "undefined") {
+ return res.status(400).send({ error: "Task ID is missing" });
}
const task = await Task.findById(
taskId,
- '-__v -createdDatetime -modifiedDatetime',
+ "-__v -createdDatetime -modifiedDatetime"
);
if (!task) {
- return res.status(400).send({ error: 'This is not a valid task' });
+ return res.status(400).send({ error: "This is not a valid task" });
}
- const hoursLogged = await timeEntryHelper.getAllHoursLoggedForSpecifiedProject(taskId);
- task.set('hoursLogged', hoursLogged, { strict: false });
+ const hoursLogged =
+ await timeEntryHelper.getAllHoursLoggedForSpecifiedProject(taskId);
+ task.set("hoursLogged", hoursLogged, { strict: false });
// Fetch the resource names for all resources
- const resourceNamesPromises = task.resources.map(resource => taskHelper.getUserProfileFirstAndLastName(resource.userID));
+ const resourceNamesPromises = task.resources.map((resource) =>
+ taskHelper.getUserProfileFirstAndLastName(resource.userID)
+ );
const resourceNames = await Promise.all(resourceNamesPromises);
// Update the task's resources with the fetched names
task.resources.forEach((resource, index) => {
- resource.name = resourceNames[index] !== ' ' ? resourceNames[index] : resource.name;
+ resource.name =
+ resourceNames[index] !== " " ? resourceNames[index] : resource.name;
});
res.status(200).send(task);
@@ -820,7 +841,7 @@ const taskController = function (Task) {
// Generic error message, you can adjust as needed
res
.status(500)
- .send({ error: 'Internal Server Error', details: error.message });
+ .send({ error: "Internal Server Error", details: error.message });
}
};
@@ -829,20 +850,20 @@ const taskController = function (Task) {
try {
Task.find({ wbsId: { $in: [wbsId] } }).then((tasks) => {
- tasks = tasks.filter(task => task.level === 1);
+ tasks = tasks.filter((task) => task.level === 1);
tasks.forEach((task) => {
updateParents(task.wbsId, task.taskId.toString());
});
- res.status(200).send('done');
+ res.status(200).send("done");
});
- res.status(200).send('done');
+ res.status(200).send("done");
} catch (error) {
res.status(400).send(error);
}
};
const fixTasks = function (req, res) {
- res.status(200).send('done');
+ res.status(200).send("done");
};
const getTasksByUserId = async (req, res) => {
@@ -850,19 +871,19 @@ const taskController = function (Task) {
try {
Task.find(
{
- 'resources.userID': mongoose.Types.ObjectId(userId),
+ "resources.userID": mongoose.Types.ObjectId(userId),
},
- '-resources.profilePic',
+ "-resources.profilePic"
).then((results) => {
WBS.find({
- _id: { $in: results.map(item => item.wbsId) },
+ _id: { $in: results.map((item) => item.wbsId) },
}).then((WBSs) => {
const resultsWithProjectsIds = results.map((item) => {
item.set(
- 'projectId',
- WBSs?.find(wbs => wbs._id.toString() === item.wbsId.toString())
+ "projectId",
+ WBSs?.find((wbs) => wbs._id.toString() === item.wbsId.toString())
?.projectId,
- { strict: false },
+ { strict: false }
);
return item;
});
@@ -897,10 +918,10 @@ const taskController = function (Task) {
Task.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(taskId) },
- { ...req.body, modifiedDatetime: Date.now() },
+ { ...req.body, modifiedDatetime: Date.now() }
)
.then(() => res.status(201).send())
- .catch(error => res.status(404).send(error));
+ .catch((error) => res.status(404).send(error));
};
const getReviewReqEmailBody = function (name, taskName) {
@@ -917,10 +938,10 @@ const taskController = function (Task) {
const recipients = [];
const user = await UserProfile.findById(myUserId);
const membership = await UserProfile.find({
- role: { $in: ['Administrator', 'Manager', 'Mentor'] },
+ role: { $in: ["Administrator", "Manager", "Mentor"] },
});
membership.forEach((member) => {
- if (member.teams.some(team => user.teams.includes(team))) {
+ if (member.teams.some((team) => user.teams.includes(team))) {
recipients.push(member.email);
}
});
@@ -938,11 +959,11 @@ const taskController = function (Task) {
`Review Request from ${name}`,
emailBody,
null,
- null,
+ null
);
- res.status(200).send('Success');
+ res.status(200).send("Success");
} catch (err) {
- res.status(500).send('Failed');
+ res.status(500).send("Failed");
}
};
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index 9cd98036e..0570afc00 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -138,11 +138,11 @@ const teamcontroller = function (Team) {
if (operation === 'Assign') {
- await Team.findOneAndUpdate({ _id: teamId }, { $addToSet: { members: { userId } }, $set: { modifiedDatetime: Date.now() } }, { new: true });
+ await Team.findOneAndUpdate({ _id: teamId }, { $addToSet: { members: { userId } } }, { new: true });
const newMember = await userProfile.findOneAndUpdate({ _id: userId }, { $addToSet: { teams: teamId } }, { new: true });
res.status(200).send({ newMember });
} else {
- await Team.findOneAndUpdate({ _id: teamId }, { $pull: { members: { userId } }, $set: { modifiedDatetime: Date.now() } });
+ await Team.findOneAndUpdate({ _id: teamId }, { $pull: { members: { userId } } });
await userProfile.findOneAndUpdate({ _id: userId }, { $pull: { teams: teamId } }, { new: true });
res.status(200).send({ result: 'Delete Success' });
}
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 9bedb0e8f..929b5781b 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -163,10 +163,10 @@ 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)=>{ return res; }).catch((e)=>{});
- if (userById == null) return null;
+ if(userById==null) return null;
const userRole = userById.role;
const pdtstart = moment()
.tz('America/Los_Angeles')
@@ -177,39 +177,42 @@ const dashboardhelper = function () {
.endOf('week')
.format('YYYY-MM-DD');
- let teamMemberIds = [userid];
+ let teamMemberIds = [userid]
let teamMembers = [];
- if (userRole != 'Administrator' && userRole != 'Owner' && userRole != 'Core Team') // Manager , Mentor , Volunteer ... , Show only team members
+ 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);
- });
- });
-
- 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 teamsResult = await team.find( { "members.userId": { $in: [userid] } }, {members:1} )
+ .then((res)=>{ return res; }).catch((e)=>{})
+
+ 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,isVisible:1,weeklycommittedHours:1,weeklySummaries:1})
+ .then((res)=>{ return 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,
-})
- .then(res => res).catch((e) => {});
+ teamMembers = await userProfile.find({ isActive:true , role: { $nin: excludedRoles } },
+ {role:1,firstName:1,lastName:1,isVisible:1,weeklycommittedHours:1,weeklySummaries:1})
+ .then((res)=>{ return 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})
+ .then((res)=>{ return res; }).catch((e)=>{})
+ }
+
+
+ }
teamMemberIds = teamMembers.map(member => member._id);
@@ -218,14 +221,16 @@ const dashboardhelper = function () {
$gte: pdtstart,
$lte: pdtend,
},
- personId: { $in: teamMemberIds },
+ personId: { $in: teamMemberIds }
});
- const timeEntryByPerson = {};
- timeEntries.map((timeEntry) => {
- const personIdStr = timeEntry.personId.toString();
+ let timeEntryByPerson = {}
+ timeEntries.map((timeEntry)=>{
+
+ let 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;
@@ -234,40 +239,41 @@ const dashboardhelper = function () {
}
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,
- };
+ })
+
+
+ let leaderBoardData = [];
+ teamMembers.map((teamMember)=>{
+ let 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 sortedLBData = leaderBoardData.sort((a, b) => {
+ let sortedLBData = leaderBoardData.sort((a, b) => {
// Sort by totaltangibletime_hrs in descending order
if (b.totaltangibletime_hrs !== a.totaltangibletime_hrs) {
return b.totaltangibletime_hrs - a.totaltangibletime_hrs;
}
-
+
// Then sort by name in ascending order
if (a.name !== b.name) {
return a.name.localeCompare(b.name);
}
-
+
// Finally, sort by role in ascending order
return a.role.localeCompare(b.role);
});
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 800d1ee6b..8c45df737 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,5 +1,4 @@
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');
@@ -7,16 +6,15 @@ const team = require('../models/team');
const Task = require('../models/task');
const TaskNotification = require('../models/taskNotification');
const Wbs = require('../models/wbs');
+const mongoose = require('mongoose');
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})
+ .then((res)=>{ return res; }).catch((e)=>{});
- if (userById == null) return null;
+ if(userById==null) return null;
const userRole = userById.role;
const pdtstart = moment()
@@ -28,39 +26,39 @@ const taskHelper = function () {
.endOf('week')
.format('YYYY-MM-DD');
- let teamMemberIds = [userid];
+ let teamMemberIds = [userid]
let teamMembers = [];
- if (userRole != 'Administrator' && userRole != 'Owner' && userRole != 'Core Team') // Manager , Mentor , Volunteer ... , Show only team members
+ 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) => {});
+
+ const teamsResult = await team.find( { "members.userId": { $in: [userid] } }, {members:1} )
+ .then((res)=>{ return 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 );
+ } )
+ })
- 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
+ teamMembers = await userProfile.find({ _id: { $in: teamMemberIds } , isActive:true },
+ {role:1,firstName:1,lastName:1,weeklycommittedHours:1})
+ .then((res)=>{ return 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({ isActive:true , role: { $nin: excludedRoles } },
+ {role:1,firstName:1,lastName:1,weeklycommittedHours:1})
+ .then((res)=>{ return 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)=>{ return res; }).catch((e)=>{})
+ }
+ }
teamMemberIds = teamMembers.map(member => member._id);
@@ -69,80 +67,88 @@ const taskHelper = function () {
$gte: pdtstart,
$lte: pdtend,
},
- personId: { $in: teamMemberIds },
+ personId: { $in: teamMemberIds }
});
-
- const timeEntryByPerson = {};
- timeEntries.map((timeEntry) => {
- const personIdStr = timeEntry.personId.toString();
-
- if (timeEntryByPerson[personIdStr] == null) { timeEntryByPerson[personIdStr] = { tangibleSeconds: 0, intangibleSeconds: 0, totalSeconds: 0 }; }
-
+
+ let timeEntryByPerson = {}
+ timeEntries.map((timeEntry)=>{
+
+ let personIdStr = timeEntry.personId.toString();
+
+ 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;
- });
+ })
- const teamMemberTasks = await Task.find({ 'resources.userID': { $in: teamMemberIds } }, { 'resources.profilePic': 0 })
- .populate({
+ 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 teamMemberTaskNotifications = await TaskNotification.find({"taskId" : {$in : teamMemberTaskIds }})
+
+ const taskNotificationByTaskNdUser = []
+ teamMemberTaskNotifications.map(teamMemberTaskNotification => {
- const taskNotificationByTaskNdUser = [];
- teamMemberTaskNotifications.map((teamMemberTaskNotification) => {
- const taskIdStr = teamMemberTaskNotification.taskId.toString();
- const userIdStr = teamMemberTaskNotification.userId.toString();
- const taskNdUserID = `${taskIdStr},${userIdStr}`;
+ let taskIdStr = teamMemberTaskNotification.taskId.toString();
+ let userIdStr = teamMemberTaskNotification.userId.toString();
+ let 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 => {
- teamMemberTasks.map((teamMemberTask) => {
- const projId = teamMemberTask.wbsId?.projectId;
- const _teamMemberTask = { ...teamMemberTask._doc };
+ let projId = teamMemberTask.wbsId?.projectId;
+ let _teamMemberTask = {...teamMemberTask._doc}
_teamMemberTask.projectId = projId;
- const taskIdStr = _teamMemberTask._id.toString();
+ let 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 => {
+
+ let resourceIdStr = resource.userID.toString();
+ let 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()] || [],
- };
+
+ let teamMemberTasksData = [];
+ teamMembers.map((teamMember)=>{
+ let 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);
- });
+ })
return teamMemberTasksData;
-
+
// return myteam.aggregate([
// {
diff --git a/src/models/mapLocation.js b/src/models/mapLocation.js
index cb5644d31..851587dc3 100644
--- a/src/models/mapLocation.js
+++ b/src/models/mapLocation.js
@@ -5,7 +5,7 @@ const { Schema } = mongoose;
const mapLocation = new Schema({
title: {
type: String,
- default: 'Prior to HGN Data Collection',
+ default: 'Prior to HGN Data Collection'
},
firstName: String,
lastName: String,
@@ -27,7 +27,7 @@ const mapLocation = new Schema({
lng: {
type: String,
required: true,
- },
+ }
},
country: {
type: String,
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index 9a520d7d6..51c5f437f 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -9,11 +9,11 @@ const routes = function (itemMaterial, buildingMaterial) {
materialsRouter.route('/updateMaterialRecord')
.post(controller.bmPostMaterialUpdateRecord);
-
+
materialsRouter.route('/updateMaterialRecordBulk')
.post(controller.bmPostMaterialUpdateBulk);
-
-
+
+
return materialsRouter;
};
diff --git a/src/routes/mapLocationsRouter.js b/src/routes/mapLocationsRouter.js
index 84cb85feb..db004ff18 100644
--- a/src/routes/mapLocationsRouter.js
+++ b/src/routes/mapLocationsRouter.js
@@ -11,7 +11,7 @@ const router = function (mapLocations) {
.patch(controller.updateUserLocation);
mapRouter.route('/mapLocations/:locationId')
- .delete(controller.deleteLocation);
+ .delete(controller.deleteLocation)
return mapRouter;
};
diff --git a/src/routes/profileInitialSetupRouter.js b/src/routes/profileInitialSetupRouter.js
index 544c5c878..12f677224 100644
--- a/src/routes/profileInitialSetupRouter.js
+++ b/src/routes/profileInitialSetupRouter.js
@@ -1,8 +1,8 @@
const express = require('express');
-const routes = function (ProfileInitialSetupToken, userProfile, Project, mapLocations) {
+const routes = function (ProfileInitialSetupToken, userProfile, Project , mapLocations) {
const ProfileInitialSetup = express.Router();
- const controller = require('../controllers/profileInitialSetupController')(ProfileInitialSetupToken, userProfile, Project, mapLocations);
+ const controller = require('../controllers/profileInitialSetupController')(ProfileInitialSetupToken, userProfile, Project , mapLocations);
ProfileInitialSetup.route('/getInitialSetuptoken')
.post(controller.getSetupToken);
ProfileInitialSetup.route('/ProfileInitialSetup').post(controller.setUpNewUser);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 95cade0fd..da7515021 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -46,7 +46,7 @@ const popupBackupRouter = require('../routes/popupEditorBackupRouter')(popupBack
const taskNotificationRouter = require('../routes/taskNotificationRouter')(taskNotification);
const inventoryRouter = require('../routes/inventoryRouter')(inventoryItem, inventoryItemType);
const timeZoneAPIRouter = require('../routes/timeZoneAPIRoutes')();
-const profileInitialSetupRouter = require('../routes/profileInitialSetupRouter')(profileInitialSetuptoken, userProfile, project, mapLocations);
+const profileInitialSetupRouter = require('../routes/profileInitialSetupRouter')(profileInitialSetuptoken, userProfile, project , mapLocations);
const isEmailExistsRouter = require('../routes/isEmailExistsRouter')();
diff --git a/src/utilities/emailSender.js b/src/utilities/emailSender.js
index 7199202e9..b07f9a8c9 100644
--- a/src/utilities/emailSender.js
+++ b/src/utilities/emailSender.js
@@ -35,7 +35,7 @@ const closure = () => {
if (!nextItem) return;
const {
- recipient, subject, message, cc, bcc, replyTo, acknowledgingReceipt,
+ recipient, subject, message, cc, bcc, replyTo, acknowledgingReceipt
} = nextItem;
try {
@@ -60,13 +60,13 @@ const closure = () => {
const result = await transporter.sendMail(mailOptions);
if (typeof acknowledgingReceipt === 'function') {
- acknowledgingReceipt(null, result);
- }
+ acknowledgingReceipt(null,result);
+ }
logger.logInfo(result);
} catch (error) {
if (typeof acknowledgingReceipt === 'function') {
- acknowledgingReceipt(error, null);
- }
+ acknowledgingReceipt(error,null);
+ }
logger.logException(error);
}
}, process.env.MAIL_QUEUE_INTERVAL || 1000);
@@ -88,7 +88,7 @@ const closure = () => {
cc,
bcc,
replyTo,
- acknowledgingReceipt,
+ acknowledgingReceipt
});
}
};
From 33f99abc2e707af336d50a25eb8ab05bdc81acce Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Fri, 5 Jan 2024 22:14:07 -0600
Subject: [PATCH 255/272] revert changes
---
src/controllers/teamController.js | 4 ++--
src/routes/bmdashboard/bmMaterialsRouter.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/controllers/teamController.js b/src/controllers/teamController.js
index 0570afc00..9cd98036e 100644
--- a/src/controllers/teamController.js
+++ b/src/controllers/teamController.js
@@ -138,11 +138,11 @@ const teamcontroller = function (Team) {
if (operation === 'Assign') {
- await Team.findOneAndUpdate({ _id: teamId }, { $addToSet: { members: { userId } } }, { new: true });
+ await Team.findOneAndUpdate({ _id: teamId }, { $addToSet: { members: { userId } }, $set: { modifiedDatetime: Date.now() } }, { new: true });
const newMember = await userProfile.findOneAndUpdate({ _id: userId }, { $addToSet: { teams: teamId } }, { new: true });
res.status(200).send({ newMember });
} else {
- await Team.findOneAndUpdate({ _id: teamId }, { $pull: { members: { userId } } });
+ await Team.findOneAndUpdate({ _id: teamId }, { $pull: { members: { userId } }, $set: { modifiedDatetime: Date.now() } });
await userProfile.findOneAndUpdate({ _id: userId }, { $pull: { teams: teamId } }, { new: true });
res.status(200).send({ result: 'Delete Success' });
}
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index 51c5f437f..9fef2f956 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -17,4 +17,4 @@ const routes = function (itemMaterial, buildingMaterial) {
return materialsRouter;
};
-module.exports = routes;
+module.exports = routes;
\ No newline at end of file
From f939225f6a6a7b5404c423a533392b91287cd99a Mon Sep 17 00:00:00 2001
From: tsunami776 <43768723+tsunami776@users.noreply.github.com>
Date: Fri, 5 Jan 2024 22:15:57 -0600
Subject: [PATCH 256/272] revert lint
---
src/controllers/dashBoardController.js | 2 +-
src/routes/bmdashboard/bmMaterialsRouter.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/dashBoardController.js b/src/controllers/dashBoardController.js
index 3fdda9eb7..30bddc871 100644
--- a/src/controllers/dashBoardController.js
+++ b/src/controllers/dashBoardController.js
@@ -274,4 +274,4 @@ const dashboardcontroller = function () {
};
};
-module.exports = dashboardcontroller;
+module.exports = dashboardcontroller;
\ No newline at end of file
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index 9fef2f956..51c5f437f 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -17,4 +17,4 @@ const routes = function (itemMaterial, buildingMaterial) {
return materialsRouter;
};
-module.exports = routes;
\ No newline at end of file
+module.exports = routes;
From f08d2d5066115bfd10ef6d3d5781d7e464438099 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Sun, 7 Jan 2024 12:18:39 -0800
Subject: [PATCH 257/272] update mats route, controller to use updated model.
isolate populate method causing fetch err.
---
src/controllers/bmdashboard/bmMaterialsController.js | 10 +++++-----
src/routes/bmdashboard/bmMaterialsRouter.js | 4 ++--
src/startup/routes.js | 7 ++++---
3 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index da45aad1d..0191b56fc 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -1,6 +1,6 @@
const mongoose = require('mongoose');
-const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
+const bmMaterialsController = function (BuildingMaterial) {
const bmMaterialsList = async function _matsList(req, res) {
try {
BuildingMaterial.find()
@@ -9,10 +9,10 @@ const bmMaterialsController = function (ItemMaterial, BuildingMaterial) {
path: 'project',
select: '_id name',
},
- {
- path: 'itemType',
- select: '_id name unit',
- },
+ // {
+ // path: 'itemType',
+ // select: '_id name unit',
+ // },
{
path: 'updateRecord',
populate: {
diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js
index 9a520d7d6..733148d14 100644
--- a/src/routes/bmdashboard/bmMaterialsRouter.js
+++ b/src/routes/bmdashboard/bmMaterialsRouter.js
@@ -1,8 +1,8 @@
const express = require('express');
-const routes = function (itemMaterial, buildingMaterial) {
+const routes = function (buildingMaterial) {
const materialsRouter = express.Router();
- const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial, buildingMaterial);
+ const controller = require('../../controllers/bmdashboard/bmMaterialsController')(buildingMaterial);
materialsRouter.route('/materials')
.get(controller.bmMaterialsList)
.post(controller.bmPurchaseMaterials);
diff --git a/src/startup/routes.js b/src/startup/routes.js
index 1ac1d669b..492e455cd 100644
--- a/src/startup/routes.js
+++ b/src/startup/routes.js
@@ -21,10 +21,10 @@ const weeklySummaryAIPrompt = require('../models/weeklySummaryAIPrompt');
const profileInitialSetuptoken = require('../models/profileInitialSetupToken');
const reason = require('../models/reason');
const mouseoverText = require('../models/mouseoverText');
-const inventoryItemMaterial = require('../models/inventoryItemMaterial');
+// const inventoryItemMaterial = require('../models/inventoryItemMaterial');
const mapLocations = require('../models/mapLocation');
const buildingProject = require('../models/bmdashboard/buildingProject');
-const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
+// const buildingMaterial = require('../models/bmdashboard/buildingMaterial');
const {
invTypeBase,
materialType,
@@ -35,6 +35,7 @@ const {
} = require('../models/bmdashboard/buildingInventoryType');
const {
buildingConsumable,
+ buildingMaterial,
} = require('../models/bmdashboard/buildingInventoryItem');
const buildingTool = require('../models/bmdashboard/buildingTool');
@@ -75,7 +76,7 @@ const mapLocationRouter = require('../routes/mapLocationsRouter')(mapLocations);
// bm dashboard
const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')();
-const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial, buildingMaterial);
+const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(buildingMaterial);
const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject);
const bmConsumablesRouter = require('../routes/bmdashboard/bmConsumablesRouter')(buildingConsumable);
const bmInventoryTypeRouter = require('../routes/bmdashboard/bmInventoryTypeRouter')(invTypeBase, materialType, consumableType, reusableType, toolType, equipmentType);
From 273fa005f4cf6ebd3f1d60b734858cba39fa436b Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Sun, 7 Jan 2024 12:52:01 -0800
Subject: [PATCH 258/272] update populate ref string
---
src/controllers/bmdashboard/bmMaterialsController.js | 8 ++++----
src/models/bmdashboard/buildingInventoryItem.js | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 0191b56fc..51295d035 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -9,10 +9,10 @@ const bmMaterialsController = function (BuildingMaterial) {
path: 'project',
select: '_id name',
},
- // {
- // path: 'itemType',
- // select: '_id name unit',
- // },
+ {
+ path: 'itemType',
+ select: '_id name unit',
+ },
{
path: 'updateRecord',
populate: {
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
index dfaa8c73a..c44f37211 100644
--- a/src/models/bmdashboard/buildingInventoryItem.js
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -11,7 +11,7 @@ const mongoose = require('mongoose');
// documents stored in 'buildingInventoryItems' collection
const smallItemBaseSchema = mongoose.Schema({
- itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'invTypeBase' },
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
stockBought: { type: Number, default: 0 }, // total amount of item bought for use in the project
// TODO: can stockAvailable default be a function?
From 66d3814f11d40fc94c0b028556cde2d1b7e2aaf4 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Sun, 7 Jan 2024 13:27:58 -0800
Subject: [PATCH 259/272] update brand to brandPref
---
.../bmdashboard/bmMaterialsController.js | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js
index 51295d035..207e2428a 100644
--- a/src/controllers/bmdashboard/bmMaterialsController.js
+++ b/src/controllers/bmdashboard/bmMaterialsController.js
@@ -42,15 +42,9 @@ const bmMaterialsController = function (BuildingMaterial) {
matTypeId,
quantity,
priority,
- brand,
+ brand: brandPref,
requestor: { requestorId },
} = req.body;
- const newPurchaseRecord = {
- quantity,
- priority,
- brand,
- requestedBy: requestorId,
- };
try {
// check if requestor has permission to make purchase request
//! Note: this code is disabled until permissions are added
@@ -64,6 +58,12 @@ const bmMaterialsController = function (BuildingMaterial) {
// check if the material is already being used in the project
// if no, add a new document to the collection
// if yes, update the existing document
+ const newPurchaseRecord = {
+ quantity,
+ priority,
+ brandPref,
+ requestedBy: requestorId,
+ };
const doc = await BuildingMaterial.findOne({ project: projectId, itemType: matTypeId });
if (!doc) {
const newDoc = {
From 7b4f5431ff0fdf48b097fb9fea7181fef8d93f2d Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Sun, 7 Jan 2024 19:55:18 -0800
Subject: [PATCH 260/272] update lookup func in BuildingProject aggregator to
fetch from correct collection and limit results to materials
---
src/controllers/bmdashboard/bmProjectController.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js
index b6b3e4e18..a4f6712e0 100644
--- a/src/controllers/bmdashboard/bmProjectController.js
+++ b/src/controllers/bmdashboard/bmProjectController.js
@@ -31,10 +31,11 @@ const bmMProjectController = function (BuildingProject) {
{ $unwind: '$buildingManager' },
{
$lookup: {
- from: 'buildingMaterials',
+ from: 'buildingInventoryItems',
let: { id: '$_id' },
pipeline: [
{ $match: { $expr: { $eq: ['$project', '$$id'] } } },
+ { $match: { __t: 'material_item' } },
{ $project: { updateRecord: 0, project: 0 } },
{
$lookup: {
From 90692149b687e823f3de95c2ba21bf71b03ef376 Mon Sep 17 00:00:00 2001
From: Tim Kent
Date: Sun, 7 Jan 2024 20:32:38 -0800
Subject: [PATCH 261/272] update itemType ref in large item schema
---
src/models/bmdashboard/buildingInventoryItem.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/models/bmdashboard/buildingInventoryItem.js b/src/models/bmdashboard/buildingInventoryItem.js
index c44f37211..fdcfde3dd 100644
--- a/src/models/bmdashboard/buildingInventoryItem.js
+++ b/src/models/bmdashboard/buildingInventoryItem.js
@@ -41,7 +41,7 @@ const smallItemBase = mongoose.model('smallItemBase', smallItemBaseSchema, 'buil
// documents stored in 'buildingInventoryItems' collection
const largeItemBaseSchema = mongoose.Schema({
- itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingInventoryType' },
+ itemType: { type: mongoose.SchemaTypes.ObjectId, ref: 'invTypeBase' },
project: { type: mongoose.SchemaTypes.ObjectId, ref: 'buildingProject' },
purchaseStatus: { type: String, enum: ['Rental', 'Purchase'], required: true },
// rental fields are required if purchaseStatus = "Rental" (hopefully correct syntax)
From 37ba941687f2a59a3b5741089fd5b7215288590f Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 8 Jan 2024 03:45:22 -0500
Subject: [PATCH 262/272] added timeOffFrom and timeOffTill fields to new
aggregation in taskHelper and dashboardHelper
---
src/helpers/dashboardhelper.js | 719 +++++++++++++++++++-----------
src/helpers/taskHelper.js | 789 ++++++++++++++++++++-------------
2 files changed, 935 insertions(+), 573 deletions(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 48f9047da..4a6605213 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -3,6 +3,7 @@ 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) {
@@ -69,6 +70,16 @@ const dashboardhelper = function () {
{
$lte: ["$$timeentry.dateOfWork", pdtend],
},
+ {
+ $not: [
+ {
+ $in: [
+ "$$timeentry.entryType",
+ ["person", "team", "project"],
+ ],
+ },
+ ],
+ },
],
},
},
@@ -152,8 +163,15 @@ const dashboardhelper = function () {
return output;
};
- const getLeaderboard = function (userId) {
+ 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) => {});
+
+ if (userById == null) return null;
+ const userRole = userById.role;
const pdtstart = moment()
.tz("America/Los_Angeles")
.startOf("week")
@@ -162,274 +180,416 @@ const dashboardhelper = function () {
.tz("America/Los_Angeles")
.endOf("week")
.format("YYYY-MM-DD");
- return myTeam.aggregate([
- {
- $match: {
- _id: userid,
- },
- },
- {
- $unwind: "$myteam",
- },
- {
- $project: {
- _id: 0,
- role: 1,
- personId: "$myteam._id",
- name: "$myteam.fullName",
- },
- },
- {
- $lookup: {
- from: "userProfiles",
- localField: "personId",
- foreignField: "_id",
- as: "persondata",
- },
- },
- {
- $match: {
- // leaderboard user roles hierarchy
- $or: [
- {
- role: { $in: ["Owner", "Core Team"] },
- },
- {
- $and: [
- {
- role: "Administrator",
- },
- { "persondata.0.role": { $nin: ["Owner", "Administrator"] } },
- ],
- },
- {
- $and: [
- {
- role: { $in: ["Manager", "Mentor"] },
- },
- {
- "persondata.0.role": {
- $nin: [
- "Manager",
- "Mentor",
- "Core Team",
- "Administrator",
- "Owner",
- ],
- },
- },
- ],
- },
- { "persondata.0._id": userId },
- { "persondata.0.role": "Volunteer" },
- { "persondata.0.isVisible": true },
- ],
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: {
- $arrayElemAt: ["$persondata.role", 0],
- },
- isVisible: {
- $arrayElemAt: ["$persondata.isVisible", 0],
- },
- hasSummary: {
- $ne: [
- {
- $arrayElemAt: [
- {
- $arrayElemAt: ["$persondata.weeklySummaries.summary", 0],
- },
- 0,
- ],
- },
- "",
- ],
- },
- weeklycommittedHours: {
- $sum: [
- {
- $arrayElemAt: ["$persondata.weeklycommittedHours", 0],
- },
- {
- $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0],
- },
- ],
- },
- timeOffFrom: {
- $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null],
- },
- timeOffTill: {
- $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null],
- },
- },
- },
- {
- $lookup: {
- from: "timeEntries",
- localField: "personId",
- foreignField: "personId",
- as: "timeEntryData",
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- timeOffFrom: 1,
- timeOffTill: 1,
- timeEntryData: {
- $filter: {
- input: "$timeEntryData",
- as: "timeentry",
- cond: {
- $and: [
- {
- $gte: ["$$timeentry.dateOfWork", pdtstart],
- },
- {
- $lte: ["$$timeentry.dateOfWork", pdtend],
- },
- ],
- },
- },
- },
- },
- },
- {
- $unwind: {
- path: "$timeEntryData",
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- timeOffFrom: 1,
- timeOffTill: 1,
- totalSeconds: {
- $cond: [
- {
- $gte: ["$timeEntryData.totalSeconds", 0],
- },
- "$timeEntryData.totalSeconds",
- 0,
- ],
- },
- isTangible: {
- $cond: [
- {
- $gte: ["$timeEntryData.totalSeconds", 0],
- },
- "$timeEntryData.isTangible",
- false,
- ],
- },
- },
- },
- {
- $addFields: {
- tangibletime: {
- $cond: [
- {
- $eq: ["$isTangible", true],
- },
- "$totalSeconds",
- 0,
- ],
- },
- intangibletime: {
- $cond: [
- {
- $eq: ["$isTangible", false],
- },
- "$totalSeconds",
- 0,
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- personId: "$personId",
- weeklycommittedHours: "$weeklycommittedHours",
- timeOffFrom: "$timeOffFrom",
- timeOffTill: "$timeOffTill",
- name: "$name",
- role: "$role",
- isVisible: "$isVisible",
- hasSummary: "$hasSummary",
- },
- totalSeconds: {
- $sum: "$totalSeconds",
- },
- tangibletime: {
- $sum: "$tangibletime",
- },
- intangibletime: {
- $sum: "$intangibletime",
- },
- },
- },
- {
- $project: {
- _id: 0,
- personId: "$_id.personId",
- name: "$_id.name",
- role: "$_id.role",
- isVisible: "$_id.isVisible",
- hasSummary: "$_id.hasSummary",
- weeklycommittedHours: "$_id.weeklycommittedHours",
- totaltime_hrs: {
- $divide: ["$totalSeconds", 3600],
- },
- totaltangibletime_hrs: {
- $divide: ["$tangibletime", 3600],
- },
- totalintangibletime_hrs: {
- $divide: ["$intangibletime", 3600],
- },
- percentagespentintangible: {
- $cond: [
- {
- $eq: ["$totalSeconds", 0],
- },
- 0,
- {
- $multiply: [
- {
- $divide: ["$tangibletime", "$totalSeconds"],
- },
- 100,
- ],
- },
- ],
- },
- timeOffFrom: "$_id.timeOffFrom",
- timeOffTill: "$_id.timeOffTill",
- },
- },
- {
- $sort: {
- totaltangibletime_hrs: -1,
- name: 1,
- role: 1,
- },
+
+ 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) => {});
+
+ 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,
+ 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,
+ 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);
+
+ const timeEntries = await timeentry.find({
+ dateOfWork: {
+ $gte: pdtstart,
+ $lte: pdtend,
},
- ]);
+ personId: { $in: teamMemberIds },
+ });
+
+ const timeEntryByPerson = {};
+ timeEntries.map((timeEntry) => {
+ const personIdStr = timeEntry.personId.toString();
+
+ if (timeEntryByPerson[personIdStr] == null) {
+ timeEntryByPerson[personIdStr] = {
+ tangibleSeconds: 0,
+ intangibleSeconds: 0,
+ totalSeconds: 0,
+ };
+ }
+
+ if (timeEntry.isTangible === true) {
+ timeEntryByPerson[personIdStr].tangibleSeconds +=
+ timeEntry.totalSeconds;
+ } else {
+ 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,
+ timeOffFrom: teamMember.timeOffFrom || null,
+ timeOffTill: teamMember.timeOffTill || null,
+ };
+ leaderBoardData.push(obj);
+ });
+
+ const sortedLBData = leaderBoardData.sort((a, b) => {
+ // Sort by totaltangibletime_hrs in descending order
+ if (b.totaltangibletime_hrs !== a.totaltangibletime_hrs) {
+ return b.totaltangibletime_hrs - a.totaltangibletime_hrs;
+ }
+
+ // Then sort by name in ascending order
+ if (a.name !== b.name) {
+ return a.name.localeCompare(b.name);
+ }
+
+ // Finally, sort by role in ascending order
+ return a.role.localeCompare(b.role);
+ });
+
+ return sortedLBData;
+
+ // return myTeam.aggregate([
+ // {
+ // $match: {
+ // _id: userid,
+ // },
+ // },
+ // {
+ // $unwind: '$myteam',
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // role: 1,
+ // personId: '$myteam._id',
+ // name: '$myteam.fullName',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'userProfiles',
+ // localField: 'personId',
+ // foreignField: '_id',
+ // as: 'persondata',
+ // },
+ // },
+ // {
+ // $match: {
+ // // leaderboard user roles hierarchy
+ // $or: [
+ // {
+ // role: { $in: ['Owner', 'Core Team'] },
+ // },
+ // {
+ // $and: [
+ // {
+ // role: 'Administrator',
+ // },
+ // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ // ],
+ // },
+ // {
+ // $and: [
+ // {
+ // role: { $in: ['Manager', 'Mentor'] },
+ // },
+ // {
+ // 'persondata.0.role': {
+ // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ // },
+ // },
+ // ],
+ // },
+ // { 'persondata.0._id': userId },
+ // { 'persondata.0.role': 'Volunteer' },
+ // { 'persondata.0.isVisible': true },
+ // ],
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: {
+ // $arrayElemAt: ['$persondata.role', 0],
+ // },
+ // isVisible: {
+ // $arrayElemAt: ['$persondata.isVisible', 0],
+ // },
+ // hasSummary: {
+ // $ne: [
+ // {
+ // $arrayElemAt: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklySummaries.summary', 0],
+ // },
+ // 0,
+ // ],
+ // },
+ // '',
+ // ],
+ // },
+ // weeklycommittedHours: {
+ // $sum: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ // },
+ // {
+ // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'timeEntries',
+ // localField: 'personId',
+ // foreignField: 'personId',
+ // as: 'timeEntryData',
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: 1,
+ // isVisible: 1,
+ // hasSummary: 1,
+ // weeklycommittedHours: 1,
+ // timeEntryData: {
+ // $filter: {
+ // input: '$timeEntryData',
+ // as: 'timeentry',
+ // cond: {
+ // $and: [
+ // {
+ // $gte: ['$$timeentry.dateOfWork', pdtstart],
+ // },
+ // {
+ // $lte: ['$$timeentry.dateOfWork', pdtend],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$timeEntryData',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // role: 1,
+ // isVisible: 1,
+ // hasSummary: 1,
+ // weeklycommittedHours: 1,
+ // totalSeconds: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.totalSeconds',
+ // 0,
+ // ],
+ // },
+ // isTangible: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.isTangible',
+ // false,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // tangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', true],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // intangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', false],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: {
+ // personId: '$personId',
+ // weeklycommittedHours: '$weeklycommittedHours',
+ // name: '$name',
+ // role: '$role',
+ // isVisible: '$isVisible',
+ // hasSummary: '$hasSummary',
+ // },
+ // totalSeconds: {
+ // $sum: '$totalSeconds',
+ // },
+ // tangibletime: {
+ // $sum: '$tangibletime',
+ // },
+ // intangibletime: {
+ // $sum: '$intangibletime',
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$_id.personId',
+ // name: '$_id.name',
+ // role: '$_id.role',
+ // isVisible: '$_id.isVisible',
+ // hasSummary: '$_id.hasSummary',
+ // weeklycommittedHours: '$_id.weeklycommittedHours',
+ // totaltime_hrs: {
+ // $divide: ['$totalSeconds', 3600],
+ // },
+ // totaltangibletime_hrs: {
+ // $divide: ['$tangibletime', 3600],
+ // },
+ // totalintangibletime_hrs: {
+ // $divide: ['$intangibletime', 3600],
+ // },
+ // percentagespentintangible: {
+ // $cond: [
+ // {
+ // $eq: ['$totalSeconds', 0],
+ // },
+ // 0,
+ // {
+ // $multiply: [
+ // {
+ // $divide: ['$tangibletime', '$totalSeconds'],
+ // },
+ // 100,
+ // ],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $sort: {
+ // totaltangibletime_hrs: -1,
+ // name: 1,
+ // role: 1,
+ // },
+ // },
+ // ]);
};
/**
@@ -458,6 +618,7 @@ const dashboardhelper = function () {
$gte: pdtStart,
$lte: pdtEnd,
},
+ entryType: { $in: ["default", null] },
personId: userId,
});
@@ -485,8 +646,6 @@ const dashboardhelper = function () {
totalintangibletime_hrs: intangibleSeconds / 3600,
percentagespentintangible:
(intangibleSeconds / tangibleSeconds) * 100,
- timeOffFrom: user.timeOffFrom,
- timeOffTill: user.timeOffTill,
},
];
} catch (err) {
@@ -597,6 +756,16 @@ const dashboardhelper = function () {
{
$lte: ["$$timeentry.dateOfWork", todate],
},
+ {
+ $not: [
+ {
+ $in: [
+ "$$timeentry.entryType",
+ ["person", "team", "project"],
+ ],
+ },
+ ],
+ },
],
},
},
@@ -674,6 +843,16 @@ const dashboardhelper = function () {
{
$lte: ["$$timeentry.dateOfWork", todate],
},
+ {
+ $not: [
+ {
+ $in: [
+ "$$timeentry.entryType",
+ ["person", "team", "project"],
+ ],
+ },
+ ],
+ },
],
},
},
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index b5268734e..f96257a67 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,9 +1,37 @@
const moment = require("moment-timezone");
+const mongoose = require("mongoose");
const userProfile = require("../models/userProfile");
-const myteam = require("../helpers/helperModels/myTeam");
+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 = function (userId) {
+ 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,
+ 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")
@@ -12,308 +40,460 @@ const taskHelper = function () {
.tz("America/Los_Angeles")
.endOf("week")
.format("YYYY-MM-DD");
- return myteam.aggregate([
- {
- $match: {
- _id: userId,
- },
- },
- {
- $unwind: "$myteam",
- },
- {
- $project: {
- _id: 0,
- personId: "$myteam._id",
- name: "$myteam.fullName",
- role: 1,
- },
- },
- // have personId, name, role
- {
- $lookup: {
- from: "userProfiles",
- localField: "personId",
- foreignField: "_id",
- as: "persondata",
- },
- },
- {
- $match: {
- // dashboard tasks user roles hierarchy
- $or: [
- {
- role: { $in: ["Owner", "Core Team"] },
- },
- {
- $and: [
- {
- role: "Administrator",
- },
- { "persondata.0.role": { $nin: ["Owner", "Administrator"] } },
- ],
- },
- {
- $and: [
- {
- role: { $in: ["Manager", "Mentor"] },
- },
- {
- "persondata.0.role": {
- $nin: [
- "Manager",
- "Mentor",
- "Core Team",
- "Administrator",
- "Owner",
- ],
- },
- },
- ],
- },
- { "persondata.0._id": userId },
- { "persondata.0.role": "Volunteer" },
- { "persondata.0.isVisible": true },
- ],
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: {
- $sum: [
- {
- $arrayElemAt: ["$persondata.weeklycommittedHours", 0],
- },
- {
- $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0],
- },
- ],
- },
- timeOffFrom: {
- $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null],
- },
- timeOffTill: {
- $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null],
- },
- role: 1,
- },
- },
- {
- $lookup: {
- from: "timeEntries",
- localField: "personId",
- foreignField: "personId",
- as: "timeEntryData",
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: 1,
- timeOffFrom: 1,
- timeOffTill: 1,
- timeEntryData: {
- $filter: {
- input: "$timeEntryData",
- as: "timeentry",
- cond: {
- $and: [
- {
- $gte: ["$$timeentry.dateOfWork", pdtstart],
- },
- {
- $lte: ["$$timeentry.dateOfWork", pdtend],
- },
- ],
- },
- },
- },
- role: 1,
- },
- },
- {
- $unwind: {
- path: "$timeEntryData",
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- weeklycommittedHours: 1,
- timeOffFrom: 1,
- timeOffTill: 1,
- totalSeconds: {
- $cond: [
- {
- $gte: ["$timeEntryData.totalSeconds", 0],
- },
- "$timeEntryData.totalSeconds",
- 0,
- ],
- },
- isTangible: {
- $cond: [
- {
- $gte: ["$timeEntryData.totalSeconds", 0],
- },
- "$timeEntryData.isTangible",
- false,
- ],
- },
- role: 1,
- },
- },
- {
- $addFields: {
- tangibletime: {
- $cond: [
- {
- $eq: ["$isTangible", true],
- },
- "$totalSeconds",
- 0,
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- personId: "$personId",
- weeklycommittedHours: "$weeklycommittedHours",
- timeOffFrom: "$timeOffFrom",
- timeOffTill: "$timeOffTill",
- name: "$name",
- role: "$role",
- },
- totalSeconds: {
- $sum: "$totalSeconds",
- },
- tangibletime: {
- $sum: "$tangibletime",
- },
- },
- },
- {
- $project: {
- _id: 0,
- personId: "$_id.personId",
- name: "$_id.name",
- weeklycommittedHours: "$_id.weeklycommittedHours",
- timeOffFrom: "$_id.timeOffFrom",
- timeOffTill: "$_id.timeOffTill",
- totaltime_hrs: {
- $divide: ["$totalSeconds", 3600],
- },
- totaltangibletime_hrs: {
- $divide: ["$tangibletime", 3600],
- },
- role: "$_id.role",
- },
- },
- {
- $lookup: {
- from: "tasks",
- localField: "personId",
- foreignField: "resources.userID",
- as: "tasks",
- },
- },
- {
- $project: {
- tasks: {
- resources: {
- profilePic: 0,
- },
- },
- },
- },
- {
- $unwind: {
- path: "$tasks",
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $lookup: {
- from: "wbs",
- localField: "tasks.wbsId",
- foreignField: "_id",
- as: "projectId",
- },
- },
- {
- $addFields: {
- "tasks.projectId": {
- $cond: [
- { $ne: ["$projectId", []] },
- { $arrayElemAt: ["$projectId", 0] },
- "$tasks.projectId",
- ],
- },
- },
- },
- {
- $project: {
- projectId: 0,
- tasks: {
- projectId: {
- _id: 0,
- isActive: 0,
- modifiedDatetime: 0,
- wbsName: 0,
- createdDatetime: 0,
- __v: 0,
- },
- },
- },
- },
- {
- $addFields: {
- "tasks.projectId": "$tasks.projectId.projectId",
- },
- },
- {
- $lookup: {
- from: "taskNotifications",
- localField: "tasks._id",
- foreignField: "taskId",
- as: "tasks.taskNotifications",
- },
- },
- {
- $group: {
- _id: "$personId",
- tasks: {
- $push: "$tasks",
- },
- data: {
- $first: "$$ROOT",
- },
- },
- },
- {
- $addFields: {
- "data.tasks": {
- $filter: {
- input: "$tasks",
- as: "task",
- cond: { $ne: ["$$task", {}] },
- },
- },
- },
- },
- {
- $replaceRoot: {
- newRoot: "$data",
- },
+
+ 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) => {});
+
+ 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,
+ 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,
+ timeOffFrom: 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);
+
+ const timeEntries = await timeentry.find({
+ dateOfWork: {
+ $gte: pdtstart,
+ $lte: pdtend,
},
- ]);
+ personId: { $in: teamMemberIds },
+ });
+
+ const timeEntryByPerson = {};
+ timeEntries.map((timeEntry) => {
+ const personIdStr = timeEntry.personId.toString();
+
+ 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;
+ });
+
+ 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}`;
+
+ if (taskNotificationByTaskNdUser[taskNdUserID]) {
+ taskNotificationByTaskNdUser[taskNdUserID].push(
+ teamMemberTaskNotification
+ );
+ } else {
+ taskNotificationByTaskNdUser[taskNdUserID] = [
+ teamMemberTaskNotification,
+ ];
+ }
+ });
+
+ const taskByPerson = [];
+
+ 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];
+ }
+ });
+ });
+
+ const teamMemberTasksData = [];
+ teamMembers.map((teamMember) => {
+ const obj = {
+ personId: teamMember._id,
+ role: teamMember.role,
+ name: `${teamMember.firstName} ${teamMember.lastName}`,
+ weeklycommittedHours: teamMember.weeklycommittedHours,
+ timeOffFrom: teamMember.timeOffFrom || null,
+ timeOffTill: teamMember.timeOffTill || null,
+ 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);
+ });
+
+ return teamMemberTasksData;
+
+ // return myteam.aggregate([
+ // {
+ // $match: {
+ // _id: userId,
+ // },
+ // },
+ // {
+ // $unwind: '$myteam',
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$myteam._id',
+ // name: '$myteam.fullName',
+ // role: 1,
+ // },
+ // },
+ // // have personId, name, role
+ // {
+ // $lookup: {
+ // from: 'userProfiles',
+ // localField: 'personId',
+ // foreignField: '_id',
+ // as: 'persondata',
+ // },
+ // },
+ // {
+ // $match: {
+ // // dashboard tasks user roles hierarchy
+ // $or: [
+ // {
+ // role: { $in: ['Owner', 'Core Team'] },
+ // },
+ // {
+ // $and: [
+ // {
+ // role: 'Administrator',
+ // },
+ // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } },
+ // ],
+ // },
+ // {
+ // $and: [
+ // {
+ // role: { $in: ['Manager', 'Mentor'] },
+ // },
+ // {
+ // 'persondata.0.role': {
+ // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'],
+ // },
+ // },
+ // ],
+ // },
+ // { 'persondata.0._id': userId },
+ // { 'persondata.0.role': 'Volunteer' },
+ // { 'persondata.0.isVisible': true },
+ // ],
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: {
+ // $sum: [
+ // {
+ // $arrayElemAt: ['$persondata.weeklycommittedHours', 0],
+ // },
+ // {
+ // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0],
+ // },
+ // ],
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'timeEntries',
+ // localField: 'personId',
+ // foreignField: 'personId',
+ // as: 'timeEntryData',
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: 1,
+ // timeEntryData: {
+ // $filter: {
+ // input: '$timeEntryData',
+ // as: 'timeentry',
+ // cond: {
+ // $and: [
+ // {
+ // $gte: ['$$timeentry.dateOfWork', pdtstart],
+ // },
+ // {
+ // $lte: ['$$timeentry.dateOfWork', pdtend],
+ // },
+ // ],
+ // },
+ // },
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$timeEntryData',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $project: {
+ // personId: 1,
+ // name: 1,
+ // weeklycommittedHours: 1,
+ // totalSeconds: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.totalSeconds',
+ // 0,
+ // ],
+ // },
+ // isTangible: {
+ // $cond: [
+ // {
+ // $gte: ['$timeEntryData.totalSeconds', 0],
+ // },
+ // '$timeEntryData.isTangible',
+ // false,
+ // ],
+ // },
+ // role: 1,
+ // },
+ // },
+ // {
+ // $addFields: {
+ // tangibletime: {
+ // $cond: [
+ // {
+ // $eq: ['$isTangible', true],
+ // },
+ // '$totalSeconds',
+ // 0,
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: {
+ // personId: '$personId',
+ // weeklycommittedHours: '$weeklycommittedHours',
+ // name: '$name',
+ // role: '$role',
+ // },
+ // totalSeconds: {
+ // $sum: '$totalSeconds',
+ // },
+ // tangibletime: {
+ // $sum: '$tangibletime',
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // _id: 0,
+ // personId: '$_id.personId',
+ // name: '$_id.name',
+ // weeklycommittedHours: '$_id.weeklycommittedHours',
+ // totaltime_hrs: {
+ // $divide: ['$totalSeconds', 3600],
+ // },
+ // totaltangibletime_hrs: {
+ // $divide: ['$tangibletime', 3600],
+ // },
+ // role: '$_id.role',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'tasks',
+ // localField: 'personId',
+ // foreignField: 'resources.userID',
+ // as: 'tasks',
+ // },
+ // },
+ // {
+ // $project: {
+ // tasks: {
+ // resources: {
+ // profilePic: 0,
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $unwind: {
+ // path: '$tasks',
+ // preserveNullAndEmptyArrays: true,
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'wbs',
+ // localField: 'tasks.wbsId',
+ // foreignField: '_id',
+ // as: 'projectId',
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'tasks.projectId': {
+ // $cond: [
+ // { $ne: ['$projectId', []] },
+ // { $arrayElemAt: ['$projectId', 0] },
+ // '$tasks.projectId',
+ // ],
+ // },
+ // },
+ // },
+ // {
+ // $project: {
+ // projectId: 0,
+ // tasks: {
+ // projectId: {
+ // _id: 0,
+ // isActive: 0,
+ // modifiedDatetime: 0,
+ // wbsName: 0,
+ // createdDatetime: 0,
+ // __v: 0,
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'tasks.projectId': '$tasks.projectId.projectId',
+ // },
+ // },
+ // {
+ // $lookup: {
+ // from: 'taskNotifications',
+ // localField: 'tasks._id',
+ // foreignField: 'taskId',
+ // as: 'tasks.taskNotifications',
+ // },
+ // },
+ // {
+ // $group: {
+ // _id: '$personId',
+ // tasks: {
+ // $push: '$tasks',
+ // },
+ // data: {
+ // $first: '$$ROOT',
+ // },
+ // },
+ // },
+ // {
+ // $addFields: {
+ // 'data.tasks': {
+ // $filter: {
+ // input: '$tasks',
+ // as: 'task',
+ // cond: { $ne: ['$$task', {}] },
+ // },
+ // },
+ // },
+ // },
+ // {
+ // $replaceRoot: {
+ // newRoot: '$data',
+ // },
+ // },
+ // ]);
};
const getTasksForSingleUser = function (userId) {
const pdtstart = moment()
@@ -381,6 +561,9 @@ const taskHelper = function () {
{
$lte: ["$$timeentry.dateOfWork", pdtend],
},
+ {
+ $in: ["$$timeentry.entryType", ["default", null]],
+ },
],
},
},
From b81b0a15340148a6378ce6aa920e39bfe01a76b2 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Wed, 6 Dec 2023 17:16:44 -0500
Subject: [PATCH 263/272] added timeOffFrom and timeOffTill fields to mongoDB
---
src/controllers/reasonSchedulingController.js | 171 ++++----
src/helpers/dashboardhelper.js | 374 ++++++++++--------
src/models/userProfile.js | 104 +++--
3 files changed, 387 insertions(+), 262 deletions(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 6f872f338..4d56c5a5e 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,61 @@ 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,
});
}
+ // new changes
+
+ if (
+ foundUser.hasOwnProperty("timeOffFrom") &&
+ foundUser.hasOwnProperty("timeOffTill")
+ ) {
+ if (currentDate >= foundUser.timeOffTill) {
+ await UserModel.findOneAndUpdate(
+ {
+ _id: userId,
+ },
+ {
+ $set: {
+ timeOffFrom: currentDate,
+ timeOffTill: newDate,
+ },
+ }
+ );
+ } else {
+ await UserModel.findOneAndUpdate(
+ {
+ _id: userId,
+ },
+ {
+ $set: {
+ timeOffTill: newDate,
+ },
+ }
+ );
+ }
+ } else {
+ 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 +112,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 +128,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 +144,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 +180,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 +194,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 +218,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 +244,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 +265,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 +275,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 +300,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 +312,21 @@ 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!",
});
} 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 +337,10 @@ 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 +350,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 +372,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..a200a0095 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,15 @@ const dashboardhelper = function () {
$group: {
_id: 0,
memberCount: { $sum: 1 },
- totalweeklycommittedHours: { $sum: '$_id.weeklycommittedHours' },
+ totalweeklycommittedHours: { $sum: "$_id.weeklycommittedHours" },
totaltime_hrs: {
- $sum: '$time_hrs',
+ $sum: "$time_hrs",
},
totaltangibletime_hrs: {
- $sum: '$tangibletime_hrs',
+ $sum: "$tangibletime_hrs",
},
totalintangibletime_hrs: {
- $sum: '$intangibletime_hrs',
+ $sum: "$intangibletime_hrs",
},
},
},
@@ -163,55 +165,93 @@ 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,
+ }
+ )
+ .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,
+ }
+ )
+ .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,
-})
- .then(res => res).catch((e) => {});
- }
+ role: 1,
+ firstName: 1,
+ lastName: 1,
+ isVisible: 1,
+ weeklycommittedHours: 1,
+ weeklySummaries: 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 +265,56 @@ 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,
+ };
+ leaderBoardData.push(obj);
});
const sortedLBData = leaderBoardData.sort((a, b) => {
@@ -532,14 +592,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 +610,7 @@ const dashboardhelper = function () {
$gte: pdtStart,
$lte: pdtEnd,
},
- entryType: { $in: ['default', null] },
+ entryType: { $in: ["default", null] },
personId: userId,
});
@@ -570,7 +630,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,
@@ -583,8 +643,8 @@ const dashboardhelper = function () {
} catch (err) {
return [
{
- personId: 'error',
- name: 'Error Error',
+ personId: "error",
+ name: "Error Error",
totaltime_hrs: 0,
totaltangibletime_hrs: 0,
totalintangibletime_hrs: 0,
@@ -595,8 +655,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 +672,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 +693,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 +707,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 +724,10 @@ const dashboardhelper = function () {
},
{
$lookup: {
- from: 'timeEntries',
- localField: '_id',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "_id",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -675,23 +735,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 +766,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 +794,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 +811,10 @@ const dashboardhelper = function () {
},
{
$lookup: {
- from: 'timeEntries',
- localField: '_id',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "_id",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -759,23 +822,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 +853,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 +891,7 @@ const dashboardhelper = function () {
$project: {
_id: 1,
timeSpent_hrs: {
- $divide: ['$effort', 3600],
+ $divide: ["$effort", 3600],
},
},
},
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index 8a8de2e18..762b61c02 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,25 @@ 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 },
+ },
],
privacySettings: {
blueSquares: { type: Boolean, default: true },
@@ -104,7 +114,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 +144,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 +162,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"
+);
From 02ba9860461b0e01b15bc68c0b89fa14bb2817df Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Sun, 17 Dec 2023 14:16:00 -0500
Subject: [PATCH 264/272] added timeOffFrom and timeOffTill to taskHelper
---
src/helpers/taskHelper.js | 420 +++++++++++++++++++++-----------------
1 file changed, 237 insertions(+), 183 deletions(-)
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 800d1ee6b..fc6a331b3 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -1,149 +1,207 @@
-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,
+ }
+ )
+ .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);
+ });
+ });
- 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,
+ }
+ )
+ .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) => {});
+ }
- 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()] || [],
+ };
+ teamMemberTasksData.push(obj);
});
-
return teamMemberTasksData;
-
// return myteam.aggregate([
// {
// $match: {
@@ -429,13 +487,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,20 +502,16 @@ 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],
},
],
},
@@ -465,10 +519,10 @@ const taskHelper = function () {
},
{
$lookup: {
- from: 'timeEntries',
- localField: 'personId',
- foreignField: 'personId',
- as: 'timeEntryData',
+ from: "timeEntries",
+ localField: "personId",
+ foreignField: "personId",
+ as: "timeEntryData",
},
},
{
@@ -479,18 +533,18 @@ const taskHelper = function () {
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 +554,7 @@ const taskHelper = function () {
},
{
$unwind: {
- path: '$timeEntryData',
+ path: "$timeEntryData",
preserveNullAndEmptyArrays: true,
},
},
@@ -513,18 +567,18 @@ const taskHelper = function () {
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 +589,9 @@ const taskHelper = function () {
tangibletime: {
$cond: [
{
- $eq: ['$isTangible', true],
+ $eq: ["$isTangible", true],
},
- '$totalSeconds',
+ "$totalSeconds",
0,
],
},
@@ -546,40 +600,40 @@ const taskHelper = function () {
{
$group: {
_id: {
- personId: '$personId',
- weeklycommittedHours: '$weeklycommittedHours',
- name: '$name',
- role: '$role',
+ personId: "$personId",
+ weeklycommittedHours: "$weeklycommittedHours",
+ 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",
+ 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 +647,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 +687,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 +728,7 @@ const taskHelper = function () {
const getUserProfileFirstAndLastName = function (userId) {
return userProfile.findById(userId).then((results) => {
if (!results) {
- return ' ';
+ return " ";
}
return `${results.firstName} ${results.lastName}`;
});
From c26046ec38728b000962cfd42dd7c71ca1fe24c1 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Sun, 17 Dec 2023 14:55:58 -0500
Subject: [PATCH 265/272] added timeOffFrom and timeOffTill to reportHelper
---
src/helpers/reporthelper.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
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: {
From a153942136a951dde7b4503a58f52218087ffe33 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 18 Dec 2023 14:32:17 -0500
Subject: [PATCH 266/272] updated dashboardhelper and taskHelper to add
timeOffFrom anf timeOffTill for individual task and leaderboard data
---
src/helpers/dashboardhelper.js | 2 ++
src/helpers/taskHelper.js | 14 ++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index a200a0095..0482f4252 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -638,6 +638,8 @@ const dashboardhelper = function () {
totalintangibletime_hrs: intangibleSeconds / 3600,
percentagespentintangible:
(intangibleSeconds / tangibleSeconds) * 100,
+ timeOffFrom: user.timeOffFrom,
+ timeOffTill: user.timeOffTill,
},
];
} catch (err) {
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index fc6a331b3..6d5449bc8 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -515,6 +515,12 @@ const taskHelper = function () {
},
],
},
+ timeOffFrom: {
+ $ifNull: ["$timeOffFrom", null],
+ },
+ timeOffTill: {
+ $ifNull: ["$timeOffTill", null],
+ },
},
},
{
@@ -530,6 +536,8 @@ const taskHelper = function () {
personId: 1,
name: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
role: 1,
timeEntryData: {
$filter: {
@@ -563,6 +571,8 @@ const taskHelper = function () {
personId: 1,
name: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
role: 1,
totalSeconds: {
$cond: [
@@ -602,6 +612,8 @@ const taskHelper = function () {
_id: {
personId: "$personId",
weeklycommittedHours: "$weeklycommittedHours",
+ timeOffFrom: "$timeOffFrom",
+ timeOffTill: "$timeOffTill",
name: "$name",
role: "$role",
},
@@ -619,6 +631,8 @@ const taskHelper = function () {
personId: "$_id.personId",
name: "$_id.name",
weeklycommittedHours: "$_id.weeklycommittedHours",
+ timeOffFrom: "$_id.timeOffFrom",
+ timeOffTill: "$_id.timeOffTill",
role: "$_id.role",
totaltime_hrs: {
$divide: ["$totalSeconds", 3600],
From f484767ccef78e1e8e6118f8323003241c9daa1d Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 18 Dec 2023 17:50:04 -0500
Subject: [PATCH 267/272] modified the array representation for timeOffFrom and
TimeOffTill to a value instead of array
---
src/helpers/dashboardhelper.js | 265 +++++++++++++++++++++++++++++++++
1 file changed, 265 insertions(+)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 0482f4252..e6d5118f6 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -258,6 +258,7 @@ const dashboardhelper = function () {
$gte: pdtstart,
$lte: pdtend,
},
+<<<<<<< HEAD
personId: { $in: teamMemberIds },
});
@@ -582,6 +583,270 @@ const dashboardhelper = function () {
// },
// },
// ]);
+=======
+ {
+ $unwind: "$myteam",
+ },
+ {
+ $project: {
+ _id: 0,
+ role: 1,
+ personId: "$myteam._id",
+ name: "$myteam.fullName",
+ },
+ },
+ {
+ $lookup: {
+ from: "userProfiles",
+ localField: "personId",
+ foreignField: "_id",
+ as: "persondata",
+ },
+ },
+ {
+ $match: {
+ // leaderboard user roles hierarchy
+ $or: [
+ {
+ role: { $in: ["Owner", "Core Team"] },
+ },
+ {
+ $and: [
+ {
+ role: "Administrator",
+ },
+ { "persondata.0.role": { $nin: ["Owner", "Administrator"] } },
+ ],
+ },
+ {
+ $and: [
+ {
+ role: { $in: ["Manager", "Mentor"] },
+ },
+ {
+ "persondata.0.role": {
+ $nin: [
+ "Manager",
+ "Mentor",
+ "Core Team",
+ "Administrator",
+ "Owner",
+ ],
+ },
+ },
+ ],
+ },
+ { "persondata.0._id": userId },
+ { "persondata.0.role": "Volunteer" },
+ { "persondata.0.isVisible": true },
+ ],
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ role: {
+ $arrayElemAt: ["$persondata.role", 0],
+ },
+ isVisible: {
+ $arrayElemAt: ["$persondata.isVisible", 0],
+ },
+ hasSummary: {
+ $ne: [
+ {
+ $arrayElemAt: [
+ {
+ $arrayElemAt: ["$persondata.weeklySummaries.summary", 0],
+ },
+ 0,
+ ],
+ },
+ "",
+ ],
+ },
+ weeklycommittedHours: {
+ $sum: [
+ {
+ $arrayElemAt: ["$persondata.weeklycommittedHours", 0],
+ },
+ {
+ $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0],
+ },
+ ],
+ },
+ timeOffFrom: {
+ $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null],
+ },
+ timeOffTill: {
+ $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null],
+ },
+ },
+ },
+ {
+ $lookup: {
+ from: "timeEntries",
+ localField: "personId",
+ foreignField: "personId",
+ as: "timeEntryData",
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ role: 1,
+ isVisible: 1,
+ hasSummary: 1,
+ weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
+ timeEntryData: {
+ $filter: {
+ input: "$timeEntryData",
+ as: "timeentry",
+ cond: {
+ $and: [
+ {
+ $gte: ["$$timeentry.dateOfWork", pdtstart],
+ },
+ {
+ $lte: ["$$timeentry.dateOfWork", pdtend],
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ {
+ $unwind: {
+ path: "$timeEntryData",
+ preserveNullAndEmptyArrays: true,
+ },
+ },
+ {
+ $project: {
+ personId: 1,
+ name: 1,
+ role: 1,
+ isVisible: 1,
+ hasSummary: 1,
+ weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
+ totalSeconds: {
+ $cond: [
+ {
+ $gte: ["$timeEntryData.totalSeconds", 0],
+ },
+ "$timeEntryData.totalSeconds",
+ 0,
+ ],
+ },
+ isTangible: {
+ $cond: [
+ {
+ $gte: ["$timeEntryData.totalSeconds", 0],
+ },
+ "$timeEntryData.isTangible",
+ false,
+ ],
+ },
+ },
+ },
+ {
+ $addFields: {
+ tangibletime: {
+ $cond: [
+ {
+ $eq: ["$isTangible", true],
+ },
+ "$totalSeconds",
+ 0,
+ ],
+ },
+ intangibletime: {
+ $cond: [
+ {
+ $eq: ["$isTangible", false],
+ },
+ "$totalSeconds",
+ 0,
+ ],
+ },
+ },
+ },
+ {
+ $group: {
+ _id: {
+ personId: "$personId",
+ weeklycommittedHours: "$weeklycommittedHours",
+ timeOffFrom: "$timeOffFrom",
+ timeOffTill: "$timeOffTill",
+ name: "$name",
+ role: "$role",
+ isVisible: "$isVisible",
+ hasSummary: "$hasSummary",
+ },
+ totalSeconds: {
+ $sum: "$totalSeconds",
+ },
+ tangibletime: {
+ $sum: "$tangibletime",
+ },
+ intangibletime: {
+ $sum: "$intangibletime",
+ },
+ },
+ },
+ {
+ $project: {
+ _id: 0,
+ personId: "$_id.personId",
+ name: "$_id.name",
+ role: "$_id.role",
+ isVisible: "$_id.isVisible",
+ hasSummary: "$_id.hasSummary",
+ weeklycommittedHours: "$_id.weeklycommittedHours",
+ totaltime_hrs: {
+ $divide: ["$totalSeconds", 3600],
+ },
+ totaltangibletime_hrs: {
+ $divide: ["$tangibletime", 3600],
+ },
+ totalintangibletime_hrs: {
+ $divide: ["$intangibletime", 3600],
+ },
+ percentagespentintangible: {
+ $cond: [
+ {
+ $eq: ["$totalSeconds", 0],
+ },
+ 0,
+ {
+ $multiply: [
+ {
+ $divide: ["$tangibletime", "$totalSeconds"],
+ },
+ 100,
+ ],
+ },
+ ],
+ },
+ timeOffFrom: "$_id.timeOffFrom",
+ timeOffTill: "$_id.timeOffTill",
+ },
+ },
+ {
+ $sort: {
+ totaltangibletime_hrs: -1,
+ name: 1,
+ role: 1,
+ },
+ },
+ ]);
+>>>>>>> 367abce (modified the array representation for timeOffFrom and TimeOffTill to a value instead of array)
};
/**
From a956753af7579b5049338493273f19cefb419f0d Mon Sep 17 00:00:00 2001
From: Shiwani99 <78906820+Shiwani99@users.noreply.github.com>
Date: Mon, 18 Dec 2023 18:53:26 -0500
Subject: [PATCH 268/272] Added comments to reasonSchedulingController.js
---
src/controllers/reasonSchedulingController.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 4d56c5a5e..63dc51fed 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -55,12 +55,13 @@ const postReason = async (req, res) => {
});
}
- // new changes
+ // 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(
{
@@ -74,6 +75,7 @@ const postReason = async (req, res) => {
}
);
} else {
+ // else only timeOffTill will be updated
await UserModel.findOneAndUpdate(
{
_id: userId,
@@ -86,6 +88,7 @@ const postReason = async (req, res) => {
);
}
} else {
+ // if both the fields are not present then these fields will be added to mongoDB for that user
await UserModel.findOneAndUpdate(
{
_id: userId,
From 6346f4a40093db72230a5a4a673b50a3bd3324be Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 8 Jan 2024 06:04:11 -0500
Subject: [PATCH 269/272] fixed issues with rebasing current branch with
development and added timeOffFrom and timeOffTill to the new aggregation in
dashboard and task helper
---
package-lock.json | 106 ++++++-------
src/helpers/dashboardhelper.js | 273 +--------------------------------
src/helpers/taskHelper.js | 10 ++
3 files changed, 71 insertions(+), 318 deletions(-)
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/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index e6d5118f6..9335a67c4 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -212,6 +212,8 @@ const dashboardhelper = function () {
isVisible: 1,
weeklycommittedHours: 1,
weeklySummaries: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
}
)
.then((res) => res)
@@ -229,6 +231,8 @@ const dashboardhelper = function () {
isVisible: 1,
weeklycommittedHours: 1,
weeklySummaries: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
}
)
.then((res) => res)
@@ -245,6 +249,8 @@ const dashboardhelper = function () {
isVisible: 1,
weeklycommittedHours: 1,
weeklySummaries: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
}
)
.then((res) => res)
@@ -258,7 +264,6 @@ const dashboardhelper = function () {
$gte: pdtstart,
$lte: pdtend,
},
-<<<<<<< HEAD
personId: { $in: teamMemberIds },
});
@@ -314,6 +319,8 @@ const dashboardhelper = function () {
timeEntryByPerson[teamMember._id.toString()]?.totalSeconds) *
100
: 0,
+ timeOffFrom: teamMember.timeOffFrom || null,
+ timeOffTill: teamMember.timeOffTill || null,
};
leaderBoardData.push(obj);
});
@@ -583,270 +590,6 @@ const dashboardhelper = function () {
// },
// },
// ]);
-=======
- {
- $unwind: "$myteam",
- },
- {
- $project: {
- _id: 0,
- role: 1,
- personId: "$myteam._id",
- name: "$myteam.fullName",
- },
- },
- {
- $lookup: {
- from: "userProfiles",
- localField: "personId",
- foreignField: "_id",
- as: "persondata",
- },
- },
- {
- $match: {
- // leaderboard user roles hierarchy
- $or: [
- {
- role: { $in: ["Owner", "Core Team"] },
- },
- {
- $and: [
- {
- role: "Administrator",
- },
- { "persondata.0.role": { $nin: ["Owner", "Administrator"] } },
- ],
- },
- {
- $and: [
- {
- role: { $in: ["Manager", "Mentor"] },
- },
- {
- "persondata.0.role": {
- $nin: [
- "Manager",
- "Mentor",
- "Core Team",
- "Administrator",
- "Owner",
- ],
- },
- },
- ],
- },
- { "persondata.0._id": userId },
- { "persondata.0.role": "Volunteer" },
- { "persondata.0.isVisible": true },
- ],
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: {
- $arrayElemAt: ["$persondata.role", 0],
- },
- isVisible: {
- $arrayElemAt: ["$persondata.isVisible", 0],
- },
- hasSummary: {
- $ne: [
- {
- $arrayElemAt: [
- {
- $arrayElemAt: ["$persondata.weeklySummaries.summary", 0],
- },
- 0,
- ],
- },
- "",
- ],
- },
- weeklycommittedHours: {
- $sum: [
- {
- $arrayElemAt: ["$persondata.weeklycommittedHours", 0],
- },
- {
- $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0],
- },
- ],
- },
- timeOffFrom: {
- $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null],
- },
- timeOffTill: {
- $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null],
- },
- },
- },
- {
- $lookup: {
- from: "timeEntries",
- localField: "personId",
- foreignField: "personId",
- as: "timeEntryData",
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- timeOffFrom: 1,
- timeOffTill: 1,
- timeEntryData: {
- $filter: {
- input: "$timeEntryData",
- as: "timeentry",
- cond: {
- $and: [
- {
- $gte: ["$$timeentry.dateOfWork", pdtstart],
- },
- {
- $lte: ["$$timeentry.dateOfWork", pdtend],
- },
- ],
- },
- },
- },
- },
- },
- {
- $unwind: {
- path: "$timeEntryData",
- preserveNullAndEmptyArrays: true,
- },
- },
- {
- $project: {
- personId: 1,
- name: 1,
- role: 1,
- isVisible: 1,
- hasSummary: 1,
- weeklycommittedHours: 1,
- timeOffFrom: 1,
- timeOffTill: 1,
- totalSeconds: {
- $cond: [
- {
- $gte: ["$timeEntryData.totalSeconds", 0],
- },
- "$timeEntryData.totalSeconds",
- 0,
- ],
- },
- isTangible: {
- $cond: [
- {
- $gte: ["$timeEntryData.totalSeconds", 0],
- },
- "$timeEntryData.isTangible",
- false,
- ],
- },
- },
- },
- {
- $addFields: {
- tangibletime: {
- $cond: [
- {
- $eq: ["$isTangible", true],
- },
- "$totalSeconds",
- 0,
- ],
- },
- intangibletime: {
- $cond: [
- {
- $eq: ["$isTangible", false],
- },
- "$totalSeconds",
- 0,
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- personId: "$personId",
- weeklycommittedHours: "$weeklycommittedHours",
- timeOffFrom: "$timeOffFrom",
- timeOffTill: "$timeOffTill",
- name: "$name",
- role: "$role",
- isVisible: "$isVisible",
- hasSummary: "$hasSummary",
- },
- totalSeconds: {
- $sum: "$totalSeconds",
- },
- tangibletime: {
- $sum: "$tangibletime",
- },
- intangibletime: {
- $sum: "$intangibletime",
- },
- },
- },
- {
- $project: {
- _id: 0,
- personId: "$_id.personId",
- name: "$_id.name",
- role: "$_id.role",
- isVisible: "$_id.isVisible",
- hasSummary: "$_id.hasSummary",
- weeklycommittedHours: "$_id.weeklycommittedHours",
- totaltime_hrs: {
- $divide: ["$totalSeconds", 3600],
- },
- totaltangibletime_hrs: {
- $divide: ["$tangibletime", 3600],
- },
- totalintangibletime_hrs: {
- $divide: ["$intangibletime", 3600],
- },
- percentagespentintangible: {
- $cond: [
- {
- $eq: ["$totalSeconds", 0],
- },
- 0,
- {
- $multiply: [
- {
- $divide: ["$tangibletime", "$totalSeconds"],
- },
- 100,
- ],
- },
- ],
- },
- timeOffFrom: "$_id.timeOffFrom",
- timeOffTill: "$_id.timeOffTill",
- },
- },
- {
- $sort: {
- totaltangibletime_hrs: -1,
- name: 1,
- role: 1,
- },
- },
- ]);
->>>>>>> 367abce (modified the array representation for timeOffFrom and TimeOffTill to a value instead of array)
};
/**
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 6d5449bc8..8347a56ef 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -22,6 +22,8 @@ const taskHelper = function () {
isVisible: 1,
weeklycommittedHours: 1,
weeklySummaries: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
}
)
.then((res) => res)
@@ -68,6 +70,8 @@ const taskHelper = function () {
firstName: 1,
lastName: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
}
)
.then((res) => res)
@@ -83,6 +87,8 @@ const taskHelper = function () {
firstName: 1,
lastName: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
}
)
.then((res) => res)
@@ -97,6 +103,8 @@ const taskHelper = function () {
firstName: 1,
lastName: 1,
weeklycommittedHours: 1,
+ timeOffFrom: 1,
+ timeOffTill: 1,
}
)
.then((res) => res)
@@ -196,6 +204,8 @@ const taskHelper = function () {
timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 ||
0,
tasks: taskByPerson[teamMember._id.toString()] || [],
+ timeOffFrom: teamMember.timeOffFrom || null,
+ timeOffTill: teamMember.timeOffTill || null,
};
teamMemberTasksData.push(obj);
});
From 2f362910ce36b623aff3ddfe2ce02d2353153e74 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 8 Jan 2024 07:22:46 -0500
Subject: [PATCH 270/272] resolved errors after merge conflicts
---
src/controllers/reasonSchedulingController.js | 11 +---------
src/helpers/dashboardhelper.js | 21 ++++++++++---------
src/helpers/taskHelper.js | 15 -------------
3 files changed, 12 insertions(+), 35 deletions(-)
diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js
index 4fce71b3a..a76dcf4a2 100644
--- a/src/controllers/reasonSchedulingController.js
+++ b/src/controllers/reasonSchedulingController.js
@@ -11,9 +11,6 @@ const postReason = async (req, res) => {
.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) {
@@ -38,7 +35,6 @@ const postReason = async (req, res) => {
});
}
-
// Commented this condition to make reason scheduler available to all the users.
// error case 1
// if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') {
@@ -160,7 +156,6 @@ const postReason = async (req, res) => {
// emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null);
}
-
return res.sendStatus(200);
} catch (error) {
console.log(error);
@@ -307,11 +302,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 emailBody = ` Hi !
const emailBody = ` Hi !
This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has updated their Blue Square Reason.
@@ -331,7 +324,6 @@ const patchReason = async (req, res) => {
// emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null);
}
-
return res.status(200).json({
message: "Reason Updated!",
message: "Reason Updated!",
@@ -348,13 +340,12 @@ const deleteReason = async (req, res) => {
const { reasonData, requestor } = req.body;
const { userId } = req.params;
-
// error case 1
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,
});
}
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 2babef0b2..9f172dd2a 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -174,20 +174,17 @@ const dashboardhelper = function () {
.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");
+
+ const pdtend = moment()
.tz("America/Los_Angeles")
- .startOf("week")
+ .endOf("week")
.format("YYYY-MM-DD");
- const pdtend = moment()
- .tz('America/Los_Angeles')
- .endOf('week')
- .format('YYYY-MM-DD');
let teamMemberIds = [userid];
let teamMembers = [];
@@ -210,9 +207,6 @@ const dashboardhelper = function () {
});
});
- teamMembers = await userProfile
- .find(
- { _id: { $in: teamMemberIds }, isActive: true },
teamMembers = await userProfile
.find(
{ _id: { $in: teamMemberIds }, isActive: true },
@@ -235,6 +229,7 @@ const dashboardhelper = function () {
teamMembers = await userProfile
.find(
{ isActive: true, role: { $nin: excludedRoles } },
+ {
role: 1,
firstName: 1,
lastName: 1,
@@ -300,7 +295,13 @@ 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 +=
diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js
index 0d26b96bb..372c960dd 100644
--- a/src/helpers/taskHelper.js
+++ b/src/helpers/taskHelper.js
@@ -40,25 +40,10 @@ const taskHelper = function () {
.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" &&
From bd9a1500299a597190de07ff4eb38e6ef4b2ef77 Mon Sep 17 00:00:00 2001
From: Shiwani Rajagopalan
Date: Mon, 8 Jan 2024 07:26:38 -0500
Subject: [PATCH 271/272] resolved errors in userProfile.js after conflicts
---
src/models/userProfile.js | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/models/userProfile.js b/src/models/userProfile.js
index 8f5e23d2c..aaa3923f5 100644
--- a/src/models/userProfile.js
+++ b/src/models/userProfile.js
@@ -1,13 +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();
From b03f597e8d3cb2bf59adbaad42d2f15262a6c81f Mon Sep 17 00:00:00 2001
From: Vishala Ramasamy
Date: Wed, 10 Jan 2024 16:23:36 -0800
Subject: [PATCH 272/272] Lb view hier. for Admins
---
src/helpers/dashboardhelper.js | 40 +---------------------------------
1 file changed, 1 insertion(+), 39 deletions(-)
diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js
index 9f172dd2a..8df4f6c9d 100644
--- a/src/helpers/dashboardhelper.js
+++ b/src/helpers/dashboardhelper.js
@@ -223,46 +223,8 @@ const dashboardhelper = function () {
)
.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,
- timeOffFrom: 1,
- timeOffTill: 1,
- }
- )
- .then((res) => res)
- .catch((e) => {});
} else {
- // 'Core Team', 'Owner' //All users
+ // 'Core Team', 'Owner' , 'Admin' //Show All users
teamMembers = await userProfile
.find(
{ isActive: true },