mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
Merge branch 'release' into develop
This commit is contained in:
2
npm-shrinkwrap.json
generated
2
npm-shrinkwrap.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"version": "3.101.0",
|
"version": "3.101.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gulp-sourcemaps/map-sources": {
|
"@gulp-sourcemaps/map-sources": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"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": "3.101.0",
|
"version": "3.101.1",
|
||||||
"main": "./website/server/index.js",
|
"main": "./website/server/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@slack/client": "^3.8.1",
|
"@slack/client": "^3.8.1",
|
||||||
|
|||||||
@@ -130,7 +130,8 @@ describe('GET /tasks/user', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns dailies with isDue for the date specified', async () => {
|
it('returns dailies with isDue for the date specified', async () => {
|
||||||
let startDate = moment().subtract('1', 'days').toDate();
|
// @TODO Add required format
|
||||||
|
let startDate = moment().subtract('1', 'days').toISOString();
|
||||||
let createdTasks = await user.post('/tasks/user', [
|
let createdTasks = await user.post('/tasks/user', [
|
||||||
{
|
{
|
||||||
text: 'test daily',
|
text: 'test daily',
|
||||||
@@ -150,4 +151,28 @@ describe('GET /tasks/user', () => {
|
|||||||
expect(dailys2[0]._id).to.equal(createdTasks._id);
|
expect(dailys2[0]._id).to.equal(createdTasks._id);
|
||||||
expect(dailys2[0].isDue).to.be.true;
|
expect(dailys2[0].isDue).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns dailies with isDue for the date specified and will add CDS offset if time is not supplied', async () => {
|
||||||
|
await user.update({
|
||||||
|
'preferences.dayStart': 7,
|
||||||
|
});
|
||||||
|
let startDate = moment().subtract('4', 'days').startOf('day').toISOString();
|
||||||
|
await user.post('/tasks/user', [
|
||||||
|
{
|
||||||
|
text: 'test daily',
|
||||||
|
type: 'daily',
|
||||||
|
startDate,
|
||||||
|
frequency: 'daily',
|
||||||
|
everyX: 2,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
let today = moment().format('YYYY-MM-DD');
|
||||||
|
let dailys = await user.get(`/tasks/user?type=dailys&dueDate=${today}`);
|
||||||
|
expect(dailys[0].isDue).to.be.true;
|
||||||
|
|
||||||
|
let yesterday = moment().subtract('1', 'days').format('YYYY-MM-DD');
|
||||||
|
let dailys2 = await user.get(`/tasks/user?type=dailys&dueDate=${yesterday}`);
|
||||||
|
expect(dailys2[0].isDue).to.be.false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
habitrpg.controller('NotificationCtrl',
|
habitrpg.controller('NotificationCtrl',
|
||||||
['$scope', '$rootScope', 'Shared', 'Content', 'User', 'Guide', 'Notification', 'Analytics', 'Achievement', 'Social', 'Tasks',
|
['$scope', '$rootScope', 'Shared', 'Content', 'User', 'Guide', 'Notification', 'Analytics', 'Achievement', 'Social', 'Tasks',
|
||||||
function ($scope, $rootScope, Shared, Content, User, Guide, Notification, Analytics, Achievement, Social, Tasks) {
|
function ($scope, $rootScope, Shared, Content, User, Guide, Notification, Analytics, Achievement, Social, Tasks) {
|
||||||
|
var isRunningYesterdailies = false;
|
||||||
|
|
||||||
$rootScope.$watch('user', function (after, before) {
|
$rootScope.$watch('user', function (after, before) {
|
||||||
runYesterDailies();
|
runYesterDailies();
|
||||||
});
|
});
|
||||||
@@ -12,13 +14,17 @@ habitrpg.controller('NotificationCtrl',
|
|||||||
});
|
});
|
||||||
|
|
||||||
function runYesterDailies() {
|
function runYesterDailies() {
|
||||||
|
if (isRunningYesterdailies) return;
|
||||||
|
|
||||||
var userLastCron = moment(User.user.lastCron).local();
|
var userLastCron = moment(User.user.lastCron).local();
|
||||||
var userDayStart = moment().startOf('day').add({ hours: User.user.preferences.dayStart });
|
var userDayStart = moment().startOf('day').add({ hours: User.user.preferences.dayStart });
|
||||||
|
|
||||||
if (!User.user.needsCron) return;
|
if (!User.user.needsCron) return;
|
||||||
var dailys = User.user.dailys;
|
var dailys = User.user.dailys;
|
||||||
|
|
||||||
if (!Boolean(dailys) || dailys.length === 0) return;
|
if (!$rootScope.appLoaded) return;
|
||||||
|
|
||||||
|
isRunningYesterdailies = true;
|
||||||
|
|
||||||
var yesterDay = moment().subtract('1', 'day').startOf('day').add({ hours: User.user.preferences.dayStart });
|
var yesterDay = moment().subtract('1', 'day').startOf('day').add({ hours: User.user.preferences.dayStart });
|
||||||
var yesterDailies = [];
|
var yesterDailies = [];
|
||||||
@@ -31,7 +37,9 @@ habitrpg.controller('NotificationCtrl',
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (yesterDailies.length === 0) {
|
if (yesterDailies.length === 0) {
|
||||||
User.runCron();
|
User.runCron().then(function () {
|
||||||
|
isRunningYesterdailies = false;
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +69,10 @@ habitrpg.controller('NotificationCtrl',
|
|||||||
});
|
});
|
||||||
|
|
||||||
$scope.ageDailies = function () {
|
$scope.ageDailies = function () {
|
||||||
User.runCron();
|
User.runCron()
|
||||||
|
.then(function () {
|
||||||
|
isRunningYesterdailies = false;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ angular.module('habitrpg')
|
|||||||
},
|
},
|
||||||
|
|
||||||
runCron: function () {
|
runCron: function () {
|
||||||
$http({
|
return $http({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: 'api/v3/cron',
|
url: 'api/v3/cron',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export function shouldDo (day, dailyTask, options = {}) {
|
|||||||
}
|
}
|
||||||
let o = sanitizeOptions(options);
|
let o = sanitizeOptions(options);
|
||||||
let startOfDayWithCDSTime = startOfDay(defaults({ now: day }, o));
|
let startOfDayWithCDSTime = startOfDay(defaults({ now: day }, o));
|
||||||
|
|
||||||
// The time portion of the Start Date is never visible to or modifiable by the user so we must ignore it.
|
// The time portion of the Start Date is never visible to or modifiable by the user so we must ignore it.
|
||||||
// Therefore, we must also ignore the time portion of the user's day start (startOfDayWithCDSTime), otherwise the date comparison will be wrong for some times.
|
// Therefore, we must also ignore the time portion of the user's day start (startOfDayWithCDSTime), otherwise the date comparison will be wrong for some times.
|
||||||
// NB: The user's day start date has already been converted to the PREVIOUS day's date if the time portion was before CDS.
|
// NB: The user's day start date has already been converted to the PREVIOUS day's date if the time portion was before CDS.
|
||||||
|
|||||||
@@ -26,10 +26,21 @@ async function _validateTaskAlias (tasks, res) {
|
|||||||
export function setNextDue (task, user, dueDateOption) {
|
export function setNextDue (task, user, dueDateOption) {
|
||||||
if (task.type !== 'daily') return;
|
if (task.type !== 'daily') return;
|
||||||
|
|
||||||
|
let now = moment().toDate();
|
||||||
let dateTaskIsDue = Date.now();
|
let dateTaskIsDue = Date.now();
|
||||||
if (dueDateOption) dateTaskIsDue = moment(dueDateOption);
|
if (dueDateOption) {
|
||||||
|
dateTaskIsDue = moment(dueDateOption);
|
||||||
|
// If not time is supplied. Let's assume we want start of Custom Day Start day.
|
||||||
|
if (dateTaskIsDue.hour() === 0 && dateTaskIsDue.minute() === 0 && dateTaskIsDue.second() === 0 && dateTaskIsDue.millisecond() === 0) {
|
||||||
|
dateTaskIsDue.add(user.preferences.dayStart, 'hours');
|
||||||
|
}
|
||||||
|
|
||||||
|
now = dateTaskIsDue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let optionsForShouldDo = user.preferences.toObject();
|
let optionsForShouldDo = user.preferences.toObject();
|
||||||
|
optionsForShouldDo.now = now;
|
||||||
task.isDue = shared.shouldDo(dateTaskIsDue, task, optionsForShouldDo);
|
task.isDue = shared.shouldDo(dateTaskIsDue, task, optionsForShouldDo);
|
||||||
optionsForShouldDo.nextDue = true;
|
optionsForShouldDo.nextDue = true;
|
||||||
let nextDue = shared.shouldDo(dateTaskIsDue, task, optionsForShouldDo);
|
let nextDue = shared.shouldDo(dateTaskIsDue, task, optionsForShouldDo);
|
||||||
@@ -176,6 +187,12 @@ export async function getTasks (req, res, options = {}) {
|
|||||||
|
|
||||||
let tasks = await mQuery.exec();
|
let tasks = await mQuery.exec();
|
||||||
|
|
||||||
|
if (dueDate) {
|
||||||
|
tasks.forEach((task) => {
|
||||||
|
setNextDue(task, user, dueDate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Order tasks based on tasksOrder
|
// Order tasks based on tasksOrder
|
||||||
if (type && type !== 'completedTodos' && type !== '_allCompletedTodos') {
|
if (type && type !== 'completedTodos' && type !== '_allCompletedTodos') {
|
||||||
let order = owner.tasksOrder[type];
|
let order = owner.tasksOrder[type];
|
||||||
@@ -190,8 +207,6 @@ export async function getTasks (req, res, options = {}) {
|
|||||||
} else {
|
} else {
|
||||||
orderedTasks[i] = task;
|
orderedTasks[i] = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dueDate) setNextDue(task, user, dueDate);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove empty values from the array and add any unordered task
|
// Remove empty values from the array and add any unordered task
|
||||||
|
|||||||
Reference in New Issue
Block a user