diff --git a/apidoc/apidoc.json b/apidoc/apidoc.json
index 8b2893529d..2b7651614d 100644
--- a/apidoc/apidoc.json
+++ b/apidoc/apidoc.json
@@ -2,6 +2,7 @@
"name": "Habitica V3 API Documentation",
"title": "Habitica",
"url": "https://habitica.com",
+ "version": "3.0.0",
"sampleUrl": null,
"header": {
"title": "Introduction",
diff --git a/habitica-images b/habitica-images
index 6e9d17b8a4..8d63ff55e5 160000
--- a/habitica-images
+++ b/habitica-images
@@ -1 +1 @@
-Subproject commit 6e9d17b8a4af295ba2d9dc9870b2904035d6fba7
+Subproject commit 8d63ff55e5c63872f95a3c9106d0b5f90af9ab6f
diff --git a/migrations/tasks/team-tasks-v2.js b/migrations/tasks/team-tasks-v2.js
new file mode 100644
index 0000000000..a5c90cab95
--- /dev/null
+++ b/migrations/tasks/team-tasks-v2.js
@@ -0,0 +1,71 @@
+import filter from 'lodash/filter';
+import find from 'lodash/find';
+import isArray from 'lodash/isArray';
+import { model as Group } from '../../website/server/models/group';
+import { model as User } from '../../website/server/models/user';
+import * as Tasks from '../../website/server/models/task';
+
+async function updateTeamTasks (team) {
+ const toSave = [];
+ const teamTasks = await Tasks.Task.find({
+ 'group.id': team._id,
+ }).exec();
+
+ const teamBoardTasks = filter(teamTasks, task => !task.userId);
+ const teamUserTasks = filter(teamTasks, task => task.userId);
+
+ for (const boardTask of teamBoardTasks) {
+ if (isArray(boardTask.group.assignedUsers)) {
+ boardTask.group.approval = undefined;
+ boardTask.group.assignedDate = undefined;
+ boardTask.group.assigningUsername = undefined;
+ boardTask.group.sharedCompletion = undefined;
+
+ for (const assignedUserId of boardTask.group.assignedUsers) {
+ const assignedUser = await User.findById(assignedUserId, 'auth'); // eslint-disable-line no-await-in-loop
+ const userTask = find(teamUserTasks, task => task.userId === assignedUserId
+ && task.group.taskId === boardTask._id);
+ if (!boardTask.group.assignedUsersDetail) boardTask.group.assignedUsersDetail = {};
+ if (userTask && assignedUser) {
+ boardTask.group.assignedUsersDetail[assignedUserId] = {
+ assignedDate: userTask.group.assignedDate,
+ assignedUsername: assignedUser.auth.local.username,
+ assigningUsername: userTask.group.assigningUsername,
+ completed: userTask.completed || false,
+ completedDate: userTask.dateCompleted,
+ };
+ } else if (assignedUser) {
+ boardTask.group.assignedUsersDetail[assignedUserId] = {
+ assignedDate: new Date(),
+ assignedUsername: assignedUser.auth.local.username,
+ assigningUsername: null,
+ completed: false,
+ completedDate: null,
+ };
+ } else {
+ const taskIndex = boardTask.group.assignedUsers.indexOf(assignedUserId);
+ boardTask.group.assignedUsers.splice(taskIndex, 1);
+ }
+ if (userTask) toSave.push(Tasks.Task.findByIdAndDelete(userTask._id));
+ }
+ boardTask.markModified('group');
+ toSave.push(boardTask.save());
+ }
+ }
+
+ return Promise.all(toSave);
+}
+
+export default async function processTeams () {
+ const activeTeams = await Group.find({
+ 'purchased.plan.customerId': { $exists: true },
+ $or: [
+ { 'purchased.plan.dateTerminated': { $exists: false } },
+ { 'purchased.plan.dateTerminated': null },
+ { 'purchased.plan.dateTerminated': { $gt: new Date() } },
+ ],
+ }).exec();
+
+ const taskPromises = activeTeams.map(updateTeamTasks);
+ return Promise.all(taskPromises);
+}
diff --git a/package-lock.json b/package-lock.json
index 494106b0c3..076a98060c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "habitica",
- "version": "4.239.0",
+ "version": "4.242.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -22,25 +22,25 @@
}
},
"@babel/compat-data": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz",
- "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ=="
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz",
+ "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ=="
},
"@babel/core": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz",
- "integrity": "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==",
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz",
+ "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==",
"requires": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.6",
- "@babel/helper-compilation-targets": "^7.18.6",
- "@babel/helper-module-transforms": "^7.18.6",
- "@babel/helpers": "^7.18.6",
- "@babel/parser": "^7.18.6",
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.6",
- "@babel/types": "^7.18.6",
+ "@babel/generator": "^7.18.13",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helpers": "^7.18.9",
+ "@babel/parser": "^7.18.13",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.18.13",
+ "@babel/types": "^7.18.13",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -56,103 +56,21 @@
"@babel/highlight": "^7.18.6"
}
},
- "@babel/compat-data": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz",
- "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ=="
- },
"@babel/generator": {
- "version": "7.18.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz",
- "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==",
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz",
+ "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==",
"requires": {
- "@babel/types": "^7.18.7",
+ "@babel/types": "^7.18.13",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
}
},
- "@babel/helper-compilation-targets": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz",
- "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==",
- "requires": {
- "@babel/compat-data": "^7.18.6",
- "@babel/helper-validator-option": "^7.18.6",
- "browserslist": "^4.20.2",
- "semver": "^6.3.0"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz",
- "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q=="
- },
- "@babel/helper-function-name": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz",
- "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==",
- "requires": {
- "@babel/template": "^7.18.6",
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-hoist-variables": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
- "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
- "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz",
- "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==",
- "requires": {
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-module-imports": "^7.18.6",
- "@babel/helper-simple-access": "^7.18.6",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/helper-validator-identifier": "^7.18.6",
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.6",
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-simple-access": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
- "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
- "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
"@babel/helper-validator-identifier": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
},
- "@babel/helper-validator-option": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
- "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw=="
- },
"@babel/highlight": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
@@ -164,42 +82,43 @@
}
},
"@babel/parser": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz",
- "integrity": "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw=="
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz",
+ "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg=="
},
"@babel/template": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
- "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"requires": {
"@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.18.6",
- "@babel/types": "^7.18.6"
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
}
},
"@babel/traverse": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz",
- "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==",
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz",
+ "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==",
"requires": {
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.6",
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-function-name": "^7.18.6",
+ "@babel/generator": "^7.18.13",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.18.6",
- "@babel/types": "^7.18.6",
+ "@babel/parser": "^7.18.13",
+ "@babel/types": "^7.18.13",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
- "version": "7.18.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz",
- "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==",
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
+ "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
"requires": {
+ "@babel/helper-string-parser": "^7.18.10",
"@babel/helper-validator-identifier": "^7.18.6",
"to-fast-properties": "^2.0.0"
}
@@ -214,22 +133,6 @@
"@jridgewell/trace-mapping": "^0.3.9"
}
},
- "browserslist": {
- "version": "4.21.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz",
- "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001359",
- "electron-to-chromium": "^1.4.172",
- "node-releases": "^2.0.5",
- "update-browserslist-db": "^1.0.4"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001361",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz",
- "integrity": "sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ=="
- },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -240,16 +143,6 @@
"supports-color": "^5.3.0"
}
},
- "electron-to-chromium": {
- "version": "1.4.173",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.173.tgz",
- "integrity": "sha512-Qo3LnVW6JRNhD32viSdPebxKI7K+3WeBDjU1+Q2yZS83zAh8C2LyPpzTimlciv6U74KpY9n/0ESAhUByRke0jw=="
- },
- "node-releases": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
- "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q=="
- },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -258,15 +151,30 @@
}
},
"@babel/generator": {
- "version": "7.18.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz",
- "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==",
+ "version": "7.18.12",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz",
+ "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==",
"requires": {
- "@babel/types": "^7.18.7",
+ "@babel/types": "^7.18.10",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
"dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
"@jridgewell/gen-mapping": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
@@ -288,46 +196,42 @@
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz",
- "integrity": "sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz",
+ "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==",
"requires": {
"@babel/helper-explode-assignable-expression": "^7.18.6",
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.18.9"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-compilation-targets": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz",
- "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
+ "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
"requires": {
- "@babel/compat-data": "^7.18.6",
+ "@babel/compat-data": "^7.18.8",
"@babel/helper-validator-option": "^7.18.6",
"browserslist": "^4.20.2",
"semver": "^6.3.0"
},
"dependencies": {
- "browserslist": {
- "version": "4.21.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz",
- "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==",
- "requires": {
- "caniuse-lite": "^1.0.30001359",
- "electron-to-chromium": "^1.4.172",
- "node-releases": "^2.0.5",
- "update-browserslist-db": "^1.0.4"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30001361",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz",
- "integrity": "sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ=="
- },
- "node-releases": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
- "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q=="
- },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -336,16 +240,16 @@
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz",
- "integrity": "sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz",
+ "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==",
"requires": {
"@babel/helper-annotate-as-pure": "^7.18.6",
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-function-name": "^7.18.6",
- "@babel/helper-member-expression-to-functions": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
"@babel/helper-optimise-call-expression": "^7.18.6",
- "@babel/helper-replace-supers": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.9",
"@babel/helper-split-export-declaration": "^7.18.6"
}
},
@@ -359,14 +263,12 @@
}
},
"@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.3.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz",
+ "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==",
"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.17.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
"debug": "^4.1.1",
"lodash.debounce": "^4.0.8",
"resolve": "^1.14.2",
@@ -381,9 +283,9 @@
}
},
"@babel/helper-environment-visitor": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz",
- "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q=="
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg=="
},
"@babel/helper-explode-assignable-expression": {
"version": "7.18.6",
@@ -394,12 +296,29 @@
}
},
"@babel/helper-function-name": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz",
- "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
+ "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
"requires": {
"@babel/template": "^7.18.6",
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.18.9"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-hoist-variables": {
@@ -411,11 +330,28 @@
}
},
"@babel/helper-member-expression-to-functions": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz",
- "integrity": "sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz",
+ "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==",
"requires": {
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.18.9"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-module-imports": {
@@ -427,24 +363,34 @@
}
},
"@babel/helper-module-transforms": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz",
- "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
+ "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
"requires": {
- "@babel/helper-environment-visitor": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-module-imports": "^7.18.6",
"@babel/helper-simple-access": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/helper-validator-identifier": "^7.18.6",
"@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.6",
- "@babel/types": "^7.18.6"
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
},
"dependencies": {
"@babel/helper-validator-identifier": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
}
}
},
@@ -457,31 +403,65 @@
}
},
"@babel/helper-plugin-utils": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz",
- "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg=="
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
+ "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w=="
},
"@babel/helper-remap-async-to-generator": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz",
- "integrity": "sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz",
+ "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==",
"requires": {
"@babel/helper-annotate-as-pure": "^7.18.6",
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-wrap-function": "^7.18.6",
- "@babel/types": "^7.18.6"
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-wrap-function": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-replace-supers": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz",
- "integrity": "sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz",
+ "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==",
"requires": {
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-member-expression-to-functions": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
"@babel/helper-optimise-call-expression": "^7.18.6",
- "@babel/traverse": "^7.18.6",
- "@babel/types": "^7.18.6"
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-simple-access": {
@@ -493,11 +473,28 @@
}
},
"@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz",
- "integrity": "sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz",
+ "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==",
"requires": {
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.18.9"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-split-export-declaration": {
@@ -508,6 +505,11 @@
"@babel/types": "^7.18.6"
}
},
+ "@babel/helper-string-parser": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
+ "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw=="
+ },
"@babel/helper-validator-identifier": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
@@ -519,24 +521,14 @@
"integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw=="
},
"@babel/helper-wrap-function": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz",
- "integrity": "sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw==",
+ "version": "7.18.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz",
+ "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==",
"requires": {
- "@babel/helper-function-name": "^7.18.6",
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.6",
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helpers": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz",
- "integrity": "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==",
- "requires": {
- "@babel/template": "^7.18.6",
- "@babel/traverse": "^7.18.6",
- "@babel/types": "^7.18.6"
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.18.11",
+ "@babel/types": "^7.18.10"
},
"dependencies": {
"@babel/code-frame": {
@@ -547,46 +539,6 @@
"@babel/highlight": "^7.18.6"
}
},
- "@babel/generator": {
- "version": "7.18.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz",
- "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==",
- "requires": {
- "@babel/types": "^7.18.7",
- "@jridgewell/gen-mapping": "^0.3.2",
- "jsesc": "^2.5.1"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz",
- "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q=="
- },
- "@babel/helper-function-name": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz",
- "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==",
- "requires": {
- "@babel/template": "^7.18.6",
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-hoist-variables": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
- "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
- "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
"@babel/helper-validator-identifier": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
@@ -603,56 +555,30 @@
}
},
"@babel/parser": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz",
- "integrity": "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw=="
+ "version": "7.18.11",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
+ "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ=="
},
"@babel/template": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
- "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"requires": {
"@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.18.6",
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/traverse": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz",
- "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==",
- "requires": {
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.6",
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-function-name": "^7.18.6",
- "@babel/helper-hoist-variables": "^7.18.6",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.18.6",
- "@babel/types": "^7.18.6",
- "debug": "^4.1.0",
- "globals": "^11.1.0"
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
}
},
"@babel/types": {
- "version": "7.18.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz",
- "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
"requires": {
+ "@babel/helper-string-parser": "^7.18.10",
"@babel/helper-validator-identifier": "^7.18.6",
"to-fast-properties": "^2.0.0"
}
},
- "@jridgewell/gen-mapping": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
- "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
- "requires": {
- "@jridgewell/set-array": "^1.0.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
- }
- },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -665,6 +591,33 @@
}
}
},
+ "@babel/helpers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
+ "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
+ "requires": {
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
+ "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
"@babel/highlight": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
@@ -701,23 +654,23 @@
}
},
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz",
- "integrity": "sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6",
- "@babel/plugin-proposal-optional-chaining": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9"
}
},
"@babel/plugin-proposal-async-generator-functions": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz",
- "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz",
+ "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==",
"requires": {
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6",
- "@babel/helper-remap-async-to-generator": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-remap-async-to-generator": "^7.18.9",
"@babel/plugin-syntax-async-generators": "^7.8.4"
}
},
@@ -750,11 +703,11 @@
}
},
"@babel/plugin-proposal-export-namespace-from": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz",
- "integrity": "sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz",
+ "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3"
}
},
@@ -768,11 +721,11 @@
}
},
"@babel/plugin-proposal-logical-assignment-operators": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz",
- "integrity": "sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz",
+ "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
}
},
@@ -795,15 +748,15 @@
}
},
"@babel/plugin-proposal-object-rest-spread": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz",
- "integrity": "sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz",
+ "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==",
"requires": {
- "@babel/compat-data": "^7.18.6",
- "@babel/helper-compilation-targets": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.18.6"
+ "@babel/plugin-transform-parameters": "^7.18.8"
}
},
"@babel/plugin-proposal-optional-catch-binding": {
@@ -816,12 +769,12 @@
}
},
"@babel/plugin-proposal-optional-chaining": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz",
- "integrity": "sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
"@babel/plugin-syntax-optional-chaining": "^7.8.3"
}
},
@@ -1001,42 +954,42 @@
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz",
- "integrity": "sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz",
+ "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-classes": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.6.tgz",
- "integrity": "sha512-XTg8XW/mKpzAF3actL554Jl/dOYoJtv3l8fxaEczpgz84IeeVf+T1u2CSvPHuZbt0w3JkIx4rdn/MRQI7mo0HQ==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz",
+ "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==",
"requires": {
"@babel/helper-annotate-as-pure": "^7.18.6",
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-function-name": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
"@babel/helper-optimise-call-expression": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6",
- "@babel/helper-replace-supers": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-replace-supers": "^7.18.9",
"@babel/helper-split-export-declaration": "^7.18.6",
"globals": "^11.1.0"
}
},
"@babel/plugin-transform-computed-properties": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz",
- "integrity": "sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz",
+ "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz",
- "integrity": "sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz",
+ "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-dotall-regex": {
@@ -1049,11 +1002,11 @@
}
},
"@babel/plugin-transform-duplicate-keys": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz",
- "integrity": "sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz",
+ "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-exponentiation-operator": {
@@ -1066,29 +1019,29 @@
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.6.tgz",
- "integrity": "sha512-WAjoMf4wIiSsy88KmG7tgj2nFdEK7E46tArVtcgED7Bkj6Fg/tG5SbvNIOKxbFS2VFgNh6+iaPswBeQZm4ox8w==",
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz",
+ "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.18.6"
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz",
- "integrity": "sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz",
+ "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==",
"requires": {
- "@babel/helper-compilation-targets": "^7.18.6",
- "@babel/helper-function-name": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-literals": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz",
- "integrity": "sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz",
+ "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-member-expression-literals": {
@@ -1121,13 +1074,13 @@
}
},
"@babel/plugin-transform-modules-systemjs": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz",
- "integrity": "sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz",
+ "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==",
"requires": {
"@babel/helper-hoist-variables": "^7.18.6",
- "@babel/helper-module-transforms": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
"@babel/helper-validator-identifier": "^7.18.6",
"babel-plugin-dynamic-import-node": "^2.3.3"
},
@@ -1175,9 +1128,9 @@
}
},
"@babel/plugin-transform-parameters": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.6.tgz",
- "integrity": "sha512-FjdqgMv37yVl/gwvzkcB+wfjRI8HQmc5EgOG9iGNvUY1ok+TjsoaMP7IqCDZBhkFcM5f3OPVMs6Dmp03C5k4/A==",
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz",
+ "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==",
"requires": {
"@babel/helper-plugin-utils": "^7.18.6"
}
@@ -1216,12 +1169,12 @@
}
},
"@babel/plugin-transform-spread": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz",
- "integrity": "sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz",
+ "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9"
}
},
"@babel/plugin-transform-sticky-regex": {
@@ -1233,27 +1186,27 @@
}
},
"@babel/plugin-transform-template-literals": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz",
- "integrity": "sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz",
+ "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-typeof-symbol": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz",
- "integrity": "sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz",
+ "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-unicode-escapes": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz",
- "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz",
+ "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
+ "@babel/helper-plugin-utils": "^7.18.9"
}
},
"@babel/plugin-transform-unicode-regex": {
@@ -1266,28 +1219,28 @@
}
},
"@babel/preset-env": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.6.tgz",
- "integrity": "sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz",
+ "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==",
"requires": {
- "@babel/compat-data": "^7.18.6",
- "@babel/helper-compilation-targets": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
"@babel/helper-validator-option": "^7.18.6",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.6",
- "@babel/plugin-proposal-async-generator-functions": "^7.18.6",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-async-generator-functions": "^7.18.10",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-class-static-block": "^7.18.6",
"@babel/plugin-proposal-dynamic-import": "^7.18.6",
- "@babel/plugin-proposal-export-namespace-from": "^7.18.6",
+ "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
"@babel/plugin-proposal-json-strings": "^7.18.6",
- "@babel/plugin-proposal-logical-assignment-operators": "^7.18.6",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-numeric-separator": "^7.18.6",
- "@babel/plugin-proposal-object-rest-spread": "^7.18.6",
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
"@babel/plugin-proposal-optional-catch-binding": "^7.18.6",
- "@babel/plugin-proposal-optional-chaining": "^7.18.6",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-proposal-private-property-in-object": "^7.18.6",
"@babel/plugin-proposal-unicode-property-regex": "^7.18.6",
@@ -1309,44 +1262,59 @@
"@babel/plugin-transform-arrow-functions": "^7.18.6",
"@babel/plugin-transform-async-to-generator": "^7.18.6",
"@babel/plugin-transform-block-scoped-functions": "^7.18.6",
- "@babel/plugin-transform-block-scoping": "^7.18.6",
- "@babel/plugin-transform-classes": "^7.18.6",
- "@babel/plugin-transform-computed-properties": "^7.18.6",
- "@babel/plugin-transform-destructuring": "^7.18.6",
+ "@babel/plugin-transform-block-scoping": "^7.18.9",
+ "@babel/plugin-transform-classes": "^7.18.9",
+ "@babel/plugin-transform-computed-properties": "^7.18.9",
+ "@babel/plugin-transform-destructuring": "^7.18.9",
"@babel/plugin-transform-dotall-regex": "^7.18.6",
- "@babel/plugin-transform-duplicate-keys": "^7.18.6",
+ "@babel/plugin-transform-duplicate-keys": "^7.18.9",
"@babel/plugin-transform-exponentiation-operator": "^7.18.6",
- "@babel/plugin-transform-for-of": "^7.18.6",
- "@babel/plugin-transform-function-name": "^7.18.6",
- "@babel/plugin-transform-literals": "^7.18.6",
+ "@babel/plugin-transform-for-of": "^7.18.8",
+ "@babel/plugin-transform-function-name": "^7.18.9",
+ "@babel/plugin-transform-literals": "^7.18.9",
"@babel/plugin-transform-member-expression-literals": "^7.18.6",
"@babel/plugin-transform-modules-amd": "^7.18.6",
"@babel/plugin-transform-modules-commonjs": "^7.18.6",
- "@babel/plugin-transform-modules-systemjs": "^7.18.6",
+ "@babel/plugin-transform-modules-systemjs": "^7.18.9",
"@babel/plugin-transform-modules-umd": "^7.18.6",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6",
"@babel/plugin-transform-new-target": "^7.18.6",
"@babel/plugin-transform-object-super": "^7.18.6",
- "@babel/plugin-transform-parameters": "^7.18.6",
+ "@babel/plugin-transform-parameters": "^7.18.8",
"@babel/plugin-transform-property-literals": "^7.18.6",
"@babel/plugin-transform-regenerator": "^7.18.6",
"@babel/plugin-transform-reserved-words": "^7.18.6",
"@babel/plugin-transform-shorthand-properties": "^7.18.6",
- "@babel/plugin-transform-spread": "^7.18.6",
+ "@babel/plugin-transform-spread": "^7.18.9",
"@babel/plugin-transform-sticky-regex": "^7.18.6",
- "@babel/plugin-transform-template-literals": "^7.18.6",
- "@babel/plugin-transform-typeof-symbol": "^7.18.6",
- "@babel/plugin-transform-unicode-escapes": "^7.18.6",
+ "@babel/plugin-transform-template-literals": "^7.18.9",
+ "@babel/plugin-transform-typeof-symbol": "^7.18.9",
+ "@babel/plugin-transform-unicode-escapes": "^7.18.10",
"@babel/plugin-transform-unicode-regex": "^7.18.6",
"@babel/preset-modules": "^0.1.5",
- "@babel/types": "^7.18.6",
- "babel-plugin-polyfill-corejs2": "^0.3.1",
- "babel-plugin-polyfill-corejs3": "^0.5.2",
- "babel-plugin-polyfill-regenerator": "^0.3.1",
+ "@babel/types": "^7.18.10",
+ "babel-plugin-polyfill-corejs2": "^0.3.2",
+ "babel-plugin-polyfill-corejs3": "^0.5.3",
+ "babel-plugin-polyfill-regenerator": "^0.4.0",
"core-js-compat": "^3.22.1",
"semver": "^6.3.0"
},
"dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -1379,9 +1347,9 @@
}
},
"@babel/runtime": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz",
- "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==",
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
+ "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
@@ -1432,18 +1400,18 @@
}
},
"@babel/traverse": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz",
- "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==",
+ "version": "7.18.11",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz",
+ "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==",
"requires": {
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.18.6",
- "@babel/helper-environment-visitor": "^7.18.6",
- "@babel/helper-function-name": "^7.18.6",
+ "@babel/generator": "^7.18.10",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.18.6",
- "@babel/types": "^7.18.6",
+ "@babel/parser": "^7.18.11",
+ "@babel/types": "^7.18.10",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -1471,6 +1439,21 @@
"js-tokens": "^4.0.0"
}
},
+ "@babel/parser": {
+ "version": "7.18.11",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
+ "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ=="
+ },
+ "@babel/types": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+ "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -3025,12 +3008,12 @@
}
},
"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.3.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz",
+ "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==",
"requires": {
- "@babel/compat-data": "^7.13.11",
- "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "@babel/compat-data": "^7.17.7",
+ "@babel/helper-define-polyfill-provider": "^0.3.2",
"semver": "^6.1.1"
},
"dependencies": {
@@ -3042,20 +3025,20 @@
}
},
"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.5.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz",
+ "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==",
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "@babel/helper-define-polyfill-provider": "^0.3.2",
"core-js-compat": "^3.21.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.4.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz",
+ "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==",
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.3.1"
+ "@babel/helper-define-polyfill-provider": "^0.3.2"
}
},
"babel-runtime": {
@@ -4755,39 +4738,43 @@
"dev": true
},
"core-js-compat": {
- "version": "3.23.3",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz",
- "integrity": "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==",
+ "version": "3.24.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz",
+ "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==",
"requires": {
- "browserslist": "^4.21.0",
+ "browserslist": "^4.21.3",
"semver": "7.0.0"
},
"dependencies": {
"browserslist": {
- "version": "4.21.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz",
- "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==",
+ "version": "4.21.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
+ "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
"requires": {
- "caniuse-lite": "^1.0.30001359",
- "electron-to-chromium": "^1.4.172",
- "node-releases": "^2.0.5",
- "update-browserslist-db": "^1.0.4"
+ "caniuse-lite": "^1.0.30001370",
+ "electron-to-chromium": "^1.4.202",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.5"
}
},
"caniuse-lite": {
- "version": "1.0.30001361",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz",
- "integrity": "sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ=="
- },
- "node-releases": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
- "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q=="
+ "version": "1.0.30001376",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001376.tgz",
+ "integrity": "sha512-I27WhtOQ3X3v3it9gNs/oTpoE5KpwmqKR5oKPA8M0G7uMXh9Ty81Q904HpKUrM30ei7zfcL5jE7AXefgbOfMig=="
},
"semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="
+ },
+ "update-browserslist-db": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
+ "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
}
}
},
@@ -5547,9 +5534,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
- "version": "1.4.174",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.174.tgz",
- "integrity": "sha512-JER+w+9MV2MBVFOXxP036bLlNOnzbYAWrWU8sNUwoOO69T3w4564WhM5H5atd8VVS8U4vpi0i0kdoYzm1NPQgQ=="
+ "version": "1.4.219",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.219.tgz",
+ "integrity": "sha512-zoQJsXOUw0ZA0YxbjkmzBumAJRtr6je5JySuL/bAoFs0DuLiLJ+5FzRF7/ZayihxR2QcewlRZVm5QZdUhwjOgA=="
},
"emitter-listener": {
"version": "1.1.2",
diff --git a/package.json b/package.json
index 9025860b28..f179eeb8ee 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,11 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
- "version": "4.239.0",
+ "version": "4.242.0",
"main": "./website/server/index.js",
"dependencies": {
- "@babel/core": "^7.18.6",
- "@babel/preset-env": "^7.18.6",
+ "@babel/core": "^7.18.13",
+ "@babel/preset-env": "^7.18.10",
"@babel/register": "^7.18.9",
"@google-cloud/trace-agent": "^5.1.6",
"@parse/node-apn": "^5.1.3",
diff --git a/scripts/team-cron.js b/scripts/team-cron.js
new file mode 100644
index 0000000000..11f67fbf4f
--- /dev/null
+++ b/scripts/team-cron.js
@@ -0,0 +1,105 @@
+import forEach from 'lodash/forEach';
+import { model as Group } from '../website/server/models/group';
+import { model as User } from '../website/server/models/user';
+import * as Tasks from '../website/server/models/task';
+import { daysSince, shouldDo } from '../website/common/script/cron';
+
+const TASK_VALUE_CHANGE_FACTOR = 0.9747;
+const MIN_TASK_VALUE = -47.27;
+
+async function updateTeamTasks (team) {
+ const toSave = [];
+ let teamLeader = await User.findOne({ _id: team.leader }, 'preferences').exec();
+
+ if (!teamLeader) { // why would this happen?
+ teamLeader = {
+ preferences: { }, // when options are sanitized this becomes CDS 0 at UTC
+ };
+ }
+
+ if (
+ !team.cron || !team.cron.lastProcessed
+ || daysSince(team.cron.lastProcessed, teamLeader.preferences) > 0
+ ) {
+ const tasks = await Tasks.Task.find({
+ 'group.id': team._id,
+ userId: { $exists: false },
+ $or: [
+ { type: 'todo', completed: false },
+ { type: { $in: ['habit', 'daily'] } },
+ ],
+ }).exec();
+
+ const tasksByType = {
+ habits: [], dailys: [], todos: [], rewards: [],
+ };
+ forEach(tasks, task => tasksByType[`${task.type}s`].push(task));
+
+ forEach(tasksByType.habits, habit => {
+ if (!(habit.up && habit.down) && habit.value !== 0) {
+ habit.value *= 0.5;
+ if (Math.abs(habit.value) < 0.1) habit.value = 0;
+ toSave.push(habit.save());
+ }
+ });
+ forEach(tasksByType.todos, todo => {
+ if (!todo.completed) {
+ const delta = TASK_VALUE_CHANGE_FACTOR ** todo.value;
+ todo.value -= delta;
+ if (todo.value < MIN_TASK_VALUE) todo.value = MIN_TASK_VALUE;
+ toSave.push(todo.save());
+ }
+ });
+ forEach(tasksByType.dailys, daily => {
+ let processChecklist = false;
+ let assignments = 0;
+ let completions = 0;
+ for (const assignedUser in daily.group.assignedUsersDetail) {
+ if (Object.prototype.hasOwnProperty.call(daily.group.assignedUsersDetail, assignedUser)) {
+ assignments += 1;
+ if (daily.group.assignedUsersDetail[assignedUser].completed) {
+ completions += 1;
+ daily.group.assignedUsersDetail[assignedUser].completed = false;
+ }
+ }
+ }
+ if (completions > 0) daily.markModified('group.assignedUsersDetail');
+ if (daily.completed) {
+ processChecklist = true;
+ daily.completed = false;
+ } else if (shouldDo(team.cron.lastProcessed, daily, teamLeader.preferences)) {
+ processChecklist = true;
+ const delta = TASK_VALUE_CHANGE_FACTOR ** daily.value;
+ if (assignments > 0) {
+ daily.value -= ((completions / assignments) * delta);
+ }
+ if (daily.value < MIN_TASK_VALUE) daily.value = MIN_TASK_VALUE;
+ }
+ daily.isDue = shouldDo(new Date(), daily, teamLeader.preferences);
+ if (processChecklist && daily.checklist.length > 0) {
+ daily.checklist.forEach(i => { i.completed = false; });
+ }
+ toSave.push(daily.save());
+ });
+
+ if (!team.cron) team.cron = {};
+ team.cron.lastProcessed = new Date();
+ toSave.push(team.save());
+ }
+
+ return Promise.all(toSave);
+}
+
+export default async function processTeamsCron () {
+ const activeTeams = await Group.find({
+ 'purchased.plan.customerId': { $exists: true },
+ $or: [
+ { 'purchased.plan.dateTerminated': { $exists: false } },
+ { 'purchased.plan.dateTerminated': null },
+ { 'purchased.plan.dateTerminated': { $gt: new Date() } },
+ ],
+ }).exec();
+
+ const cronPromises = activeTeams.map(updateTeamTasks);
+ return Promise.all(cronPromises);
+}
diff --git a/test/api/unit/models/group_tasks.test.js b/test/api/unit/models/group_tasks.test.js
index 1c60fa947b..f4a37e194c 100644
--- a/test/api/unit/models/group_tasks.test.js
+++ b/test/api/unit/models/group_tasks.test.js
@@ -1,12 +1,10 @@
-import { each, find, findIndex } from 'lodash';
-import { model as Challenge } from '../../../../website/server/models/challenge';
+import { each, findIndex } from 'lodash';
import { model as Group } from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
describe('Group Task Methods', () => {
- let guild; let leader; let challenge; let
- task;
+ let guild; let leader; let task;
const tasksToTest = {
habit: {
text: 'test habit',
@@ -31,10 +29,6 @@ describe('Group Task Methods', () => {
},
};
- function findLinkedTask (updatedLeadersTask) {
- return updatedLeadersTask.group.taskId === task._id;
- }
-
beforeEach(async () => {
guild = new Group({
name: 'test party',
@@ -47,19 +41,9 @@ describe('Group Task Methods', () => {
guild.leader = leader._id;
- challenge = new Challenge({
- name: 'Test Challenge',
- shortName: 'Test',
- leader: leader._id,
- group: guild._id,
- });
-
- leader.challenges = [challenge._id];
-
await Promise.all([
guild.save(),
leader.save(),
- challenge.save(),
]);
});
@@ -78,7 +62,15 @@ describe('Group Task Methods', () => {
});
it('syncs an assigned task to a user', async () => {
- await guild.syncTask(task, leader);
+ await guild.syncTask(task, [leader], leader);
+
+ const updatedTask = await Tasks.Task.findOne({ _id: task._id });
+ expect(updatedTask.group.assignedUsers).to.contain(leader._id);
+ expect(updatedTask.group.assignedUsersDetail[leader._id]).to.exist;
+ });
+
+ it('creates tags for a user when task is synced', async () => {
+ await guild.syncTask(task, [leader], leader);
const updatedLeader = await User.findOne({ _id: leader._id });
const tagIndex = findIndex(updatedLeader.tags, { id: guild._id });
@@ -88,197 +80,6 @@ describe('Group Task Methods', () => {
expect(newTag.name).to.equal(guild.name);
expect(newTag.group).to.equal(guild._id);
});
-
- it('create tags for a user when task is synced', async () => {
- await guild.syncTask(task, leader);
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- expect(task.group.assignedUsers).to.contain(leader._id);
- expect(syncedTask).to.exist;
- });
-
- it('syncs updated info for assigned task to a user', async () => {
- await guild.syncTask(task, leader);
- const updatedTaskName = 'Update Task name';
- task.text = updatedTaskName;
- await guild.syncTask(task, leader);
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- expect(task.group.assignedUsers).to.contain(leader._id);
- expect(syncedTask).to.exist;
- expect(syncedTask.text).to.equal(task.text);
- });
-
- it('syncs checklist items to an assigned user', async () => {
- await guild.syncTask(task, leader);
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- if (task.type !== 'daily' && task.type !== 'todo') return;
-
- expect(syncedTask.checklist.length).to.equal(task.checklist.length);
- expect(syncedTask.checklist[0].text).to.equal(task.checklist[0].text);
- });
-
- describe('syncs updated info', async () => {
- let newMember;
-
- beforeEach(async () => {
- newMember = new User({
- guilds: [guild._id],
- });
- await newMember.save();
-
- await guild.syncTask(task, leader);
- await guild.syncTask(task, newMember);
- });
-
- it('syncs updated info for assigned task to all users', async () => {
- const updatedTaskName = 'Update Task name';
- task.text = updatedTaskName;
- task.group.approval.required = true;
-
- await guild.updateTask(task);
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- const updatedMember = await User.findOne({ _id: newMember._id });
- const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
- const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
-
- expect(task.group.assignedUsers).to.contain(leader._id);
- expect(syncedTask).to.exist;
- expect(syncedTask.text).to.equal(task.text);
- expect(syncedTask.group.approval.required).to.equal(true);
-
- expect(task.group.assignedUsers).to.contain(newMember._id);
- expect(syncedMemberTask).to.exist;
- expect(syncedMemberTask.text).to.equal(task.text);
- expect(syncedMemberTask.group.approval.required).to.equal(true);
- });
-
- it('syncs a new checklist item to all assigned users', async () => {
- if (task.type !== 'daily' && task.type !== 'todo') return;
-
- const newCheckListItem = {
- text: 'Checklist Item 1',
- completed: false,
- };
-
- task.checklist.push(newCheckListItem);
-
- await guild.updateTask(task, { newCheckListItem });
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- const updatedMember = await User.findOne({ _id: newMember._id });
- const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
- const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
-
- expect(syncedTask.checklist.length).to.equal(task.checklist.length);
- expect(syncedTask.checklist[1].text).to.equal(task.checklist[1].text);
- expect(syncedMemberTask.checklist.length).to.equal(task.checklist.length);
- expect(syncedMemberTask.checklist[1].text).to.equal(task.checklist[1].text);
- });
-
- it('syncs updated info for checklist in assigned task to all users when flag is passed', async () => {
- if (task.type !== 'daily' && task.type !== 'todo') return;
-
- const updateCheckListText = 'Updated checklist item';
- if (task.checklist) {
- task.checklist[0].text = updateCheckListText;
- }
-
- await guild.updateTask(task, { updateCheckListItems: [task.checklist[0]] });
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- const updatedMember = await User.findOne({ _id: newMember._id });
- const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
- const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
-
- expect(syncedTask.checklist.length).to.equal(task.checklist.length);
- expect(syncedTask.checklist[0].text).to.equal(updateCheckListText);
- expect(syncedMemberTask.checklist.length).to.equal(task.checklist.length);
- expect(syncedMemberTask.checklist[0].text).to.equal(updateCheckListText);
- });
-
- it('removes a checklist item in assigned task to all users when flag is passed with checklist id', async () => {
- if (task.type !== 'daily' && task.type !== 'todo') return;
-
- await guild.updateTask(task, { removedCheckListItemId: task.checklist[0].id });
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- const updatedMember = await User.findOne({ _id: newMember._id });
- const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
- const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
-
- expect(syncedTask.checklist.length).to.equal(0);
- expect(syncedMemberTask.checklist.length).to.equal(0);
- });
- });
-
- it('removes assigned tasks when master task is deleted', async () => {
- await guild.syncTask(task, leader);
- await guild.removeTask(task);
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ userId: leader._id, type: taskType });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- expect(updatedLeader.tasksOrder[`${taskType}s`]).to.not.include(task._id);
- expect(syncedTask).to.not.exist;
- });
-
- it('unlinks and deletes group tasks for a user when remove-all is specified', async () => {
- await guild.syncTask(task, leader);
- await guild.unlinkTask(task, leader, 'remove-all');
-
- const updatedLeader = await User.findOne({ _id: leader._id });
- const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- expect(task.group.assignedUsers).to.not.contain(leader._id);
- expect(syncedTask).to.not.exist;
- });
-
- it('unlinks and keeps group tasks for a user when keep-all is specified', async () => {
- await guild.syncTask(task, leader);
-
- let updatedLeader = await User.findOne({ _id: leader._id });
- let updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const syncedTask = find(updatedLeadersTasks, findLinkedTask);
-
- await guild.unlinkTask(task, leader, 'keep-all');
-
- updatedLeader = await User.findOne({ _id: leader._id });
- updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
- const updatedSyncedTask = find(
- updatedLeadersTasks,
- updatedLeadersTask => updatedLeadersTask._id === syncedTask._id,
- );
-
- expect(task.group.assignedUsers).to.not.contain(leader._id);
- expect(updatedSyncedTask).to.exist;
- expect(updatedSyncedTask.group._id).to.be.undefined;
- });
});
});
});
diff --git a/test/api/unit/models/task.test.js b/test/api/unit/models/task.test.js
index 5921a4e2c2..5da3341cbe 100644
--- a/test/api/unit/models/task.test.js
+++ b/test/api/unit/models/task.test.js
@@ -246,13 +246,23 @@ describe('Task Model', () => {
expect(foundTasks[0].text).to.eql(taskWithAlias.text);
});
- it('scopes alias lookup to user', async () => {
+ it('scopes alias lookup to user when querying aliases only', async () => {
await Tasks.Task.findMultipleByIdOrAlias([taskWithAlias.alias], user._id);
+ expect(Tasks.Task.find).to.be.calledOnce;
+ expect(Tasks.Task.find).to.be.calledWithMatch({
+ alias: { $in: [taskWithAlias.alias] },
+ userId: user._id,
+ });
+ });
+
+ it('scopes alias lookup to user when querying aliases and IDs', async () => {
+ await Tasks.Task.findMultipleByIdOrAlias([taskWithAlias.alias, secondTask._id], user._id);
+
expect(Tasks.Task.find).to.be.calledOnce;
expect(Tasks.Task.find).to.be.calledWithMatch({
$or: [
- { _id: { $in: [] } },
+ { _id: { $in: [secondTask._id] } },
{ alias: { $in: [taskWithAlias.alias] } },
],
userId: user._id,
@@ -270,10 +280,7 @@ describe('Task Model', () => {
expect(Tasks.Task.find).to.be.calledOnce;
expect(Tasks.Task.find).to.be.calledWithMatch({
- $or: [
- { _id: { $in: [] } },
- { alias: { $in: [taskWithAlias.alias] } },
- ],
+ alias: { $in: [taskWithAlias.alias] },
userId: user._id,
foo: 'bar',
});
diff --git a/test/api/v3/integration/groups/POST-group_remove_manager.test.js b/test/api/v3/integration/groups/POST-group_remove_manager.test.js
index 894a225d26..cdc37ca79f 100644
--- a/test/api/v3/integration/groups/POST-group_remove_manager.test.js
+++ b/test/api/v3/integration/groups/POST-group_remove_manager.test.js
@@ -1,4 +1,3 @@
-import { find } from 'lodash';
import {
createAndPopulateGroup,
translate as t,
@@ -11,10 +10,6 @@ describe('POST /group/:groupId/remove-manager', () => {
const groupType = 'guild';
let nonManager;
- function findAssignedTask (memberTask) {
- return memberTask.group.id === groupToUpdate._id;
- }
-
beforeEach(async () => {
const { group, groupLeader, members } = await createAndPopulateGroup({
groupDetails: {
@@ -63,28 +58,4 @@ describe('POST /group/:groupId/remove-manager', () => {
expect(updatedGroup.managers[nonLeader._id]).to.not.exist;
});
-
- it('removes group approval notifications from a manager that is removed', async () => {
- await leader.post(`/groups/${groupToUpdate._id}/add-manager`, {
- managerId: nonLeader._id,
- });
- const task = await leader.post(`/tasks/group/${groupToUpdate._id}`, {
- text: 'test todo',
- type: 'todo',
- requiresApproval: true,
- });
- await nonLeader.post(`/tasks/${task._id}/assign/${nonManager._id}`);
- const memberTasks = await nonManager.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await nonManager.post(`/tasks/${syncedTask._id}/score/up`);
-
- const updatedGroup = await leader.post(`/groups/${groupToUpdate._id}/remove-manager`, {
- managerId: nonLeader._id,
- });
-
- await nonLeader.sync();
-
- expect(nonLeader.notifications.length).to.equal(1); // user gets mystery items
- expect(updatedGroup.managers[nonLeader._id]).to.not.exist;
- });
});
diff --git a/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js b/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js
index 92fcb6a13c..ecda9500d5 100644
--- a/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js
+++ b/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js
@@ -13,6 +13,9 @@ describe('POST /tasks/clearCompletedTodos', () => {
{ 'purchased.plan.customerId': 'group-unlimited' },
);
const challenge = await generateChallenge(user, guild);
+ await user.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
await user.post(`/challenges/${challenge._id}/join`);
const initialTodoCount = user.tasksOrder.todos.length;
@@ -33,7 +36,7 @@ describe('POST /tasks/clearCompletedTodos', () => {
text: 'todo 7',
type: 'todo',
});
- await user.post(`/tasks/${groupTask._id}/assign/${user._id}`);
+ await user.post(`/tasks/${groupTask._id}/assign`, [user._id]);
const tasks = await user.get('/tasks/user?type=todos');
expect(tasks.length).to.equal(initialTodoCount + 7);
diff --git a/test/api/v3/integration/tasks/checklists/POST-tasks_taskId_checklist_itemId_score.test.js b/test/api/v3/integration/tasks/checklists/POST-tasks_taskId_checklist_itemId_score.test.js
index 4f772ebaf7..a9aae0685c 100644
--- a/test/api/v3/integration/tasks/checklists/POST-tasks_taskId_checklist_itemId_score.test.js
+++ b/test/api/v3/integration/tasks/checklists/POST-tasks_taskId_checklist_itemId_score.test.js
@@ -30,7 +30,7 @@ describe('POST /tasks/:taskId/checklist/:itemId/score', () => {
expect(savedTask.checklist[0].completed).to.equal(true);
});
- it('can use a alias to score a checklist item', async () => {
+ it('can use an alias to score a checklist item', async () => {
const task = await user.post('/tasks/user', {
type: 'daily',
text: 'Daily with checklist',
diff --git a/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js b/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js
index b6eb29db11..dda6037419 100644
--- a/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js
+++ b/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js
@@ -1,4 +1,3 @@
-import { find } from 'lodash';
import {
translate as t,
createAndPopulateGroup,
@@ -8,10 +7,6 @@ describe('Groups DELETE /tasks/:id', () => {
let user; let guild; let member; let member2; let
task;
- function findAssignedTask (memberTask) {
- return memberTask.group.id === guild._id;
- }
-
beforeEach(async () => {
const { group, members, groupLeader } = await createAndPopulateGroup({
groupDetails: {
@@ -35,8 +30,7 @@ describe('Groups DELETE /tasks/:id', () => {
notes: 1976,
});
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
- await user.post(`/tasks/${task._id}/assign/${member2._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member._id, member2._id]);
});
it('deletes a group task', async () => {
@@ -64,81 +58,4 @@ describe('Groups DELETE /tasks/:id', () => {
message: t('messageTaskNotFound'),
});
});
-
- it('removes deleted taskʾs approval pending notifications from managers', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
- await user.put(`/tasks/${task._id}/`, {
- requiresApproval: true,
- });
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await member.post(`/tasks/${syncedTask._id}/score/up`);
-
- await user.sync();
- await member2.sync();
- expect(user.notifications.length).to.equal(3); // mystery items
- expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
- expect(member2.notifications.length).to.equal(3);
- expect(member2.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
-
- await member2.del(`/tasks/${task._id}`);
-
- await user.sync();
- await member2.sync();
-
- expect(user.notifications.length).to.equal(2);
- expect(member2.notifications.length).to.equal(2);
- });
-
- it('deletes task from assigned user', async () => {
- await user.del(`/tasks/${task._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- expect(syncedTask).to.not.exist;
- });
-
- it('deletes task from all assigned users', async () => {
- await user.del(`/tasks/${task._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- const member2Tasks = await member2.get('/tasks/user');
- const member2SyncedTask = find(member2Tasks, findAssignedTask);
-
- expect(syncedTask).to.not.exist;
- expect(member2SyncedTask).to.not.exist;
- });
-
- it('prevents a user from deleting a task they are assigned to', async () => {
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- await expect(member.del(`/tasks/${syncedTask._id}`))
- .to.eventually.be.rejected.and.eql({
- code: 401,
- error: 'NotAuthorized',
- message: t('cantDeleteAssignedGroupTasks'),
- });
- });
-
- it('allows a user to delete a task after leaving a group', async () => {
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- await member.post(`/groups/${guild._id}/leave`);
-
- await member.del(`/tasks/${syncedTask._id}`);
-
- await expect(member.get(`/tasks/${syncedTask._id}`))
- .to.eventually.be.rejected.and.eql({
- code: 404,
- error: 'NotFound',
- message: 'Task not found.',
- });
- });
});
diff --git a/test/api/v3/integration/tasks/groups/GET-approvals_group_id.test.js b/test/api/v3/integration/tasks/groups/GET-approvals_group_id.test.js
deleted file mode 100644
index 520a322399..0000000000
--- a/test/api/v3/integration/tasks/groups/GET-approvals_group_id.test.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import { find } from 'lodash';
-import {
- createAndPopulateGroup,
-} from '../../../../../helpers/api-integration/v3';
-
-describe('GET /approvals/group/:groupId', () => {
- let user; let guild; let member; let addlMember; let task; let syncedTask; let
- addlSyncedTask;
-
- function findAssignedTask (memberTask) {
- return memberTask.group.id === guild._id;
- }
-
- beforeEach(async () => {
- const { group, members, groupLeader } = await createAndPopulateGroup({
- groupDetails: {
- name: 'Test Guild',
- type: 'guild',
- },
- members: 2,
- upgradeToGroupPlan: true,
- });
-
- guild = group;
- user = groupLeader;
- member = members[0]; // eslint-disable-line prefer-destructuring
- addlMember = members[1]; // eslint-disable-line prefer-destructuring
-
- task = await user.post(`/tasks/group/${guild._id}`, {
- text: 'test todo',
- type: 'todo',
- requiresApproval: true,
- });
-
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
- await user.post(`/tasks/${task._id}/assign/${addlMember._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- syncedTask = find(memberTasks, findAssignedTask);
-
- const addlMemberTasks = await addlMember.get('/tasks/user');
- addlSyncedTask = find(addlMemberTasks, findAssignedTask);
-
- try {
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- } catch (e) {
- // eslint-disable-next-line no-empty
- }
-
- try {
- await addlMember.post(`/tasks/${addlSyncedTask._id}/score/up`);
- } catch (e) {
- // eslint-disable-next-line no-empty
- }
- });
-
- it('provides only user\'s own tasks when user is not the group leader', async () => {
- const approvals = await member.get(`/approvals/group/${guild._id}`);
- expect(approvals[0]._id).to.equal(syncedTask._id);
- expect(approvals[1]).to.not.exist;
- });
-
- it('allows group leaders to get a list of tasks that need approval', async () => {
- const approvals = await user.get(`/approvals/group/${guild._id}`);
- expect(approvals[0]._id).to.equal(syncedTask._id);
- expect(approvals[1]._id).to.equal(addlSyncedTask._id);
- });
-
- it('allows managers to get a list of tasks that need approval', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member._id,
- });
-
- const approvals = await member.get(`/approvals/group/${guild._id}`);
- expect(approvals[0]._id).to.equal(syncedTask._id);
- expect(approvals[1]._id).to.equal(addlSyncedTask._id);
- });
-});
diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js
deleted file mode 100644
index 60eeaf4053..0000000000
--- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js
+++ /dev/null
@@ -1,261 +0,0 @@
-import { find } from 'lodash';
-import {
- createAndPopulateGroup,
- translate as t,
-} from '../../../../../helpers/api-integration/v3';
-
-describe('POST /tasks/:id/approve/:userId', () => {
- let user; let guild; let member; let member2; let
- task;
-
- function findAssignedTask (memberTask) {
- return memberTask.group.id === guild._id;
- }
-
- beforeEach(async () => {
- const { group, members, groupLeader } = await createAndPopulateGroup({
- groupDetails: {
- name: 'Test Guild',
- type: 'guild',
- },
- members: 2,
- upgradeToGroupPlan: true,
- });
-
- guild = group;
- user = groupLeader;
- member = members[0]; // eslint-disable-line prefer-destructuring
- member2 = members[1]; // eslint-disable-line prefer-destructuring
-
- task = await user.post(`/tasks/group/${guild._id}`, {
- text: 'test todo',
- type: 'todo',
- requiresApproval: true,
- });
- });
-
- it('errors when user is not assigned', async () => {
- await expect(user.post(`/tasks/${task._id}/approve/${member._id}`))
- .to.eventually.be.rejected.and.to.eql({
- code: 404,
- error: 'NotFound',
- message: t('messageTaskNotFound'),
- });
- });
-
- it('errors when user is not the group leader', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
- await expect(member.post(`/tasks/${task._id}/approve/${member._id}`))
- .to.eventually.be.rejected.and.to.eql({
- code: 401,
- error: 'NotAuthorized',
- message: t('onlyGroupLeaderCanEditTasks'),
- });
- });
-
- it('approves an assigned user', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
-
- let memberTasks = await member.get('/tasks/user');
- let syncedTask = find(memberTasks, findAssignedTask);
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await user.post(`/tasks/${task._id}/approve/${member._id}`);
-
- await member.sync();
-
- expect(member.notifications.length).to.equal(3);
- expect(member.notifications[2].type).to.equal('GROUP_TASK_APPROVED');
- expect(member.notifications[2].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text }));
-
- memberTasks = await member.get('/tasks/user');
- syncedTask = find(memberTasks, findAssignedTask);
-
- expect(syncedTask.group.approval.approved).to.be.true;
- expect(syncedTask.group.approval.approvingUser).to.equal(user._id);
- expect(syncedTask.group.approval.dateApproved).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
- });
-
- it('allows a manager to approve an assigned user', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
-
- await member2.post(`/tasks/${task._id}/assign/${member._id}`);
-
- let memberTasks = await member.get('/tasks/user');
- let syncedTask = find(memberTasks, findAssignedTask);
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await member2.post(`/tasks/${task._id}/approve/${member._id}`);
- await member.sync();
-
- expect(member.notifications.length).to.equal(3);
- expect(member.notifications[2].type).to.equal('GROUP_TASK_APPROVED');
- expect(member.notifications[2].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text }));
-
- memberTasks = await member.get('/tasks/user');
- syncedTask = find(memberTasks, findAssignedTask);
-
- expect(syncedTask.group.approval.approved).to.be.true;
- expect(syncedTask.group.approval.approvingUser).to.equal(member2._id);
- expect(syncedTask.group.approval.dateApproved).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
- });
-
- it('removes approval pending notifications from managers', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
-
- await member2.post(`/tasks/${task._id}/assign/${member._id}`);
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await member.post(`/tasks/${syncedTask._id}/score/up`);
-
- await user.sync();
- await member2.sync();
- expect(user.notifications.length).to.equal(3);
- expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
- expect(member2.notifications.length).to.equal(2);
- expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
-
- await member2.post(`/tasks/${task._id}/approve/${member._id}`);
-
- await user.sync();
- await member2.sync();
-
- expect(user.notifications.length).to.equal(2);
- expect(member2.notifications.length).to.equal(1);
- });
-
- it('prevents double approval on a task', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
-
- await member2.post(`/tasks/${task._id}/assign/${member._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await member2.post(`/tasks/${task._id}/approve/${member._id}`);
-
- await expect(user.post(`/tasks/${task._id}/approve/${member._id}`))
- .to.eventually.be.rejected.and.to.eql({
- code: 401,
- error: 'NotAuthorized',
- message: t('canOnlyApproveTaskOnce'),
- });
- });
-
- it('prevents approving a task if it is not waiting for approval', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
-
- await expect(user.post(`/tasks/${task._id}/approve/${member._id}`))
- .to.eventually.be.rejected.and.to.eql({
- code: 401,
- error: 'NotAuthorized',
- message: t('taskApprovalWasNotRequested'),
- });
- });
-
- it('completes master task when single-completion task is approved', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: true,
- sharedCompletion: 'singleCompletion',
- });
-
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member2._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await user.post(`/tasks/${sharedCompletionTask._id}/approve/${member._id}`);
-
- const groupTasks = await user.get(`/tasks/group/${guild._id}?type=completedTodos`);
-
- const masterTask = find(groupTasks, groupTask => groupTask._id === sharedCompletionTask._id);
-
- expect(masterTask.completed).to.equal(true);
- });
-
- it('deletes other assigned user tasks when single-completion task is approved', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: true,
- sharedCompletion: 'singleCompletion',
- });
-
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member2._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await user.post(`/tasks/${sharedCompletionTask._id}/approve/${member._id}`);
-
- const member2Tasks = await member2.get('/tasks/user');
-
- const syncedTask2 = find(
- member2Tasks,
- memberTask => memberTask.group.taskId === sharedCompletionTask._id,
- );
-
- expect(syncedTask2).to.equal(undefined);
- });
-
- it('does not complete master task when not all user tasks are approved if all assigned must complete', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: true,
- sharedCompletion: 'allAssignedCompletion',
- });
-
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member2._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await user.post(`/tasks/${sharedCompletionTask._id}/approve/${member._id}`);
-
- const groupTasks = await user.get(`/tasks/group/${guild._id}`);
-
- const masterTask = find(groupTasks, groupTask => groupTask._id === sharedCompletionTask._id);
-
- expect(masterTask.completed).to.equal(false);
- });
-
- it('completes master task when all user tasks are approved if all assigned must complete', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: true,
- sharedCompletion: 'allAssignedCompletion',
- });
-
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member2._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- const member2Tasks = await member2.get('/tasks/user');
- const member2SyncedTask = find(member2Tasks, findAssignedTask);
- await member2.post(`/tasks/${member2SyncedTask._id}/score/up`);
-
- await user.post(`/tasks/${sharedCompletionTask._id}/approve/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/approve/${member2._id}`);
-
- const groupTasks = await user.get(`/tasks/group/${guild._id}?type=completedTodos`);
-
- const masterTask = find(groupTasks, groupTask => groupTask._id === sharedCompletionTask._id);
-
- expect(masterTask.completed).to.equal(true);
- });
-});
diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js
index 72542aceba..58392e85e1 100644
--- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js
+++ b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js
@@ -1,4 +1,3 @@
-import { find } from 'lodash';
import {
createAndPopulateGroup,
translate as t,
@@ -8,10 +7,6 @@ describe('POST /tasks/:id/needs-work/:userId', () => {
let user; let guild; let member; let member2; let
task;
- function findAssignedTask (memberTask) {
- return memberTask.group.id === guild._id;
- }
-
beforeEach(async () => {
const { group, members, groupLeader } = await createAndPopulateGroup({
groupDetails: {
@@ -37,14 +32,15 @@ describe('POST /tasks/:id/needs-work/:userId', () => {
it('errors when user is not assigned', async () => {
await expect(user.post(`/tasks/${task._id}/needs-work/${member._id}`))
.to.eventually.be.rejected.and.to.eql({
- code: 404,
- error: 'NotFound',
- message: t('messageTaskNotFound'),
+ code: 400,
+ error: 'BadRequest',
+ message: 'Task not completed by this user.',
});
});
it('errors when user is not the group leader', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member._id]);
+ await member.post(`/tasks/${task._id}/score/up`);
await expect(member.post(`/tasks/${task._id}/needs-work/${member._id}`))
.to.eventually.be.rejected.and.to.eql({
code: 401,
@@ -54,132 +50,64 @@ describe('POST /tasks/:id/needs-work/:userId', () => {
});
it('marks a task as needing more work', async () => {
+ await member.sync();
const initialNotifications = member.notifications.length;
-
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
-
- let memberTasks = await member.get('/tasks/user');
- let syncedTask = find(memberTasks, findAssignedTask);
+ await user.post(`/tasks/${task._id}/assign`, [member._id]);
// score task to require approval
- await member.post(`/tasks/${syncedTask._id}/score/up`);
+ await member.post(`/tasks/${task._id}/score/up`);
await user.post(`/tasks/${task._id}/needs-work/${member._id}`);
- [memberTasks] = await Promise.all([member.get('/tasks/user'), member.sync()]);
- syncedTask = find(memberTasks, findAssignedTask);
-
- // Check that the notification approval request has been removed
- expect(syncedTask.group.approval.requested).to.equal(false);
- expect(syncedTask.group.approval.requestedDate).to.equal(undefined);
-
// Check that the notification is correct
+ await member.sync();
expect(member.notifications.length).to.equal(initialNotifications + 3);
const notification = member.notifications[member.notifications.length - 1];
expect(notification.type).to.equal('GROUP_TASK_NEEDS_WORK');
- const taskText = syncedTask.text;
- const managerName = user.profile.name;
+ const taskText = task.text;
+ const managerName = user.auth.local.username;
expect(notification.data.message).to.equal(t('taskNeedsWork', { taskText, managerName }));
- expect(notification.data.task.id).to.equal(syncedTask._id);
+ expect(notification.data.task.id).to.equal(task._id);
expect(notification.data.task.text).to.equal(taskText);
- expect(notification.data.group.id).to.equal(syncedTask.group.id);
+ expect(notification.data.group.id).to.equal(task.group.id);
expect(notification.data.group.name).to.equal(guild.name);
expect(notification.data.manager.id).to.equal(user._id);
expect(notification.data.manager.name).to.equal(managerName);
-
- // Check that the managers' GROUP_TASK_APPROVAL notifications have been removed
- await user.sync();
-
- expect(user.notifications.find(n => { // eslint-disable-line arrow-body-style
- return n.data.taskId === syncedTask._id && n.type === 'GROUP_TASK_APPROVAL';
- })).to.equal(undefined);
});
it('allows a manager to mark a task as needing work', async () => {
+ await member.sync();
+ const initialNotifications = member.notifications.length;
await user.post(`/groups/${guild._id}/add-manager`, {
managerId: member2._id,
});
- await member2.post(`/tasks/${task._id}/assign/${member._id}`);
-
- let memberTasks = await member.get('/tasks/user');
- let syncedTask = find(memberTasks, findAssignedTask);
+ await member2.post(`/tasks/${task._id}/assign`, [member._id]);
// score task to require approval
- await member.post(`/tasks/${syncedTask._id}/score/up`);
-
- const initialNotifications = member.notifications.length;
-
+ await member.post(`/tasks/${task._id}/score/up`);
await member2.post(`/tasks/${task._id}/needs-work/${member._id}`);
- [memberTasks] = await Promise.all([member.get('/tasks/user'), member.sync()]);
- syncedTask = find(memberTasks, findAssignedTask);
-
- // Check that the notification approval request has been removed
- expect(syncedTask.group.approval.requested).to.equal(false);
- expect(syncedTask.group.approval.requestedDate).to.equal(undefined);
-
+ await member.sync();
expect(member.notifications.length).to.equal(initialNotifications + 3);
const notification = member.notifications[member.notifications.length - 1];
expect(notification.type).to.equal('GROUP_TASK_NEEDS_WORK');
- const taskText = syncedTask.text;
- const managerName = member2.profile.name;
+ const taskText = task.text;
+ const managerName = member2.auth.local.username;
expect(notification.data.message).to.equal(t('taskNeedsWork', { taskText, managerName }));
- expect(notification.data.task.id).to.equal(syncedTask._id);
+ expect(notification.data.task.id).to.equal(task._id);
expect(notification.data.task.text).to.equal(taskText);
- expect(notification.data.group.id).to.equal(syncedTask.group.id);
+ expect(notification.data.group.id).to.equal(task.group.id);
expect(notification.data.group.name).to.equal(guild.name);
expect(notification.data.manager.id).to.equal(member2._id);
expect(notification.data.manager.name).to.equal(managerName);
-
- // Check that the managers' GROUP_TASK_APPROVAL notifications have been removed
- await Promise.all([user.sync(), member2.sync()]);
-
- expect(user.notifications.find(n => { // eslint-disable-line arrow-body-style
- return n.data.taskId === syncedTask._id && n.type === 'GROUP_TASK_APPROVAL';
- })).to.equal(undefined);
-
- expect(member2.notifications.find(n => { // eslint-disable-line arrow-body-style
- return n.data.taskId === syncedTask._id && n.type === 'GROUP_TASK_APPROVAL';
- })).to.equal(undefined);
- });
-
- it('prevents marking a task as needing work if it was already approved', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
-
- await member2.post(`/tasks/${task._id}/assign/${member._id}`);
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await member2.post(`/tasks/${task._id}/approve/${member._id}`);
- await expect(user.post(`/tasks/${task._id}/needs-work/${member._id}`))
- .to.eventually.be.rejected.and.to.eql({
- code: 401,
- error: 'NotAuthorized',
- message: t('canOnlyApproveTaskOnce'),
- });
- });
-
- it('prevents marking a task as needing work if it is not waiting for approval', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
-
- await expect(user.post(`/tasks/${task._id}/needs-work/${member._id}`))
- .to.eventually.be.rejected.and.to.eql({
- code: 401,
- error: 'NotAuthorized',
- message: t('taskApprovalWasNotRequested'),
- });
});
});
diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js
index eaa3cf6484..17d653895e 100644
--- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js
+++ b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js
@@ -8,10 +8,6 @@ describe('POST /tasks/:id/score/:direction', () => {
let user; let guild; let member; let member2; let
task;
- function findAssignedTask (memberTask) {
- return memberTask.group.id === guild._id;
- }
-
beforeEach(async () => {
const { group, members, groupLeader } = await createAndPopulateGroup({
groupDetails: {
@@ -30,209 +26,50 @@ describe('POST /tasks/:id/score/:direction', () => {
task = await user.post(`/tasks/group/${guild._id}`, {
text: 'test todo',
type: 'todo',
- requiresApproval: true,
});
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member._id]);
});
- it('prevents user from scoring a task that needs to be approved', async () => {
- await user.update({
- 'preferences.language': 'cs',
- });
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- const direction = 'up';
-
- const response = await member.post(`/tasks/${syncedTask._id}/score/${direction}`);
-
- expect(response.data.requiresApproval).to.equal(true);
- expect(response.message).to.equal(t('taskApprovalHasBeenRequested'));
-
- const updatedTask = await member.get(`/tasks/${syncedTask._id}`);
-
- await user.sync();
-
- expect(user.notifications.length).to.equal(3);
- expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
- expect(user.notifications[2].data.message).to.equal(t('userHasRequestedTaskApproval', {
- user: member.auth.local.username,
- taskName: updatedTask.text,
- taskId: updatedTask._id,
- direction,
- }, 'cs')); // This test only works if we have the notification translated
- expect(user.notifications[2].data.groupId).to.equal(guild._id);
-
- expect(updatedTask.group.approval.requested).to.equal(true);
- expect(updatedTask.group.approval.requestedDate).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
- });
-
- it('sends notifications to all managers', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
- const direction = 'up';
-
- await member.post(`/tasks/${syncedTask._id}/score/${direction}`);
- const updatedTask = await member.get(`/tasks/${syncedTask._id}`);
- await user.sync();
- await member2.sync();
-
- expect(user.notifications.length).to.equal(3);
- expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
- expect(user.notifications[2].data.message).to.equal(t('userHasRequestedTaskApproval', {
- user: member.auth.local.username,
- taskName: updatedTask.text,
- taskId: updatedTask._id,
- direction,
- }));
- expect(user.notifications[2].data.groupId).to.equal(guild._id);
-
- expect(member2.notifications.length).to.equal(2);
- expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
- expect(member2.notifications[1].data.message).to.equal(t('userHasRequestedTaskApproval', {
- user: member.auth.local.username,
- taskName: updatedTask.text,
- taskId: updatedTask._id,
- direction,
- }));
- expect(member2.notifications[1].data.groupId).to.equal(guild._id);
- });
-
- it('errors when approval has already been requested', async () => {
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
-
- const response = await member.post(`/tasks/${syncedTask._id}/score/up`);
- expect(response.data.requiresApproval).to.equal(true);
- expect(response.message).to.equal(t('taskRequiresApproval'));
- });
-
- it('allows a user to score an approved task', async () => {
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
-
- await user.post(`/tasks/${task._id}/approve/${member._id}`);
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- const updatedTask = await member.get(`/tasks/${syncedTask._id}`);
-
- expect(updatedTask.completed).to.equal(true);
- expect(updatedTask.dateCompleted).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
- });
-
- it('completes master task when single-completion task is completed', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: false,
- sharedCompletion: 'singleCompletion',
- });
-
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- const memberTasks = await member.get('/tasks/user');
-
- const syncedTask = find(
- memberTasks,
- memberTask => memberTask.group.taskId === sharedCompletionTask._id,
- );
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
+ it('completes single-assigned task', async () => {
+ await member.post(`/tasks/${task._id}/score/up`);
const groupTasks = await user.get(`/tasks/group/${guild._id}?type=completedTodos`);
- const masterTask = find(groupTasks, groupTask => groupTask._id === sharedCompletionTask._id);
+ const sourceTask = find(groupTasks, groupTask => groupTask._id === task._id);
- expect(masterTask.completed).to.equal(true);
+ expect(sourceTask.completed).to.equal(true);
});
- it('deletes other assigned user tasks when single-completion task is completed', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: false,
- sharedCompletion: 'singleCompletion',
+ it('errors when task has already been completed', async () => {
+ await member.post(`/tasks/${task._id}/score/up`);
+
+ await expect(member.post(`/tasks/${task._id}/score/up`)).to.be.rejected.and.to.eventually.eql({
+ code: 401,
+ error: 'NotAuthorized',
+ message: t('sessionOutdated'),
});
-
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member2._id}`);
- const memberTasks = await member.get('/tasks/user');
-
- const syncedTask = find(
- memberTasks,
- memberTask => memberTask.group.taskId === sharedCompletionTask._id,
- );
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
-
- const member2Tasks = await member2.get('/tasks/user');
-
- const syncedTask2 = find(
- member2Tasks,
- memberTask => memberTask.group.taskId === sharedCompletionTask._id,
- );
-
- expect(syncedTask2).to.equal(undefined);
});
- it('does not complete master task when not all user tasks are completed if all assigned must complete', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: false,
- sharedCompletion: 'allAssignedCompletion',
- });
+ it('does not complete multi-assigned task when not all assignees have completed', async () => {
+ await user.post(`/tasks/${task._id}/assign`, [member2._id]);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member2._id}`);
- const memberTasks = await member.get('/tasks/user');
-
- const syncedTask = find(
- memberTasks,
- memberTask => memberTask.group.taskId === sharedCompletionTask._id,
- );
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
+ await member.post(`/tasks/${task._id}/score/up`);
const groupTasks = await user.get(`/tasks/group/${guild._id}`);
- const masterTask = find(groupTasks, groupTask => groupTask._id === sharedCompletionTask._id);
+ const sourceTask = find(groupTasks, groupTask => groupTask._id === task._id);
- expect(masterTask.completed).to.equal(false);
+ expect(sourceTask.completed).to.equal(false);
});
- it('completes master task when all user tasks are completed if all assigned must complete', async () => {
- const sharedCompletionTask = await user.post(`/tasks/group/${guild._id}`, {
- text: 'shared completion todo',
- type: 'todo',
- requiresApproval: false,
- sharedCompletion: 'allAssignedCompletion',
- });
+ it('completes multi-assigned task when all assignees have completed', async () => {
+ await user.post(`/tasks/${task._id}/assign`, [member2._id]);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member._id}`);
- await user.post(`/tasks/${sharedCompletionTask._id}/assign/${member2._id}`);
- const memberTasks = await member.get('/tasks/user');
- const member2Tasks = await member2.get('/tasks/user');
- const syncedTask = find(
- memberTasks,
- memberTask => memberTask.group.taskId === sharedCompletionTask._id,
- );
- const syncedTask2 = find(
- member2Tasks,
- memberTask => memberTask.group.taskId === sharedCompletionTask._id,
- );
-
- await member.post(`/tasks/${syncedTask._id}/score/up`);
- await member2.post(`/tasks/${syncedTask2._id}/score/up`);
+ await member.post(`/tasks/${task._id}/score/up`);
+ await member2.post(`/tasks/${task._id}/score/up`);
const groupTasks = await user.get(`/tasks/group/${guild._id}?type=completedTodos`);
- const masterTask = find(groupTasks, groupTask => groupTask._id === sharedCompletionTask._id);
+ const sourceTask = find(groupTasks, groupTask => groupTask._id === task._id);
- expect(masterTask.completed).to.equal(true);
+ expect(sourceTask.completed).to.equal(true);
});
});
diff --git a/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js b/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js
index 71b29a1530..2e122e78fc 100644
--- a/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js
+++ b/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js
@@ -39,7 +39,7 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
});
it('returns error when task is not found', async () => {
- await expect(user.post(`/tasks/${generateUUID()}/assign/${member._id}`))
+ await expect(user.post(`/tasks/${generateUUID()}/assign`, [member._id]))
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
@@ -56,7 +56,7 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
notes: 1976,
});
- await expect(user.post(`/tasks/${nonGroupTask._id}/assign/${member._id}`))
+ await expect(user.post(`/tasks/${nonGroupTask._id}/assign`, [member._id]))
.to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
@@ -67,7 +67,7 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
it('returns error when user is not a member of the group', async () => {
const nonUser = await generateUser();
- await expect(nonUser.post(`/tasks/${task._id}/assign/${member._id}`))
+ await expect(nonUser.post(`/tasks/${task._id}/assign`, [member._id]))
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
@@ -76,7 +76,7 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
});
it('returns error when non leader tries to create a task', async () => {
- await expect(member2.post(`/tasks/${task._id}/assign/${member._id}`))
+ await expect(member2.post(`/tasks/${task._id}/assign`, [member._id]))
.to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
@@ -84,49 +84,23 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
});
});
- it('allows user to assign themselves (claim)', async () => {
- await member.post(`/tasks/${task._id}/assign/${member._id}`);
-
- const groupTask = await user.get(`/tasks/group/${guild._id}`);
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- expect(groupTask[0].group.assignedUsers).to.contain(member._id);
- expect(syncedTask).to.exist;
- });
-
- it('sends notifications to group leader and managers when a task is claimed', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
- await member.post(`/tasks/${task._id}/assign/${member._id}`);
- await user.sync();
- await member2.sync();
- const groupTask = await user.get(`/tasks/group/${guild._id}`);
-
- expect(user.notifications.length).to.equal(3); // includes Guild Joined achievement
- expect(user.notifications[2].type).to.equal('GROUP_TASK_CLAIMED');
- expect(user.notifications[2].data.taskId).to.equal(groupTask[0]._id);
- expect(user.notifications[2].data.groupId).to.equal(guild._id);
- expect(member2.notifications.length).to.equal(2);
- expect(member2.notifications[1].type).to.equal('GROUP_TASK_CLAIMED');
- expect(member2.notifications[1].data.taskId).to.equal(groupTask[0]._id);
- expect(member2.notifications[1].data.groupId).to.equal(guild._id);
- });
-
it('assigns a task to a user', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member._id]);
const groupTask = await user.get(`/tasks/group/${guild._id}`);
+ await member.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
const memberTasks = await member.get('/tasks/user');
const syncedTask = find(memberTasks, findAssignedTask);
expect(groupTask[0].group.assignedUsers).to.contain(member._id);
+ expect(groupTask[0].group.assignedUsersDetail[member._id]).to.exist;
expect(syncedTask).to.exist;
});
it('sends a notification to assigned user', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member._id]);
await member.sync();
const groupTask = await user.get(`/tasks/group/${guild._id}`);
@@ -137,20 +111,27 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
});
it('assigns a task to multiple users', async () => {
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
- await user.post(`/tasks/${task._id}/assign/${member2._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member._id, member2._id]);
const groupTask = await user.get(`/tasks/group/${guild._id}`);
+ await member.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
const memberTasks = await member.get('/tasks/user');
const member1SyncedTask = find(memberTasks, findAssignedTask);
+ await member2.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
const member2Tasks = await member2.get('/tasks/user');
const member2SyncedTask = find(member2Tasks, findAssignedTask);
expect(groupTask[0].group.assignedUsers).to.contain(member._id);
- expect(groupTask[0].group.assignedUsers).to.contain(member2._id);
+ expect(groupTask[0].group.assignedUsersDetail[member._id]).to.exist;
expect(member1SyncedTask).to.exist;
+ expect(groupTask[0].group.assignedUsers).to.contain(member2._id);
+ expect(groupTask[0].group.assignedUsersDetail[member2._id]).to.exist;
expect(member2SyncedTask).to.exist;
});
@@ -159,13 +140,17 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
managerId: member2._id,
});
- await member2.post(`/tasks/${task._id}/assign/${member._id}`);
+ await member2.post(`/tasks/${task._id}/assign`, [member._id]);
const groupTask = await member2.get(`/tasks/group/${guild._id}`);
+ await member.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
const memberTasks = await member.get('/tasks/user');
const syncedTask = find(memberTasks, findAssignedTask);
expect(groupTask[0].group.assignedUsers).to.contain(member._id);
+ expect(groupTask[0].group.assignedUsersDetail[member._id]).to.exist;
expect(syncedTask).to.exist;
});
});
diff --git a/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js b/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js
index 83d67246d6..117c9f760f 100644
--- a/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js
+++ b/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js
@@ -37,7 +37,7 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => {
notes: 1976,
});
- await user.post(`/tasks/${task._id}/assign/${member._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member._id]);
});
it('returns error when task is not found', async () => {
@@ -96,7 +96,7 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => {
});
it('unassigns a user and only that user from a task', async () => {
- await user.post(`/tasks/${task._id}/assign/${member2._id}`);
+ await user.post(`/tasks/${task._id}/assign`, [member2._id]);
await user.post(`/tasks/${task._id}/unassign/${member._id}`);
@@ -105,6 +105,9 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => {
const memberTasks = await member.get('/tasks/user');
const member1SyncedTask = find(memberTasks, findAssignedTask);
+ await member2.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
const member2Tasks = await member2.get('/tasks/user');
const member2SyncedTask = find(member2Tasks, findAssignedTask);
@@ -130,20 +133,7 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => {
expect(syncedTask).to.not.exist;
});
- it('allows a user to unassign themselves', async () => {
- await member.post(`/tasks/${task._id}/unassign/${member._id}`);
-
- const groupTask = await user.get(`/tasks/group/${guild._id}`);
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- expect(groupTask[0].group.assignedUsers).to.not.contain(member._id);
- expect(syncedTask).to.not.exist;
- });
-
- // @TODO: Which do we want? The user to unassign themselves or not. This test was in
- // here, but then we had a request to allow to unaissgn.
- xit('returns error when non leader tries to unassign their a task', async () => {
+ it('returns error when non leader tries to unassign a task', async () => {
await expect(member.post(`/tasks/${task._id}/unassign/${member._id}`))
.to.eventually.be.rejected.and.eql({
code: 401,
diff --git a/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js b/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js
index abfd5ae629..330983c70c 100644
--- a/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js
+++ b/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js
@@ -1,4 +1,3 @@
-import { find } from 'lodash';
import {
createAndPopulateGroup, translate as t,
} from '../../../../../helpers/api-integration/v3';
@@ -11,10 +10,6 @@ describe('PUT /tasks/:id', () => {
let habit;
let todo;
- function findAssignedTask (memberTask) {
- return memberTask.group.id === guild._id;
- }
-
beforeEach(async () => {
const { group, members, groupLeader } = await createAndPopulateGroup({
groupDetails: {
@@ -44,8 +39,7 @@ describe('PUT /tasks/:id', () => {
notes: 1976,
});
- await user.post(`/tasks/${habit._id}/assign/${member._id}`);
- await user.post(`/tasks/${habit._id}/assign/${member2._id}`);
+ await user.post(`/tasks/${habit._id}/assign`, [member._id, member2._id]);
});
it('updates a group task', async () => {
@@ -56,28 +50,6 @@ describe('PUT /tasks/:id', () => {
expect(savedHabit.notes).to.eql('some new notes');
});
- it('updates a group task - approval is required', async () => {
- // allow to manage
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member._id,
- });
-
- // change the habit
- habit = await member.put(`/tasks/${habit._id}`, {
- text: 'new text!',
- requiresApproval: true,
- });
-
- const memberTasks = await member2.get('/tasks/user');
- const syncedTask = find(memberTasks, memberTask => memberTask.group.taskId === habit._id);
-
- // score up to trigger approval
- const response = await member2.post(`/tasks/${syncedTask._id}/score/up`);
-
- expect(response.data.requiresApproval).to.equal(true);
- expect(response.message).to.equal(t('taskApprovalHasBeenRequested'));
- });
-
it('member updates a group task value - not allowed', async () => {
// change the todo
await expect(member.put(`/tasks/${habit._id}`, {
@@ -120,7 +92,7 @@ describe('PUT /tasks/:id', () => {
],
});
- await user.post(`/tasks/${habit._id}/assign/${member._id}`);
+ await user.post(`/tasks/${habit._id}/assign`, [member._id]);
// change the checklist text
habit = await user.put(`/tasks/${habit._id}`, {
@@ -137,63 +109,4 @@ describe('PUT /tasks/:id', () => {
expect(habit.checklist.length).to.eql(2);
});
-
- it('updates the linked tasks', async () => {
- await user.put(`/tasks/${habit._id}`, {
- text: 'some new text',
- up: false,
- down: false,
- notes: 'some new notes',
- });
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- expect(syncedTask.text).to.eql('some new text');
- expect(syncedTask.up).to.eql(false);
- expect(syncedTask.down).to.eql(false);
- });
-
- it('updates the linked tasks for all assigned users', async () => {
- await user.put(`/tasks/${habit._id}`, {
- text: 'some new text',
- up: false,
- down: false,
- notes: 'some new notes',
- });
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- const member2Tasks = await member2.get('/tasks/user');
- const member2SyncedTask = find(member2Tasks, findAssignedTask);
-
- expect(syncedTask.text).to.eql('some new text');
- expect(syncedTask.up).to.eql(false);
- expect(syncedTask.down).to.eql(false);
-
- expect(member2SyncedTask.text).to.eql('some new text');
- expect(member2SyncedTask.up).to.eql(false);
- expect(member2SyncedTask.down).to.eql(false);
- });
-
- it('updates the linked tasks', async () => {
- await user.post(`/groups/${guild._id}/add-manager`, {
- managerId: member2._id,
- });
-
- await member2.put(`/tasks/${habit._id}`, {
- text: 'some new text',
- up: false,
- down: false,
- notes: 'some new notes',
- });
-
- const memberTasks = await member.get('/tasks/user');
- const syncedTask = find(memberTasks, findAssignedTask);
-
- expect(syncedTask.text).to.eql('some new text');
- expect(syncedTask.up).to.eql(false);
- expect(syncedTask.down).to.eql(false);
- });
});
diff --git a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js
index df7676b945..eeda226b45 100644
--- a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js
+++ b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js
@@ -145,19 +145,16 @@ describe('POST /user/class/cast/:spellId', () => {
text: 'todo group',
type: 'todo',
});
- await groupLeader.post(`/tasks/${groupTask._id}/assign/${groupLeader._id}`);
- const memberTasks = await groupLeader.get('/tasks/user');
- const syncedGroupTask = find(memberTasks, memberTask => memberTask.group.id === group._id);
-
+ await groupLeader.post(`/tasks/${groupTask._id}/assign`, [groupLeader._id]);
await groupLeader.update({ 'stats.class': 'rogue', 'stats.lvl': 11 });
await sleep(0.5);
await groupLeader.sync();
- await expect(groupLeader.post(`/user/class/cast/pickPocket?targetId=${syncedGroupTask._id}`))
+ await expect(groupLeader.post(`/user/class/cast/pickPocket?targetId=${groupTask._id}`))
.to.eventually.be.rejected.and.eql({
- code: 400,
- error: 'BadRequest',
- message: t('groupTasksNoCast'),
+ code: 404,
+ error: 'NotFound',
+ message: t('messageTaskNotFound'),
});
});
@@ -279,7 +276,10 @@ describe('POST /user/class/cast/:spellId', () => {
type: 'todo',
});
await user.update({ 'stats.class': 'healer', 'stats.mp': 200, 'stats.lvl': 15 });
- await user.post(`/tasks/${groupTask._id}/assign/${user._id}`);
+ await user.post(`/tasks/${groupTask._id}/assign`, [user._id]);
+ await user.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
await user.post('/user/class/cast/brightness');
await user.sync();
diff --git a/test/api/v3/integration/user/POST-user_reset.test.js b/test/api/v3/integration/user/POST-user_reset.test.js
index 5d750fde98..a3c00a90a3 100644
--- a/test/api/v3/integration/user/POST-user_reset.test.js
+++ b/test/api/v3/integration/user/POST-user_reset.test.js
@@ -100,11 +100,14 @@ describe('POST /user/reset', () => {
text: 'todo group',
type: 'todo',
});
- await user.post(`/tasks/${groupTask._id}/assign/${user._id}`);
+ await user.post(`/tasks/${groupTask._id}/assign`, [user._id]);
await user.post('/user/reset');
await user.sync();
+ await user.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
const memberTasks = await user.get('/tasks/user');
const syncedGroupTask = find(memberTasks, memberTask => memberTask.group.id === guild._id);
diff --git a/test/api/v3/integration/user/PUT-user.test.js b/test/api/v3/integration/user/PUT-user.test.js
index 1a0451318f..ced94b2232 100644
--- a/test/api/v3/integration/user/PUT-user.test.js
+++ b/test/api/v3/integration/user/PUT-user.test.js
@@ -35,7 +35,7 @@ describe('PUT /user', () => {
})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: 'mustBeArray',
+ message: 'Tag list must be an array.',
});
});
diff --git a/test/api/v4/user/POST-user_class_cast_spellId.test.js b/test/api/v4/user/POST-user_class_cast_spellId.test.js
index b9382bba3d..8602cb7c2a 100644
--- a/test/api/v4/user/POST-user_class_cast_spellId.test.js
+++ b/test/api/v4/user/POST-user_class_cast_spellId.test.js
@@ -130,19 +130,16 @@ describe('POST /user/class/cast/:spellId', () => {
text: 'todo group',
type: 'todo',
});
- await groupLeader.post(`/tasks/${groupTask._id}/assign/${groupLeader._id}`);
- const memberTasks = await groupLeader.get('/tasks/user');
- const syncedGroupTask = find(memberTasks, memberTask => memberTask.group.id === group._id);
-
+ await groupLeader.post(`/tasks/${groupTask._id}/assign`, [groupLeader._id]);
await groupLeader.update({ 'stats.class': 'rogue', 'stats.lvl': 11 });
await sleep(0.5);
await groupLeader.sync();
- await expect(groupLeader.post(`/user/class/cast/pickPocket?targetId=${syncedGroupTask._id}`))
+ await expect(groupLeader.post(`/user/class/cast/pickPocket?targetId=${groupTask._id}`))
.to.eventually.be.rejected.and.eql({
- code: 400,
- error: 'BadRequest',
- message: t('groupTasksNoCast'),
+ code: 404,
+ error: 'NotFound',
+ message: t('messageTaskNotFound'),
});
});
@@ -247,7 +244,10 @@ describe('POST /user/class/cast/:spellId', () => {
type: 'todo',
});
await user.update({ 'stats.class': 'healer', 'stats.mp': 200, 'stats.lvl': 15 });
- await user.post(`/tasks/${groupTask._id}/assign/${user._id}`);
+ await user.post(`/tasks/${groupTask._id}/assign`, [user._id]);
+ await user.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
await user.post('/user/class/cast/brightness');
await user.sync();
diff --git a/test/api/v4/user/POST-user_reset.test.js b/test/api/v4/user/POST-user_reset.test.js
index ced9126eb2..c96e30f93a 100644
--- a/test/api/v4/user/POST-user_reset.test.js
+++ b/test/api/v4/user/POST-user_reset.test.js
@@ -100,11 +100,14 @@ describe('POST /user/reset', () => {
text: 'todo group',
type: 'todo',
});
- await user.post(`/tasks/${groupTask._id}/assign/${user._id}`);
+ await user.post(`/tasks/${groupTask._id}/assign`, [user._id]);
await user.post('/user/reset');
await user.sync();
+ await user.put('/user', {
+ 'preferences.tasks.mirrorGroupTasks': [guild._id],
+ });
const memberTasks = await user.get('/tasks/user');
const syncedGroupTask = find(memberTasks, memberTask => memberTask.group.id === guild._id);
diff --git a/test/api/v4/user/PUT-user.test.js b/test/api/v4/user/PUT-user.test.js
index a588a6f386..1abf4f8d24 100644
--- a/test/api/v4/user/PUT-user.test.js
+++ b/test/api/v4/user/PUT-user.test.js
@@ -34,7 +34,7 @@ describe('PUT /user', () => {
})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: 'mustBeArray',
+ message: 'Tag list must be an array.',
});
});
diff --git a/test/common/ops/scoreTask.test.js b/test/common/ops/scoreTask.test.js
index 7282359aff..bee676a1fd 100644
--- a/test/common/ops/scoreTask.test.js
+++ b/test/common/ops/scoreTask.test.js
@@ -249,18 +249,6 @@ describe('shared.ops.scoreTask', () => {
expect(ref.afterUser._tmp.quest.progressDelta).to.eql(secondTaskDelta);
});
- it('does not modify stats when task need approval', () => {
- todo.group.approval.required = true;
- options = {
- user: ref.afterUser, task: todo, direction: 'up', times: 5, cron: false,
- };
- scoreTask(options);
-
- expect(ref.afterUser.stats.hp).to.eql(50);
- expect(ref.afterUser.stats.exp).to.equal(ref.beforeUser.stats.exp);
- expect(ref.afterUser.stats.gp).to.equal(ref.beforeUser.stats.gp);
- });
-
context('habits', () => {
it('up', () => {
options = {
diff --git a/website/client/package-lock.json b/website/client/package-lock.json
index 1275af51c4..0f25f93dfb 100644
--- a/website/client/package-lock.json
+++ b/website/client/package-lock.json
@@ -15880,9 +15880,9 @@
}
},
"core-js": {
- "version": "3.23.5",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.5.tgz",
- "integrity": "sha512-7Vh11tujtAZy82da4duVreQysIoO2EvVrur7y6IzZkH1IHPSekuDi8Vuw1+YKjkbfWLRD7Nc9ICQ/sIUDutcyg=="
+ "version": "3.24.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz",
+ "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg=="
},
"core-js-compat": {
"version": "3.11.0",
diff --git a/website/client/package.json b/website/client/package.json
index 105b9cc28c..de0c012ae1 100644
--- a/website/client/package.json
+++ b/website/client/package.json
@@ -32,7 +32,7 @@
"bootstrap": "^4.6.0",
"bootstrap-vue": "^2.22.0",
"chai": "^4.3.6",
- "core-js": "^3.23.5",
+ "core-js": "^3.24.1",
"dompurify": "^2.3.10",
"eslint": "^6.8.0",
"eslint-config-habitrpg": "^6.2.0",
diff --git a/website/client/scripts/npm-postinstall.js b/website/client/scripts/npm-postinstall.js
index d710bc97aa..ed949bb316 100644
--- a/website/client/scripts/npm-postinstall.js
+++ b/website/client/scripts/npm-postinstall.js
@@ -7,7 +7,7 @@ if (process.env.NODE_ENV === 'production') {
stdio: 'inherit',
});
- execSync('npm run storybook:build', {
+ /* execSync('npm run storybook:build', {
stdio: 'inherit',
- });
+ }); */
}
diff --git a/website/client/src/assets/css/sprites/spritesmith-main.css b/website/client/src/assets/css/sprites/spritesmith-main.css
index a31d767fb4..4944d95ed6 100644
--- a/website/client/src/assets/css/sprites/spritesmith-main.css
+++ b/website/client/src/assets/css/sprites/spritesmith-main.css
@@ -27015,6 +27015,31 @@
width: 68px;
height: 68px;
}
+.shield_mystery_202209 {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_mystery_202209.png');
+ width: 114px;
+ height: 90px;
+}
+.shop_set_mystery_202209 {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_set_mystery_202209.png');
+ width: 68px;
+ height: 68px;
+}
+.shop_shield_mystery_202209 {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_mystery_202209.png');
+ width: 68px;
+ height: 68px;
+}
+.shop_weapon_mystery_202209 {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_mystery_202209.png');
+ width: 68px;
+ height: 68px;
+}
+.weapon_mystery_202209 {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_mystery_202209.png');
+ width: 114px;
+ height: 90px;
+}
.broad_armor_mystery_301404 {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_mystery_301404.png');
width: 90px;
@@ -36693,6 +36718,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_BearCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_BearCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_BearCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_BearCub-Rainbow.png');
width: 105px;
@@ -37108,6 +37138,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_Cactus-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Cactus-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_Cactus-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Cactus-Rainbow.png');
width: 105px;
@@ -37623,6 +37658,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_Dragon-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Dragon-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_Dragon-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Dragon-Rainbow.png');
width: 105px;
@@ -38038,6 +38078,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_FlyingPig-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_FlyingPig-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_FlyingPig-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_FlyingPig-Rainbow.png');
width: 105px;
@@ -38303,6 +38348,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_Fox-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Fox-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_Fox-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Fox-Rainbow.png');
width: 105px;
@@ -38958,6 +39008,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_LionCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_LionCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_LionCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_LionCub-Rainbow.png');
width: 105px;
@@ -39443,6 +39498,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_PandaCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_PandaCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_PandaCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_PandaCub-Rainbow.png');
width: 105px;
@@ -40663,6 +40723,11 @@
width: 105px;
height: 105px;
}
+.Mount_Body_TigerCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_TigerCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Body_TigerCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_TigerCub-Rainbow.png');
width: 105px;
@@ -41238,6 +41303,11 @@
width: 135px;
height: 135px;
}
+.Mount_Body_Wolf-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Wolf-Porcelain.png');
+ width: 135px;
+ height: 135px;
+}
.Mount_Body_Wolf-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Body_Wolf-Rainbow.png');
width: 135px;
@@ -41758,6 +41828,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_BearCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_BearCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_BearCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_BearCub-Rainbow.png');
width: 105px;
@@ -42173,6 +42248,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_Cactus-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Cactus-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_Cactus-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Cactus-Rainbow.png');
width: 105px;
@@ -42688,6 +42768,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_Dragon-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Dragon-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_Dragon-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Dragon-Rainbow.png');
width: 105px;
@@ -43103,6 +43188,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_FlyingPig-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_FlyingPig-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_FlyingPig-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_FlyingPig-Rainbow.png');
width: 105px;
@@ -43368,6 +43458,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_Fox-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Fox-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_Fox-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Fox-Rainbow.png');
width: 105px;
@@ -44023,6 +44118,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_LionCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_LionCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_LionCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_LionCub-Rainbow.png');
width: 105px;
@@ -44508,6 +44608,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_PandaCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_PandaCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_PandaCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_PandaCub-Rainbow.png');
width: 105px;
@@ -45728,6 +45833,11 @@
width: 105px;
height: 105px;
}
+.Mount_Head_TigerCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_TigerCub-Porcelain.png');
+ width: 105px;
+ height: 105px;
+}
.Mount_Head_TigerCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_TigerCub-Rainbow.png');
width: 105px;
@@ -46303,6 +46413,11 @@
width: 135px;
height: 135px;
}
+.Mount_Head_Wolf-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Wolf-Porcelain.png');
+ width: 135px;
+ height: 135px;
+}
.Mount_Head_Wolf-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Head_Wolf-Rainbow.png');
width: 135px;
@@ -46828,6 +46943,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_BearCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_BearCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_BearCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_BearCub-Rainbow.png');
width: 81px;
@@ -47243,6 +47363,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_Cactus-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Cactus-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_Cactus-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Cactus-Rainbow.png');
width: 81px;
@@ -47758,6 +47883,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_Dragon-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Dragon-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_Dragon-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Dragon-Rainbow.png');
width: 81px;
@@ -48173,6 +48303,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_FlyingPig-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_FlyingPig-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_FlyingPig-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_FlyingPig-Rainbow.png');
width: 81px;
@@ -48438,6 +48573,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_Fox-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Fox-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_Fox-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Fox-Rainbow.png');
width: 81px;
@@ -49098,6 +49238,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_LionCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_LionCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_LionCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_LionCub-Rainbow.png');
width: 81px;
@@ -49583,6 +49728,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_PandaCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_PandaCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_PandaCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_PandaCub-Rainbow.png');
width: 81px;
@@ -50803,6 +50953,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_TigerCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_TigerCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_TigerCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_TigerCub-Rainbow.png');
width: 81px;
@@ -51378,6 +51533,11 @@
width: 81px;
height: 99px;
}
+.Mount_Icon_Wolf-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Wolf-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Mount_Icon_Wolf-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Mount_Icon_Wolf-Rainbow.png');
width: 81px;
@@ -51908,6 +52068,11 @@
width: 81px;
height: 99px;
}
+.Pet-BearCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-BearCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-BearCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-BearCub-Rainbow.png');
width: 81px;
@@ -52338,6 +52503,11 @@
width: 81px;
height: 99px;
}
+.Pet-Cactus-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Cactus-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-Cactus-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Cactus-Rainbow.png');
width: 81px;
@@ -52873,6 +53043,11 @@
width: 81px;
height: 99px;
}
+.Pet-Dragon-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Dragon-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-Dragon-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Dragon-Rainbow.png');
width: 81px;
@@ -53303,6 +53478,11 @@
width: 81px;
height: 99px;
}
+.Pet-FlyingPig-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-FlyingPig-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-FlyingPig-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-FlyingPig-Rainbow.png');
width: 81px;
@@ -53583,6 +53763,11 @@
width: 81px;
height: 99px;
}
+.Pet-Fox-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Fox-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-Fox-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Fox-Rainbow.png');
width: 81px;
@@ -54258,6 +54443,11 @@
width: 81px;
height: 99px;
}
+.Pet-LionCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-LionCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-LionCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-LionCub-Rainbow.png');
width: 81px;
@@ -54758,6 +54948,11 @@
width: 81px;
height: 99px;
}
+.Pet-PandaCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-PandaCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-PandaCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-PandaCub-Rainbow.png');
width: 81px;
@@ -56003,6 +56198,11 @@
width: 81px;
height: 99px;
}
+.Pet-TigerCub-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-TigerCub-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-TigerCub-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-TigerCub-Rainbow.png');
width: 81px;
@@ -56598,6 +56798,11 @@
width: 81px;
height: 99px;
}
+.Pet-Wolf-Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Wolf-Porcelain.png');
+ width: 81px;
+ height: 99px;
+}
.Pet-Wolf-Rainbow {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Wolf-Rainbow.png');
width: 81px;
@@ -56928,6 +57133,11 @@
width: 68px;
height: 68px;
}
+.Pet_HatchingPotion_Porcelain {
+ background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Porcelain.png');
+ width: 68px;
+ height: 68px;
+}
.Pet_HatchingPotion_Purple {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Purple.png');
width: 68px;
diff --git a/website/client/src/assets/images/bug.png b/website/client/src/assets/images/bug.png
new file mode 100644
index 0000000000..e3116a7229
Binary files /dev/null and b/website/client/src/assets/images/bug.png differ
diff --git a/website/client/src/assets/images/group-plans/purple-diagonal.png b/website/client/src/assets/images/group-plans/purple-diagonal.png
new file mode 100644
index 0000000000..f928a387f7
Binary files /dev/null and b/website/client/src/assets/images/group-plans/purple-diagonal.png differ
diff --git a/website/client/src/assets/images/group-plans/task-columns.png b/website/client/src/assets/images/group-plans/task-columns.png
new file mode 100644
index 0000000000..f755d4a488
Binary files /dev/null and b/website/client/src/assets/images/group-plans/task-columns.png differ
diff --git a/website/client/src/assets/images/group-plans/task-columns@2x.png b/website/client/src/assets/images/group-plans/task-columns@2x.png
new file mode 100644
index 0000000000..057b77b4e6
Binary files /dev/null and b/website/client/src/assets/images/group-plans/task-columns@2x.png differ
diff --git a/website/client/src/assets/images/group-plans/task-columns@3x.png b/website/client/src/assets/images/group-plans/task-columns@3x.png
new file mode 100644
index 0000000000..072709382c
Binary files /dev/null and b/website/client/src/assets/images/group-plans/task-columns@3x.png differ
diff --git a/website/client/src/assets/scss/create-task.scss b/website/client/src/assets/scss/create-task.scss
index c97d9afb05..42a04b2522 100644
--- a/website/client/src/assets/scss/create-task.scss
+++ b/website/client/src/assets/scss/create-task.scss
@@ -1,9 +1,56 @@
.create-task-area {
position: absolute;
- right: 24px;
+ right: 12px;
top: -24px;
z-index: 998;
align-items: center;
+
+ .dropdown {
+ width: 140px;
+ border-radius: 2px;
+ box-shadow: 0 3px 6px 0 rgba(26, 24, 29, 0.16), 0 3px 6px 0 rgba(26, 24, 29, 0.24);
+ background-color: $white;
+ margin-top: 2px;
+ position: absolute;
+ right: 0px;
+
+ .task-icon {
+ width: 30px;
+ }
+
+ .task-label {
+ margin-top: 1px;
+ }
+
+ .dropdown-item:hover {
+ .svg-icon {
+ color: $purple-300;
+ }
+ }
+ .svg-icon {
+ color: $gray-200;
+
+ &.icon-habit {
+ width: 30px;
+ height: 20px;
+ }
+
+ &.icon-daily {
+ width: 24px;
+ height: 20px;
+ }
+
+ &.icon-todo {
+ width: 20px;
+ height: 20px;
+ }
+
+ &.icon-reward {
+ width: 26px;
+ height: 20px;
+ }
+ }
+ }
}
.slide-tasks-btns-leave-active, .slide-tasks-btns-enter-active {
@@ -17,70 +64,14 @@
overflow-x: hidden;
}
-.diamond-btn {
- margin-left: 24px;
- background: $white;
- width: 40px;
- height: 40px;
- display: flex;
- justify-content: center;
- align-items: center;
- border-radius: 4px;
- box-shadow: 0 2px 2px 0 rgba($black, 0.16), 0 1px 4px 0 rgba($black, 0.12);
- cursor: pointer;
- color: $gray-200;
- transform: rotate(45deg);
-
- &:hover:not(.create-btn) {
- color: $purple-400;
- box-shadow: 0 1px 8px 0 rgba($black, 0.12), 0 4px 4px 0 rgba($black, 0.16);
- }
-
- .svg-icon {
- width: 20px;
- height: 20px;
- transform: rotate(-45deg);
-
- &.icon-habit {
- width: 24px;
- height: 16px;
- }
-
- &.icon-daily {
- width: 21.6px;
- height: 18px;
- }
-
- &.icon-todo {
- width: 18px;
- height: 18px;
- }
-
- &.icon-reward {
- width: 23.4px;
- height: 18px;
- }
- }
-}
-
.create-btn {
color: $white;
- background-color: $green-100;
- height: 48px;
- width: 48px;
+ background-color: $purple-200;
+ height: 32px;
.svg-icon {
- width: 16px;
- height: 16px;
- transform: rotate(-45deg);
- transition: transform 0.3s cubic-bezier(0, 1, 0.5, 1);
- }
-
- &.open {
- background: $gray-200 !important;
-
- .svg-icon {
- transform: rotate(-90deg);
- }
+ color: $purple-500;
+ width: 10px;
+ height: 10px;
}
}
diff --git a/website/client/src/assets/scss/task.scss b/website/client/src/assets/scss/task.scss
index 4ff3a77810..dbd19622e3 100644
--- a/website/client/src/assets/scss/task.scss
+++ b/website/client/src/assets/scss/task.scss
@@ -30,7 +30,7 @@
&-bg {
background: $maroon-100 !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($black, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive { background: $maroon-100 !important; }
&-inner-habit { background: rgba($black, 0.25) !important; }
@@ -41,7 +41,7 @@
&-modal {
&-bg { background: $maroon-100 !important; }
- &-headings { color: $white; }
+ &-headings { color: $white !important; }
&-icon { color: $maroon-100 !important; }
&-text { color: $red-1 !important; }
&-content {
@@ -61,7 +61,7 @@
&-bg {
background: $red-100 !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($black, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive { background: $red-100 !important; }
&-inner-habit { background: rgba($black, 0.25) !important; }
@@ -92,7 +92,7 @@
&-bg {
background: $orange-100 !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($orange-1, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive { background: $orange-100 !important; }
&-inner-habit { background: rgba($orange-1, 0.25) !important; }
@@ -123,7 +123,7 @@
&-bg {
background: $yellow-100 !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($yellow-1, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive { background: $yellow-100 !important; }
&-inner-habit { background: rgba($yellow-1, 0.25) !important; }
@@ -154,7 +154,7 @@
&-bg {
background: $green-100 !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($black, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive { background: $green-100 !important; }
&-inner-habit { background: rgba($black, 0.25) !important; }
@@ -186,7 +186,7 @@
&-bg {
background: $teal-100 !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($black, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive { background: $teal-100 !important; }
&-inner-habit { background: rgba($black, 0.25) !important; }
@@ -217,7 +217,7 @@
&-bg {
background: $blue-100 !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($black, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive { background: $blue-100 !important; }
&-inner-habit { background: rgba($black, 0.25) !important; }
@@ -249,7 +249,7 @@
&-bg {
background: $purple-task !important;
.habit-control:not(.task-not-scoreable):hover { background: rgba($black, 0.5) !important; }
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-inner-habit { background: rgba($black, 0.25) !important; }
&-inner-daily-todo { background: rgba($white, 0.5) !important; }
@@ -258,7 +258,7 @@
&-modal {
&-bg { background: $purple-300 !important; }
- &-headings { color: $white; }
+ &-headings { color: $white !important; }
&-icon { color: $purple-300 !important; }
&-text { color: $black !important; }
&-content {
@@ -281,11 +281,11 @@
background: rgba($yellow-100, 0.15) !important;
.small-text { color: $yellow-1 !important; }
- &:hover { background: rgba($yellow-100, 0.25) !important; }
+ &:hover:not(.task-not-scoreable) { background: rgba($yellow-100, 0.25) !important; }
}
&-bg-noninteractive {
- background: rgba($yellow-100, 0.15) !important;
- .small-text { color: $yellow-1 !important; }
+ background-color: $gray-500 !important;
+ .small-text { color: $gray-100 !important; }
}
}
}
@@ -312,7 +312,7 @@
&-control {
&-bg {
background: $gray-200 !important;
- .daily-todo-control:hover { background: rgba($white, 0.75) !important; }
+ .daily-todo-control:not(.task-not-scoreable):hover { background: rgba($white, 0.75) !important; }
}
&-bg-noninteractive {
background: $gray-200 !important;
@@ -323,7 +323,7 @@
background: $gray-600;
.task-title, .task-notes {
- color: $gray-300 !important;
+ opacity: 0.75;
}
}
}
diff --git a/website/client/src/assets/svg/last-complete.svg b/website/client/src/assets/svg/last-complete.svg
new file mode 100644
index 0000000000..bda38f7415
--- /dev/null
+++ b/website/client/src/assets/svg/last-complete.svg
@@ -0,0 +1,3 @@
+
diff --git a/website/client/src/assets/svg/users.svg b/website/client/src/assets/svg/users.svg
index ca1d736b16..8d4d0ec37e 100644
--- a/website/client/src/assets/svg/users.svg
+++ b/website/client/src/assets/svg/users.svg
@@ -1,20 +1 @@
-
+
\ No newline at end of file
diff --git a/website/client/src/components/auth/registerLoginReset.vue b/website/client/src/components/auth/registerLoginReset.vue
index 60a08f3b70..890581ca5f 100644
--- a/website/client/src/components/auth/registerLoginReset.vue
+++ b/website/client/src/components/auth/registerLoginReset.vue
@@ -757,8 +757,7 @@ export default {
}, 500),
sanitizeRedirect (redirect) {
if (!redirect) return '/';
- let sanitizedString = DOMPurify.sanitize(redirect).replace(/\\|\/\/|\./g, '');
- sanitizedString = `/${sanitizedString}`;
+ const sanitizedString = DOMPurify.sanitize(redirect).replace(/\\|\/\/|\./g, '');
return sanitizedString;
},
async register () {
diff --git a/website/client/src/components/challenges/groupChallenges.vue b/website/client/src/components/challenges/groupChallenges.vue
index 6a19e34700..fc370700c8 100644
--- a/website/client/src/components/challenges/groupChallenges.vue
+++ b/website/client/src/components/challenges/groupChallenges.vue
@@ -112,10 +112,8 @@ export default {
},
},
watch: {
- 'group._id': {
- async groupId () {
- this.loadChallenges();
- },
+ 'group._id': function groupId () {
+ this.loadChallenges();
},
},
mounted () {
diff --git a/website/client/src/components/group-plans/groupPlansUpdateModal.vue b/website/client/src/components/group-plans/groupPlansUpdateModal.vue
new file mode 100644
index 0000000000..30205a0576
--- /dev/null
+++ b/website/client/src/components/group-plans/groupPlansUpdateModal.vue
@@ -0,0 +1,204 @@
+
+
+ {{ $t('newGroupsWelcome') }}
+
+
+
+
+ {{ $t('newGroupsWhatsNew') }}
+
+
+
+
+
+
+
+
+
+
+