Updated task service to use api v3 (#7136)

* Updated task service to use api v3

* Add user.ops functions back

* Removed extra parameter
This commit is contained in:
Keith Holliday
2016-05-08 09:52:43 -05:00
committed by Matteo Pagliazzi
parent 78a8eea79a
commit 4c37417bd4
9 changed files with 363 additions and 63 deletions

View File

@@ -1,22 +1,147 @@
'use strict';
describe('Tasks Service', function() {
var rootScope, tasks, user;
var rootScope, tasks, user, $httpBackend;
var apiV3Prefix = 'api/v3/tasks';
beforeEach(function() {
module(function($provide) {
user = specHelper.newUser();
$provide.value('User', {user: user});
});
inject(function(_$rootScope_, Tasks, User) {
inject(function(_$httpBackend_, _$rootScope_, Tasks, User) {
$httpBackend = _$httpBackend_;
rootScope = _$rootScope_;
rootScope.charts = {};
tasks = Tasks;
});
});
it('calls get user tasks endpoint', function() {
$httpBackend.expectGET(apiV3Prefix + '/user').respond({});
tasks.getUserTasks();
$httpBackend.flush();
});
it('calls post user tasks endpoint', function() {
$httpBackend.expectPOST(apiV3Prefix + '/user').respond({});
tasks.createUserTasks();
$httpBackend.flush();
});
it('calls get challenge tasks endpoint', function() {
var challengeId = 1;
$httpBackend.expectGET(apiV3Prefix + '/challenge/' + challengeId).respond({});
tasks.getChallengeTasks(challengeId);
$httpBackend.flush();
});
it('calls create challenge tasks endpoint', function() {
var challengeId = 1;
$httpBackend.expectPOST(apiV3Prefix + '/challenge/' + challengeId).respond({});
tasks.createChallengeTasks(challengeId, {});
$httpBackend.flush();
});
it('calls get task endpoint', function() {
var taskId = 1;
$httpBackend.expectGET(apiV3Prefix + '/' + taskId).respond({});
tasks.getTask(taskId);
$httpBackend.flush();
});
it('calls update task endpoint', function() {
var taskId = 1;
$httpBackend.expectPUT(apiV3Prefix + '/' + taskId).respond({});
tasks.updateTask(taskId, {});
$httpBackend.flush();
});
it('calls delete task endpoint', function() {
var taskId = 1;
$httpBackend.expectDELETE(apiV3Prefix + '/' + taskId).respond({});
tasks.deleteTask(taskId);
$httpBackend.flush();
});
it('calls score task endpoint', function() {
var taskId = 1;
var direction = "down";
$httpBackend.expectPOST(apiV3Prefix + '/' + taskId + '/score/' + direction).respond({});
tasks.scoreTask(taskId, direction);
$httpBackend.flush();
});
it('calls move task endpoint', function() {
var taskId = 1;
var position = 0;
$httpBackend.expectPOST(apiV3Prefix + '/' + taskId + '/move/to/' + position).respond({});
tasks.moveTask(taskId, position);
$httpBackend.flush();
});
it('calls add check list item endpoint', function() {
var taskId = 1;
$httpBackend.expectPOST(apiV3Prefix + '/' + taskId + '/checklist').respond({});
tasks.addChecklistItem(taskId, {});
$httpBackend.flush();
});
it('calls score check list item endpoint', function() {
var taskId = 1;
var itemId = 2;
$httpBackend.expectPOST(apiV3Prefix + '/' + taskId + '/checklist/' + itemId + '/score').respond({});
tasks.scoreCheckListItem(taskId, itemId);
$httpBackend.flush();
});
it('calls update check list item endpoint', function() {
var taskId = 1;
var itemId = 2;
$httpBackend.expectPUT(apiV3Prefix + '/' + taskId + '/checklist/' + itemId).respond({});
tasks.updateChecklistItem(taskId, itemId, {});
$httpBackend.flush();
});
it('calls remove check list item endpoint', function() {
var taskId = 1;
var itemId = 2;
$httpBackend.expectDELETE(apiV3Prefix + '/' + taskId + '/checklist/' + itemId).respond({});
tasks.removeChecklistItem(taskId, itemId);
$httpBackend.flush();
});
it('calls add tag to list item endpoint', function() {
var taskId = 1;
var tagId = 2;
$httpBackend.expectPOST(apiV3Prefix + '/' + taskId + '/tags/' + tagId).respond({});
tasks.addTagToTask(taskId, tagId);
$httpBackend.flush();
});
it('calls remove tag to list item endpoint', function() {
var taskId = 1;
var tagId = 2;
$httpBackend.expectDELETE(apiV3Prefix + '/' + taskId + '/tags/' + tagId).respond({});
tasks.removeTagFromTask(taskId, tagId);
$httpBackend.flush();
});
it('calls unlink task endpoint', function() {
var taskId = 1;
var keep = "keep-all";
$httpBackend.expectPOST(apiV3Prefix + '/unlink/' + taskId + '?keep=' + keep).respond({});
tasks.unlinkTask(taskId);
$httpBackend.flush();
});
it('calls clear completed todo task endpoint', function() {
$httpBackend.expectPOST(apiV3Prefix + '/clearCompletedTodos').respond({});
tasks.clearCompletedTodos();
$httpBackend.flush();
});
describe('editTask', function() {
var task;
@@ -82,24 +207,22 @@ describe('Tasks Service', function() {
expect(clonedTask.attribute).to.eql(task.attribute);
});
it('does not clone original task\'s id or _id', function() {
it('does not clone original task\'s _id', function() {
var task = specHelper.newTask();
var clonedTask = tasks.cloneTask(task);
expect(clonedTask.id).to.exist;
expect(clonedTask.id).to.not.eql(task.id);
expect(clonedTask._id).to.exist;
expect(clonedTask._id).to.not.eql(task._id);
});
it('does not clone original task\'s dateCreated attribute', function() {
var task = specHelper.newTask({
dateCreated: new Date(2014, 5, 1, 1, 1, 1, 1),
createdAt: new Date(2014, 5, 1, 1, 1, 1, 1),
});
var clonedTask = tasks.cloneTask(task);
expect(clonedTask.dateCreated).to.exist;
expect(clonedTask.dateCreated).to.not.eql(task.dateCreated);
expect(clonedTask.createdAt).to.exist;
expect(clonedTask.createdAt).to.not.eql(task.createdAt);
});
it('does not clone original task\'s value', function() {

View File

@@ -180,12 +180,20 @@ window.habitrpg = angular.module('habitrpg',
url: '/:cid',
templateUrl: 'partials/options.social.challenges.detail.html',
title: env.t('titleChallenges'),
controller: ['$scope', 'Challenges', '$stateParams',
function ($scope, Challenges, $stateParams) {
controller: ['$scope', 'Challenges', '$stateParams', 'Tasks',
function ($scope, Challenges, $stateParams, Tasks) {
Challenges.getChallenge($stateParams.cid)
.then(function (response) {
$scope.obj = $scope.challenge = response.data.data;
$scope.challenge._locked = true;
return Tasks.getChallengeTasks($scope.challenge._id);
})
.then(function (response) {
var tasks = response.data.data;
tasks.forEach(function (element, index, array) {
if (!$scope.challenge[element.type + 's']) $scope.challenge[element.type + 's'] = [];
$scope.challenge[element.type + 's'].push(element);
})
});
}]
})
@@ -193,12 +201,20 @@ window.habitrpg = angular.module('habitrpg',
url: '/:cid/edit',
templateUrl: 'partials/options.social.challenges.detail.html',
title: env.t('titleChallenges'),
controller: ['$scope', 'Challenges', '$stateParams',
function ($scope, Challenges, $stateParams) {
controller: ['$scope', 'Challenges', '$stateParams', 'Tasks',
function ($scope, Challenges, $stateParams, Tasks) {
Challenges.getChallenge($stateParams.cid)
.then(function (response) {
$scope.obj = $scope.challenge = response.data.data;
$scope.challenge._locked = false;
return Tasks.getChallengeTasks($scope.challenge._id);
})
.then(function (response) {
var tasks = response.data.data;
tasks.forEach(function (element, index, array) {
if (!$scope.challenge[element.type + 's']) $scope.challenge[element.type + 's'] = [];
$scope.challenge[element.type + 's'].push(element);
})
});
}]
})

View File

@@ -132,9 +132,16 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User',
$state.transitionTo('options.social.challenges.detail', { cid: _challenge._id }, {
reload: true, inherit: false, notify: true
});
var challengeTasks = [];
challengeTasks.concat(challenge.todos);
challengeTasks.concat(challenge.habits);
challengeTasks.concat(challenge.dailys);
challengeTasks.concat(challenge.reqards);
Tasks.createChallengeTasks(_challenge._id, challengeTasks);
});
} else {
Challenges.updateChallenge(challenge)
Challenges.updateChallenge(challenge._id, challenge)
.then(function (response) {
var _challenge = response.data.data;
$state.transitionTo('options.social.challenges.detail', { cid: _challenge._id }, {
@@ -223,19 +230,19 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User',
//------------------------------------------------------------
// Tasks
//------------------------------------------------------------
$scope.addTask = function(addTo, listDef) {
$scope.addTask = function(addTo, listDef, challenge) {
var task = Shared.taskDefaults({text: listDef.newTask, type: listDef.type});
addTo.unshift(task);
//User.log({op: "addTask", data: task}); //TODO persist
Tasks.createChallengeTasks(challenge._id, task);
if (!challenge[task.type + 's']) challenge[task.type + 's'] = [];
challenge[task.type + 's'].push(task);
delete listDef.newTask;
};
$scope.removeTask = function(task, list) {
if (!confirm(window.env.t('sureDelete', {taskType: window.env.t(task.type), taskText: task.text}))) return;
//TODO persist
// User.log({op: "delTask", data: task});
_.remove(list, task);
Tasks.deleteTask(task._id);
var index = challenge[task.type + 's'].indexOf(task);
challenge[task.type + 's'].splice(index, 1);
};
$scope.saveTask = function(task){
@@ -407,7 +414,8 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User',
function _getChallenges() {
if ($scope.cid) {
Challenges.getChallenge($scope.cid)
.then(function (challenge) {
.then(function (response) {
var challenge = response.data.data;
$scope.challenges = [challenge];
});
} else {

View File

@@ -46,7 +46,9 @@ habitrpg.controller("PartyCtrl", ['$rootScope','$scope','Groups','Chat','User','
}
}
Chat.markChatSeen($scope.group._id);
if ($scope.group && $scope.group._id) {
Chat.markChatSeen($scope.group._id);
}
$scope.create = function(group) {
if (!group.name) group.name = env.t('possessiveParty', {name: User.user.profile.name});

View File

@@ -33,10 +33,11 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
var newTask = {
text: task,
type: listDef.type,
tags: _.transform(User.user.filters, function(m,v,k){
if (v) m[k]=v;
})
tags: _.transform(User.user.filters, function(m, v, k) {
if (v) m.push(v);
}),
};
User.user.ops.addTask({body:newTask});
}
@@ -70,7 +71,9 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
/**
* Add the new task to the actions log
*/
$scope.clearDoneTodos = function() {};
$scope.clearDoneTodos = function() {
Tasks.clearCompletedTodos();
};
/**
* Pushes task to top or bottom of list
@@ -97,12 +100,20 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
};
$scope.saveTask = function(task, stayOpen, isSaveAndClose) {
if (task.checklist)
task.checklist = _.filter(task.checklist,function(i){return !!i.text});
//@TODO: We will need to fix tag saving when user service is ported since tags are attached at the user level
if (task.checklist) {
task.checklist = _.filter(task.checklist, function(i) {return !!i.text});
}
User.user.ops.updateTask({params:{id:task.id},body:task});
if (!stayOpen) task._editing = false;
if (isSaveAndClose)
if (isSaveAndClose) {
$("#task-" + task.id).parent().children('.popover').removeClass('in');
}
if (task.type == 'habit') Guide.goto('intro', 3);
};
@@ -120,9 +131,8 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
};
$scope.unlink = function(task, keep) {
// TODO move this to userServices, turn userSerivces.user into ng-resource
$http.post(ApiUrl.get() + '/api/v2/user/tasks/' + task.id + '/unlink?keep=' + keep)
.success(function(){
Tasks.unlinkTask(task.id, keep)
.success(function () {
User.log({});
});
};
@@ -157,50 +167,57 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
$('#task-'+task.id+' .checklist-form input[type="text"]')[index].focus();
});
}
$scope.addChecklist = function(task) {
task.checklist = [{completed:false,text:""}];
task.checklist = [{completed:false, text:""}];
focusChecklist(task,0);
}
$scope.addChecklistItem = function(task,$event,$index) {
$scope.addChecklistItem = function(task, $event, $index) {
if (!task.checklist[$index].text) {
// Don't allow creation of an empty checklist item
// TODO Provide UI feedback that this item is still blank
} else if ($index == task.checklist.length-1){
User.user.ops.updateTask({params:{id:task.id},body:task}); // don't preen the new empty item
task.checklist.push({completed:false,text:''});
focusChecklist(task,task.checklist.length-1);
} else if ($index == task.checklist.length - 1) {
User.user.ops.updateTask({params:{id:task.id},body:task});
task.checklist.push({completed: false, text: ''});
focusChecklist(task, task.checklist.length - 1);
} else {
$scope.saveTask(task,true);
focusChecklist(task,$index+1);
$scope.saveTask(task, true);
focusChecklist(task, $index + 1);
}
}
$scope.removeChecklistItem = function(task,$event,$index,force){
$scope.removeChecklistItem = function(task, $event, $index, force){
// Remove item if clicked on trash icon
if (force) {
task.checklist.splice($index,1);
$scope.saveTask(task,true);
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
$scope.saveTask(task,true);
Tasks.removeChecklistItem(task.id, task.checklist[$index]._id);
// Move focus if the list is still non-empty
if ($index > 0)
focusChecklist(task,$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.checklist.splice(oldIndex, 1)[0];
task.checklist.splice(newIndex, 0, toSwap);
$scope.saveTask(task, true);
}
$scope.navigateChecklist = function(task,$index,$event){
focusChecklist(task, $event.keyCode == '40' ? $index+1 : $index-1);
}
$scope.checklistCompletion = function(checklist){
return _.reduce(checklist,function(m,i){return m+(i.completed ? 1 : 0);},0)
}
$scope.collapseChecklist = function(task) {
task.collapseChecklist = !task.collapseChecklist;
$scope.saveTask(task,true);
@@ -224,7 +241,6 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
User.user.ops.buy({params:{key:item.key}});
};
/*
------------------------
Hiding Tasks

View File

@@ -1,19 +1,138 @@
'use strict';
(function(){
var TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'date', 'dateCompleted', 'dateCreated', 'history', 'id', 'streak'];
var TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'date', 'dateCompleted', 'dateCreated', 'history', 'id', 'streak', 'createdAt'];
angular
.module('habitrpg')
.factory('Tasks', tasksFactory);
angular.module('habitrpg')
.factory('Tasks', ['$rootScope', 'Shared', 'User', '$http',
function tasksFactory($rootScope, Shared, User, $http) {
tasksFactory.$inject = [
'$rootScope',
'Shared',
'User'
];
function getUserTasks () {
return $http({
method: 'GET',
url: 'api/v3/tasks/user',
});
};
function tasksFactory($rootScope, Shared, User) {
function createUserTasks (taskDetails) {
return $http({
method: 'POST',
url: 'api/v3/tasks/user',
data: taskDetails,
});
};
function getChallengeTasks (challengeId) {
return $http({
method: 'GET',
url: 'api/v3/tasks/challenge/' + challengeId,
});
};
function createChallengeTasks (challengeId, taskDetails) {
return $http({
method: 'POST',
url: 'api/v3/tasks/challenge/' + challengeId,
data: taskDetails,
});
};
function getTask (taskId) {
return $http({
method: 'GET',
url: 'api/v3/tasks/' + taskId,
});
};
function updateTask (taskId, taskDetails) {
return $http({
method: 'PUT',
url: 'api/v3/tasks/' + taskId,
data: taskDetails,
});
};
function deleteTask (taskId) {
return $http({
method: 'DELETE',
url: 'api/v3/tasks/' + taskId,
});
};
function scoreTask (taskId, direction) {
return $http({
method: 'POST',
url: 'api/v3/tasks/' + taskId + '/score/' + direction,
});
};
function moveTask (taskId, position) {
return $http({
method: 'POST',
url: 'api/v3/tasks/' + taskId + '/move/to/' + position,
});
};
function addChecklistItem (taskId, checkListItem) {
return $http({
method: 'POST',
url: 'api/v3/tasks/' + taskId + '/checklist',
data: checkListItem,
});
};
function scoreCheckListItem (taskId, itemId) {
return $http({
method: 'POST',
url: 'api/v3/tasks/' + taskId + '/checklist/' + itemId + '/score',
});
};
function updateChecklistItem (taskId, itemId, itemDetails) {
return $http({
method: 'PUT',
url: 'api/v3/tasks/' + taskId + '/checklist/' + itemId,
data: itemDetails,
});
};
function removeChecklistItem (taskId, itemId) {
return $http({
method: 'DELETE',
url: 'api/v3/tasks/' + taskId + '/checklist/' + itemId,
});
};
function addTagToTask (taskId, tagId) {
return $http({
method: 'POST',
url: 'api/v3/tasks/' + taskId + '/tags/' + tagId,
});
};
function removeTagFromTask (taskId, tagId) {
return $http({
method: 'DELETE',
url: 'api/v3/tasks/' + taskId + '/tags/' + tagId,
});
};
function unlinkTask (taskId, keep) {
if (!keep) {
keep = "keep-all";
}
return $http({
method: 'POST',
url: 'api/v3/tasks/unlink/' + taskId + '?keep=' + keep,
});
};
function clearCompletedTodos () {
return $http({
method: 'POST',
url: 'api/v3/tasks/clearCompletedTodos',
});
};
function editTask(task) {
task._editing = !task._editing;
@@ -46,8 +165,24 @@
}
return {
getUserTasks: getUserTasks,
createUserTasks: createUserTasks,
getChallengeTasks: getChallengeTasks,
createChallengeTasks: createChallengeTasks,
getTask: getTask,
updateTask: updateTask,
deleteTask: deleteTask,
scoreTask: scoreTask,
moveTask: moveTask,
addChecklistItem: addChecklistItem,
scoreCheckListItem: scoreCheckListItem,
updateChecklistItem: updateChecklistItem,
removeChecklistItem: removeChecklistItem,
addTagToTask: addTagToTask,
removeTagFromTask: removeTagFromTask,
unlinkTask: unlinkTask,
clearCompletedTodos: clearCompletedTodos,
editTask: editTask,
cloneTask: cloneTask
};
}
})();
}]);

View File

@@ -1,5 +1,5 @@
fieldset.option-group(ng-if='!$state.includes("options.social.challenges")')
p.option-title.mega(ng-class='{active: task._tags}', ng-click='task._tags = !task._tags', tooltip=env.t('expandCollapse'))=env.t('tags')
label.checkbox(ng-repeat='tag in user.tags', ng-if='task._tags')
input(type='checkbox', ng-model='task.tags[tag.id]')
input(type='checkbox', ng-model='task.tags[tag.id]', ng-checked="task.tags.indexOf(tag.id) !== -1")
markdown(text='tag.name')

View File

@@ -43,7 +43,7 @@
span.glyphicon.glyphicon-bullhorn(tooltip=env.t('challenge'))
|  
// delete
a(ng-if='!task.challenge.id', ng-click='removeTask(task, obj[list.type+"s"])', tooltip=env.t('delete'))
a(ng-if='!task.challenge.id', ng-click='removeTask(task, $index)', tooltip=env.t('delete'))
span.glyphicon.glyphicon-trash
|  

View File

@@ -1,4 +1,4 @@
form.task-add(name='new{{list.type}}form', ng-hide='obj._locked', ng-submit='addTask(obj[list.type+"s"],list)', novalidate)
form.task-add(name='new{{list.type}}form', ng-hide='obj._locked', ng-submit='addTask(obj[list.type+"s"], list, obj)', novalidate)
textarea(rows='6', focus-element='list.bulk && list.focus', ng-model='list.newTask', placeholder='{{list.placeHolderBulk}}', ng-if='list.bulk', ui-keydown='{"meta-enter ctrl-enter":"addTask(obj[list.type+\'s\'],list)"}', required)
input(type='text', focus-element='!list.bulk && list.focus', ng-model='list.newTask', placeholder='{{list.placeHolder}}', ng-if='!list.bulk', required)
button(type='submit', ng-disabled='new{{list.type}}form.$invalid')