diff --git a/test/spec/services/taskServicesSpec.js b/test/spec/services/taskServicesSpec.js index 6dfe84f948..59d1a5d49e 100644 --- a/test/spec/services/taskServicesSpec.js +++ b/test/spec/services/taskServicesSpec.js @@ -158,9 +158,11 @@ describe('Tasks Service', function() { task = specHelper.newTask(); }); - it('sets _editing to true', function() { + it('toggles the _editing property', function() { tasks.editTask(task, user); expect(task._editing).to.eql(true); + tasks.editTask(task, user); + expect(task._editing).to.eql(false); }); it('sets _tags to true by default', function() { @@ -198,20 +200,6 @@ describe('Tasks Service', function() { }); }); - describe('cancelTaskEdit', function() { - var task; - - beforeEach(function(){ - task = specHelper.newTask(); - }); - - it('sets _editing to false', function() { - task._editing = true; - tasks.cancelTaskEdit(task); - expect(task._editing).to.eql(false); - }); - }); - describe('cloneTask', function() { context('generic tasks', function() { diff --git a/website/client/js/controllers/challengesCtrl.js b/website/client/js/controllers/challengesCtrl.js index 67bd27703a..02ed54154f 100644 --- a/website/client/js/controllers/challengesCtrl.js +++ b/website/client/js/controllers/challengesCtrl.js @@ -35,7 +35,6 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User', } $scope.editTask = Tasks.editTask; - $scope.cancelTaskEdit = Tasks.cancelTaskEdit; $scope.canEdit = function(task) { return true; @@ -305,10 +304,8 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User', }; $scope.saveTask = function(task){ - angular.copy(task._edit, task); - task._edit = undefined; - task._editing = false; Tasks.updateTask(task._id, task); + task._editing = false; } $scope.toggleBulk = Tasks.toggleBulk; diff --git a/website/client/js/controllers/tasksCtrl.js b/website/client/js/controllers/tasksCtrl.js index 559ca729fe..2b8e0f3d66 100644 --- a/website/client/js/controllers/tasksCtrl.js +++ b/website/client/js/controllers/tasksCtrl.js @@ -99,18 +99,17 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N } }; - $scope.saveTask = function(task, stayOpen, isSaveAndClose) { - if (task._edit) { - angular.copy(task._edit, task); - } - task._edit = undefined; + $scope.removeTask = function(task) { + if (!confirm(window.env.t('sureDelete', {taskType: window.env.t(task.type), taskText: task.text}))) return; + User.deleteTask({params:{id: task._id, taskType: task.type}}) + }; + $scope.saveTask = function(task, stayOpen, isSaveAndClose) { if (task.checklist) { task.checklist = _.filter(task.checklist, function (i) { return !!i.text }); } - User.updateTask(task, {body: task}); if (!stayOpen) task._editing = false; @@ -121,19 +120,17 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N if (task.type == 'habit') Guide.goto('intro', 3); }; - $scope.completeChecklistItem = function completeChecklistItem(task) { - User.updateTask(task, {body: task}); - }; - /** * Reset $scope.task to $scope.originalTask */ - $scope.cancelTaskEdit = Tasks.cancelTaskEdit; - - $scope.removeTask = function(task) { - if (!confirm(window.env.t('sureDelete', {taskType: window.env.t(task.type), taskText: task.text}))) return; - task._edit = undefined; - User.deleteTask({params:{id: task._id, taskType: task.type}}) + $scope.cancel = function() { + var key; + for (key in $scope.task) { + $scope.task[key] = $scope.originalTask[key]; + } + $scope.originalTask = null; + $scope.editedTask = null; + $scope.editing = false; }; $scope.unlink = function(task, keep) { @@ -196,16 +193,16 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N } $scope.addChecklist = function(task) { - task._edit.checklist = [{completed:false, text:""}]; - focusChecklist(task._edit,0); + task.checklist = [{completed:false, text:""}]; + focusChecklist(task,0); } $scope.addChecklistItem = function(task, $event, $index) { - if (task._edit.checklist[$index].text) { - if ($index === task._edit.checklist.length - 1) { - task._edit.checklist.push({ completed: false, text: '' }); - } - focusChecklist(task._edit, $index + 1); + if (task.checklist[$index].text) { + $scope.saveTask(task, true); + if ($index === task.checklist.length - 1) + task.checklist.push({ completed: false, text: '' }); + focusChecklist(task, $index + 1); } else { // TODO Provide UI feedback that this item is still blank } @@ -214,21 +211,24 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N $scope.removeChecklistItem = function(task, $event, $index, force) { // Remove item if clicked on trash icon if (force) { - task._edit.checklist.splice($index, 1); - } else if (!task._edit.checklist[$index].text) { + if (task.checklist[$index].id) Tasks.removeChecklistItem(task._id, task.checklist[$index].id); + task.checklist.splice($index, 1); + } else if (!task.checklist[$index].text) { // User deleted all the text and is now wishing to delete the item // saveTask will prune the empty item + if (task.checklist[$index].id) Tasks.removeChecklistItem(task._id, task.checklist[$index].id); // Move focus if the list is still non-empty if ($index > 0) - focusChecklist(task._edit, $index-1); + focusChecklist(task, $index-1); // Don't allow the backspace key to navigate back now that the field is gone $event.preventDefault(); } } $scope.swapChecklistItems = function(task, oldIndex, newIndex) { - var toSwap = task._edit.checklist.splice(oldIndex, 1)[0]; - task._edit.checklist.splice(newIndex, 0, toSwap); + var toSwap = task.checklist.splice(oldIndex, 1)[0]; + task.checklist.splice(newIndex, 0, toSwap); + $scope.saveTask(task, true); } $scope.navigateChecklist = function(task,$index,$event){ @@ -332,7 +332,7 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N */ $scope.updateTaskTags = function (tagId, task) { - var tagIndex = task._edit.tags.indexOf(tagId); + var tagIndex = task.tags.indexOf(tagId); if (tagIndex === -1) { Tasks.addTagToTask(task._id, tagId); task.tags.push(tagId); @@ -340,7 +340,6 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N Tasks.removeTagFromTask(task._id, tagId); task.tags.splice(tagIndex, 1); } - angular.copy(task.tags, task._edit.tags); } /* diff --git a/website/client/js/services/taskServices.js b/website/client/js/services/taskServices.js index 604f007fd7..54cba505ca 100644 --- a/website/client/js/services/taskServices.js +++ b/website/client/js/services/taskServices.js @@ -174,18 +174,12 @@ angular.module('habitrpg') }; function editTask(task, user) { - task._editing = true; + task._editing = !task._editing; task._tags = !user.preferences.tagsCollapsed; task._advanced = !user.preferences.advancedCollapsed; - task._edit = angular.copy(task); if($rootScope.charts[task._id]) $rootScope.charts[task.id] = false; } - function cancelTaskEdit(task) { - task._edit = undefined; - task._editing = false; - }; - function cloneTask(task) { var clonedTask = _.cloneDeep(task); clonedTask = _cleanUpTask(clonedTask); @@ -232,7 +226,6 @@ angular.module('habitrpg') unlinkAllTasks: unlinkAllTasks, clearCompletedTodos: clearCompletedTodos, editTask: editTask, - cancelTaskEdit: cancelTaskEdit, cloneTask: cloneTask }; }]); diff --git a/website/views/shared/tasks/edit/advanced_options.jade b/website/views/shared/tasks/edit/advanced_options.jade index 74cef48845..413cb332e0 100644 --- a/website/views/shared/tasks/edit/advanced_options.jade +++ b/website/views/shared/tasks/edit/advanced_options.jade @@ -1,22 +1,22 @@ div(ng-if='::task.type!="reward"') button.advanced-options-toggle.option-title.mega(type='button', - ng-class='{active: task._edit._advanced}', - ng-click='task._edit._advanced = !task._edit._advanced', tooltip=env.t('expandCollapse')) + ng-class='{active: task._advanced}', + ng-click='task._advanced = !task._advanced', tooltip=env.t('expandCollapse')) =env.t('advancedOptions') - fieldset.option-group.advanced-option(ng-if="task.userId" ng-show="task._edit._advanced") + fieldset.option-group.advanced-option(ng-if="task.userId" ng-show="task._advanced") legend.option-title - a.hint(href='http://habitica.wikia.com/wiki/Task_Alias', target='_blank', popover-trigger='mouseenter', popover="{{::env.t('taskAliasPopover')}} {{::task._edit.alias ? '\n\n\' + env.t('taskAliasPopoverWarning') : ''}}")=env.t('taskAlias') - input.form-control(ng-model='task._edit.alias' type='text' placeholder=env.t('taskAliasPlaceholder')) + a.hint(href='http://habitica.wikia.com/wiki/Task_Alias', target='_blank', popover-trigger='mouseenter', popover="{{::env.t('taskAliasPopover')}} {{::task.alias ? '\n\n\' + env.t('taskAliasPopoverWarning') : ''}}")=env.t('taskAlias') + input.form-control(ng-model='task.alias' type='text' placeholder=env.t('taskAliasPlaceholder')) - div(ng-show='task._edit._advanced') + div(ng-show='task._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', + input.form-control(type='text', ng-model='task.startDate', datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened', ng-click='datepickerOpened = true', ng-disabled='!canEdit(task)') @@ -24,7 +24,7 @@ div(ng-if='::task.type!="reward"') .form-group legend.option-title=env.t('repeat') - select.form-control(ng-model='task._edit.frequency', ng-disabled='!canEdit(task)') + select.form-control(ng-model='task.frequency', ng-disabled='!canEdit(task)') option(value='weekly')=env.t('repeatWeek') option(value='daily')=env.t('repeatDays') @@ -32,38 +32,38 @@ div(ng-if='::task.type!="reward"') hr - fieldset.option-group.advanced-option(ng-show="task._edit._advanced") + fieldset.option-group.advanced-option(ng-show="task._advanced") 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') ul.priority-multiplier li - button(type='button', ng-class='{active: task._edit.priority==0.1}', - ng-click='!canEdit(task) || (task._edit.priority=0.1)') + button(type='button', ng-class='{active: task.priority==0.1}', + ng-click='!canEdit(task) || (task.priority=0.1)') =env.t('trivial') li - button(type='button', ng-class='{active: task._edit.priority==1 || !task._edit.priority}', - ng-click='!canEdit(task) || (task._edit.priority=1)') + button(type='button', ng-class='{active: task.priority==1 || !task.priority}', + ng-click='!canEdit(task) || (task.priority=1)') =env.t('easy') li - button(type='button', ng-class='{active: task._edit.priority==1.5}', - ng-click='!canEdit(task) || (task._edit.priority=1.5)') + button(type='button', ng-class='{active: task.priority==1.5}', + ng-click='!canEdit(task) || (task.priority=1.5)') =env.t('medium') li - button(type='button', ng-class='{active: task._edit.priority==2}', - ng-click='!canEdit(task) || (task._edit.priority=2)') + button(type='button', ng-class='{active: task.priority==2}', + ng-click='!canEdit(task) || (task.priority=2)') =env.t('hard') span(ng-if='task.type=="daily" && !$state.includes("options.social.challenges")') legend.option-title.pull-left=env.t('restoreStreak') - input.option-content(type='number', ng-model='task._edit.streak') + input.option-content(type='number', ng-model='task.streak') div(ng-if='::(user.preferences.allocationMode == "taskbased" && user.preferences.automaticAllocation) || $state.is("options.social.challenges")') legend.option-title.pull-left=env.t('attributes') ul.task-attributes each attribute, short in {str: 'strength', int: 'intelligence', con: 'constitution', per: 'perception'} li - button(type='button', ng-class='{active: task._edit.attribute=="#{short}"}', - ng-click='task._edit.attribute="#{short}"', + button(type='button', ng-class='{active: task.attribute=="#{short}"}', + ng-click='task.attribute="#{short}"', popover=env.t('#{attribute}Example'), popover-trigger='mouseenter', popover-placement='top') =env.t(attribute) diff --git a/website/views/shared/tasks/edit/checklist.jade b/website/views/shared/tasks/edit/checklist.jade index 2a578d7217..1c88e36559 100644 --- a/website/views/shared/tasks/edit/checklist.jade +++ b/website/views/shared/tasks/edit/checklist.jade @@ -1,19 +1,19 @@ .task-checklist-edit(ng-if='::!$state.includes("options.social.challenges") && (task.type=="daily" || task.type=="todo")') ul li - button(type='button', ng-if='!task._edit.checklist[0]' + button(type='button', ng-if='!task.checklist[0]' popover=env.t('checklistText'), popover-trigger='mouseenter', popover-placement='bottom', ng-click='addChecklist(task)') span.glyphicon.glyphicon-tasks span=env.t('addChecklist') - .checklist-form(ng-if='task._edit.checklist') + .checklist-form(ng-if='task.checklist') fieldset.option-group(ng-if='!$state.includes("options.social.challenges")') - legend.option-title(ng-if='task._edit.checklist[0]') + legend.option-title(ng-if='task.checklist[0]') span.hint(popover=env.t('checklistText'), popover-trigger='mouseenter', popover-placement='bottom') =env.t('checklist') ul(hrpg-sort-checklist) - li(ng-repeat='item in task._edit.checklist') + li(ng-repeat='item in task.checklist') //input(type='checkbox',ng-model='item.completed',ng-change='saveTask(task,true)') //-,ng-blur='saveTask(task,true)') span.checklist-icon.glyphicon.glyphicon-resize-vertical diff --git a/website/views/shared/tasks/edit/dailies/repeat_options.jade b/website/views/shared/tasks/edit/dailies/repeat_options.jade index 48c17d7631..8388c4ecaa 100644 --- a/website/views/shared/tasks/edit/dailies/repeat_options.jade +++ b/website/views/shared/tasks/edit/dailies/repeat_options.jade @@ -1,22 +1,22 @@ legend.option-title span.hint(popover-trigger='mouseenter', popover-title=env.t('repeatHelpTitle'), - popover='{{env.t(task._edit.frequency + "RepeatHelpContent")}}')=env.t('repeatEvery') + popover='{{env.t(task.frequency + "RepeatHelpContent")}}')=env.t('repeatEvery') // If frequency is daily -ng-form.form-group(name='everyX', ng-if='task._edit.frequency=="daily"') +ng-form.form-group(name='everyX', ng-if='task.frequency=="daily"') .input-group - input.form-control(type='number', ng-model='task._edit.everyX', min='0', ng-disabled='!canEdit(task)', required) - span.input-group-addon {{task._edit.everyX == 1 ? env.t('day') : env.t('days')}} + 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 -.form-group(ng-if='task._edit.frequency=="weekly"') +.form-group(ng-if='task.frequency=="weekly"') ul.repeat-days // note, does not use data-toggle="buttons-checkbox" - it would interfere with our own click binding mixin dayOfWeek(day, num) li - button(type='button', ng-class='{active: task._edit.repeat.#{day}}', - ng-disabled='!canEdit(task)', ng-click='task._edit.repeat.#{day} = !task._edit.repeat.#{day}', - tooltip='{{env.t((task._edit.repeat.#{day}) ? "due" : "notDue")}}') + button(type='button', ng-class='{active: 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})}} +dayOfWeek('su', 0) diff --git a/website/views/shared/tasks/edit/habits/plus_minus.jade b/website/views/shared/tasks/edit/habits/plus_minus.jade index 5d8e474fef..034fb432ce 100644 --- a/website/views/shared/tasks/edit/habits/plus_minus.jade +++ b/website/views/shared/tasks/edit/habits/plus_minus.jade @@ -1,8 +1,8 @@ -fieldset.option-group.plusminus(ng-if='task.type === "habit" && canEdit(task)') +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._edit.up') + input.visuallyhidden.focusable(id='{{obj._id}}_{{task._id}}-option-plus', type='checkbox', ng-model='task.up') label(for='{{obj._id}}_{{task._id}}-option-plus') span.task-checker - input.visuallyhidden.focusable(id='{{obj._id}}_{{task._id}}-option-minus', type='checkbox', ng-model='task._edit.down') + input.visuallyhidden.focusable(id='{{obj._id}}_{{task._id}}-option-minus', type='checkbox', ng-model='task.down') label(for='{{obj._id}}_{{task._id}}-option-minus') diff --git a/website/views/shared/tasks/edit/rewards/pricing.jade b/website/views/shared/tasks/edit/rewards/pricing.jade index 2e1f3a817a..f322dc06d9 100644 --- a/website/views/shared/tasks/edit/rewards/pricing.jade +++ b/website/views/shared/tasks/edit/rewards/pricing.jade @@ -1,5 +1,5 @@ -fieldset.option-group.option-short(ng-if='task.type=="reward" && !task._edit.challenge.id') +fieldset.option-group.option-short(ng-if='task.type=="reward" && !task.challenge.id') legend.option-title=env.t('price') - input.option-content(type='number', size='16', min='0', step='any', ng-model='task._edit.value', required) + input.option-content(type='number', size='16', min='0', step='any', ng-model='task.value', required) .money.input-suffix span.shop_gold diff --git a/website/views/shared/tasks/edit/text_notes.jade b/website/views/shared/tasks/edit/text_notes.jade index 7adc2ca2d0..ef947557c3 100644 --- a/website/views/shared/tasks/edit/text_notes.jade +++ b/website/views/shared/tasks/edit/text_notes.jade @@ -1,7 +1,7 @@ fieldset.option-group label.option-title=env.t('text') - input.form-control(type='text', ng-model='task._edit.text', ng-disabled='!canEdit(task)', required) + input.form-control(type='text', ng-model='task.text', ng-disabled='!canEdit(task)', required) fieldset.option-group label.option-title=env.t('extraNotes') - textarea.form-control(rows='3', ng-model='task._edit.notes') + textarea.form-control(rows='3', ng-model='task.notes', ng-model-options="{debounce: 1000}") diff --git a/website/views/shared/tasks/meta_controls.jade b/website/views/shared/tasks/meta_controls.jade index f3504cbe31..448886ae5e 100644 --- a/website/views/shared/tasks/meta_controls.jade +++ b/website/views/shared/tasks/meta_controls.jade @@ -27,11 +27,11 @@ |   span.glyphicon.glyphicon-pencil(ng-hide='task._editing') |   - a(ng-hide='!task._editing', ng-click='cancelTaskEdit(task)', tooltip=env.t('cancel')) + a(ng-hide='!task._editing', ng-click='editTask(task, user)', tooltip=env.t('cancel')) span.glyphicon.glyphicon-remove(ng-hide='!task._editing') |   // save - a(ng-hide='!task._editing', ng-click='saveTask(task)', tooltip=env.t('save')) + a(ng-hide='!task._editing', ng-click='editTask(task, user);saveTask(task)', tooltip=env.t('save')) span.glyphicon.glyphicon-ok(ng-hide='!task._editing') |   //challenges diff --git a/website/views/shared/tasks/task_view/index.jade b/website/views/shared/tasks/task_view/index.jade index 0ac7cf2104..0c782358bf 100644 --- a/website/views/shared/tasks/task_view/index.jade +++ b/website/views/shared/tasks/task_view/index.jade @@ -38,10 +38,10 @@ // main content .task-text(ng-dblclick='doubleClickTask(obj, task)') - markdown(text='task._editing ? task._edit.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') fieldset.option-group.task-checklist label.checkbox(ng-repeat='item in task.checklist') - input(type='checkbox', ng-model='item.completed', ng-change='completeChecklistItem(task)') + input(type='checkbox', ng-model='item.completed', ng-change='saveTask(task,true)') markdown(text='item.text', target='_blank')