mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 07:37:25 +01:00
Merge remote-tracking branch 'origin/due-dates-in-todos' into due-dates-in-todos
This commit is contained in:
Submodule habitica-images updated: 311cb01059...dac6a71d1f
1075
package-lock.json
generated
1075
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||||
"version": "4.269.0",
|
"version": "4.270.1",
|
||||||
"main": "./website/server/index.js",
|
"main": "./website/server/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.21.4",
|
"@babel/core": "^7.21.8",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.21.5",
|
||||||
"@babel/register": "^7.21.0",
|
"@babel/register": "^7.21.0",
|
||||||
"@google-cloud/trace-agent": "^7.1.2",
|
"@google-cloud/trace-agent": "^7.1.2",
|
||||||
"@parse/node-apn": "^5.1.3",
|
"@parse/node-apn": "^5.1.3",
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
"image-size": "^1.0.2",
|
"image-size": "^1.0.2",
|
||||||
"in-app-purchase": "^1.11.3",
|
"in-app-purchase": "^1.11.3",
|
||||||
"js2xmlparser": "^5.0.0",
|
"js2xmlparser": "^5.0.0",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"jwks-rsa": "^2.1.5",
|
"jwks-rsa": "^2.1.5",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"merge-stream": "^2.0.0",
|
"merge-stream": "^2.0.0",
|
||||||
@@ -67,8 +67,8 @@
|
|||||||
"remove-markdown": "^0.5.0",
|
"remove-markdown": "^0.5.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"short-uuid": "^4.2.2",
|
"short-uuid": "^4.2.2",
|
||||||
"stripe": "^11.10.0",
|
"stripe": "^12.5.0",
|
||||||
"superagent": "^8.0.6",
|
"superagent": "^8.0.9",
|
||||||
"universal-analytics": "^0.5.3",
|
"universal-analytics": "^0.5.3",
|
||||||
"useragent": "^2.1.9",
|
"useragent": "^2.1.9",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ describe('cron middleware', () => {
|
|||||||
|
|
||||||
sandbox.spy(cronLib, 'recoverCron');
|
sandbox.spy(cronLib, 'recoverCron');
|
||||||
|
|
||||||
sandbox.stub(User, 'update')
|
sandbox.stub(User, 'updateOne')
|
||||||
.withArgs({
|
.withArgs({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
$or: [
|
$or: [
|
||||||
|
|||||||
@@ -1732,7 +1732,7 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('updates participting members (not including user)', async () => {
|
it('updates participting members (not including user)', async () => {
|
||||||
sandbox.spy(User, 'update');
|
sandbox.spy(User, 'updateMany');
|
||||||
|
|
||||||
await party.startQuest(nonParticipatingMember);
|
await party.startQuest(nonParticipatingMember);
|
||||||
|
|
||||||
@@ -1740,7 +1740,7 @@ describe('Group Model', () => {
|
|||||||
questLeader._id, participatingMember._id, sleepingParticipatingMember._id,
|
questLeader._id, participatingMember._id, sleepingParticipatingMember._id,
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(User.update).to.be.calledWith(
|
expect(User.updateMany).to.be.calledWith(
|
||||||
{ _id: { $in: members } },
|
{ _id: { $in: members } },
|
||||||
{
|
{
|
||||||
$set: {
|
$set: {
|
||||||
@@ -1753,11 +1753,11 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('updates non-user quest leader and decrements quest scroll', async () => {
|
it('updates non-user quest leader and decrements quest scroll', async () => {
|
||||||
sandbox.spy(User, 'update');
|
sandbox.spy(User, 'updateOne');
|
||||||
|
|
||||||
await party.startQuest(participatingMember);
|
await party.startQuest(participatingMember);
|
||||||
|
|
||||||
expect(User.update).to.be.calledWith(
|
expect(User.updateOne).to.be.calledWith(
|
||||||
{ _id: questLeader._id },
|
{ _id: questLeader._id },
|
||||||
{
|
{
|
||||||
$inc: {
|
$inc: {
|
||||||
@@ -1819,29 +1819,29 @@ describe('Group Model', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
it('doesn\'t retry successful operations', async () => {
|
it('doesn\'t retry successful operations', async () => {
|
||||||
sandbox.stub(User, 'update').returns(successfulMock);
|
sandbox.stub(User, 'updateOne').returns(successfulMock);
|
||||||
|
|
||||||
await party.finishQuest(quest);
|
await party.finishQuest(quest);
|
||||||
|
|
||||||
expect(User.update).to.be.calledThrice;
|
expect(User.updateOne).to.be.calledThrice;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('stops retrying when a successful update has occurred', async () => {
|
it('stops retrying when a successful update has occurred', async () => {
|
||||||
const updateStub = sandbox.stub(User, 'update');
|
const updateStub = sandbox.stub(User, 'updateOne');
|
||||||
updateStub.onCall(0).returns(failedMock);
|
updateStub.onCall(0).returns(failedMock);
|
||||||
updateStub.returns(successfulMock);
|
updateStub.returns(successfulMock);
|
||||||
|
|
||||||
await party.finishQuest(quest);
|
await party.finishQuest(quest);
|
||||||
|
|
||||||
expect(User.update.callCount).to.equal(4);
|
expect(User.updateOne.callCount).to.equal(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('retries failed updates at most five times per user', async () => {
|
it('retries failed updates at most five times per user', async () => {
|
||||||
sandbox.stub(User, 'update').returns(failedMock);
|
sandbox.stub(User, 'updateOne').returns(failedMock);
|
||||||
|
|
||||||
await expect(party.finishQuest(quest)).to.eventually.be.rejected;
|
await expect(party.finishQuest(quest)).to.eventually.be.rejected;
|
||||||
|
|
||||||
expect(User.update.callCount).to.eql(15); // for 3 users
|
expect(User.updateOne.callCount).to.eql(15); // for 3 users
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2088,17 +2088,17 @@ describe('Group Model', () => {
|
|||||||
|
|
||||||
context('Party quests', () => {
|
context('Party quests', () => {
|
||||||
it('updates participating members with rewards', async () => {
|
it('updates participating members with rewards', async () => {
|
||||||
sandbox.spy(User, 'update');
|
sandbox.spy(User, 'updateOne');
|
||||||
await party.finishQuest(quest);
|
await party.finishQuest(quest);
|
||||||
|
|
||||||
expect(User.update).to.be.calledThrice;
|
expect(User.updateOne).to.be.calledThrice;
|
||||||
expect(User.update).to.be.calledWithMatch({
|
expect(User.updateOne).to.be.calledWithMatch({
|
||||||
_id: questLeader._id,
|
_id: questLeader._id,
|
||||||
});
|
});
|
||||||
expect(User.update).to.be.calledWithMatch({
|
expect(User.updateOne).to.be.calledWithMatch({
|
||||||
_id: participatingMember._id,
|
_id: participatingMember._id,
|
||||||
});
|
});
|
||||||
expect(User.update).to.be.calledWithMatch({
|
expect(User.updateOne).to.be.calledWithMatch({
|
||||||
_id: sleepingParticipatingMember._id,
|
_id: sleepingParticipatingMember._id,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -2173,11 +2173,11 @@ describe('Group Model', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('updates all users with rewards', async () => {
|
it('updates all users with rewards', async () => {
|
||||||
sandbox.spy(User, 'update');
|
sandbox.spy(User, 'updateMany');
|
||||||
await party.finishQuest(tavernQuest);
|
await party.finishQuest(tavernQuest);
|
||||||
|
|
||||||
expect(User.update).to.be.calledOnce;
|
expect(User.updateMany).to.be.calledOnce;
|
||||||
expect(User.update).to.be.calledWithMatch({});
|
expect(User.updateMany).to.be.calledWithMatch({});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets quest completed to the world quest key', async () => {
|
it('sets quest completed to the world quest key', async () => {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { v4 as generateUUID } from 'uuid';
|
|||||||
import {
|
import {
|
||||||
generateUser,
|
generateUser,
|
||||||
createAndPopulateGroup,
|
createAndPopulateGroup,
|
||||||
checkExistence,
|
|
||||||
translate as t,
|
translate as t,
|
||||||
} from '../../../../helpers/api-integration/v3';
|
} from '../../../../helpers/api-integration/v3';
|
||||||
|
|
||||||
|
|||||||
@@ -626,7 +626,8 @@ describe('Post /groups/:groupId/invite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('party size limits', () => {
|
describe('party size limits', () => {
|
||||||
let party, partyLeader;
|
let party;
|
||||||
|
let partyLeader;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
group = await createAndPopulateGroup({
|
group = await createAndPopulateGroup({
|
||||||
|
|||||||
@@ -202,18 +202,86 @@ describe('POST /user/class/cast/:spellId', () => {
|
|||||||
await group.groupLeader.post('/user/class/cast/mpheal');
|
await group.groupLeader.post('/user/class/cast/mpheal');
|
||||||
|
|
||||||
promises = [];
|
promises = [];
|
||||||
|
promises.push(group.groupLeader.sync());
|
||||||
promises.push(group.members[0].sync());
|
promises.push(group.members[0].sync());
|
||||||
promises.push(group.members[1].sync());
|
promises.push(group.members[1].sync());
|
||||||
promises.push(group.members[2].sync());
|
promises.push(group.members[2].sync());
|
||||||
promises.push(group.members[3].sync());
|
promises.push(group.members[3].sync());
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
expect(group.groupLeader.stats.mp).to.be.equal(170); // spell caster
|
||||||
expect(group.members[0].stats.mp).to.be.greaterThan(0); // warrior
|
expect(group.members[0].stats.mp).to.be.greaterThan(0); // warrior
|
||||||
expect(group.members[1].stats.mp).to.equal(0); // wizard
|
expect(group.members[1].stats.mp).to.equal(0); // wizard
|
||||||
expect(group.members[2].stats.mp).to.be.greaterThan(0); // rogue
|
expect(group.members[2].stats.mp).to.be.greaterThan(0); // rogue
|
||||||
expect(group.members[3].stats.mp).to.be.greaterThan(0); // healer
|
expect(group.members[3].stats.mp).to.be.greaterThan(0); // healer
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const spellList = [
|
||||||
|
{
|
||||||
|
className: 'warrior',
|
||||||
|
spells: [['smash', 'task'], ['defensiveStance'], ['valorousPresence'], ['intimidate']],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'wizard',
|
||||||
|
spells: [['fireball', 'task'], ['mpheal'], ['earth'], ['frost']],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'healer',
|
||||||
|
spells: [['heal'], ['brightness'], ['protectAura'], ['healAll']],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'rogue',
|
||||||
|
spells: [['pickPocket', 'task'], ['backStab', 'task'], ['toolsOfTrade'], ['stealth']],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
spellList.forEach(async habitClass => {
|
||||||
|
describe(`For a ${habitClass.className}`, async () => {
|
||||||
|
habitClass.spells.forEach(async spell => {
|
||||||
|
describe(`Using ${spell[0]}`, async () => {
|
||||||
|
it('Deducts MP from spell caster', async () => {
|
||||||
|
const { groupLeader } = await createAndPopulateGroup({
|
||||||
|
groupDetails: { type: 'party', privacy: 'private' },
|
||||||
|
members: 3,
|
||||||
|
});
|
||||||
|
await groupLeader.update({
|
||||||
|
'stats.mp': 200, 'stats.class': habitClass.className, 'stats.lvl': 20, 'stats.hp': 40,
|
||||||
|
});
|
||||||
|
// need this for task spells and for stealth
|
||||||
|
const task = await groupLeader.post('/tasks/user', {
|
||||||
|
text: 'test habit',
|
||||||
|
type: 'daily',
|
||||||
|
});
|
||||||
|
if (spell.length === 2 && spell[1] === 'task') {
|
||||||
|
await groupLeader.post(`/user/class/cast/${spell[0]}?targetId=${task._id}`);
|
||||||
|
} else {
|
||||||
|
await groupLeader.post(`/user/class/cast/${spell[0]}`);
|
||||||
|
}
|
||||||
|
await groupLeader.sync();
|
||||||
|
expect(groupLeader.stats.mp).to.be.lessThan(200);
|
||||||
|
});
|
||||||
|
it('works without a party', async () => {
|
||||||
|
await user.update({
|
||||||
|
'stats.mp': 200, 'stats.class': habitClass.className, 'stats.lvl': 20, 'stats.hp': 40,
|
||||||
|
});
|
||||||
|
// need this for task spells and for stealth
|
||||||
|
const task = await user.post('/tasks/user', {
|
||||||
|
text: 'test habit',
|
||||||
|
type: 'daily',
|
||||||
|
});
|
||||||
|
if (spell.length === 2 && spell[1] === 'task') {
|
||||||
|
await user.post(`/user/class/cast/${spell[0]}?targetId=${task._id}`);
|
||||||
|
} else {
|
||||||
|
await user.post(`/user/class/cast/${spell[0]}`);
|
||||||
|
}
|
||||||
|
await user.sync();
|
||||||
|
expect(user.stats.mp).to.be.lessThan(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('cast bulk', async () => {
|
it('cast bulk', async () => {
|
||||||
let { group, groupLeader } = await createAndPopulateGroup({ // eslint-disable-line prefer-const
|
let { group, groupLeader } = await createAndPopulateGroup({ // eslint-disable-line prefer-const
|
||||||
groupDetails: { type: 'party', privacy: 'private' },
|
groupDetails: { type: 'party', privacy: 'private' },
|
||||||
|
|||||||
71
website/client/package-lock.json
generated
71
website/client/package-lock.json
generated
@@ -16901,9 +16901,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"core-js": {
|
"core-js": {
|
||||||
"version": "3.30.1",
|
"version": "3.30.2",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz",
|
||||||
"integrity": "sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ=="
|
"integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg=="
|
||||||
},
|
},
|
||||||
"core-js-compat": {
|
"core-js-compat": {
|
||||||
"version": "3.11.0",
|
"version": "3.11.0",
|
||||||
@@ -17952,9 +17952,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dompurify": {
|
"dompurify": {
|
||||||
"version": "2.4.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
|
||||||
"integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
|
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
|
||||||
},
|
},
|
||||||
"domutils": {
|
"domutils": {
|
||||||
"version": "1.7.0",
|
"version": "1.7.0",
|
||||||
@@ -21071,6 +21071,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
||||||
},
|
},
|
||||||
|
"immutable": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg=="
|
||||||
|
},
|
||||||
"import-cwd": {
|
"import-cwd": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
||||||
@@ -21431,9 +21436,9 @@
|
|||||||
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="
|
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="
|
||||||
},
|
},
|
||||||
"intro.js": {
|
"intro.js": {
|
||||||
"version": "6.0.0",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/intro.js/-/intro.js-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/intro.js/-/intro.js-7.0.1.tgz",
|
||||||
"integrity": "sha512-ZUiR6BoLSvPSlLG0boewnWVgji1fE1gBvP/pyw5pgCKXEDQz1mMeUxarggClPNs71UTq364LwSk9zxz17A9gaQ=="
|
"integrity": "sha512-1oqz6aOz9cGQ3CrtVYhCSo6AkjnXUn302kcIWLaZ3TI4kKssRXDwDSz4VRoGcfC1jN+WfaSJXRBrITz+QVEBzg=="
|
||||||
},
|
},
|
||||||
"invariant": {
|
"invariant": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
@@ -22013,9 +22018,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jquery": {
|
"jquery": {
|
||||||
"version": "3.6.4",
|
"version": "3.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.4.tgz",
|
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz",
|
||||||
"integrity": "sha512-v28EW9DWDFpzcD9O5iyJXg3R3+q+mET5JhnjJzQUZMHOv67bpSIHq81GEYpPNZHG+XXHsfSme3nxp/hndKEcsQ=="
|
"integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ=="
|
||||||
},
|
},
|
||||||
"js-message": {
|
"js-message": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
@@ -27361,17 +27366,19 @@
|
|||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
"sass": {
|
"sass": {
|
||||||
"version": "1.34.0",
|
"version": "1.62.1",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz",
|
||||||
"integrity": "sha512-rHEN0BscqjUYuomUEaqq3BMgsXqQfkcMVR7UhscsAVub0/spUrZGBMxQXFS2kfiDsPLZw5yuU9iJEFNC2x38Qw==",
|
"integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chokidar": ">=3.0.0 <4.0.0"
|
"chokidar": ">=3.0.0 <4.0.0",
|
||||||
|
"immutable": "^4.0.0",
|
||||||
|
"source-map-js": ">=0.6.2 <2.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": {
|
"anymatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"picomatch": "^2.0.4"
|
"picomatch": "^2.0.4"
|
||||||
@@ -27391,18 +27398,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "3.5.1",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
|
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
"fsevents": "~2.3.1",
|
"fsevents": "~2.3.2",
|
||||||
"glob-parent": "~5.1.0",
|
"glob-parent": "~5.1.2",
|
||||||
"is-binary-path": "~2.1.0",
|
"is-binary-path": "~2.1.0",
|
||||||
"is-glob": "~4.0.1",
|
"is-glob": "~4.0.1",
|
||||||
"normalize-path": "~3.0.0",
|
"normalize-path": "~3.0.0",
|
||||||
"readdirp": "~3.5.0"
|
"readdirp": "~3.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fill-range": {
|
"fill-range": {
|
||||||
@@ -27441,9 +27448,9 @@
|
|||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
|
||||||
},
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"picomatch": "^2.2.1"
|
"picomatch": "^2.2.1"
|
||||||
}
|
}
|
||||||
@@ -30265,9 +30272,9 @@
|
|||||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "8.3.2",
|
"version": "9.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
|
||||||
},
|
},
|
||||||
"uuid-browser": {
|
"uuid-browser": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
|
|||||||
@@ -32,8 +32,8 @@
|
|||||||
"bootstrap": "^4.6.0",
|
"bootstrap": "^4.6.0",
|
||||||
"bootstrap-vue": "^2.23.1",
|
"bootstrap-vue": "^2.23.1",
|
||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"core-js": "^3.30.1",
|
"core-js": "^3.30.2",
|
||||||
"dompurify": "^2.4.3",
|
"dompurify": "^3.0.3",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-habitrpg": "^6.2.0",
|
"eslint-config-habitrpg": "^6.2.0",
|
||||||
"eslint-plugin-mocha": "^5.3.0",
|
"eslint-plugin-mocha": "^5.3.0",
|
||||||
@@ -41,12 +41,12 @@
|
|||||||
"habitica-markdown": "^3.0.0",
|
"habitica-markdown": "^3.0.0",
|
||||||
"hellojs": "^1.20.0",
|
"hellojs": "^1.20.0",
|
||||||
"inspectpack": "^4.7.1",
|
"inspectpack": "^4.7.1",
|
||||||
"intro.js": "^6.0.0",
|
"intro.js": "^7.0.1",
|
||||||
"jquery": "^3.6.4",
|
"jquery": "^3.7.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"nconf": "^0.12.0",
|
"nconf": "^0.12.0",
|
||||||
"sass": "^1.34.0",
|
"sass": "^1.62.1",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^8.0.2",
|
||||||
"smartbanner.js": "^1.19.2",
|
"smartbanner.js": "^1.19.2",
|
||||||
"stopword": "^2.0.8",
|
"stopword": "^2.0.8",
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
"svg-url-loader": "^7.1.1",
|
"svg-url-loader": "^7.1.1",
|
||||||
"svgo": "^1.3.2",
|
"svgo": "^1.3.2",
|
||||||
"svgo-loader": "^2.2.1",
|
"svgo-loader": "^2.2.1",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^9.0.0",
|
||||||
"validator": "^13.9.0",
|
"validator": "^13.9.0",
|
||||||
"vue": "^2.7.10",
|
"vue": "^2.7.10",
|
||||||
"vue-cli-plugin-storybook": "2.1.0",
|
"vue-cli-plugin-storybook": "2.1.0",
|
||||||
|
|||||||
@@ -820,6 +820,11 @@
|
|||||||
width: 141px;
|
width: 141px;
|
||||||
height: 147px;
|
height: 147px;
|
||||||
}
|
}
|
||||||
|
.background_cretaceous_forest {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_cretaceous_forest.png');
|
||||||
|
width: 141px;
|
||||||
|
height: 147px;
|
||||||
|
}
|
||||||
.background_crosscountry_ski_trail {
|
.background_crosscountry_ski_trail {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_crosscountry_ski_trail.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_crosscountry_ski_trail.png');
|
||||||
width: 141px;
|
width: 141px;
|
||||||
@@ -1054,6 +1059,11 @@
|
|||||||
width: 141px;
|
width: 141px;
|
||||||
height: 147px;
|
height: 147px;
|
||||||
}
|
}
|
||||||
|
.background_flying_over_hedge_maze {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_flying_over_hedge_maze.png');
|
||||||
|
width: 141px;
|
||||||
|
height: 147px;
|
||||||
|
}
|
||||||
.background_flying_over_icy_steppes {
|
.background_flying_over_icy_steppes {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_flying_over_icy_steppes.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_flying_over_icy_steppes.png');
|
||||||
width: 141px;
|
width: 141px;
|
||||||
@@ -1329,6 +1339,11 @@
|
|||||||
width: 141px;
|
width: 141px;
|
||||||
height: 147px;
|
height: 147px;
|
||||||
}
|
}
|
||||||
|
.background_in_a_painting {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_in_a_painting.png');
|
||||||
|
width: 141px;
|
||||||
|
height: 147px;
|
||||||
|
}
|
||||||
.background_in_an_ancient_tomb {
|
.background_in_an_ancient_tomb {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_in_an_ancient_tomb.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_in_an_ancient_tomb.png');
|
||||||
width: 141px;
|
width: 141px;
|
||||||
@@ -2506,6 +2521,11 @@
|
|||||||
width: 68px;
|
width: 68px;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
}
|
}
|
||||||
|
.icon_background_cretaceous_forest {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_cretaceous_forest.png');
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
}
|
||||||
.icon_background_crosscountry_ski_trail {
|
.icon_background_crosscountry_ski_trail {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_crosscountry_ski_trail.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_crosscountry_ski_trail.png');
|
||||||
width: 68px;
|
width: 68px;
|
||||||
@@ -2740,6 +2760,11 @@
|
|||||||
width: 68px;
|
width: 68px;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
}
|
}
|
||||||
|
.icon_background_flying_over_hedge_maze {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_flying_over_hedge_maze.png');
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
}
|
||||||
.icon_background_flying_over_icy_steppes {
|
.icon_background_flying_over_icy_steppes {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_flying_over_icy_steppes.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_flying_over_icy_steppes.png');
|
||||||
width: 68px;
|
width: 68px;
|
||||||
@@ -3015,6 +3040,11 @@
|
|||||||
width: 68px;
|
width: 68px;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
}
|
}
|
||||||
|
.icon_background_in_a_painting {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_in_a_painting.png');
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
}
|
||||||
.icon_background_in_an_ancient_tomb {
|
.icon_background_in_an_ancient_tomb {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_in_an_ancient_tomb.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_in_an_ancient_tomb.png');
|
||||||
width: 68px;
|
width: 68px;
|
||||||
@@ -18640,6 +18670,11 @@
|
|||||||
width: 90px;
|
width: 90px;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
}
|
}
|
||||||
|
.broad_armor_armoire_paintersApron {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_paintersApron.png');
|
||||||
|
width: 114px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
.broad_armor_armoire_pirateOutfit {
|
.broad_armor_armoire_pirateOutfit {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_pirateOutfit.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_pirateOutfit.png');
|
||||||
width: 114px;
|
width: 114px;
|
||||||
@@ -19130,6 +19165,11 @@
|
|||||||
width: 90px;
|
width: 90px;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
}
|
}
|
||||||
|
.head_armoire_paintersBeret {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_armoire_paintersBeret.png');
|
||||||
|
width: 114px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
.head_armoire_paperBag {
|
.head_armoire_paperBag {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_armoire_paperBag.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_armoire_paperBag.png');
|
||||||
width: 90px;
|
width: 90px;
|
||||||
@@ -19470,6 +19510,11 @@
|
|||||||
width: 90px;
|
width: 90px;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
}
|
}
|
||||||
|
.shield_armoire_paintersPalette {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_armoire_paintersPalette.png');
|
||||||
|
width: 114px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
.shield_armoire_perchingFalcon {
|
.shield_armoire_perchingFalcon {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_armoire_perchingFalcon.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_armoire_perchingFalcon.png');
|
||||||
width: 90px;
|
width: 90px;
|
||||||
@@ -19910,6 +19955,11 @@
|
|||||||
width: 68px;
|
width: 68px;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
}
|
}
|
||||||
|
.shop_armor_armoire_paintersApron {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_paintersApron.png');
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
}
|
||||||
.shop_armor_armoire_pirateOutfit {
|
.shop_armor_armoire_pirateOutfit {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_pirateOutfit.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_pirateOutfit.png');
|
||||||
width: 68px;
|
width: 68px;
|
||||||
@@ -20415,6 +20465,11 @@
|
|||||||
width: 68px;
|
width: 68px;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
}
|
}
|
||||||
|
.shop_head_armoire_paintersBeret {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_armoire_paintersBeret.png');
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
}
|
||||||
.shop_head_armoire_paperBag {
|
.shop_head_armoire_paperBag {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_armoire_paperBag.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_armoire_paperBag.png');
|
||||||
width: 68px;
|
width: 68px;
|
||||||
@@ -20755,6 +20810,11 @@
|
|||||||
width: 68px;
|
width: 68px;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
}
|
}
|
||||||
|
.shop_shield_armoire_paintersPalette {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_armoire_paintersPalette.png');
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
}
|
||||||
.shop_shield_armoire_perchingFalcon {
|
.shop_shield_armoire_perchingFalcon {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_armoire_perchingFalcon.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_armoire_perchingFalcon.png');
|
||||||
width: 68px;
|
width: 68px;
|
||||||
@@ -21200,6 +21260,11 @@
|
|||||||
width: 68px;
|
width: 68px;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
}
|
}
|
||||||
|
.shop_weapon_armoire_paintbrush {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_armoire_paintbrush.png');
|
||||||
|
width: 68px;
|
||||||
|
height: 68px;
|
||||||
|
}
|
||||||
.shop_weapon_armoire_paperCutter {
|
.shop_weapon_armoire_paperCutter {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_armoire_paperCutter.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_armoire_paperCutter.png');
|
||||||
width: 68px;
|
width: 68px;
|
||||||
@@ -21655,6 +21720,11 @@
|
|||||||
width: 90px;
|
width: 90px;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
}
|
}
|
||||||
|
.slim_armor_armoire_paintersApron {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_paintersApron.png');
|
||||||
|
width: 114px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
.slim_armor_armoire_pirateOutfit {
|
.slim_armor_armoire_pirateOutfit {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_pirateOutfit.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_pirateOutfit.png');
|
||||||
width: 114px;
|
width: 114px;
|
||||||
@@ -22110,6 +22180,11 @@
|
|||||||
width: 114px;
|
width: 114px;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
}
|
}
|
||||||
|
.weapon_armoire_paintbrush {
|
||||||
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_armoire_paintbrush.png');
|
||||||
|
width: 114px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
.weapon_armoire_paperCutter {
|
.weapon_armoire_paperCutter {
|
||||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_armoire_paperCutter.png');
|
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_armoire_paperCutter.png');
|
||||||
width: 114px;
|
width: 114px;
|
||||||
|
|||||||
@@ -264,12 +264,6 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.seeking = Boolean(this.user.party.seeking);
|
this.seeking = Boolean(this.user.party.seeking);
|
||||||
Analytics.track({
|
|
||||||
eventName: 'Start a Party button',
|
|
||||||
eventAction: 'Start a Party button',
|
|
||||||
eventCategory: 'behavior',
|
|
||||||
hitType: 'event',
|
|
||||||
}, { trackOnClient: true });
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createParty () {
|
async createParty () {
|
||||||
|
|||||||
@@ -243,8 +243,6 @@ import rogueIcon from '@/assets/svg/rogue.svg';
|
|||||||
import healerIcon from '@/assets/svg/healer.svg';
|
import healerIcon from '@/assets/svg/healer.svg';
|
||||||
import wizardIcon from '@/assets/svg/wizard.svg';
|
import wizardIcon from '@/assets/svg/wizard.svg';
|
||||||
|
|
||||||
import * as Analytics from '@/libs/analytics';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Avatar,
|
Avatar,
|
||||||
@@ -287,12 +285,6 @@ export default {
|
|||||||
section: this.$t('lookingForPartyTitle'),
|
section: this.$t('lookingForPartyTitle'),
|
||||||
});
|
});
|
||||||
this.seekers = await this.$store.dispatch('party:lookingForParty');
|
this.seekers = await this.$store.dispatch('party:lookingForParty');
|
||||||
await Analytics.track({
|
|
||||||
hitType: 'event',
|
|
||||||
eventName: 'View Find Members',
|
|
||||||
eventAction: 'View Find Members',
|
|
||||||
eventCategory: 'behavior',
|
|
||||||
}, { trackOnClient: true });
|
|
||||||
this.canLoadMore = this.seekers.length === 30;
|
this.canLoadMore = this.seekers.length === 30;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
|
import * as Analytics from '@/libs/analytics';
|
||||||
import { mapGetters, mapActions } from '@/libs/store';
|
import { mapGetters, mapActions } from '@/libs/store';
|
||||||
import MemberDetails from '../memberDetails';
|
import MemberDetails from '../memberDetails';
|
||||||
import createPartyModal from '../groups/createPartyModal';
|
import createPartyModal from '../groups/createPartyModal';
|
||||||
@@ -232,10 +233,24 @@ export default {
|
|||||||
this.expandedMember = memberId;
|
this.expandedMember = memberId;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createOrInviteParty () {
|
async createOrInviteParty () {
|
||||||
if (this.user.party._id) {
|
if (this.user.party._id) {
|
||||||
|
await Analytics.track({
|
||||||
|
eventName: 'Header Party CTA',
|
||||||
|
eventAction: 'Header Party CTA',
|
||||||
|
eventCategory: 'behavior',
|
||||||
|
hitType: 'event',
|
||||||
|
state: 'Find Party Members',
|
||||||
|
});
|
||||||
this.$router.push('/looking-for-party');
|
this.$router.push('/looking-for-party');
|
||||||
} else {
|
} else {
|
||||||
|
await Analytics.track({
|
||||||
|
eventName: 'Header Party CTA',
|
||||||
|
eventAction: 'Header Party CTA',
|
||||||
|
eventCategory: 'behavior',
|
||||||
|
hitType: 'event',
|
||||||
|
state: 'Get Started',
|
||||||
|
});
|
||||||
this.$root.$emit('bv::show::modal', 'create-party-modal');
|
this.$root.$emit('bv::show::modal', 'create-party-modal');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -144,22 +144,6 @@
|
|||||||
>{{ $t('startAdvCollapsed') }}</span>
|
>{{ $t('startAdvCollapsed') }}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
v-model="user.preferences.dailyDueDefaultView"
|
|
||||||
type="checkbox"
|
|
||||||
class="mr-2"
|
|
||||||
@change="set('dailyDueDefaultView')"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="hint"
|
|
||||||
popover-trigger="mouseenter"
|
|
||||||
popover-placement="right"
|
|
||||||
:popover="$t('dailyDueDefaultViewPop')"
|
|
||||||
>{{ $t('dailyDueDefaultView') }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-if="party.memberCount === 1"
|
v-if="party.memberCount === 1"
|
||||||
class="checkbox"
|
class="checkbox"
|
||||||
|
|||||||
@@ -521,7 +521,12 @@ export default {
|
|||||||
// Get Category Filter Labels
|
// Get Category Filter Labels
|
||||||
this.typeFilters = getFilterLabels(this.type, this.challenge);
|
this.typeFilters = getFilterLabels(this.type, this.challenge);
|
||||||
// Set default filter for task column
|
// Set default filter for task column
|
||||||
this.activateFilter(this.type);
|
|
||||||
|
if (this.challenge) {
|
||||||
|
this.activateFilter(this.type);
|
||||||
|
} else {
|
||||||
|
this.activateFilter(this.type, this.user.preferences.tasks.activeFilter[this.type], true);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.setColumnBackgroundVisibility();
|
this.setColumnBackgroundVisibility();
|
||||||
@@ -661,7 +666,7 @@ export default {
|
|||||||
taskSummary (task) {
|
taskSummary (task) {
|
||||||
this.$emit('taskSummary', task);
|
this.$emit('taskSummary', task);
|
||||||
},
|
},
|
||||||
activateFilter (type, filter = '') {
|
activateFilter (type, filter = '', skipSave = false) {
|
||||||
// Needs a separate API call as this data may not reside in store
|
// Needs a separate API call as this data may not reside in store
|
||||||
if (type === 'todo' && filter === 'complete2') {
|
if (type === 'todo' && filter === 'complete2') {
|
||||||
if (this.group && this.group._id) {
|
if (this.group && this.group._id) {
|
||||||
@@ -677,14 +682,16 @@ export default {
|
|||||||
// as default filter for daily
|
// as default filter for daily
|
||||||
// and set the filter as 'due' only when the component first
|
// and set the filter as 'due' only when the component first
|
||||||
// loads and not on subsequent reloads.
|
// loads and not on subsequent reloads.
|
||||||
if (
|
if (type === 'daily' && filter === '' && !this.challenge) {
|
||||||
type === 'daily' && filter === '' && !this.challenge
|
|
||||||
&& this.user.preferences.dailyDueDefaultView
|
|
||||||
) {
|
|
||||||
filter = 'due'; // eslint-disable-line no-param-reassign
|
filter = 'due'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activeFilter = getActiveFilter(type, filter, this.challenge);
|
this.activeFilter = getActiveFilter(type, filter, this.challenge);
|
||||||
|
|
||||||
|
if (!skipSave && !this.challenge) {
|
||||||
|
const propertyToUpdate = `preferences.tasks.activeFilter.${type}`;
|
||||||
|
this.$store.dispatch('user:set', { [propertyToUpdate]: filter });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setColumnBackgroundVisibility () {
|
setColumnBackgroundVisibility () {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
'groupTask': task.group.id,
|
'groupTask': task.group.id,
|
||||||
'task-not-editable': !teamManagerAccess,
|
'task-not-editable': !teamManagerAccess,
|
||||||
'task-not-scoreable': showTaskLockIcon,
|
'task-not-scoreable': showTaskLockIcon,
|
||||||
|
'link-exempt': !isChallengeTask && !isGroupTask,
|
||||||
}, `type_${task.type}`
|
}, `type_${task.type}`
|
||||||
]"
|
]"
|
||||||
@click="castEnd($event, task)"
|
@click="castEnd($event, task)"
|
||||||
|
|||||||
@@ -110,7 +110,9 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
updated () {
|
updated () {
|
||||||
this.handleExternalLinks();
|
window.setTimeout(() => {
|
||||||
|
this.handleExternalLinks();
|
||||||
|
}, 500);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({ user: 'user.data' }),
|
...mapState({ user: 'user.data' }),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((link.classList.value.indexOf('external-link') === -1)
|
if ((link.classList.value.indexOf('external-link') === -1)
|
||||||
|
&& (!link.offsetParent || link.offsetParent.classList.value.indexOf('link-exempt') === -1)
|
||||||
&& domainIndex !== 1
|
&& domainIndex !== 1
|
||||||
&& !some(TRUSTED_DOMAINS.split(','), domain => link.href.indexOf(domain) === domainIndex)) {
|
&& !some(TRUSTED_DOMAINS.split(','), domain => link.href.indexOf(domain) === domainIndex)) {
|
||||||
link.classList.add('external-link');
|
link.classList.add('external-link');
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export default {
|
|||||||
this.castCancel();
|
this.castCancel();
|
||||||
|
|
||||||
// the selected member doesn't have the flags property which sets `cardReceived`
|
// the selected member doesn't have the flags property which sets `cardReceived`
|
||||||
if (spell.pinType !== 'card') {
|
if (spell.pinType !== 'card' && spell.bulk !== true) {
|
||||||
try {
|
try {
|
||||||
spell.cast(this.user, target, {});
|
spell.cast(this.user, target, {});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VueRouter from 'vue-router';
|
import VueRouter from 'vue-router';
|
||||||
|
import * as Analytics from '@/libs/analytics';
|
||||||
import getStore from '@/store';
|
import getStore from '@/store';
|
||||||
import handleRedirect from './handleRedirect';
|
import handleRedirect from './handleRedirect';
|
||||||
|
|
||||||
@@ -439,6 +440,15 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
router.app.$root.$emit('update-party');
|
router.app.$root.$emit('update-party');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (to.name === 'lookingForParty') {
|
||||||
|
Analytics.track({
|
||||||
|
hitType: 'event',
|
||||||
|
eventName: 'View Find Members',
|
||||||
|
eventAction: 'View Find Members',
|
||||||
|
eventCategory: 'behavior',
|
||||||
|
}, { trackOnClient: true });
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect old guild urls
|
// Redirect old guild urls
|
||||||
if (to.hash.indexOf('#/options/groups/guilds/') !== -1) {
|
if (to.hash.indexOf('#/options/groups/guilds/') !== -1) {
|
||||||
const splits = to.hash.split('/');
|
const splits = to.hash.split('/');
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ describe('Task Column', () => {
|
|||||||
getters: {
|
getters: {
|
||||||
'tasks:getFilteredTaskList': () => [],
|
'tasks:getFilteredTaskList': () => [],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
state: {
|
||||||
|
user: {
|
||||||
|
data: {
|
||||||
|
preferences: {
|
||||||
|
tasks: {
|
||||||
|
activeFilter: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mocks,
|
mocks,
|
||||||
stubs,
|
stubs,
|
||||||
@@ -76,7 +88,20 @@ describe('Task Column', () => {
|
|||||||
'tasks:getFilteredTaskList': () => () => habits,
|
'tasks:getFilteredTaskList': () => () => habits,
|
||||||
};
|
};
|
||||||
|
|
||||||
const store = new Store({ getters });
|
const store = new Store({
|
||||||
|
getters,
|
||||||
|
state: {
|
||||||
|
user: {
|
||||||
|
data: {
|
||||||
|
preferences: {
|
||||||
|
tasks: {
|
||||||
|
activeFilter: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
wrapper = makeWrapper({ store });
|
wrapper = makeWrapper({ store });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
import Task from '@/components/tasks/task.vue';
|
|
||||||
import Store from '@/libs/store';
|
|
||||||
|
|
||||||
const localVue = createLocalVue();
|
|
||||||
localVue.use(Store);
|
|
||||||
|
|
||||||
describe('Task', () => {
|
|
||||||
let wrapper;
|
|
||||||
|
|
||||||
function makeWrapper (additionalTaskData = {}, additionalUserData = {}) {
|
|
||||||
return shallowMount(Task, {
|
|
||||||
propsData: {
|
|
||||||
task: {
|
|
||||||
group: {},
|
|
||||||
...additionalTaskData,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
store: {
|
|
||||||
state: {
|
|
||||||
user: {
|
|
||||||
data: {
|
|
||||||
preferences: {},
|
|
||||||
...additionalUserData,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
'tasks:getTaskClasses': () => ({}),
|
|
||||||
'tasks:canEdit': () => ({}),
|
|
||||||
'tasks:canDelete': () => ({}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mocks: { $t: (key, params) => key + (params ? JSON.stringify(params) : '') },
|
|
||||||
directives: { 'b-tooltip': {} },
|
|
||||||
localVue,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
it('returns a vue instance', () => {
|
|
||||||
wrapper = makeWrapper();
|
|
||||||
expect(wrapper.isVueInstance()).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Due date calculation', () => {
|
|
||||||
let clock;
|
|
||||||
|
|
||||||
function setClockTo (time) {
|
|
||||||
const now = moment(time);
|
|
||||||
clock = sinon.useFakeTimers(now.toDate());
|
|
||||||
return now;
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
clock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('formats due date to today if due today', () => {
|
|
||||||
const now = setClockTo('2019-09-17T17:57:00+02:00');
|
|
||||||
wrapper = makeWrapper({ date: now });
|
|
||||||
|
|
||||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"today"}');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('formats due date to tomorrow if due tomorrow', () => {
|
|
||||||
const now = setClockTo('2012-06-12T14:17:28Z');
|
|
||||||
wrapper = makeWrapper({ date: now.add(1, 'day') });
|
|
||||||
|
|
||||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"in a day"}');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('formats due date to 5 days if due in 5 days', () => {
|
|
||||||
const now = setClockTo();
|
|
||||||
wrapper = makeWrapper({ date: now.add(5, 'days') });
|
|
||||||
|
|
||||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"in 5 days"}');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('formats due date to tomorrow if today but before dayStart', () => {
|
|
||||||
const now = setClockTo('2019-06-12T04:23:37+02:00');
|
|
||||||
wrapper = makeWrapper({ date: now.add(8, 'hours') }, { preferences: { dayStart: 7 } });
|
|
||||||
|
|
||||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"in a day"}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -875,6 +875,14 @@
|
|||||||
"backgroundUnderWisteriaText": "Under Wisteria",
|
"backgroundUnderWisteriaText": "Under Wisteria",
|
||||||
"backgroundUnderWisteriaNotes": "Relax Under Wisteria.",
|
"backgroundUnderWisteriaNotes": "Relax Under Wisteria.",
|
||||||
|
|
||||||
|
"backgrounds052023": "SET 108: Released May 2023",
|
||||||
|
"backgroundInAPaintingText": "In A Painting",
|
||||||
|
"backgroundInAPaintingNotes": "Enjoy creative pursuits Inside a Painting.",
|
||||||
|
"backgroundFlyingOverHedgeMazeText": "Flying Over Hedge Maze",
|
||||||
|
"backgroundFlyingOverHedgeMazeNotes": "Marvel while Flying over a Hedge Maze.",
|
||||||
|
"backgroundCretaceousForestText": "Cretaceous Forest",
|
||||||
|
"backgroundCretaceousForestNotes": "Take in the ancient greenery of a Cretaceous Forest.",
|
||||||
|
|
||||||
"timeTravelBackgrounds": "Steampunk Backgrounds",
|
"timeTravelBackgrounds": "Steampunk Backgrounds",
|
||||||
"backgroundAirshipText": "Airship",
|
"backgroundAirshipText": "Airship",
|
||||||
"backgroundAirshipNotes": "Become a sky sailor on board your very own Airship.",
|
"backgroundAirshipNotes": "Become a sky sailor on board your very own Airship.",
|
||||||
|
|||||||
@@ -694,6 +694,8 @@
|
|||||||
"weaponArmoireMagicSpatulaNotes": "Watch your food fly and flip in the air. You get good luck for the day if it magically flips over three times and then lands back on your spatula. Increases Perception by <%= per %>. Enchanted Armoire: Cooking Implements Set (Item 1 of 2).",
|
"weaponArmoireMagicSpatulaNotes": "Watch your food fly and flip in the air. You get good luck for the day if it magically flips over three times and then lands back on your spatula. Increases Perception by <%= per %>. Enchanted Armoire: Cooking Implements Set (Item 1 of 2).",
|
||||||
"weaponArmoireFinelyCutGemText": "Finely Cut Gem",
|
"weaponArmoireFinelyCutGemText": "Finely Cut Gem",
|
||||||
"weaponArmoireFinelyCutGemNotes": "What a find! This stunning, precision-cut gem will be the prize of your collection. And it might contain some special magic, just waiting for you to tap into it. Increases Constitution by <%= con %>. Enchanted Armoire: Jeweler Set (Item 4 of 4).",
|
"weaponArmoireFinelyCutGemNotes": "What a find! This stunning, precision-cut gem will be the prize of your collection. And it might contain some special magic, just waiting for you to tap into it. Increases Constitution by <%= con %>. Enchanted Armoire: Jeweler Set (Item 4 of 4).",
|
||||||
|
"weaponArmoirePaintbrushText": "Paintbrush",
|
||||||
|
"weaponArmoirePaintbrushNotes": "A jolt of pure inspiration rushes through you when you pick up this brush, allowing you to paint anything you can imagine. Increases Intelligence by <%= int %>. Enchanted Armoire: Painter Set (Item 3 of 4).",
|
||||||
|
|
||||||
"armor": "armor",
|
"armor": "armor",
|
||||||
"armorCapitalized": "Armor",
|
"armorCapitalized": "Armor",
|
||||||
@@ -1453,6 +1455,8 @@
|
|||||||
"armorArmoireTeaGownNotes": "You’re resilient, creative, brilliant, and so fashionable! Increases Strength and Intelligence by <%= attrs %> each. Enchanted Armoire: Tea Party Set (Item 1 of 3).",
|
"armorArmoireTeaGownNotes": "You’re resilient, creative, brilliant, and so fashionable! Increases Strength and Intelligence by <%= attrs %> each. Enchanted Armoire: Tea Party Set (Item 1 of 3).",
|
||||||
"armorArmoireBasketballUniformText": "Basketball Uniform",
|
"armorArmoireBasketballUniformText": "Basketball Uniform",
|
||||||
"armorArmoireBasketballUniformNotes": "Wondering what’s printed on the back of this uniform? It’s your lucky number, of course! Increases Perception by <% per %>. Enchanted Armoire: Old Timey Basketball Set (Item 1 of 2).",
|
"armorArmoireBasketballUniformNotes": "Wondering what’s printed on the back of this uniform? It’s your lucky number, of course! Increases Perception by <% per %>. Enchanted Armoire: Old Timey Basketball Set (Item 1 of 2).",
|
||||||
|
"armorArmoirePaintersApronText": "Painter's Apron",
|
||||||
|
"armorArmoirePaintersApronNotes": "This apron can protect your clothes from paint and your creative projects from harsh critiques. Increases Constitution by <%= con %>. Enchanted Armoire: Painter Set (Item 1 of 4).",
|
||||||
|
|
||||||
"headgear": "helm",
|
"headgear": "helm",
|
||||||
"headgearCapitalized": "Headgear",
|
"headgearCapitalized": "Headgear",
|
||||||
@@ -2232,6 +2236,8 @@
|
|||||||
"headArmoireTeaHatNotes": "This elegant hat is both fancy and functional. Increases Perception by <%= per %>. Enchanted Armoire: Tea Party Set (Item 2 of 3).",
|
"headArmoireTeaHatNotes": "This elegant hat is both fancy and functional. Increases Perception by <%= per %>. Enchanted Armoire: Tea Party Set (Item 2 of 3).",
|
||||||
"headArmoireBeaniePropellerHatText": "Beanie Propeller Hat",
|
"headArmoireBeaniePropellerHatText": "Beanie Propeller Hat",
|
||||||
"headArmoireBeaniePropellerHatNotes": "This isn’t the time to keep your feet on the ground! Spin this little propeller and rise as high as your ambitions will take you. Increases all stats by <%= attrs %>. Enchanted Armoire: Independent Item.",
|
"headArmoireBeaniePropellerHatNotes": "This isn’t the time to keep your feet on the ground! Spin this little propeller and rise as high as your ambitions will take you. Increases all stats by <%= attrs %>. Enchanted Armoire: Independent Item.",
|
||||||
|
"headArmoirePaintersBeretText": "Painter's Beret",
|
||||||
|
"headArmoirePaintersBeretNotes": "See the world with a more artistic eye when you wear this jaunty beret. Increases Perception by <%= per %>. Enchanted Armoire: Painter Set (Item 2 of 4).",
|
||||||
|
|
||||||
"offhand": "off-hand item",
|
"offhand": "off-hand item",
|
||||||
"offHandCapitalized": "Off-Hand Item",
|
"offHandCapitalized": "Off-Hand Item",
|
||||||
@@ -2646,7 +2652,9 @@
|
|||||||
"shieldArmoireTeaKettleText": "Tea Kettle",
|
"shieldArmoireTeaKettleText": "Tea Kettle",
|
||||||
"shieldArmoireTeaKettleNotes": "All your favorite, flavorful teas can be brewed in this kettle. Are you in the mood for black tea, green tea, oolong, or perhaps an herbal infusion? Increases Constitution by <%= con %>. Enchanted Armoire: Tea Party Set (Item 3 of 3).",
|
"shieldArmoireTeaKettleNotes": "All your favorite, flavorful teas can be brewed in this kettle. Are you in the mood for black tea, green tea, oolong, or perhaps an herbal infusion? Increases Constitution by <%= con %>. Enchanted Armoire: Tea Party Set (Item 3 of 3).",
|
||||||
"shieldArmoireBasketballText": "Basketball",
|
"shieldArmoireBasketballText": "Basketball",
|
||||||
"shieldArmoireBasketballNotes": "Swish! Whenever you shoot this magic basketball, there will be nothing but net. Increases Constitution and Strength by <%= attrs %> each. Enchanted Armoire: Old Timey Basketball Set (Item 2 of 2).",
|
"shieldArmoireBasketballNotes": "Swish! Whenever you shoot this magic basketball, there will be nothing but net. Increases Constitution and Strength by <%= attrs %> each. Enchanted Armoire: Old Timey Basketball Set (Item 2 of 2).",
|
||||||
|
"shieldArmoirePaintersPaletteText": "Painter's Palette",
|
||||||
|
"shieldArmoirePaintersPaletteNotes": "Paints in all colors of the rainbow are at your disposal. Is it magic that makes them so vivid when you use them, or is it your talent? Increases Strength by <%= str %>. Enchanted Armoire: Painter Set (Item 4 of 4).",
|
||||||
|
|
||||||
"back": "Back Accessory",
|
"back": "Back Accessory",
|
||||||
"backBase0Text": "No Back Accessory",
|
"backBase0Text": "No Back Accessory",
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
"helpWithTranslation": "Would you like to help with the translation of Habitica? Great! Then visit <a href=\"/groups/guild/7732f64c-33ee-4cce-873c-fc28f147a6f7\">the Aspiring Linguists Guild</a>!",
|
"helpWithTranslation": "Would you like to help with the translation of Habitica? Great! Then visit <a href=\"/groups/guild/7732f64c-33ee-4cce-873c-fc28f147a6f7\">the Aspiring Linguists Guild</a>!",
|
||||||
"stickyHeader": "Sticky header",
|
"stickyHeader": "Sticky header",
|
||||||
"newTaskEdit": "Open new tasks in edit mode",
|
"newTaskEdit": "Open new tasks in edit mode",
|
||||||
"dailyDueDefaultView": "Set Dailies default to 'due' tab",
|
|
||||||
"dailyDueDefaultViewPop": "With this option set, the Dailies tasks will default to 'due' instead of 'all'",
|
|
||||||
"reverseChatOrder": "Show chat messages in reverse order",
|
"reverseChatOrder": "Show chat messages in reverse order",
|
||||||
"startAdvCollapsed": "Advanced Settings in tasks start collapsed",
|
"startAdvCollapsed": "Advanced Settings in tasks start collapsed",
|
||||||
"startAdvCollapsedPop": "With this option set, Advanced Settings will be hidden when you first open a task for editing.",
|
"startAdvCollapsedPop": "With this option set, Advanced Settings will be hidden when you first open a task for editing.",
|
||||||
|
|||||||
@@ -555,6 +555,11 @@ const backgrounds = {
|
|||||||
springtime_shower: { },
|
springtime_shower: { },
|
||||||
under_wisteria: { },
|
under_wisteria: { },
|
||||||
},
|
},
|
||||||
|
backgrounds052023: {
|
||||||
|
in_a_painting: { },
|
||||||
|
flying_over_hedge_maze: { },
|
||||||
|
cretaceous_forest: { },
|
||||||
|
},
|
||||||
eventBackgrounds: {
|
eventBackgrounds: {
|
||||||
birthday_bash: {
|
birthday_bash: {
|
||||||
price: 0,
|
price: 0,
|
||||||
|
|||||||
@@ -10,11 +10,15 @@ const gemsPromo = {
|
|||||||
|
|
||||||
export const EVENTS = {
|
export const EVENTS = {
|
||||||
noEvent: {
|
noEvent: {
|
||||||
start: '2023-05-01T23:59-04:00',
|
start: '2023-05-31T23:59-04:00',
|
||||||
end: '2023-06-22T08:00-04:00',
|
end: '2023-06-22T08:00-04:00',
|
||||||
season: 'normal',
|
season: 'normal',
|
||||||
npcImageSuffix: '',
|
npcImageSuffix: '',
|
||||||
},
|
},
|
||||||
|
potions202305: {
|
||||||
|
start:'2023-05-16T08:00-04:00',
|
||||||
|
end:'2023-05-31T23:59-04:00',
|
||||||
|
},
|
||||||
aprilFools2023: {
|
aprilFools2023: {
|
||||||
start: '2023-04-01T08:00-04:00',
|
start: '2023-04-01T08:00-04:00',
|
||||||
end: '2023-04-02T08:00-04:00',
|
end: '2023-04-02T08:00-04:00',
|
||||||
|
|||||||
@@ -420,6 +420,10 @@ const armor = {
|
|||||||
per: 10,
|
per: 10,
|
||||||
set: 'oldTimeyBasketball',
|
set: 'oldTimeyBasketball',
|
||||||
},
|
},
|
||||||
|
paintersApron: {
|
||||||
|
con: 10,
|
||||||
|
set: 'painters',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
@@ -851,6 +855,10 @@ const head = {
|
|||||||
str: 3,
|
str: 3,
|
||||||
int: 3,
|
int: 3,
|
||||||
},
|
},
|
||||||
|
paintersBeret: {
|
||||||
|
per: 9,
|
||||||
|
set: 'painters',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const shield = {
|
const shield = {
|
||||||
@@ -1161,6 +1169,10 @@ const shield = {
|
|||||||
str: 5,
|
str: 5,
|
||||||
set: 'oldTimeyBasketball',
|
set: 'oldTimeyBasketball',
|
||||||
},
|
},
|
||||||
|
paintersPalette: {
|
||||||
|
str: 7,
|
||||||
|
set: 'painters',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const headAccessory = {
|
const headAccessory = {
|
||||||
@@ -1603,6 +1615,10 @@ const weapon = {
|
|||||||
con: 10,
|
con: 10,
|
||||||
set: 'jewelers',
|
set: 'jewelers',
|
||||||
},
|
},
|
||||||
|
paintbrush: {
|
||||||
|
int: 8,
|
||||||
|
set: 'painters',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
forEach({
|
forEach({
|
||||||
|
|||||||
@@ -88,26 +88,26 @@ const premium = {
|
|||||||
value: 2,
|
value: 2,
|
||||||
text: t('hatchingPotionFairy'),
|
text: t('hatchingPotionFairy'),
|
||||||
limited: true,
|
limited: true,
|
||||||
event: EVENTS.potions202105,
|
event: EVENTS.potions202305,
|
||||||
_addlNotes: t('eventAvailabilityReturning', {
|
_addlNotes: t('eventAvailabilityReturning', {
|
||||||
availableDate: t('dateEndMay'),
|
availableDate: t('dateEndMay'),
|
||||||
previousDate: t('mayYYYY', { year: 2020 }),
|
previousDate: t('mayYYYY', { year: 2021 }),
|
||||||
}),
|
}),
|
||||||
canBuy () {
|
canBuy () {
|
||||||
return moment().isBefore(EVENTS.potions202105.end);
|
return moment().isBefore(EVENTS.potions202305.end);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Floral: {
|
Floral: {
|
||||||
value: 2,
|
value: 2,
|
||||||
text: t('hatchingPotionFloral'),
|
text: t('hatchingPotionFloral'),
|
||||||
limited: true,
|
limited: true,
|
||||||
event: EVENTS.potions202205,
|
event: EVENTS.potions202305,
|
||||||
_addlNotes: t('eventAvailabilityReturning', {
|
_addlNotes: t('eventAvailabilityReturning', {
|
||||||
availableDate: t('dateEndMay'),
|
availableDate: t('dateEndMay'),
|
||||||
previousDate: t('mayYYYY', { year: 2021 }),
|
previousDate: t('mayYYYY', { year: 2022 }),
|
||||||
}),
|
}),
|
||||||
canBuy () {
|
canBuy () {
|
||||||
return moment().isBefore(EVENTS.potions202205.end);
|
return moment().isBefore(EVENTS.potions202305.end);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Aquatic: {
|
Aquatic: {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { EVENTS } from './constants';
|
|||||||
// path: 'premiumHatchingPotions.Rainbow',
|
// path: 'premiumHatchingPotions.Rainbow',
|
||||||
const featuredItems = {
|
const featuredItems = {
|
||||||
market () {
|
market () {
|
||||||
if (moment().isBetween(EVENTS.spring2023.start, EVENTS.spring2023.end)) {
|
if (moment().isBetween(EVENTS.potions202305.start, EVENTS.potions202305.end)) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'armoire',
|
type: 'armoire',
|
||||||
@@ -13,15 +13,15 @@ const featuredItems = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'premiumHatchingPotion',
|
type: 'premiumHatchingPotion',
|
||||||
path: 'premiumHatchingPotions.PolkaDot',
|
path: 'premiumHatchingPotions.Fairy',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'premiumHatchingPotion',
|
type: 'premiumHatchingPotion',
|
||||||
path: 'premiumHatchingPotions.BirchBark',
|
path: 'premiumHatchingPotions.Floral',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'premiumHatchingPotion',
|
type: 'hatchingPotions',
|
||||||
path: 'premiumHatchingPotions.Rainbow',
|
path: 'hatchingPotions.Golden',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,13 +77,11 @@ spells.wizard = {
|
|||||||
lvl: 12,
|
lvl: 12,
|
||||||
target: 'party',
|
target: 'party',
|
||||||
notes: t('spellWizardMPHealNotes'),
|
notes: t('spellWizardMPHealNotes'),
|
||||||
cast (user, target) {
|
bulk: true,
|
||||||
each(target, member => {
|
cast (user, data) {
|
||||||
const bonus = statsComputed(user).int;
|
const bonus = statsComputed(user).int;
|
||||||
if (user._id !== member._id && member.stats.class !== 'wizard') {
|
data.query['stats.class'] = { $ne: 'wizard' };
|
||||||
member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125));
|
data.update = { $inc: { 'stats.mp': Math.ceil(diminishingReturns(bonus, 25, 125)) } };
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
earth: { // Earthquake
|
earth: { // Earthquake
|
||||||
@@ -92,12 +90,10 @@ spells.wizard = {
|
|||||||
lvl: 13,
|
lvl: 13,
|
||||||
target: 'party',
|
target: 'party',
|
||||||
notes: t('spellWizardEarthNotes'),
|
notes: t('spellWizardEarthNotes'),
|
||||||
cast (user, target) {
|
bulk: true,
|
||||||
each(target, member => {
|
cast (user, data) {
|
||||||
const bonus = statsComputed(user).int - user.stats.buffs.int;
|
const bonus = statsComputed(user).int - user.stats.buffs.int;
|
||||||
if (!member.stats.buffs.int) member.stats.buffs.int = 0;
|
data.update = { $inc: { 'stats.buffs.int': Math.ceil(diminishingReturns(bonus, 30, 200)) } };
|
||||||
member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30, 200));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
frost: { // Chilling Frost
|
frost: { // Chilling Frost
|
||||||
@@ -147,12 +143,10 @@ spells.warrior = {
|
|||||||
lvl: 13,
|
lvl: 13,
|
||||||
target: 'party',
|
target: 'party',
|
||||||
notes: t('spellWarriorValorousPresenceNotes'),
|
notes: t('spellWarriorValorousPresenceNotes'),
|
||||||
cast (user, target) {
|
bulk: true,
|
||||||
each(target, member => {
|
cast (user, data) {
|
||||||
const bonus = statsComputed(user).str - user.stats.buffs.str;
|
const bonus = statsComputed(user).str - user.stats.buffs.str;
|
||||||
if (!member.stats.buffs.str) member.stats.buffs.str = 0;
|
data.update = { $inc: { 'stats.buffs.str': Math.ceil(diminishingReturns(bonus, 20, 200)) } };
|
||||||
member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
intimidate: { // Intimidating Gaze
|
intimidate: { // Intimidating Gaze
|
||||||
@@ -161,12 +155,10 @@ spells.warrior = {
|
|||||||
lvl: 14,
|
lvl: 14,
|
||||||
target: 'party',
|
target: 'party',
|
||||||
notes: t('spellWarriorIntimidateNotes'),
|
notes: t('spellWarriorIntimidateNotes'),
|
||||||
cast (user, target) {
|
bulk: true,
|
||||||
each(target, member => {
|
cast (user, data) {
|
||||||
const bonus = statsComputed(user).con - user.stats.buffs.con;
|
const bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
data.update = { $inc: { 'stats.buffs.con': Math.ceil(diminishingReturns(bonus, 24, 200)) } };
|
||||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 24, 200));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -203,12 +195,10 @@ spells.rogue = {
|
|||||||
lvl: 13,
|
lvl: 13,
|
||||||
target: 'party',
|
target: 'party',
|
||||||
notes: t('spellRogueToolsOfTradeNotes'),
|
notes: t('spellRogueToolsOfTradeNotes'),
|
||||||
cast (user, target) {
|
bulk: true,
|
||||||
each(target, member => {
|
cast (user, data) {
|
||||||
const bonus = statsComputed(user).per - user.stats.buffs.per;
|
const bonus = statsComputed(user).per - user.stats.buffs.per;
|
||||||
if (!member.stats.buffs.per) member.stats.buffs.per = 0;
|
data.update = { $inc: { 'stats.buffs.per': Math.ceil(diminishingReturns(bonus, 100, 50)) } };
|
||||||
member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
stealth: { // Stealth
|
stealth: { // Stealth
|
||||||
@@ -257,12 +247,10 @@ spells.healer = {
|
|||||||
lvl: 13,
|
lvl: 13,
|
||||||
target: 'party',
|
target: 'party',
|
||||||
notes: t('spellHealerProtectAuraNotes'),
|
notes: t('spellHealerProtectAuraNotes'),
|
||||||
cast (user, target) {
|
bulk: true,
|
||||||
each(target, member => {
|
cast (user, data) {
|
||||||
const bonus = statsComputed(user).con - user.stats.buffs.con;
|
const bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
data.update = { $inc: { 'stats.buffs.con': Math.ceil(diminishingReturns(bonus, 200, 200)) } };
|
||||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
healAll: { // Blessing
|
healAll: { // Blessing
|
||||||
|
|||||||
@@ -282,6 +282,8 @@ api.postChat = {
|
|||||||
analyticsObject.groupName = group.name;
|
analyticsObject.groupName = group.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.analytics.track('group chat', analyticsObject);
|
||||||
|
|
||||||
if (chatUpdated) {
|
if (chatUpdated) {
|
||||||
res.respond(200, { chat: chatRes.chat });
|
res.respond(200, { chat: chatRes.chat });
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ api.inviteToQuest = {
|
|||||||
user.party.quest.RSVPNeeded = false;
|
user.party.quest.RSVPNeeded = false;
|
||||||
user.party.quest.key = questKey;
|
user.party.quest.key = questKey;
|
||||||
|
|
||||||
await User.update({
|
await User.updateMany({
|
||||||
'party._id': group._id,
|
'party._id': group._id,
|
||||||
_id: { $ne: user._id },
|
_id: { $ne: user._id },
|
||||||
}, {
|
}, {
|
||||||
@@ -101,7 +101,7 @@ api.inviteToQuest = {
|
|||||||
'party.quest.RSVPNeeded': true,
|
'party.quest.RSVPNeeded': true,
|
||||||
'party.quest.key': questKey,
|
'party.quest.key': questKey,
|
||||||
},
|
},
|
||||||
}, { multi: true }).exec();
|
}).exec();
|
||||||
|
|
||||||
_.each(members, member => {
|
_.each(members, member => {
|
||||||
group.quest.members[member._id] = null;
|
group.quest.members[member._id] = null;
|
||||||
@@ -409,10 +409,9 @@ api.cancelQuest = {
|
|||||||
const [savedGroup] = await Promise.all([
|
const [savedGroup] = await Promise.all([
|
||||||
group.save(),
|
group.save(),
|
||||||
newChatMessage.save(),
|
newChatMessage.save(),
|
||||||
User.update(
|
User.updateMany(
|
||||||
{ 'party._id': groupId },
|
{ 'party._id': groupId },
|
||||||
Group.cleanQuestParty(),
|
Group.cleanQuestParty(),
|
||||||
{ multi: true },
|
|
||||||
).exec(),
|
).exec(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -467,12 +466,11 @@ api.abortQuest = {
|
|||||||
});
|
});
|
||||||
await newChatMessage.save();
|
await newChatMessage.save();
|
||||||
|
|
||||||
const memberUpdates = User.update({
|
const memberUpdates = User.updateMany({
|
||||||
'party._id': groupId,
|
'party._id': groupId,
|
||||||
}, Group.cleanQuestParty(),
|
}, Group.cleanQuestParty()).exec();
|
||||||
{ multi: true }).exec();
|
|
||||||
|
|
||||||
const questLeaderUpdate = User.update({
|
const questLeaderUpdate = User.updateOne({
|
||||||
_id: group.quest.leader,
|
_id: group.quest.leader,
|
||||||
}, {
|
}, {
|
||||||
$inc: {
|
$inc: {
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ api.deleteTag = {
|
|||||||
const tagFound = find(user.tags, tag => tag.id === req.params.tagId);
|
const tagFound = find(user.tags, tag => tag.id === req.params.tagId);
|
||||||
if (!tagFound) throw new NotFound(res.t('tagNotFound'));
|
if (!tagFound) throw new NotFound(res.t('tagNotFound'));
|
||||||
|
|
||||||
await user.update({
|
await user.updateOne({
|
||||||
$pull: { tags: { id: tagFound.id } },
|
$pull: { tags: { id: tagFound.id } },
|
||||||
}).exec();
|
}).exec();
|
||||||
|
|
||||||
@@ -237,13 +237,13 @@ api.deleteTag = {
|
|||||||
user._v += 1;
|
user._v += 1;
|
||||||
|
|
||||||
// Remove from all the tasks TODO test
|
// Remove from all the tasks TODO test
|
||||||
await Tasks.Task.update({
|
await Tasks.Task.updateMany({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
}, {
|
}, {
|
||||||
$pull: {
|
$pull: {
|
||||||
tags: tagFound.id,
|
tags: tagFound.id,
|
||||||
},
|
},
|
||||||
}, { multi: true }).exec();
|
}).exec();
|
||||||
|
|
||||||
res.respond(200, {});
|
res.respond(200, {});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -840,7 +840,7 @@ api.moveTask = {
|
|||||||
// Cannot send $pull and $push on same field in one single op
|
// Cannot send $pull and $push on same field in one single op
|
||||||
const pullQuery = { $pull: {} };
|
const pullQuery = { $pull: {} };
|
||||||
pullQuery.$pull[`tasksOrder.${task.type}s`] = task.id;
|
pullQuery.$pull[`tasksOrder.${task.type}s`] = task.id;
|
||||||
await owner.update(pullQuery).exec();
|
await owner.updateOne(pullQuery).exec();
|
||||||
|
|
||||||
let position = to;
|
let position = to;
|
||||||
if (to === -1) position = order.length - 1; // push to bottom
|
if (to === -1) position = order.length - 1; // push to bottom
|
||||||
@@ -850,7 +850,7 @@ api.moveTask = {
|
|||||||
$each: [task._id],
|
$each: [task._id],
|
||||||
$position: position,
|
$position: position,
|
||||||
};
|
};
|
||||||
await owner.update(updateQuery).exec();
|
await owner.updateOne(updateQuery).exec();
|
||||||
|
|
||||||
// Update the user version field manually,
|
// Update the user version field manually,
|
||||||
// it cannot be updated in the pre update hook
|
// it cannot be updated in the pre update hook
|
||||||
@@ -1434,7 +1434,7 @@ api.deleteTask = {
|
|||||||
|
|
||||||
const pullQuery = { $pull: {} };
|
const pullQuery = { $pull: {} };
|
||||||
pullQuery.$pull[`tasksOrder.${task.type}s`] = task._id;
|
pullQuery.$pull[`tasksOrder.${task.type}s`] = task._id;
|
||||||
const taskOrderUpdate = (challenge || user).update(pullQuery).exec();
|
const taskOrderUpdate = (challenge || user).updateOne(pullQuery).exec();
|
||||||
|
|
||||||
// Update the user version field manually,
|
// Update the user version field manually,
|
||||||
// it cannot be updated in the pre update hook
|
// it cannot be updated in the pre update hook
|
||||||
|
|||||||
@@ -37,7 +37,15 @@ export default function baseModel (schema, options = {}) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
schema.pre('update', function preUpdateModel () {
|
schema.pre('update', function preUpdateModel () {
|
||||||
this.update({}, { $set: { updatedAt: new Date() } });
|
this.set({}, { $set: { updatedAt: new Date() } });
|
||||||
|
});
|
||||||
|
|
||||||
|
schema.pre('updateOne', function preUpdateModel () {
|
||||||
|
this.set({}, { $set: { updatedAt: new Date() } });
|
||||||
|
});
|
||||||
|
|
||||||
|
schema.pre('updateMany', function preUpdateModel () {
|
||||||
|
this.set({}, { $set: { updatedAt: new Date() } });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const apnProvider = APN_ENABLED ? new apn.Provider({
|
|||||||
}) : undefined;
|
}) : undefined;
|
||||||
|
|
||||||
function removePushDevice (user, pushDevice) {
|
function removePushDevice (user, pushDevice) {
|
||||||
return User.update({ _id: user._id }, {
|
return User.updateOne({ _id: user._id }, {
|
||||||
$pull: { pushDevices: { regId: pushDevice.regId } },
|
$pull: { pushDevices: { regId: pushDevice.regId } },
|
||||||
}).exec().catch(err => {
|
}).exec().catch(err => {
|
||||||
logger.error(err, `Error removing pushDevice ${pushDevice.regId} for user ${user._id}`);
|
logger.error(err, `Error removing pushDevice ${pushDevice.regId} for user ${user._id}`);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function readController (router, controller, overrides = []) {
|
|||||||
|
|
||||||
// If an authentication middleware is used run getUserLanguage after it, otherwise before
|
// If an authentication middleware is used run getUserLanguage after it, otherwise before
|
||||||
// for cron instead use it only if an authentication middleware is present
|
// for cron instead use it only if an authentication middleware is present
|
||||||
const authMiddlewareIndex = _.findIndex(middlewares, middleware => {
|
let authMiddlewareIndex = _.findIndex(middlewares, middleware => {
|
||||||
if (middleware.name.indexOf('authWith') === 0) { // authWith{Headers|Session|Url|...}
|
if (middleware.name.indexOf('authWith') === 0) { // authWith{Headers|Session|Url|...}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,7 @@ export function readController (router, controller, overrides = []) {
|
|||||||
// disable caching for all routes with mandatory or optional authentication
|
// disable caching for all routes with mandatory or optional authentication
|
||||||
if (authMiddlewareIndex !== -1) {
|
if (authMiddlewareIndex !== -1) {
|
||||||
middlewares.unshift(disableCache);
|
middlewares.unshift(disableCache);
|
||||||
|
authMiddlewareIndex += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.noLanguage !== true) { // unless getting the language is explictly disabled
|
if (action.noLanguage !== true) { // unless getting the language is explictly disabled
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
} from '../models/group';
|
} from '../models/group';
|
||||||
import apiError from './apiError';
|
import apiError from './apiError';
|
||||||
|
|
||||||
const partyMembersFields = 'profile.name stats achievements items.special notifications flags pinnedItems';
|
const partyMembersFields = 'profile.name stats achievements items.special pinnedItems notifications flags';
|
||||||
// Excluding notifications and flags from the list of public fields to return.
|
// Excluding notifications and flags from the list of public fields to return.
|
||||||
const partyMembersPublicFields = 'profile.name stats achievements items.special';
|
const partyMembersPublicFields = 'profile.name stats achievements items.special';
|
||||||
|
|
||||||
@@ -74,12 +74,13 @@ async function castSelfSpell (req, user, spell, quantity = 1) {
|
|||||||
await user.save();
|
await user.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function castPartySpell (req, party, partyMembers, user, spell, quantity = 1) {
|
async function getPartyMembers (user, party) {
|
||||||
|
let partyMembers;
|
||||||
if (!party) {
|
if (!party) {
|
||||||
// Act as solo party
|
// Act as solo party
|
||||||
partyMembers = [user]; // eslint-disable-line no-param-reassign
|
partyMembers = [user];
|
||||||
} else {
|
} else {
|
||||||
partyMembers = await User // eslint-disable-line no-param-reassign
|
partyMembers = await User
|
||||||
.find({
|
.find({
|
||||||
'party._id': party._id,
|
'party._id': party._id,
|
||||||
_id: { $ne: user._id }, // add separately
|
_id: { $ne: user._id }, // add separately
|
||||||
@@ -89,22 +90,40 @@ async function castPartySpell (req, party, partyMembers, user, spell, quantity =
|
|||||||
|
|
||||||
partyMembers.unshift(user);
|
partyMembers.unshift(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < quantity; i += 1) {
|
|
||||||
spell.cast(user, partyMembers, req);
|
|
||||||
}
|
|
||||||
await Promise.all(partyMembers.map(m => m.save()));
|
|
||||||
|
|
||||||
return partyMembers;
|
return partyMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function castUserSpell (res, req, party, partyMembers, targetId, user, spell, quantity = 1) {
|
async function castPartySpell (req, party, user, spell, quantity = 1) {
|
||||||
|
let partyMembers;
|
||||||
|
if (spell.bulk) {
|
||||||
|
const data = { };
|
||||||
|
if (party) {
|
||||||
|
data.query = { 'party._id': party._id };
|
||||||
|
} else {
|
||||||
|
data.query = { _id: user._id };
|
||||||
|
}
|
||||||
|
spell.cast(user, data);
|
||||||
|
await User.updateMany(data.query, data.update);
|
||||||
|
await user.save();
|
||||||
|
partyMembers = await getPartyMembers(user, party);
|
||||||
|
} else {
|
||||||
|
partyMembers = await getPartyMembers(user, party);
|
||||||
|
for (let i = 0; i < quantity; i += 1) {
|
||||||
|
spell.cast(user, partyMembers, req);
|
||||||
|
}
|
||||||
|
await Promise.all(partyMembers.map(m => m.save()));
|
||||||
|
}
|
||||||
|
return partyMembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function castUserSpell (res, req, party, targetId, user, spell, quantity = 1) {
|
||||||
|
let partyMembers;
|
||||||
if (!party && (!targetId || user._id === targetId)) {
|
if (!party && (!targetId || user._id === targetId)) {
|
||||||
partyMembers = user; // eslint-disable-line no-param-reassign
|
partyMembers = user;
|
||||||
} else {
|
} else {
|
||||||
if (!targetId) throw new BadRequest(res.t('targetIdUUID'));
|
if (!targetId) throw new BadRequest(res.t('targetIdUUID'));
|
||||||
if (!party) throw new NotFound(res.t('partyNotFound'));
|
if (!party) throw new NotFound(res.t('partyNotFound'));
|
||||||
partyMembers = await User // eslint-disable-line no-param-reassign
|
partyMembers = await User
|
||||||
.findOne({ _id: targetId, 'party._id': party._id })
|
.findOne({ _id: targetId, 'party._id': party._id })
|
||||||
.select(partyMembersFields)
|
.select(partyMembersFields)
|
||||||
.exec();
|
.exec();
|
||||||
@@ -195,10 +214,10 @@ async function castSpell (req, res, { isV3 = false }) {
|
|||||||
let partyMembers;
|
let partyMembers;
|
||||||
|
|
||||||
if (targetType === 'party') {
|
if (targetType === 'party') {
|
||||||
partyMembers = await castPartySpell(req, party, partyMembers, user, spell, quantity);
|
partyMembers = await castPartySpell(req, party, user, spell, quantity);
|
||||||
} else {
|
} else {
|
||||||
partyMembers = await castUserSpell(
|
partyMembers = await castUserSpell(
|
||||||
res, req, party, partyMembers,
|
res, req, party,
|
||||||
targetId, user, spell, quantity,
|
targetId, user, spell, quantity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ async function createTasks (req, res, options = {}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
await owner.update(taskOrderUpdateQuery).exec();
|
await owner.updateOne(taskOrderUpdateQuery).exec();
|
||||||
|
|
||||||
// tasks with aliases need to be validated asynchronously
|
// tasks with aliases need to be validated asynchronously
|
||||||
await validateTaskAlias(toSave, res);
|
await validateTaskAlias(toSave, res);
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ async function checkNewInputForProfanity (user, res, newValue) {
|
|||||||
export async function update (req, res, { isV3 = false }) {
|
export async function update (req, res, { isV3 = false }) {
|
||||||
const { user } = res.locals;
|
const { user } = res.locals;
|
||||||
|
|
||||||
const promisesForTagsRemoval = [];
|
let promisesForTagsRemoval = [];
|
||||||
|
|
||||||
if (req.body['party.seeking'] !== undefined && req.body['party.seeking'] !== null) {
|
if (req.body['party.seeking'] !== undefined && req.body['party.seeking'] !== null) {
|
||||||
user.invitations.party = {};
|
user.invitations.party = {};
|
||||||
@@ -218,13 +218,13 @@ export async function update (req, res, { isV3 = false }) {
|
|||||||
// Remove from all the tasks
|
// Remove from all the tasks
|
||||||
// NOTE each tag to remove requires a query
|
// NOTE each tag to remove requires a query
|
||||||
|
|
||||||
promisesForTagsRemoval.push(removedTagsIds.map(tagId => Tasks.Task.update({
|
promisesForTagsRemoval = removedTagsIds.map(tagId => Tasks.Task.updateMany({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
}, {
|
}, {
|
||||||
$pull: {
|
$pull: {
|
||||||
tags: tagId,
|
tags: tagId,
|
||||||
},
|
},
|
||||||
}, { multi: true }).exec()));
|
}).exec());
|
||||||
} else if (key === 'flags.newStuff' && val === false) {
|
} else if (key === 'flags.newStuff' && val === false) {
|
||||||
// flags.newStuff was removed from the user schema and is only returned for compatibility
|
// flags.newStuff was removed from the user schema and is only returned for compatibility
|
||||||
// reasons but we're keeping the ability to set it in API v3
|
// reasons but we're keeping the ability to set it in API v3
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ function sendWebhook (webhook, body, user) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return User.update({
|
return User.updateOne({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
'webhooks.id': webhook.id,
|
'webhooks.id': webhook.id,
|
||||||
}, update).exec();
|
}, update).exec();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ async function checkForActiveCron (user, now) {
|
|||||||
|
|
||||||
// To avoid double cron we first set _cronSignature
|
// To avoid double cron we first set _cronSignature
|
||||||
// and then check that it's not changed while processing
|
// and then check that it's not changed while processing
|
||||||
const userUpdateResult = await User.update({
|
const userUpdateResult = await User.updateOne({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
$or: [ // Make sure last cron was successful or failed before cronRetryTime
|
$or: [ // Make sure last cron was successful or failed before cronRetryTime
|
||||||
{ _cronSignature: 'NOT_RUNNING' },
|
{ _cronSignature: 'NOT_RUNNING' },
|
||||||
@@ -36,7 +36,7 @@ async function checkForActiveCron (user, now) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function updateLastCron (user, now) {
|
async function updateLastCron (user, now) {
|
||||||
await User.update({
|
await User.updateOne({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
}, {
|
}, {
|
||||||
lastCron: now, // setting lastCron now so we don't risk re-running parts of cron if it fails
|
lastCron: now, // setting lastCron now so we don't risk re-running parts of cron if it fails
|
||||||
@@ -44,7 +44,7 @@ async function updateLastCron (user, now) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function unlockUser (user) {
|
async function unlockUser (user) {
|
||||||
await User.update({
|
await User.updateOne({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
}, {
|
}, {
|
||||||
_cronSignature: 'NOT_RUNNING',
|
_cronSignature: 'NOT_RUNNING',
|
||||||
@@ -125,7 +125,7 @@ async function cronAsync (req, res) {
|
|||||||
await Group.processQuestProgress(user, progress);
|
await Group.processQuestProgress(user, progress);
|
||||||
|
|
||||||
// Set _cronSignature, lastCron and auth.timestamps.loggedin to signal end of cron
|
// Set _cronSignature, lastCron and auth.timestamps.loggedin to signal end of cron
|
||||||
await User.update({
|
await User.updateOne({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
}, {
|
}, {
|
||||||
$set: {
|
$set: {
|
||||||
@@ -153,7 +153,7 @@ async function cronAsync (req, res) {
|
|||||||
// For any other error make sure to reset _cronSignature
|
// For any other error make sure to reset _cronSignature
|
||||||
// so that it doesn't prevent cron from running
|
// so that it doesn't prevent cron from running
|
||||||
// at the next request
|
// at the next request
|
||||||
await User.update({
|
await User.updateOne({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
}, {
|
}, {
|
||||||
_cronSignature: 'NOT_RUNNING',
|
_cronSignature: 'NOT_RUNNING',
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ schema.methods.addToUser = async function addChallengeToUser (user) {
|
|||||||
// Add challenge to users challenges atomically (with a condition that checks that it
|
// Add challenge to users challenges atomically (with a condition that checks that it
|
||||||
// is not there already) to prevent multiple concurrent requests from passing through
|
// is not there already) to prevent multiple concurrent requests from passing through
|
||||||
// see https://github.com/HabitRPG/habitica/issues/11295
|
// see https://github.com/HabitRPG/habitica/issues/11295
|
||||||
const result = await User.update(
|
const result = await User.updateOne(
|
||||||
{
|
{
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
challenges: { $nin: [this._id] },
|
challenges: { $nin: [this._id] },
|
||||||
@@ -249,7 +249,7 @@ async function _addTaskFn (challenge, tasks, memberId) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const updateUserParams = { ...updateTasksOrderQ, ...addToChallengeTagSet };
|
const updateUserParams = { ...updateTasksOrderQ, ...addToChallengeTagSet };
|
||||||
toSave.unshift(User.update({ _id: memberId }, updateUserParams).exec());
|
toSave.unshift(User.updateOne({ _id: memberId }, updateUserParams).exec());
|
||||||
|
|
||||||
return Promise.all(toSave);
|
return Promise.all(toSave);
|
||||||
}
|
}
|
||||||
@@ -278,11 +278,11 @@ schema.methods.updateTask = async function challengeUpdateTask (task) {
|
|||||||
const taskSchema = Tasks[task.type];
|
const taskSchema = Tasks[task.type];
|
||||||
// Updating instead of loading and saving for performances,
|
// Updating instead of loading and saving for performances,
|
||||||
// risks becoming a problem if we introduce more complexity in tasks
|
// risks becoming a problem if we introduce more complexity in tasks
|
||||||
await taskSchema.update({
|
await taskSchema.updateMany({
|
||||||
userId: { $exists: true },
|
userId: { $exists: true },
|
||||||
'challenge.id': challenge.id,
|
'challenge.id': challenge.id,
|
||||||
'challenge.taskId': task._id,
|
'challenge.taskId': task._id,
|
||||||
}, updateCmd, { multi: true }).exec();
|
}, updateCmd).exec();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove a task from challenge members
|
// Remove a task from challenge members
|
||||||
@@ -290,13 +290,13 @@ schema.methods.removeTask = async function challengeRemoveTask (task) {
|
|||||||
const challenge = this;
|
const challenge = this;
|
||||||
|
|
||||||
// Set the task as broken
|
// Set the task as broken
|
||||||
await Tasks.Task.update({
|
await Tasks.Task.updateMany({
|
||||||
userId: { $exists: true },
|
userId: { $exists: true },
|
||||||
'challenge.id': challenge.id,
|
'challenge.id': challenge.id,
|
||||||
'challenge.taskId': task._id,
|
'challenge.taskId': task._id,
|
||||||
}, {
|
}, {
|
||||||
$set: { 'challenge.broken': 'TASK_DELETED' },
|
$set: { 'challenge.broken': 'TASK_DELETED' },
|
||||||
}, { multi: true }).exec();
|
}).exec();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unlink challenges tasks (and the challenge itself) from user. TODO rename to 'leave'
|
// Unlink challenges tasks (and the challenge itself) from user. TODO rename to 'leave'
|
||||||
@@ -311,9 +311,9 @@ schema.methods.unlinkTasks = async function challengeUnlinkTasks (user, keep, sa
|
|||||||
this.memberCount -= 1;
|
this.memberCount -= 1;
|
||||||
|
|
||||||
if (keep === 'keep-all') {
|
if (keep === 'keep-all') {
|
||||||
await Tasks.Task.update(findQuery, {
|
await Tasks.Task.updateMany(findQuery, {
|
||||||
$set: { challenge: {} },
|
$set: { challenge: {} },
|
||||||
}, { multi: true }).exec();
|
}).exec();
|
||||||
|
|
||||||
const promises = [this.save()];
|
const promises = [this.save()];
|
||||||
|
|
||||||
@@ -356,11 +356,12 @@ schema.methods.closeChal = async function closeChal (broken = {}) {
|
|||||||
|
|
||||||
// Refund the leader if the challenge is deleted (no winner chosen)
|
// Refund the leader if the challenge is deleted (no winner chosen)
|
||||||
if (brokenReason === 'CHALLENGE_DELETED') {
|
if (brokenReason === 'CHALLENGE_DELETED') {
|
||||||
await User.update({ _id: challenge.leader }, { $inc: { balance: challenge.prize / 4 } }).exec();
|
await User.updateOne({ _id: challenge.leader }, { $inc: { balance: challenge.prize / 4 } })
|
||||||
|
.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the challengeCount on the group
|
// Update the challengeCount on the group
|
||||||
await Group.update({ _id: challenge.group }, { $inc: { challengeCount: -1 } }).exec();
|
await Group.updateOne({ _id: challenge.group }, { $inc: { challengeCount: -1 } }).exec();
|
||||||
|
|
||||||
// Award prize to winner and notify
|
// Award prize to winner and notify
|
||||||
if (winner) {
|
if (winner) {
|
||||||
@@ -370,7 +371,7 @@ schema.methods.closeChal = async function closeChal (broken = {}) {
|
|||||||
// reimburse the leader
|
// reimburse the leader
|
||||||
const winnerCanGetGems = await winner.canGetGems();
|
const winnerCanGetGems = await winner.canGetGems();
|
||||||
if (!winnerCanGetGems) {
|
if (!winnerCanGetGems) {
|
||||||
await User.update(
|
await User.updateOne(
|
||||||
{ _id: challenge.leader },
|
{ _id: challenge.leader },
|
||||||
{ $inc: { balance: challenge.prize / 4 } },
|
{ $inc: { balance: challenge.prize / 4 } },
|
||||||
).exec();
|
).exec();
|
||||||
@@ -408,22 +409,22 @@ schema.methods.closeChal = async function closeChal (broken = {}) {
|
|||||||
Tasks.Task.remove({ 'challenge.id': challenge._id, userId: { $exists: false } }).exec(),
|
Tasks.Task.remove({ 'challenge.id': challenge._id, userId: { $exists: false } }).exec(),
|
||||||
// Set the challenge tag to non-challenge status
|
// Set the challenge tag to non-challenge status
|
||||||
// and remove the challenge from the user's challenges
|
// and remove the challenge from the user's challenges
|
||||||
User.update({
|
User.updateMany({
|
||||||
challenges: challenge._id,
|
challenges: challenge._id,
|
||||||
'tags.id': challenge._id,
|
'tags.id': challenge._id,
|
||||||
}, {
|
}, {
|
||||||
$set: { 'tags.$.challenge': false },
|
$set: { 'tags.$.challenge': false },
|
||||||
$pull: { challenges: challenge._id },
|
$pull: { challenges: challenge._id },
|
||||||
}, { multi: true }).exec(),
|
}).exec(),
|
||||||
// Break users' tasks
|
// Break users' tasks
|
||||||
Tasks.Task.update({
|
Tasks.Task.updateMany({
|
||||||
'challenge.id': challenge._id,
|
'challenge.id': challenge._id,
|
||||||
}, {
|
}, {
|
||||||
$set: {
|
$set: {
|
||||||
'challenge.broken': brokenReason,
|
'challenge.broken': brokenReason,
|
||||||
'challenge.winner': winner && winner.profile.name,
|
'challenge.winner': winner && winner.profile.name,
|
||||||
},
|
},
|
||||||
}, { multi: true }).exec(),
|
}).exec(),
|
||||||
];
|
];
|
||||||
|
|
||||||
Promise.all(backgroundTasks);
|
Promise.all(backgroundTasks);
|
||||||
|
|||||||
@@ -268,10 +268,13 @@ schema.statics.getGroup = async function getGroup (options = {}) {
|
|||||||
if (groupId === user.party._id) {
|
if (groupId === user.party._id) {
|
||||||
// reset party object to default state
|
// reset party object to default state
|
||||||
user.party = {};
|
user.party = {};
|
||||||
|
await user.save();
|
||||||
} else {
|
} else {
|
||||||
removeFromArray(user.guilds, groupId);
|
const item = removeFromArray(user.guilds, groupId);
|
||||||
|
if (item) {
|
||||||
|
await user.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await user.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
@@ -659,7 +662,7 @@ schema.methods.handleQuestInvitation = async function handleQuestInvitation (use
|
|||||||
// to prevent multiple concurrent requests overriding updates
|
// to prevent multiple concurrent requests overriding updates
|
||||||
// see https://github.com/HabitRPG/habitica/issues/11398
|
// see https://github.com/HabitRPG/habitica/issues/11398
|
||||||
const Group = this.constructor;
|
const Group = this.constructor;
|
||||||
const result = await Group.update(
|
const result = await Group.updateOne(
|
||||||
{
|
{
|
||||||
_id: this._id,
|
_id: this._id,
|
||||||
[`quest.members.${user._id}`]: { $type: 10 }, // match BSON Type Null (type number 10)
|
[`quest.members.${user._id}`]: { $type: 10 }, // match BSON Type Null (type number 10)
|
||||||
@@ -707,7 +710,7 @@ schema.methods.startQuest = async function startQuest (user) {
|
|||||||
|
|
||||||
// Persist quest.members early to avoid simultaneous handling of accept/reject
|
// Persist quest.members early to avoid simultaneous handling of accept/reject
|
||||||
// while processing the rest of this script
|
// while processing the rest of this script
|
||||||
await this.update({ $set: { 'quest.members': this.quest.members } }).exec();
|
await this.updateOne({ $set: { 'quest.members': this.quest.members } }).exec();
|
||||||
|
|
||||||
const nonUserQuestMembers = _.keys(this.quest.members);
|
const nonUserQuestMembers = _.keys(this.quest.members);
|
||||||
removeFromArray(nonUserQuestMembers, user._id);
|
removeFromArray(nonUserQuestMembers, user._id);
|
||||||
@@ -747,7 +750,7 @@ schema.methods.startQuest = async function startQuest (user) {
|
|||||||
user.markModified('items.quests');
|
user.markModified('items.quests');
|
||||||
promises.push(user.save());
|
promises.push(user.save());
|
||||||
} else { // another user is starting the quest, update the leader separately
|
} else { // another user is starting the quest, update the leader separately
|
||||||
promises.push(User.update({ _id: this.quest.leader }, {
|
promises.push(User.updateOne({ _id: this.quest.leader }, {
|
||||||
$inc: {
|
$inc: {
|
||||||
[`items.quests.${this.quest.key}`]: -1,
|
[`items.quests.${this.quest.key}`]: -1,
|
||||||
},
|
},
|
||||||
@@ -755,7 +758,7 @@ schema.methods.startQuest = async function startQuest (user) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update the remaining users
|
// update the remaining users
|
||||||
promises.push(User.update({
|
promises.push(User.updateMany({
|
||||||
_id: { $in: nonUserQuestMembers },
|
_id: { $in: nonUserQuestMembers },
|
||||||
}, {
|
}, {
|
||||||
$set: {
|
$set: {
|
||||||
@@ -763,16 +766,15 @@ schema.methods.startQuest = async function startQuest (user) {
|
|||||||
'party.quest.progress.down': 0,
|
'party.quest.progress.down': 0,
|
||||||
'party.quest.completed': null,
|
'party.quest.completed': null,
|
||||||
},
|
},
|
||||||
}, { multi: true }).exec());
|
}).exec());
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
|
||||||
// update the users who are not participating
|
// update the users who are not participating
|
||||||
// Do not block updates
|
// Do not block updates
|
||||||
User.update({
|
User.updateMany({
|
||||||
_id: { $in: nonMembers },
|
_id: { $in: nonMembers },
|
||||||
}, _cleanQuestParty(),
|
}, _cleanQuestParty()).exec();
|
||||||
{ multi: true }).exec();
|
|
||||||
|
|
||||||
const newMessage = this.sendChat({
|
const newMessage = this.sendChat({
|
||||||
message: `\`${shared.i18n.t('chatQuestStarted', { questName: quest.text('en') }, 'en')}\``,
|
message: `\`${shared.i18n.t('chatQuestStarted', { questName: quest.text('en') }, 'en')}\``,
|
||||||
@@ -903,7 +905,7 @@ function _getUserUpdateForQuestReward (itemToAward, allAwardedItems) {
|
|||||||
async function _updateUserWithRetries (userId, updates, numTry = 1, query = {}) {
|
async function _updateUserWithRetries (userId, updates, numTry = 1, query = {}) {
|
||||||
query._id = userId;
|
query._id = userId;
|
||||||
try {
|
try {
|
||||||
return await User.update(query, updates).exec();
|
return await User.updateOne(query, updates).exec();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (numTry < MAX_UPDATE_RETRIES) {
|
if (numTry < MAX_UPDATE_RETRIES) {
|
||||||
numTry += 1; // eslint-disable-line no-param-reassign
|
numTry += 1; // eslint-disable-line no-param-reassign
|
||||||
@@ -949,7 +951,7 @@ schema.methods.finishQuest = async function finishQuest (quest) {
|
|||||||
this.markModified('quest');
|
this.markModified('quest');
|
||||||
|
|
||||||
if (this._id === TAVERN_ID) {
|
if (this._id === TAVERN_ID) {
|
||||||
return User.update({}, updates, { multi: true }).exec();
|
return User.updateMany({}, updates).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = participants.map(userId => {
|
const promises = participants.map(userId => {
|
||||||
@@ -1389,10 +1391,10 @@ schema.methods.leave = async function leaveGroup (user, keep = 'keep-all', keepC
|
|||||||
const userUpdate = { $pull: { 'preferences.tasks.mirrorGroupTasks': group._id } };
|
const userUpdate = { $pull: { 'preferences.tasks.mirrorGroupTasks': group._id } };
|
||||||
if (group.type === 'guild') {
|
if (group.type === 'guild') {
|
||||||
userUpdate.$pull.guilds = group._id;
|
userUpdate.$pull.guilds = group._id;
|
||||||
promises.push(User.update({ _id: user._id }, userUpdate).exec());
|
promises.push(User.updateOne({ _id: user._id }, userUpdate).exec());
|
||||||
} else {
|
} else {
|
||||||
userUpdate.$set = { party: {} };
|
userUpdate.$set = { party: {} };
|
||||||
promises.push(User.update({ _id: user._id }, userUpdate).exec());
|
promises.push(User.updateOne({ _id: user._id }, userUpdate).exec());
|
||||||
|
|
||||||
update.$unset = { [`quest.members.${user._id}`]: 1 };
|
update.$unset = { [`quest.members.${user._id}`]: 1 };
|
||||||
}
|
}
|
||||||
@@ -1508,7 +1510,7 @@ schema.methods.unlinkTask = async function groupUnlinkTask (
|
|||||||
const promises = [unlinkingTask.save()];
|
const promises = [unlinkingTask.save()];
|
||||||
|
|
||||||
if (keep === 'keep-all') {
|
if (keep === 'keep-all') {
|
||||||
await Tasks.Task.update(findQuery, {
|
await Tasks.Task.updateOne(findQuery, {
|
||||||
$set: { group: {} },
|
$set: { group: {} },
|
||||||
}).exec();
|
}).exec();
|
||||||
|
|
||||||
|
|||||||
@@ -392,6 +392,13 @@ schema.pre('update', function preUpdateUser () {
|
|||||||
this.update({}, { $inc: { _v: 1 } });
|
this.update({}, { $inc: { _v: 1 } });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
schema.pre('updateOne', function preUpdateUser () {
|
||||||
|
this.updateOne({}, { $inc: { _v: 1 } });
|
||||||
|
});
|
||||||
|
schema.pre('updateMany', function preUpdateUser () {
|
||||||
|
this.updateMany({}, { $inc: { _v: 1 } });
|
||||||
|
});
|
||||||
|
|
||||||
schema.post('save', function postSaveUser () {
|
schema.post('save', function postSaveUser () {
|
||||||
// Send a webhook notification when the user has leveled up
|
// Send a webhook notification when the user has leveled up
|
||||||
if (this._tmp && this._tmp.leveledUp && this._tmp.leveledUp.length > 0) {
|
if (this._tmp && this._tmp.leveledUp && this._tmp.leveledUp.length > 0) {
|
||||||
|
|||||||
@@ -225,10 +225,9 @@ schema.statics.pushNotification = async function pushNotification (
|
|||||||
throw validationResult;
|
throw validationResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.update(
|
await this.updateMany(
|
||||||
query,
|
query,
|
||||||
{ $push: { notifications: newNotification.toObject() } },
|
{ $push: { notifications: newNotification.toObject() } },
|
||||||
{ multi: true },
|
|
||||||
).exec();
|
).exec();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -274,13 +273,12 @@ schema.statics.addAchievementUpdate = async function addAchievementUpdate (query
|
|||||||
const validationResult = newNotification.validateSync();
|
const validationResult = newNotification.validateSync();
|
||||||
if (validationResult) throw validationResult;
|
if (validationResult) throw validationResult;
|
||||||
|
|
||||||
await this.update(
|
await this.updateMany(
|
||||||
query,
|
query,
|
||||||
{
|
{
|
||||||
$push: { notifications: newNotification.toObject() },
|
$push: { notifications: newNotification.toObject() },
|
||||||
$set: { [`achievements.${achievement}`]: true },
|
$set: { [`achievements.${achievement}`]: true },
|
||||||
},
|
},
|
||||||
{ multi: true },
|
|
||||||
).exec();
|
).exec();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ export default new Schema({
|
|||||||
stickyHeader: { $type: Boolean, default: true },
|
stickyHeader: { $type: Boolean, default: true },
|
||||||
disableClasses: { $type: Boolean, default: false },
|
disableClasses: { $type: Boolean, default: false },
|
||||||
newTaskEdit: { $type: Boolean, default: false },
|
newTaskEdit: { $type: Boolean, default: false },
|
||||||
|
// not used anymore, now the current filter is saved in preferences.activeFilter
|
||||||
dailyDueDefaultView: { $type: Boolean, default: false },
|
dailyDueDefaultView: { $type: Boolean, default: false },
|
||||||
advancedCollapsed: { $type: Boolean, default: false },
|
advancedCollapsed: { $type: Boolean, default: false },
|
||||||
toolbarCollapsed: { $type: Boolean, default: false },
|
toolbarCollapsed: { $type: Boolean, default: false },
|
||||||
@@ -594,6 +595,12 @@ export default new Schema({
|
|||||||
mirrorGroupTasks: [
|
mirrorGroupTasks: [
|
||||||
{ $type: String, validate: [v => validator.isUUID(v), 'Invalid group UUID.'], ref: 'Group' },
|
{ $type: String, validate: [v => validator.isUUID(v), 'Invalid group UUID.'], ref: 'Group' },
|
||||||
],
|
],
|
||||||
|
activeFilter: {
|
||||||
|
habit: { $type: String, default: 'all' },
|
||||||
|
daily: { $type: String, default: 'all' },
|
||||||
|
todo: { $type: String, default: 'remaining' },
|
||||||
|
reward: { $type: String, default: 'all' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
improvementCategories: {
|
improvementCategories: {
|
||||||
$type: Array,
|
$type: Array,
|
||||||
|
|||||||
Reference in New Issue
Block a user