diff --git a/website/client-old/js/services/taskServices.js b/website/client-old/js/services/taskServices.js index 52d763c8a7..195258b3f2 100644 --- a/website/client-old/js/services/taskServices.js +++ b/website/client-old/js/services/taskServices.js @@ -283,7 +283,7 @@ angular.module('habitrpg') modalScope.cancelTaskEdit = cancelTaskEdit; modalScope.task._edit.repeatsOn = 'dayOfMonth'; - if (modalScope.task === 'daily' && modalScope.task._edit.weeksOfMonth.length > 0) { + if (modalScope.task.type === 'daily' && modalScope.task._edit.weeksOfMonth && modalScope.task._edit.weeksOfMonth.length > 0) { modalScope.task._edit.repeatsOn = 'dayOfWeek'; } @@ -292,20 +292,19 @@ angular.module('habitrpg') templateUrl: 'modals/task-edit.html', controller: ['$scope', function ($scope) { $scope.$watch('task._edit', function (newValue, oldValue) { - if ($scope.task.type !== 'daily') return; + if ($scope.task.type !== 'daily' || !task._edit) return; $scope.summary = generateSummary($scope.task); $scope.repeatSuffix = generateRepeatSuffix($scope.task); - if ($scope.task._edit.repeatsOn == 'dayOfMonth') { - var date = moment().date(); + var date = moment(task._edit.startDate).date(); $scope.task._edit.weeksOfMonth = []; - $scope.task._edit.dayOfMonth = [date]; // @TODO This can handle multiple dates later + $scope.task._edit.daysOfMonth = [date]; // @TODO This can handle multiple dates later } else if ($scope.task._edit.repeatsOn == 'dayOfWeek') { - var week = Math.ceil(moment().date() / 7) - 1; - var dayOfWeek = moment().day(); + var week = Math.ceil(moment(task._edit.startDate).date() / 7) - 1; + var dayOfWeek = moment(task._edit.startDate).day(); var shortDay = numberToShortDay[dayOfWeek]; - $scope.task._edit.dayOfMonth = []; + $scope.task._edit.daysOfMonth = []; $scope.task._edit.weeksOfMonth = [week]; // @TODO: This can handle multiple weeks for (var key in $scope.task._edit.repeat) { $scope.task._edit.repeat[key] = false; @@ -358,11 +357,11 @@ angular.module('habitrpg') if (task._edit.frequency === 'weekly') summary += ' on ' + repeatDays; if (task._edit.frequency === 'monthly' && task._edit.repeatsOn == 'dayOfMonth') { - var date = moment().date(); + var date = moment(task._edit.startDate).date(); summary += ' on the ' + date; } else if (task._edit.frequency === 'monthly' && task._edit.repeatsOn == 'dayOfWeek') { - var week = Math.ceil(moment().date() / 7) - 1; - var dayOfWeek = moment().day(); + var week = Math.ceil(moment(task._edit.startDate).date() / 7) - 1; + var dayOfWeek = moment(task._edit.startDate).day(); var shortDay = numberToShortDay[dayOfWeek]; var longDay = shortDayToLongDayMap[shortDay]; diff --git a/website/common/locales/en/tasks.json b/website/common/locales/en/tasks.json index 8079d12eb7..d10959dc2a 100644 --- a/website/common/locales/en/tasks.json +++ b/website/common/locales/en/tasks.json @@ -163,5 +163,7 @@ "years": "Years", "confirmScoreNotes": "Confirm task scoring with notes", "taskScoreNotesTooLong": "Task score notes must be less than 256 characters", - "groupTasksByChallenge": "Group tasks by challenge title" + "groupTasksByChallenge": "Group tasks by challenge title", + "monthlyRepeatHelpContent": "This task will be due every X months", + "yearlyRepeatHelpContent": "This task will be due every X years" } diff --git a/website/common/script/cron.js b/website/common/script/cron.js index a473cad539..6b9dc6a16c 100644 --- a/website/common/script/cron.js +++ b/website/common/script/cron.js @@ -97,6 +97,9 @@ export function shouldDo (day, dailyTask) { return false; } + day = moment(day).startOf('day').toDate(); + let startDate = moment(dailyTask.startDate).startOf('day').toDate(); + let daysOfTheWeek = []; if (dailyTask.repeat) { @@ -105,14 +108,13 @@ export function shouldDo (day, dailyTask) { } } - if (dailyTask.frequency === 'daily') { if (!dailyTask.everyX) return false; // error condition - let schedule = moment(dailyTask.startDate).recur() + let schedule = moment(startDate).recur() .every(dailyTask.everyX).days(); return schedule.matches(day); } else if (dailyTask.frequency === 'weekly') { - let schedule = moment(dailyTask.startDate).recur(); + let schedule = moment(startDate).recur(); if (dailyTask.everyX > 1) { schedule = schedule.every(dailyTask.everyX).weeks(); @@ -122,21 +124,21 @@ export function shouldDo (day, dailyTask) { return schedule.matches(day); } else if (dailyTask.frequency === 'monthly') { - let schedule = moment(dailyTask.startDate).recur(); + let schedule = moment(startDate).recur(); - let differenceInMonths = moment(day).month() + 1 - moment(dailyTask.startDate).month() + 1; + let differenceInMonths = moment(day).month() + 1 - moment(startDate).month() + 1; let matchEveryX = differenceInMonths % dailyTask.everyX === 0; - if (dailyTask.weeksOfMonth) { + if (dailyTask.weeksOfMonth && dailyTask.weeksOfMonth.length > 0) { schedule = schedule.every(daysOfTheWeek).daysOfWeek() .every(dailyTask.weeksOfMonth).weeksOfMonthByDay(); - } else if (dailyTask.daysOfMonth) { + } else if (dailyTask.daysOfMonth && dailyTask.daysOfMonth.length > 0) { schedule = schedule.every(dailyTask.daysOfMonth).daysOfMonth(); } return schedule.matches(day) && matchEveryX; } else if (dailyTask.frequency === 'yearly') { - let schedule = moment(dailyTask.startDate).recur(); + let schedule = moment(startDate).recur(); schedule = schedule.every(dailyTask.everyX).years(); diff --git a/website/common/script/libs/taskClasses.js b/website/common/script/libs/taskClasses.js index 9ef223d9f7..f1082a9f8d 100644 --- a/website/common/script/libs/taskClasses.js +++ b/website/common/script/libs/taskClasses.js @@ -34,9 +34,10 @@ module.exports = function taskClasses (task, filters = [], dayStart = 0, lastCro } if (type === 'todo' || type === 'daily') { - if (completed || (type === 'daily' && !shouldDo(Number(new Date()), task, { // eslint-disable-line no-extra-parens - dayStart, - }))) { + let notDue = !shouldDo(Number(new Date()), task, { dayStart }); + let isNotDueDaily = type === 'daily' && notDue; + + if (completed || isNotDueDaily) { classes += ' completed'; } else { classes += ' uncompleted'; diff --git a/website/common/script/ops/updateTask.js b/website/common/script/ops/updateTask.js index 08f32a0ea5..379ac73caa 100644 --- a/website/common/script/ops/updateTask.js +++ b/website/common/script/ops/updateTask.js @@ -22,5 +22,14 @@ module.exports = function updateTask (task, req = {}) { merge(task, omit(body, ['_id', 'id', 'type', 'reminders', 'checklist', 'tags'])); + // Ensure arrays are emptied + if (body.daysOfMonth && body.daysOfMonth.length === 0) { + task.daysOfMonth = []; + } + + if (body.weeksOfMonth && body.weeksOfMonth.length === 0) { + task.weeksOfMonth = []; + } + return [task]; }; diff --git a/website/views/shared/tasks/edit/advanced_options.jade b/website/views/shared/tasks/edit/advanced_options.jade index 63bf57fbd6..6b32d520de 100644 --- a/website/views/shared/tasks/edit/advanced_options.jade +++ b/website/views/shared/tasks/edit/advanced_options.jade @@ -14,47 +14,6 @@ div(ng-if='(task.type !== "reward") || (!obj.auth && obj.purchased && obj.purcha fieldset.option-group.advanced-option(ng-show="task._edit._advanced", ng-if="!obj.auth && obj.purchased && obj.purchased.active") group-tasks-actions(task='task', group='obj') - div(ng-show='task._edit._advanced') - div(ng-if='::task.type == "daily"') - .form-group - legend.option-title - span.hint(popover-title=env.t('startDateHelpTitle'), popover=env.t("startDateHelp"), popover-trigger='mouseenter') - =env.t('startDate') - - input.form-control(type='text', ng-model='task._edit.startDate', - datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened', - ng-click='datepickerOpened = true', ng-disabled='!canEdit(task)') - - hr - - fieldset.option-group.advanced-option(ng-show="task._edit._advanced && task.type !== 'reward'") - select.form-control(ng-model='task._edit.frequency', ng-disabled='!canEdit(task)') - option(value='daily')=env.t('daily') - option(value='weekly')=env.t('weekly') - option(value='monthly')=env.t('monthly') - option(value='yearly')=env.t('yearly') - - //- select.form-control(ng-model='task._edit.frequency', ng-disabled='!canEdit(task)') - //- option(value='weekly')=env.t('repeatWeek') - //- option(value='daily')=env.t('repeatDays') - - include ./dailies/repeat_options - - .form-group(ng-show='task._edit.frequency === "monthly"') - legend.option-title=env.t('repeatsOn') - label - input(type="radio", ng-model='task._edit.repeatsOn', value='dayOfMonth') - =env.t('dayOfMonth') - label - input(type="radio", ng-model='task._edit.repeatsOn', value='dayOfWeek') - =env.t('dayOfWeek') - - .form-group - legend.option-title=env.t('summary') - div {{summary}} - - hr - fieldset.option-group.advanced-option(ng-show="task._edit._advanced && task.type !== 'reward'") legend.option-title a.hint.priority-multiplier-help(href='http://habitica.wikia.com/wiki/Difficulty', target='_blank', popover-title=env.t('difficultyHelpTitle'), popover-trigger='mouseenter', popover=env.t('difficultyHelpContent'))=env.t('difficulty') diff --git a/website/views/shared/tasks/edit/index.jade b/website/views/shared/tasks/edit/index.jade index 25c85a2bf2..25b1070299 100644 --- a/website/views/shared/tasks/edit/index.jade +++ b/website/views/shared/tasks/edit/index.jade @@ -48,12 +48,14 @@ div(ng-if='task._editing') include ./habits/plus_minus - include ./dailies/calendar + //- include ./dailies/calendar include ./rewards/pricing include ./todos/due_date + include ./repeatables + .col-md-6 include ./tags diff --git a/website/views/shared/tasks/edit/repeatables.jade b/website/views/shared/tasks/edit/repeatables.jade new file mode 100644 index 0000000000..7a7be1cd50 --- /dev/null +++ b/website/views/shared/tasks/edit/repeatables.jade @@ -0,0 +1,35 @@ +fieldset.option-group.advanced-option(ng-show="task.type === 'daily'") + legend.option-title + span.hint(popover-title=env.t('startDateHelpTitle'), popover=env.t("startDateHelp"), popover-trigger='mouseenter') + =env.t('startDate') + + input.form-control(type='text', ng-model='task._edit.startDate', + datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened', + ng-click='datepickerOpened = true', ng-disabled='!canEdit(task)') + + br + + select.form-control(ng-model='task._edit.frequency', ng-disabled='!canEdit(task)') + option(value='daily')=env.t('daily') + option(value='weekly')=env.t('weekly') + option(value='monthly')=env.t('monthly') + option(value='yearly')=env.t('yearly') + + //- select.form-control(ng-model='task._edit.frequency', ng-disabled='!canEdit(task)') + //- option(value='weekly')=env.t('repeatWeek') + //- option(value='daily')=env.t('repeatDays') + + include ./dailies/repeat_options + + .form-group(ng-show='task._edit.frequency === "monthly"') + legend.option-title=env.t('repeatsOn') + label + input(type="radio", ng-model='task._edit.repeatsOn', value='dayOfMonth') + =env.t('dayOfMonth') + label + input(type="radio", ng-model='task._edit.repeatsOn', value='dayOfWeek') + =env.t('dayOfWeek') + + .form-group + legend.option-title=env.t('summary') + div {{summary}} \ No newline at end of file