mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 06:37:23 +01:00
Repeatables fixes (#8538)
* Prevented watch functions from being called when task._edit is removed * Added start date support on the UI task summary * Fixed setting of monthly and calculations * Fixed linting issues * Added check for existence * Added existence check * Ensured correct start date is used on update * Hid repeat options from anything not a daily * Added missing locales * Moved repeatables out of advance options
This commit is contained in:
@@ -283,7 +283,7 @@ angular.module('habitrpg')
|
|||||||
modalScope.cancelTaskEdit = cancelTaskEdit;
|
modalScope.cancelTaskEdit = cancelTaskEdit;
|
||||||
|
|
||||||
modalScope.task._edit.repeatsOn = 'dayOfMonth';
|
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';
|
modalScope.task._edit.repeatsOn = 'dayOfWeek';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,20 +292,19 @@ angular.module('habitrpg')
|
|||||||
templateUrl: 'modals/task-edit.html',
|
templateUrl: 'modals/task-edit.html',
|
||||||
controller: ['$scope', function ($scope) {
|
controller: ['$scope', function ($scope) {
|
||||||
$scope.$watch('task._edit', function (newValue, oldValue) {
|
$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.summary = generateSummary($scope.task);
|
||||||
|
|
||||||
$scope.repeatSuffix = generateRepeatSuffix($scope.task);
|
$scope.repeatSuffix = generateRepeatSuffix($scope.task);
|
||||||
|
|
||||||
if ($scope.task._edit.repeatsOn == 'dayOfMonth') {
|
if ($scope.task._edit.repeatsOn == 'dayOfMonth') {
|
||||||
var date = moment().date();
|
var date = moment(task._edit.startDate).date();
|
||||||
$scope.task._edit.weeksOfMonth = [];
|
$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') {
|
} else if ($scope.task._edit.repeatsOn == 'dayOfWeek') {
|
||||||
var week = Math.ceil(moment().date() / 7) - 1;
|
var week = Math.ceil(moment(task._edit.startDate).date() / 7) - 1;
|
||||||
var dayOfWeek = moment().day();
|
var dayOfWeek = moment(task._edit.startDate).day();
|
||||||
var shortDay = numberToShortDay[dayOfWeek];
|
var shortDay = numberToShortDay[dayOfWeek];
|
||||||
$scope.task._edit.dayOfMonth = [];
|
$scope.task._edit.daysOfMonth = [];
|
||||||
$scope.task._edit.weeksOfMonth = [week]; // @TODO: This can handle multiple weeks
|
$scope.task._edit.weeksOfMonth = [week]; // @TODO: This can handle multiple weeks
|
||||||
for (var key in $scope.task._edit.repeat) {
|
for (var key in $scope.task._edit.repeat) {
|
||||||
$scope.task._edit.repeat[key] = false;
|
$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 === 'weekly') summary += ' on ' + repeatDays;
|
||||||
|
|
||||||
if (task._edit.frequency === 'monthly' && task._edit.repeatsOn == 'dayOfMonth') {
|
if (task._edit.frequency === 'monthly' && task._edit.repeatsOn == 'dayOfMonth') {
|
||||||
var date = moment().date();
|
var date = moment(task._edit.startDate).date();
|
||||||
summary += ' on the ' + date;
|
summary += ' on the ' + date;
|
||||||
} else if (task._edit.frequency === 'monthly' && task._edit.repeatsOn == 'dayOfWeek') {
|
} else if (task._edit.frequency === 'monthly' && task._edit.repeatsOn == 'dayOfWeek') {
|
||||||
var week = Math.ceil(moment().date() / 7) - 1;
|
var week = Math.ceil(moment(task._edit.startDate).date() / 7) - 1;
|
||||||
var dayOfWeek = moment().day();
|
var dayOfWeek = moment(task._edit.startDate).day();
|
||||||
var shortDay = numberToShortDay[dayOfWeek];
|
var shortDay = numberToShortDay[dayOfWeek];
|
||||||
var longDay = shortDayToLongDayMap[shortDay];
|
var longDay = shortDayToLongDayMap[shortDay];
|
||||||
|
|
||||||
|
|||||||
@@ -163,5 +163,7 @@
|
|||||||
"years": "Years",
|
"years": "Years",
|
||||||
"confirmScoreNotes": "Confirm task scoring with notes",
|
"confirmScoreNotes": "Confirm task scoring with notes",
|
||||||
"taskScoreNotesTooLong": "Task score notes must be less than 256 characters",
|
"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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ export function shouldDo (day, dailyTask) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
day = moment(day).startOf('day').toDate();
|
||||||
|
let startDate = moment(dailyTask.startDate).startOf('day').toDate();
|
||||||
|
|
||||||
let daysOfTheWeek = [];
|
let daysOfTheWeek = [];
|
||||||
|
|
||||||
if (dailyTask.repeat) {
|
if (dailyTask.repeat) {
|
||||||
@@ -105,14 +108,13 @@ export function shouldDo (day, dailyTask) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (dailyTask.frequency === 'daily') {
|
if (dailyTask.frequency === 'daily') {
|
||||||
if (!dailyTask.everyX) return false; // error condition
|
if (!dailyTask.everyX) return false; // error condition
|
||||||
let schedule = moment(dailyTask.startDate).recur()
|
let schedule = moment(startDate).recur()
|
||||||
.every(dailyTask.everyX).days();
|
.every(dailyTask.everyX).days();
|
||||||
return schedule.matches(day);
|
return schedule.matches(day);
|
||||||
} else if (dailyTask.frequency === 'weekly') {
|
} else if (dailyTask.frequency === 'weekly') {
|
||||||
let schedule = moment(dailyTask.startDate).recur();
|
let schedule = moment(startDate).recur();
|
||||||
|
|
||||||
if (dailyTask.everyX > 1) {
|
if (dailyTask.everyX > 1) {
|
||||||
schedule = schedule.every(dailyTask.everyX).weeks();
|
schedule = schedule.every(dailyTask.everyX).weeks();
|
||||||
@@ -122,21 +124,21 @@ export function shouldDo (day, dailyTask) {
|
|||||||
|
|
||||||
return schedule.matches(day);
|
return schedule.matches(day);
|
||||||
} else if (dailyTask.frequency === 'monthly') {
|
} 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;
|
let matchEveryX = differenceInMonths % dailyTask.everyX === 0;
|
||||||
|
|
||||||
if (dailyTask.weeksOfMonth) {
|
if (dailyTask.weeksOfMonth && dailyTask.weeksOfMonth.length > 0) {
|
||||||
schedule = schedule.every(daysOfTheWeek).daysOfWeek()
|
schedule = schedule.every(daysOfTheWeek).daysOfWeek()
|
||||||
.every(dailyTask.weeksOfMonth).weeksOfMonthByDay();
|
.every(dailyTask.weeksOfMonth).weeksOfMonthByDay();
|
||||||
} else if (dailyTask.daysOfMonth) {
|
} else if (dailyTask.daysOfMonth && dailyTask.daysOfMonth.length > 0) {
|
||||||
schedule = schedule.every(dailyTask.daysOfMonth).daysOfMonth();
|
schedule = schedule.every(dailyTask.daysOfMonth).daysOfMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
return schedule.matches(day) && matchEveryX;
|
return schedule.matches(day) && matchEveryX;
|
||||||
} else if (dailyTask.frequency === 'yearly') {
|
} else if (dailyTask.frequency === 'yearly') {
|
||||||
let schedule = moment(dailyTask.startDate).recur();
|
let schedule = moment(startDate).recur();
|
||||||
|
|
||||||
schedule = schedule.every(dailyTask.everyX).years();
|
schedule = schedule.every(dailyTask.everyX).years();
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ module.exports = function taskClasses (task, filters = [], dayStart = 0, lastCro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'todo' || type === 'daily') {
|
if (type === 'todo' || type === 'daily') {
|
||||||
if (completed || (type === 'daily' && !shouldDo(Number(new Date()), task, { // eslint-disable-line no-extra-parens
|
let notDue = !shouldDo(Number(new Date()), task, { dayStart });
|
||||||
dayStart,
|
let isNotDueDaily = type === 'daily' && notDue;
|
||||||
}))) {
|
|
||||||
|
if (completed || isNotDueDaily) {
|
||||||
classes += ' completed';
|
classes += ' completed';
|
||||||
} else {
|
} else {
|
||||||
classes += ' uncompleted';
|
classes += ' uncompleted';
|
||||||
|
|||||||
@@ -22,5 +22,14 @@ module.exports = function updateTask (task, req = {}) {
|
|||||||
|
|
||||||
merge(task, omit(body, ['_id', 'id', 'type', 'reminders', 'checklist', 'tags']));
|
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];
|
return [task];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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")
|
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')
|
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'")
|
fieldset.option-group.advanced-option(ng-show="task._edit._advanced && task.type !== 'reward'")
|
||||||
legend.option-title
|
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')
|
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')
|
||||||
|
|||||||
@@ -48,12 +48,14 @@ div(ng-if='task._editing')
|
|||||||
|
|
||||||
include ./habits/plus_minus
|
include ./habits/plus_minus
|
||||||
|
|
||||||
include ./dailies/calendar
|
//- include ./dailies/calendar
|
||||||
|
|
||||||
include ./rewards/pricing
|
include ./rewards/pricing
|
||||||
|
|
||||||
include ./todos/due_date
|
include ./todos/due_date
|
||||||
|
|
||||||
|
include ./repeatables
|
||||||
|
|
||||||
.col-md-6
|
.col-md-6
|
||||||
include ./tags
|
include ./tags
|
||||||
|
|
||||||
|
|||||||
35
website/views/shared/tasks/edit/repeatables.jade
Normal file
35
website/views/shared/tasks/edit/repeatables.jade
Normal file
@@ -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}}
|
||||||
Reference in New Issue
Block a user