mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
feat: allowing modification of challenge tasks after challenge creation. fixes #7320
closes #7877
This commit is contained in:
@@ -158,4 +158,57 @@ describe('Challenge Model', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('type specific updates', () => {
|
||||
it('updates habit specific field to challenge and challenge members', async () => {
|
||||
task = new Tasks.habit(Tasks.Task.sanitize(tasksToTest.habit)); // eslint-disable-line babel/new-cap
|
||||
task.challenge.id = challenge._id;
|
||||
await task.save();
|
||||
|
||||
await challenge.addTasks([task]);
|
||||
|
||||
task.up = true;
|
||||
task.down = false;
|
||||
|
||||
await challenge.updateTask(task);
|
||||
|
||||
let updatedLeader = await User.findOne({_id: leader._id});
|
||||
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.habits[0]);
|
||||
|
||||
expect(updatedUserTask.up).to.equal(true);
|
||||
expect(updatedUserTask.down).to.equal(false);
|
||||
});
|
||||
|
||||
it('updates todo specific field to challenge and challenge members', async () => {
|
||||
task = new Tasks.todo(Tasks.Task.sanitize(tasksToTest.todo)); // eslint-disable-line babel/new-cap
|
||||
task.challenge.id = challenge._id;
|
||||
await task.save();
|
||||
|
||||
await challenge.addTasks([task]);
|
||||
|
||||
task.date = new Date();
|
||||
await challenge.updateTask(task);
|
||||
|
||||
let updatedLeader = await User.findOne({_id: leader._id});
|
||||
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.todos[0]);
|
||||
|
||||
expect(updatedUserTask.date).to.exist;
|
||||
});
|
||||
|
||||
it('updates daily specific field to challenge and challenge members', async () => {
|
||||
task = new Tasks.daily(Tasks.Task.sanitize(tasksToTest.daily)); // eslint-disable-line babel/new-cap
|
||||
task.challenge.id = challenge._id;
|
||||
await task.save();
|
||||
|
||||
await challenge.addTasks([task]);
|
||||
|
||||
task.everyX = 2;
|
||||
await challenge.updateTask(task);
|
||||
|
||||
let updatedLeader = await User.findOne({_id: leader._id});
|
||||
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.dailys[0]);
|
||||
|
||||
expect(updatedUserTask.everyX).to.eql(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User', 'Challenges', 'Notification', '$compile', 'Groups', '$state', '$stateParams', 'Members', 'Tasks', 'TAVERN_ID',
|
||||
function($rootScope, $scope, Shared, User, Challenges, Notification, $compile, Groups, $state, $stateParams, Members, Tasks, TAVERN_ID) {
|
||||
habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User', 'Tasks', 'Challenges', 'Notification', '$compile', 'Groups', '$state', '$stateParams', 'Members', 'Tasks', 'TAVERN_ID',
|
||||
function($rootScope, $scope, Shared, User, Tasks, Challenges, Notification, $compile, Groups, $state, $stateParams, Members, Tasks, TAVERN_ID) {
|
||||
|
||||
// Use presence of cid to determine whether to show a list or a single
|
||||
// challenge
|
||||
@@ -36,6 +36,22 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User',
|
||||
|
||||
$scope.editTask = Tasks.editTask;
|
||||
|
||||
$scope.canEdit = function(task) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$scope.doubleClickTask = function (obj, task) {
|
||||
if (obj._locked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (task._editing) {
|
||||
$scope.saveTask(task);
|
||||
} else {
|
||||
$scope.editTask(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create
|
||||
*/
|
||||
@@ -274,8 +290,8 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User',
|
||||
};
|
||||
|
||||
$scope.saveTask = function(task){
|
||||
Tasks.updateTask(task._id, task);
|
||||
task._editing = false;
|
||||
// TODO persist
|
||||
}
|
||||
|
||||
$scope.toggleBulk = function(list) {
|
||||
|
||||
@@ -70,6 +70,23 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
|
||||
|
||||
$scope.editTask = Tasks.editTask;
|
||||
|
||||
$scope.canEdit = function(task) {
|
||||
// can't edit challenge tasks
|
||||
return !task.challenge.id;
|
||||
}
|
||||
|
||||
$scope.doubleClickTask = function (obj, task) {
|
||||
if (obj._locked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (task._editing) {
|
||||
$scope.saveTask(task);
|
||||
} else {
|
||||
$scope.editTask(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the new task to the actions log
|
||||
*/
|
||||
|
||||
@@ -209,8 +209,9 @@ schema.methods.updateTask = async function challengeUpdateTask (task) {
|
||||
updateCmd.$set[key] = syncableAttrs[key];
|
||||
}
|
||||
|
||||
let taskSchema = Tasks[task.type];
|
||||
// Updating instead of loading and saving for performances, risks becoming a problem if we introduce more complexity in tasks
|
||||
await Tasks.Task.update({
|
||||
await taskSchema.update({
|
||||
userId: {$exists: true},
|
||||
'challenge.id': challenge.id,
|
||||
'challenge.taskId': task._id,
|
||||
|
||||
@@ -18,13 +18,13 @@ div(ng-if='::task.type!="reward"')
|
||||
|
||||
input.form-control(type='text', ng-model='task.startDate',
|
||||
datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened',
|
||||
ng-click='datepickerOpened = true', ng-disabled='task.challenge.id')
|
||||
ng-click='datepickerOpened = true', ng-disabled='!canEdit(task)')
|
||||
|
||||
hr
|
||||
|
||||
.form-group
|
||||
legend.option-title=env.t('repeat')
|
||||
select.form-control(ng-model='task.frequency', ng-disabled='task.challenge.id')
|
||||
select.form-control(ng-model='task.frequency', ng-disabled='!canEdit(task)')
|
||||
option(value='weekly')=env.t('repeatWeek')
|
||||
option(value='daily')=env.t('repeatDays')
|
||||
|
||||
@@ -39,19 +39,19 @@ div(ng-if='::task.type!="reward"')
|
||||
ul.priority-multiplier
|
||||
li
|
||||
button(type='button', ng-class='{active: task.priority==0.1}',
|
||||
ng-click='task.challenge.id || (task.priority=0.1)')
|
||||
ng-click='!canEdit(task) || (task.priority=0.1)')
|
||||
=env.t('trivial')
|
||||
li
|
||||
button(type='button', ng-class='{active: task.priority==1 || !task.priority}',
|
||||
ng-click='task.challenge.id || (task.priority=1)')
|
||||
ng-click='!canEdit(task) || (task.priority=1)')
|
||||
=env.t('easy')
|
||||
li
|
||||
button(type='button', ng-class='{active: task.priority==1.5}',
|
||||
ng-click='task.challenge.id || (task.priority=1.5)')
|
||||
ng-click='!canEdit(task) || (task.priority=1.5)')
|
||||
=env.t('medium')
|
||||
li
|
||||
button(type='button', ng-class='{active: task.priority==2}',
|
||||
ng-click='task.challenge.id || (task.priority=2)')
|
||||
ng-click='!canEdit(task) || (task.priority=2)')
|
||||
=env.t('hard')
|
||||
|
||||
span(ng-if='task.type=="daily"')
|
||||
|
||||
@@ -3,9 +3,9 @@ legend.option-title
|
||||
popover='{{env.t(task.frequency + "RepeatHelpContent")}}')=env.t('repeatEvery')
|
||||
|
||||
// If frequency is daily
|
||||
ng-form.form-group(name='everyX' ng-if='task.frequency=="daily"')
|
||||
ng-form.form-group(name='everyX', ng-if='task.frequency=="daily"')
|
||||
.input-group
|
||||
input.form-control(type='number', ng-model='task.everyX', ng-disabled='task.challenge.id', min='0', required)
|
||||
input.form-control(type='number', ng-model='task.everyX', min='0', ng-disabled='!canEdit(task)', required)
|
||||
span.input-group-addon {{task.everyX == 1 ? env.t('day') : env.t('days')}}
|
||||
|
||||
// If frequency is weekly
|
||||
@@ -15,7 +15,7 @@ ng-form.form-group(name='everyX' ng-if='task.frequency=="daily"')
|
||||
mixin dayOfWeek(day, num)
|
||||
li
|
||||
button(type='button', ng-class='{active: task.repeat.#{day}}',
|
||||
ng-disabled='task.challenge.id', ng-click='task.repeat.#{day} = !task.repeat.#{day}',
|
||||
ng-disabled='!canEdit(task)', ng-click='task.repeat.#{day} = !task.repeat.#{day}',
|
||||
tooltip='{{env.t((task.repeat.#{day}) ? "due" : "notDue")}}')
|
||||
| {{::moment.weekdaysMin(#{num})}}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fieldset.option-group.plusminus(ng-if='task.type=="habit" && !task.challenge.id')
|
||||
fieldset.option-group.plusminus(ng-if='task.type=="habit" && canEdit(task)')
|
||||
legend.option-title=env.t('direction/Actions')
|
||||
span.task-checker
|
||||
input.visuallyhidden.focusable(id='{{obj._id}}_{{task._id}}-option-plus', type='checkbox', ng-model='task.up')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
fieldset.option-group
|
||||
label.option-title=env.t('text')
|
||||
input.form-control(type='text', ng-model='task.text', required, ng-disabled='task.challenge.id')
|
||||
input.form-control(type='text', ng-model='task.text', ng-disabled='!canEdit(task)', required)
|
||||
|
||||
fieldset.option-group
|
||||
label.option-title=env.t('extraNotes')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fieldset.option-group(ng-if='task.type=="todo" && !task.challenge.id')
|
||||
fieldset.option-group(ng-if='task.type=="todo" && canEdit(task)')
|
||||
legend.option-title=env.t('dueDate')
|
||||
input.option-content.datepicker(type='text', ng-model='task.date',
|
||||
datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened',
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
label(for='box-{{::obj._id}}_{{::task._id}}')
|
||||
|
||||
// main content
|
||||
.task-text(ng-dblclick='task._editing ? saveTask(task) : editTask(task, user)')
|
||||
.task-text(ng-dblclick='doubleClickTask(obj, task)')
|
||||
markdown(text='task.text',target='_blank')
|
||||
|
||||
div(ng-if='task.checklist && !$state.includes("options.social.challenges") && !task.collapseChecklist && !task._editing')
|
||||
|
||||
Reference in New Issue
Block a user