Merge branch 'develop' into release

This commit is contained in:
Sabe Jones 2021-01-22 14:09:49 -06:00
commit 4db1b1cdfa
14 changed files with 866 additions and 1022 deletions

135
package-lock.json generated
View file

@ -1382,16 +1382,6 @@
"@sinonjs/commons": "^1.7.0"
}
},
"@sinonjs/formatio": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz",
"integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1",
"@sinonjs/samsam": "^5.0.2"
}
},
"@sinonjs/samsam": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.0.tgz",
@ -1415,23 +1405,13 @@
"integrity": "sha512-tA7GG7Tj479vojfV3AoxbckalA48aK6giGjNtgH6ihpLwTyHE3fIgRrvt8TWfLwW8X8dyu7vgmAsGLRG7hWWOg=="
},
"@slack/webhook": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/@slack/webhook/-/webhook-5.0.3.tgz",
"integrity": "sha512-51vnejJ2zABNumPVukOLyerpHQT39/Lt0TYFtOEz/N2X77bPofOgfPj2atB3etaM07mxWHLT9IRJ4Zuqx38DkQ==",
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@slack/webhook/-/webhook-5.0.4.tgz",
"integrity": "sha512-IC1dpVSc2F/pmwCxOb0QzH2xnGKmyT7MofPGhNkeaoiMrLMU+Oc7xV/AxGnz40mURtCtaDchZSM3tDo9c9x6BA==",
"requires": {
"@slack/types": "^1.2.1",
"@types/node": ">=8.9.0",
"axios": "^0.19.0"
},
"dependencies": {
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"requires": {
"follow-redirects": "1.5.10"
}
}
"axios": "^0.21.1"
}
},
"@szmarczak/http-timer": {
@ -1773,9 +1753,9 @@
}
},
"apidoc": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.25.0.tgz",
"integrity": "sha512-5g9fp8OffXZOdBTzm4BBvV5Vw54s+NmKnGZIUKuH+gRTqqJuRJpcGN6sz6WnjJ+NcvXhB7rIRp6FhtJahazx2Q==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.26.0.tgz",
"integrity": "sha512-IEw/Z7HMMbjeVjK2sZvZSwAln8AqalLzf3qLDtkcedXVhdxGm6W7UgIW6fshegqNTMLzm8CFEMi4Lxbeu0xKTw==",
"requires": {
"apidoc-core": "^0.12.0",
"commander": "^2.20.0",
@ -1795,15 +1775,10 @@
"uc.micro": "^1.0.1"
}
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"markdown-it": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.0.tgz",
"integrity": "sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg==",
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.1.tgz",
"integrity": "sha512-aU1TzmBKcWNNYvH9pjq6u92BML+Hz3h5S/QpfTFwiQF852pLT+9qHsrhM9JYipkOXZxGn+sGH8oyJE9FD9WezQ==",
"requires": {
"argparse": "^1.0.7",
"entities": "~2.0.0",
@ -1827,15 +1802,13 @@
"semver": "~7.3.2"
},
"dependencies": {
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
"requires": {
"lru-cache": "^6.0.0"
}
}
}
},
@ -1857,23 +1830,13 @@
}
},
"apple-auth": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/apple-auth/-/apple-auth-1.0.6.tgz",
"integrity": "sha512-dICsYIHBTX+7/1xdJZ4y4U08zOxEnL67GQ77l/HSKqEx9uC1wsY5dNjgbZf2F/1QnzAxDbAAHo0DgUCrA1k7zQ==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/apple-auth/-/apple-auth-1.0.7.tgz",
"integrity": "sha512-vfJqy4KtT5KHflxBSemc0mkWuy2GU2wHWaZ6xVWUjPmiXkJcLj5jB3IeCbDLF4wN+ZStjOQXZWfGwccBjclVlA==",
"requires": {
"axios": "^0.19.0",
"axios": "^0.21.1",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1"
},
"dependencies": {
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"requires": {
"follow-redirects": "1.5.10"
}
}
}
},
"aproba": {
@ -8226,12 +8189,19 @@
}
},
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
"universalify": "^2.0.0"
},
"dependencies": {
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
}
}
},
"jsonwebtoken": {
@ -8310,9 +8280,9 @@
}
},
"jwks-rsa": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.12.1.tgz",
"integrity": "sha512-N7RsfrzK3+S+SqKEEhWF7Ak87Gzg0KcZq/f8h0VqL2ur3nTB6pi5J12uelGAzB3VfhWQI+zfolHE2XDu/EI7Hg==",
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.12.2.tgz",
"integrity": "sha512-6gPo/mQUxXJt75oPtjhM3Jm3FSXnmwg73QDA8dpgP7YmIKlIY+2StngFxt4w4Y1podtSbtV3jttNOdctuxAX1Q==",
"requires": {
"@types/express-jwt": "0.0.42",
"axios": "^0.21.1",
@ -9361,9 +9331,9 @@
}
},
"mongoose": {
"version": "5.11.10",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.10.tgz",
"integrity": "sha512-daE2L6VW7WNywv7tL2KUkBViWvODbzr50Of1kJpIbzW3w3N5/TYcgSmhCsEDWfYGQXbun2rdd7+sOdsEC8zQSQ==",
"version": "5.11.11",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.11.tgz",
"integrity": "sha512-JgKKAosJf6medPOZi2LmO7sMz7Sg00mgjyPAKari3alzL+R/n8D+zKK29iGtJpNNtv9IKy14H37CWuiaZ7016w==",
"requires": {
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4",
@ -9628,9 +9598,9 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
},
"nconf": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/nconf/-/nconf-0.11.0.tgz",
"integrity": "sha512-c4W7QqYF6p5BC7J/eVTOvtUlQgvS5CgbJ11xgjhSr8yyius7km7xgdIYHkFLR4TWY1HjsFkia/3l5OprGqCHvA==",
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/nconf/-/nconf-0.11.1.tgz",
"integrity": "sha512-2XY+7x3GwkkTnmkEVxsKykg0GUqCAtBZUA87FwbcUSaYBfaGCeVSf+82zap16j93B21J2AhpxrsF57jio36t0w==",
"requires": {
"async": "^1.4.0",
"ini": "^1.3.0",
@ -9708,9 +9678,9 @@
"integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg=="
},
"yargs": {
"version": "16.1.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz",
"integrity": "sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==",
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
@ -11163,9 +11133,9 @@
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"rate-limiter-flexible": {
"version": "2.1.16",
"resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-2.1.16.tgz",
"integrity": "sha512-ag2ZQLS0g7+QrMpmMQf37EJ/9drSOsrslQXnOJ3OpqIgUwdjQpChu8CLNz4GWOr9sJq+RGVYDwAcJjYK8hHCqA=="
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-2.2.1.tgz",
"integrity": "sha512-rxCP6kDDdn0cZmVqVlF06yLU+mG3TuwaHV/fUIw3OQyYhza7pzVBtdMhUmfXbBzMS+O464XP+x33pfTDGRGYVA=="
},
"raw-body": {
"version": "2.4.0",
@ -12031,14 +12001,13 @@
}
},
"sinon": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.2.tgz",
"integrity": "sha512-9Owi+RisvCZpB0bdOVFfL314I6I4YoRlz6Isi4+fr8q8YQsDPoCe5UnmNtKHRThX3negz2bXHWIuiPa42vM8EQ==",
"version": "9.2.3",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.3.tgz",
"integrity": "sha512-m+DyAWvqVHZtjnjX/nuShasykFeiZ+nPuEfD4G3gpvKGkXRhkF/6NSt2qN2FjZhfrcHXFzUzI+NLnk+42fnLEw==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1.8.1",
"@sinonjs/fake-timers": "^6.0.1",
"@sinonjs/formatio": "^5.0.1",
"@sinonjs/samsam": "^5.3.0",
"diff": "^4.0.2",
"nise": "^4.0.4",
@ -12724,9 +12693,9 @@
}
},
"stripe": {
"version": "8.129.0",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-8.129.0.tgz",
"integrity": "sha512-73b49GQg2+ig6Cet11QhN1WgBab+2xtHy57W4ZLRd9dq146vz+vik+kMQ7UAcTSF5vYyTM5Zo6POMZDPXqzWUg==",
"version": "8.130.0",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-8.130.0.tgz",
"integrity": "sha512-9e283EFhxDz7SUcgNiUFRdTZ/kS2IkoT0KBMOJHdf3vY+mvURq355s2E0Zyy9rtNmt+CEZ0nCMiZ3PqIqpp6Pg==",
"requires": {
"@types/node": ">=8.1.0",
"qs": "^6.6.0"

View file

@ -9,12 +9,12 @@
"@babel/register": "^7.12.10",
"@google-cloud/trace-agent": "^5.1.1",
"@parse/node-apn": "^4.0.0",
"@slack/webhook": "^5.0.3",
"@slack/webhook": "^5.0.4",
"accepts": "^1.3.5",
"amazon-payments": "^0.2.8",
"amplitude": "^5.1.4",
"apidoc": "^0.25.0",
"apple-auth": "^1.0.6",
"apidoc": "^0.26.0",
"apple-auth": "^1.0.7",
"bcrypt": "^5.0.0",
"body-parser": "^1.18.3",
"compression": "^1.7.4",
@ -42,15 +42,15 @@
"in-app-purchase": "^1.11.3",
"js2xmlparser": "^4.0.1",
"jsonwebtoken": "^8.5.1",
"jwks-rsa": "^1.12.1",
"jwks-rsa": "^1.12.2",
"lodash": "^4.17.20",
"merge-stream": "^2.0.0",
"method-override": "^3.0.0",
"moment": "^2.29.1",
"moment-recur": "^1.0.7",
"mongoose": "^5.11.10",
"mongoose": "^5.11.11",
"morgan": "^1.10.0",
"nconf": "^0.11.0",
"nconf": "^0.11.1",
"node-gcm": "^1.0.3",
"on-headers": "^1.0.2",
"passport": "^0.4.1",
@ -60,13 +60,13 @@
"paypal-rest-sdk": "^1.8.1",
"pp-ipn": "^1.1.0",
"ps-tree": "^1.0.0",
"rate-limiter-flexible": "^2.1.16",
"rate-limiter-flexible": "^2.2.1",
"redis": "^3.0.2",
"regenerator-runtime": "^0.13.7",
"remove-markdown": "^0.3.0",
"rimraf": "^3.0.2",
"short-uuid": "^4.1.0",
"stripe": "^8.129.0",
"stripe": "^8.130.0",
"superagent": "^6.1.0",
"universal-analytics": "^0.4.23",
"useragent": "^2.1.9",
@ -121,7 +121,7 @@
"monk": "^7.3.2",
"require-again": "^2.0.0",
"run-rs": "^0.7.3",
"sinon": "^9.2.2",
"sinon": "^9.2.3",
"sinon-chai": "^3.5.0",
"sinon-stub-promise": "^4.0.0"
},

View file

@ -8,9 +8,14 @@ import {
describe('POST /tasks/user', () => {
let user;
let tzoffset;
before(async () => {
tzoffset = new Date().getTimezoneOffset();
});
beforeEach(async () => {
user = await generateUser();
user = await generateUser({ 'preferences.timezoneOffset': tzoffset });
});
context('validates params', async () => {
@ -544,7 +549,7 @@ describe('POST /tasks/user', () => {
expect(task.everyX).to.eql(5);
expect(task.daysOfMonth).to.eql([15]);
expect(task.weeksOfMonth).to.eql([3]);
expect(new Date(task.startDate)).to.eql(now);
expect(new Date(task.startDate)).to.eql(new Date(now.setHours(0, 0, 0, 0)));
expect(task.isDue).to.be.true;
expect(task.nextDue.length).to.eql(6);
});

View file

@ -10,9 +10,14 @@ import {
describe('PUT /tasks/:id', () => {
let user;
let tzoffset;
before(async () => {
tzoffset = (new Date()).getTimezoneOffset();
});
beforeEach(async () => {
user = await generateUser();
user = await generateUser({ 'preferences.timezoneOffset': tzoffset });
});
context('validates params', () => {
@ -503,7 +508,8 @@ describe('PUT /tasks/:id', () => {
let monthly;
beforeEach(async () => {
const date1 = moment.utc('2020-07-01').toDate();
// using date literals is discouraged here, daylight savings will break everything
const date1 = moment().toDate();
monthly = await user.post('/tasks/user', {
text: 'test monthly',
type: 'daily',
@ -514,7 +520,7 @@ describe('PUT /tasks/:id', () => {
});
it('updates days of month when start date updated', async () => {
const date2 = moment.utc('2020-07-01').toDate();
const date2 = moment().add(6, 'months').toDate();
const savedMonthly = await user.put(`/tasks/${monthly._id}`, {
startDate: date2,
});
@ -523,18 +529,30 @@ describe('PUT /tasks/:id', () => {
});
it('updates next due when start date updated', async () => {
const date2 = moment.utc('2022-07-01').toDate();
const date2 = moment().add(6, 'months').toDate();
const savedMonthly = await user.put(`/tasks/${monthly._id}`, {
startDate: date2,
});
expect(savedMonthly.nextDue.length).to.eql(6);
expect(moment(savedMonthly.nextDue[0]).toDate()).to.eql(moment.utc('2022-08-01').toDate());
expect(moment(savedMonthly.nextDue[1]).toDate()).to.eql(moment.utc('2022-09-01').toDate());
expect(moment(savedMonthly.nextDue[2]).toDate()).to.eql(moment.utc('2022-10-01').toDate());
expect(moment(savedMonthly.nextDue[3]).toDate()).to.eql(moment.utc('2022-11-01').toDate());
expect(moment(savedMonthly.nextDue[4]).toDate()).to.eql(moment.utc('2022-12-01').toDate());
expect(moment(savedMonthly.nextDue[5]).toDate()).to.eql(moment.utc('2023-01-01').toDate());
expect(moment(savedMonthly.nextDue[0]).toDate()).to.eql(
moment(date2).add(1, 'months').startOf('day').toDate(),
);
expect(moment(savedMonthly.nextDue[1]).toDate()).to.eql(
moment(date2).add(2, 'months').startOf('day').toDate(),
);
expect(moment(savedMonthly.nextDue[2]).toDate()).to.eql(
moment(date2).add(3, 'months').startOf('day').toDate(),
);
expect(moment(savedMonthly.nextDue[3]).toDate()).to.eql(
moment(date2).add(4, 'months').startOf('day').toDate(),
);
expect(moment(savedMonthly.nextDue[4]).toDate()).to.eql(
moment(date2).add(5, 'months').startOf('day').toDate(),
);
expect(moment(savedMonthly.nextDue[5]).toDate()).to.eql(
moment(date2).add(6, 'months').startOf('day').toDate(),
);
});
});

View file

@ -11,13 +11,18 @@ describe('POST /tasks/challenge/:challengeId', () => {
let user;
let guild;
let challenge;
let tzoffset;
function findUserChallengeTask (memberTask) {
return memberTask.challenge.id === challenge._id;
}
before(async () => {
tzoffset = new Date().getTimezoneOffset();
});
beforeEach(async () => {
user = await generateUser({ balance: 1 });
user = await generateUser({ balance: 1, 'preferences.timezoneOffset': tzoffset });
guild = await generateGroup(user);
challenge = await generateChallenge(user, guild);
await user.post(`/challenges/${challenge._id}/join`);
@ -165,7 +170,7 @@ describe('POST /tasks/challenge/:challengeId', () => {
expect(task.type).to.eql('daily');
expect(task.frequency).to.eql('daily');
expect(task.everyX).to.eql(5);
expect(new Date(task.startDate)).to.eql(now);
expect(new Date(task.startDate)).to.eql(new Date(now.setHours(0, 0, 0, 0)));
expect(userChallengeTask.notes).to.eql(task.notes);
});

View file

@ -12,7 +12,7 @@ describe('PUT /tasks/:id', () => {
let challenge;
before(async () => {
user = await generateUser();
user = await generateUser({ 'preferences.timezoneOffset': new Date().getTimezoneOffset() });
guild = await generateGroup(user);
challenge = await generateChallenge(user, guild);
await user.post(`/challenges/${challenge._id}/join`);

View file

@ -8,12 +8,18 @@ import {
describe('POST /tasks/group/:groupid', () => {
let user; let guild; let
manager;
let tzoffset;
const groupName = 'Test Public Guild';
const groupType = 'guild';
before(async () => {
tzoffset = new Date().getTimezoneOffset();
});
beforeEach(async () => {
user = await generateUser({ balance: 1 });
// user = await generateUser({ balance: 1, 'preferences.timezoneOffset': tzoffset });
const { group, groupLeader, members } = await createAndPopulateGroup({
leaderDetails: { balance: 10, 'preferences.timezoneOffset': tzoffset },
groupDetails: {
name: groupName,
type: groupType,
@ -128,7 +134,7 @@ describe('POST /tasks/group/:groupid', () => {
expect(task.type).to.eql('daily');
expect(task.frequency).to.eql('daily');
expect(task.everyX).to.eql(5);
expect(new Date(task.startDate)).to.eql(now);
expect(new Date(task.startDate)).to.eql(new Date(now.setHours(0, 0, 0, 0)));
});
it('allows a manager to add a group task', async () => {

File diff suppressed because it is too large Load diff

View file

@ -18,13 +18,13 @@
"@storybook/addon-links": "^5.3.19",
"@storybook/addon-notes": "^5.3.21",
"@storybook/vue": "^5.3.19",
"@vue/cli-plugin-babel": "^4.5.9",
"@vue/cli-plugin-eslint": "^4.5.9",
"@vue/cli-plugin-router": "^4.5.9",
"@vue/cli-plugin-unit-mocha": "^4.5.9",
"@vue/cli-service": "^4.5.9",
"@vue/cli-plugin-babel": "^4.5.10",
"@vue/cli-plugin-eslint": "^4.5.10",
"@vue/cli-plugin-router": "^4.5.10",
"@vue/cli-plugin-unit-mocha": "^4.5.10",
"@vue/cli-service": "^4.5.10",
"@vue/test-utils": "1.0.0-beta.29",
"amplitude-js": "^7.3.3",
"amplitude-js": "^7.4.0",
"axios": "^0.21.1",
"axios-progress-bar": "^1.2.0",
"babel-eslint": "^10.1.0",
@ -43,8 +43,8 @@
"jquery": "^3.5.1",
"lodash": "^4.17.20",
"moment": "^2.29.1",
"nconf": "^0.11.0",
"sass": "^1.32.0",
"nconf": "^0.11.1",
"sass": "^1.32.2",
"sass-loader": "^8.0.2",
"smartbanner.js": "^1.16.0",
"svg-inline-loader": "^0.8.2",
@ -60,6 +60,6 @@
"vue-template-compiler": "^2.6.12",
"vuedraggable": "^2.24.3",
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#153d339e4dbebb73733658aeda1d5b7fcc55b0a0",
"webpack": "^4.44.2"
"webpack": "^4.45.0"
}
}

View file

@ -92,6 +92,7 @@
"PMUnblockUserToSendMessages": "Unblock this user to continue sending and receiving messages.",
"block": "Block",
"unblock": "Un-block",
"blockYourself": "You cannot block yourself",
"blockWarning": "Block - This will have no effect if the player is a moderator now or becomes a moderator in future.",
"inbox": "Inbox",
"messageRequired": "A message is required.",

View file

@ -2916,6 +2916,7 @@ const weapon = {
notes: t('weaponSpecialSummer2019MageNotes', { int: 15 }),
value: 90,
int: 15,
per: 0,
twoHanded: false,
canBuy: () => CURRENT_EVENT && CURRENT_EVENT.season === 'summer',
},

View file

@ -678,18 +678,29 @@ api.updateTask = {
task.group.managerNotes = sanitizedObj.managerNotes;
}
// If the daily task was set to repeat monthly on a day of the month, and the start date was
// updated, the task will then need to be updated to repeat on the same day of the month as the
// new start date. For example, if the start date is updated to 7/2/2020, the daily should
// repeat on the 2nd day of the month. It's possible that a task can repeat monthly on a
// week of the month, in which case we won't update the repetition at all.
if (
task.type === 'daily'
&& task.frequency === 'monthly'
&& task.daysOfMonth.length
&& task.startDate
// For daily tasks, update start date based on timezone to maintain consistency
if (task.type === 'daily'
&& task.startDate
) {
task.daysOfMonth = [moment(task.startDate).date()];
task.startDate = moment(task.startDate).utcOffset(
-user.preferences.timezoneOffset,
).startOf('day').toDate();
// If the daily task was set to repeat monthly on a day of the month, and the start date was
// updated, the task will then need to be updated to repeat on the same day of the month as
// the new start date. For example, if the start date is updated to 7/2/2020, the daily
// should repeat on the 2nd day of the month. It's possible that a task can repeat monthly
// on a week of the month, in which case we won't update the repetition at all.
if (
task.frequency === 'monthly'
&& task.daysOfMonth.length
) {
// We also need to aware of the user's timezone. Start date is represented as UTC, so the
// start date and day of month might be different
task.daysOfMonth = [moment(task.startDate).utcOffset(
-user.preferences.timezoneOffset,
).date()];
}
}
setNextDue(task, user);

View file

@ -124,6 +124,15 @@ export async function createTasks (req, res, options = {}) {
}
}
// set startDate to midnight in the user's timezone
if (taskType === 'daily') {
const awareStartDate = moment(newTask.startDate).utcOffset(-user.preferences.timezoneOffset);
if (awareStartDate.format('HMsS') !== '0000') {
awareStartDate.startOf('day');
newTask.startDate = awareStartDate.toDate();
}
}
setNextDue(newTask, user);
// Validate that the task is valid and throw if it isn't

View file

@ -378,7 +378,7 @@ export const DailySchema = new Schema(_.defaults({
startDate: {
$type: Date,
default () {
return moment().startOf('day').toDate();
return moment.utc().toDate();
},
required: true,
},