mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +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',
|
habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User', 'Tasks', '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) {
|
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
|
// Use presence of cid to determine whether to show a list or a single
|
||||||
// challenge
|
// challenge
|
||||||
@@ -36,6 +36,22 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User',
|
|||||||
|
|
||||||
$scope.editTask = Tasks.editTask;
|
$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
|
* Create
|
||||||
*/
|
*/
|
||||||
@@ -274,8 +290,8 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User',
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.saveTask = function(task){
|
$scope.saveTask = function(task){
|
||||||
|
Tasks.updateTask(task._id, task);
|
||||||
task._editing = false;
|
task._editing = false;
|
||||||
// TODO persist
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.toggleBulk = function(list) {
|
$scope.toggleBulk = function(list) {
|
||||||
|
|||||||
@@ -70,6 +70,23 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
|
|||||||
|
|
||||||
$scope.editTask = Tasks.editTask;
|
$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
|
* Add the new task to the actions log
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -209,8 +209,9 @@ schema.methods.updateTask = async function challengeUpdateTask (task) {
|
|||||||
updateCmd.$set[key] = syncableAttrs[key];
|
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
|
// 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},
|
userId: {$exists: true},
|
||||||
'challenge.id': challenge.id,
|
'challenge.id': challenge.id,
|
||||||
'challenge.taskId': task._id,
|
'challenge.taskId': task._id,
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ div(ng-if='::task.type!="reward"')
|
|||||||
|
|
||||||
input.form-control(type='text', ng-model='task.startDate',
|
input.form-control(type='text', ng-model='task.startDate',
|
||||||
datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened',
|
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
|
hr
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
legend.option-title=env.t('repeat')
|
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='weekly')=env.t('repeatWeek')
|
||||||
option(value='daily')=env.t('repeatDays')
|
option(value='daily')=env.t('repeatDays')
|
||||||
|
|
||||||
@@ -39,19 +39,19 @@ div(ng-if='::task.type!="reward"')
|
|||||||
ul.priority-multiplier
|
ul.priority-multiplier
|
||||||
li
|
li
|
||||||
button(type='button', ng-class='{active: task.priority==0.1}',
|
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')
|
=env.t('trivial')
|
||||||
li
|
li
|
||||||
button(type='button', ng-class='{active: task.priority==1 || !task.priority}',
|
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')
|
=env.t('easy')
|
||||||
li
|
li
|
||||||
button(type='button', ng-class='{active: task.priority==1.5}',
|
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')
|
=env.t('medium')
|
||||||
li
|
li
|
||||||
button(type='button', ng-class='{active: task.priority==2}',
|
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')
|
=env.t('hard')
|
||||||
|
|
||||||
span(ng-if='task.type=="daily"')
|
span(ng-if='task.type=="daily"')
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ legend.option-title
|
|||||||
popover='{{env.t(task.frequency + "RepeatHelpContent")}}')=env.t('repeatEvery')
|
popover='{{env.t(task.frequency + "RepeatHelpContent")}}')=env.t('repeatEvery')
|
||||||
|
|
||||||
// If frequency is daily
|
// 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-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')}}
|
span.input-group-addon {{task.everyX == 1 ? env.t('day') : env.t('days')}}
|
||||||
|
|
||||||
// If frequency is weekly
|
// If frequency is weekly
|
||||||
@@ -15,7 +15,7 @@ ng-form.form-group(name='everyX' ng-if='task.frequency=="daily"')
|
|||||||
mixin dayOfWeek(day, num)
|
mixin dayOfWeek(day, num)
|
||||||
li
|
li
|
||||||
button(type='button', ng-class='{active: task.repeat.#{day}}',
|
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")}}')
|
tooltip='{{env.t((task.repeat.#{day}) ? "due" : "notDue")}}')
|
||||||
| {{::moment.weekdaysMin(#{num})}}
|
| {{::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')
|
legend.option-title=env.t('direction/Actions')
|
||||||
span.task-checker
|
span.task-checker
|
||||||
input.visuallyhidden.focusable(id='{{obj._id}}_{{task._id}}-option-plus', type='checkbox', ng-model='task.up')
|
input.visuallyhidden.focusable(id='{{obj._id}}_{{task._id}}-option-plus', type='checkbox', ng-model='task.up')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fieldset.option-group
|
fieldset.option-group
|
||||||
label.option-title=env.t('text')
|
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
|
fieldset.option-group
|
||||||
label.option-title=env.t('extraNotes')
|
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')
|
legend.option-title=env.t('dueDate')
|
||||||
input.option-content.datepicker(type='text', ng-model='task.date',
|
input.option-content.datepicker(type='text', ng-model='task.date',
|
||||||
datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened',
|
datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened',
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
label(for='box-{{::obj._id}}_{{::task._id}}')
|
label(for='box-{{::obj._id}}_{{::task._id}}')
|
||||||
|
|
||||||
// main content
|
// 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')
|
markdown(text='task.text',target='_blank')
|
||||||
|
|
||||||
div(ng-if='task.checklist && !$state.includes("options.social.challenges") && !task.collapseChecklist && !task._editing')
|
div(ng-if='task.checklist && !$state.includes("options.social.challenges") && !task.collapseChecklist && !task._editing')
|
||||||
|
|||||||
Reference in New Issue
Block a user