api & rewrite: implement clear-completd at POST /api/v1/user/clear-completed

This commit is contained in:
Tyler Renelle
2013-08-28 22:51:45 -04:00
parent 2219068fad
commit 10b0c9f9a5
11 changed files with 183 additions and 173 deletions
-11
View File
@@ -7,17 +7,9 @@ misc = require './misc'
appExports.clearCompleted = (e, el) ->
completedIds = _.pluck( _.where(model.get('_todoList'), {completed:true}), 'id')
todoIds = user.get('todoIds')
_.each completedIds, (id) -> user.del "tasks.#{id}"; true
user.set 'todoIds', _.difference(todoIds, completedIds)
appExports.toggleTaskEdit = (e, el) ->
id = e.get('id')
[editPath, chartPath] = ["_tasks.editing.#{id}", "_page.charts.#{id}"]
model.set editPath, !(model.get editPath)
model.set chartPath, false
appExports.toggleChart = (e, el) ->
id = $(el).attr('data-id')
[historyPath, togglePath] = ['','']
@@ -43,9 +35,6 @@ misc = require './misc'
chart = new google.visualization.LineChart $(".#{id}-chart")[0]
chart.draw(data, options)
appExports.todosShowRemaining = -> model.set '_showCompleted', false
appExports.todosShowCompleted = -> model.set '_showCompleted', true
###
Undo
+1 -3
View File
@@ -6,9 +6,7 @@
habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', '$location',
function($scope, $rootScope, Groups) {
$scope.groups = Groups.query(function(){
debugger
});
$scope.groups = Groups.query();
$scope.party = true;
}
]);
+6 -20
View File
@@ -9,9 +9,6 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User',
$rootScope.User = User;
$rootScope.user = User.user;
$rootScope.settings = User.settings;
$rootScope.notPorted = function(){
alert("This feature is not yet ported from the original site.");
}
/*
FIXME this is dangerous, organize helpers.coffee better, so we can group them by which controller needs them,
@@ -20,27 +17,16 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User',
_.defaults($rootScope, window.habitrpgShared.algos);
_.defaults($rootScope, window.habitrpgShared.helpers);
/*
Very simple path-set. `set('preferences.gender','m')` for example. We'll deprecate this once we have a complete API
*/
$rootScope.set = function(k, v) {
var log = { op: 'set', data: {} };
window.habitrpgShared.helpers.dotSet(k, v, User.user);
log.data[k] = v;
User.log(log);
};
$rootScope.setMultiple = function(){
}
$rootScope.authenticated = function() {
return User.settings.auth.apiId !== "";
};
$rootScope.set = User.set;
$rootScope.authenticated = User.authenticated;
$rootScope.dismissAlert = function() {
$rootScope.modals.newStuff = false;
$rootScope.set('flags.newStuff',false);
}
$rootScope.notPorted = function(){
alert("This feature is not yet ported from the original site.");
}
}]);
+3
View File
@@ -23,5 +23,8 @@ habitrpg.controller('SettingsCtrl',
User.log({'op':'set', data:{'preferences.dayStart': dayStart}});
}
$scope.reroll = function(){
}
}
]);
+141 -134
View File
@@ -2,148 +2,155 @@
habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', 'Algos', 'Helpers', 'Notification',
function($scope, $rootScope, $location, User, Algos, Helpers, Notification) {
/*FIXME
*/
$scope.taskLists = [
{
header: 'Habits',
type: 'habit',
placeHolder: 'New Habit',
main: true,
editable: true
}, {
header: 'Dailies',
type: 'daily',
placeHolder: 'New Daily',
main: true,
editable: true
}, {
header: 'Todos',
type: 'todo',
placeHolder: 'New Todo',
main: true,
editable: true
}, {
header: 'Reward',
type: 'reward',
placeHolder: 'New Reward',
main: true,
editable: true
}
];
$scope.score = function(task, direction) {
/*save current stats to compute the difference after scoring.
/*FIXME
*/
var oldStats, statsDiff;
statsDiff = {};
oldStats = _.clone(User.user.stats);
Algos.score(User.user, task, direction);
/*compute the stats change.
*/
_.each(oldStats, function(value, key) {
var newValue;
newValue = User.user.stats[key];
if (newValue !== value) {
statsDiff[key] = newValue - value;
$scope.taskLists = [
{
header: 'Habits',
type: 'habit',
placeHolder: 'New Habit',
main: true,
editable: true
}, {
header: 'Dailies',
type: 'daily',
placeHolder: 'New Daily',
main: true,
editable: true
}, {
header: 'Todos',
type: 'todo',
placeHolder: 'New Todo',
main: true,
editable: true
}, {
header: 'Reward',
type: 'reward',
placeHolder: 'New Reward',
main: true,
editable: true
}
});
/*notify user if there are changes in stats.
*/
];
$scope.score = function(task, direction) {
/*save current stats to compute the difference after scoring.
*/
if (Object.keys(statsDiff).length > 0) {
Notification.push({
type: "stats",
stats: statsDiff
var oldStats, statsDiff;
statsDiff = {};
oldStats = _.clone(User.user.stats);
Algos.score(User.user, task, direction);
/*compute the stats change.
*/
_.each(oldStats, function(value, key) {
var newValue;
newValue = User.user.stats[key];
if (newValue !== value) {
statsDiff[key] = newValue - value;
}
});
}
if (task.type === "reward" && _.isEmpty(statsDiff)) {
Notification.push({
type: "text",
text: "Not enough GP."
});
}
User.log({
op: "score",
data: task,
dir: direction
});
};
/*notify user if there are changes in stats.
*/
$scope.addTask = function(list) {
var task = window.habitrpgShared.helpers.taskDefaults({text: list.newTask, type: list.type});
User.user[list.type + "s"].unshift(task);
// $scope.showedTasks.unshift newTask # FIXME what's thiss?
User.log({op: "addTask", data: task});
delete list.newTask;
};
/*Add the new task to the actions log
*/
$scope.clearDoneTodos = function() {};
$scope.changeCheck = function(task) {
/* This is calculated post-change, so task.completed=true if they just checked it
*/
if (task.completed) {
$scope.score(task, "up");
} else {
$scope.score(task, "down");
}
};
/* TODO this should be somewhere else, but fits the html location better here
*/
$rootScope.revive = function() {
window.habitrpgShared.algos.revive(User.user);
User.log({
op: "revive"
});
};
$scope.remove = function(task) {
var tasks;
if (confirm("Are you sure you want to delete this task?") !== true) {
return;
}
tasks = User.user[task.type + "s"];
User.log({
op: "delTask",
data: task
});
tasks.splice(tasks.indexOf(task), 1);
};
/*
------------------------
Items
------------------------
*/
$scope.$watch("user.items", function() {
var sorted, updated;
updated = window.habitrpgShared.items.updateStore(User.user);
/* Figure out whether we wanna put this in habitrpg-shared
*/
sorted = [updated.weapon, updated.armor, updated.head, updated.shield, updated.potion, updated.reroll];
$scope.itemStore = sorted;
});
$scope.buy = function(type) {
var hasEnough;
hasEnough = window.habitrpgShared.items.buyItem(User.user, type);
if (hasEnough) {
if (Object.keys(statsDiff).length > 0) {
Notification.push({
type: "stats",
stats: statsDiff
});
}
if (task.type === "reward" && _.isEmpty(statsDiff)) {
Notification.push({
type: "text",
text: "Not enough GP."
});
}
User.log({
op: "buy",
type: type
op: "score",
data: task,
dir: direction
});
Notification.push({
type: "text",
text: "Item bought!"
};
$scope.addTask = function(list) {
var task = window.habitrpgShared.helpers.taskDefaults({text: list.newTask, type: list.type});
User.user[list.type + "s"].unshift(task);
// $scope.showedTasks.unshift newTask # FIXME what's thiss?
User.log({op: "addTask", data: task});
delete list.newTask;
};
/*Add the new task to the actions log
*/
$scope.clearDoneTodos = function() {};
$scope.changeCheck = function(task) {
/* This is calculated post-change, so task.completed=true if they just checked it
*/
if (task.completed) {
$scope.score(task, "up");
} else {
$scope.score(task, "down");
}
};
/* TODO this should be somewhere else, but fits the html location better here
*/
$rootScope.revive = function() {
window.habitrpgShared.algos.revive(User.user);
User.log({
op: "revive"
});
} else {
Notification.push({
type: "text",
text: "Not enough GP."
};
$scope.remove = function(task) {
var tasks;
if (confirm("Are you sure you want to delete this task?") !== true) {
return;
}
tasks = User.user[task.type + "s"];
User.log({
op: "delTask",
data: task
});
tasks.splice(tasks.indexOf(task), 1);
};
/*
------------------------
Items
------------------------
*/
$scope.$watch("user.items", function() {
var sorted, updated;
updated = window.habitrpgShared.items.updateStore(User.user);
/* Figure out whether we wanna put this in habitrpg-shared
*/
sorted = [updated.weapon, updated.armor, updated.head, updated.shield, updated.potion, updated.reroll];
$scope.itemStore = sorted;
});
$scope.buy = function(type) {
var hasEnough;
hasEnough = window.habitrpgShared.items.buyItem(User.user, type);
if (hasEnough) {
User.log({
op: "buy",
type: type
});
Notification.push({
type: "text",
text: "Item bought!"
});
} else {
Notification.push({
type: "text",
text: "Not enough GP."
});
}
};
$scope.clearCompleted = function() {
User.user.todos = _.reject(User.user.todos, {completed:true});
User.log({op: 'clear-completed'});
}
};
}]);
+14
View File
@@ -128,6 +128,20 @@ angular.module('userServices', []).
}
},
authenticated: function(){
this.settings.auth.apiId !== "";
},
/*
Very simple path-set. `set('preferences.gender','m')` for example. We'll deprecate this once we have a complete API
*/
set: function(k, v) {
var log = { op: 'set', data: {} };
window.habitrpgShared.helpers.dotSet(k, v, this.user);
log.data[k] = v;
this.log(log);
},
log: function (action, cb) {
//push by one buy one if an array passed in.
if (_.isArray(action)) {
+12 -1
View File
@@ -92,7 +92,6 @@ deleteTask = (user, task) ->
if (ids = user["#{task.type}Ids"]) and ~(i = ids.indexOf task.id)
ids.splice(i,1)
###
API Routes
---------------
@@ -214,6 +213,16 @@ api.sortTask = (req, res, next) ->
return res.json(500,{err}) if err
res.json 200, saved.toJSON()[path]
api.clearCompleted = (req, res, next) ->
{user} = res.locals
completedIds = _.pluck( _.where(user.tasks, {type:'todo', completed:true}), 'id')
todoIds = user.todoIds
_.each completedIds, (id) -> delete user.tasks[id]; true
user.todoIds = _.difference(todoIds, completedIds)
user.save (err, saved) ->
return res.json(500, {err}) if err
res.json saved
###
------------------------------------------------------------------------
Items
@@ -449,6 +458,8 @@ api.batchUpdate = (req, res, next) ->
api.updateUser(req, res)
when "revive"
api.revive(req, res)
when "clear-completed"
api.clearCompleted(req, res)
else cb()
# Setup the array of functions we're going to call in parallel with async
+1
View File
@@ -31,6 +31,7 @@ router.post '/user/tasks', auth, cron, api.updateTasks
router.delete '/user/task/:id', auth, cron, verifyTaskExists, api.deleteTask
router.post '/user/task', auth, cron, api.createTask
router.put '/user/task/:id/sort', auth, cron, verifyTaskExists, api.sortTask
router.post '/user/clear-completed', auth, cron, api.clearCompleted
# Items
router.post '/user/buy/:type', auth, cron, api.buy
+1 -1
View File
@@ -23,7 +23,7 @@
| {{user.stats.exp | number:0}} / {{tnl(user.stats.lvl)}}
// FIXME doesn't look great here, but the "Experience" CSS title rollover covers it where it was before
span(ng-show='user.history.exp')
a(x-bind='click:toggleChart', data-id='exp', tooltip='Progress')
a(x-bind='click:toggleChart', ng-click='notPorted()', data-id='exp', tooltip='Progress')
i.icon-signal
// party
span(ng-controller='GroupsCtrl')
+3 -2
View File
@@ -6,9 +6,10 @@ div(ng-controller='TasksCtrl')
// Todos export/graph options
span.option-box.pull-right(ng-if='list.main && list.type=="todo"')
a.option-action(ng-show='user.history.todos', x-bind='click:toggleChart', data-id='todos', tooltip='Progress')
a.option-action(ng-show='user.history.todos', x-bind='click:toggleChart', ng-click='notPorted()', data-id='todos', tooltip='Progress')
i.icon-signal
//-a.option-action(ng-href='/v1/users/{{user.id}}/calendar.ics?apiToken={{user.apiToken}}', tooltip='iCal')
a.option-action(ng-click='notPorted()', tooltip='iCal')
i.icon-calendar
// <a href="https://www.google.com/calendar/render?cid={{encodeiCalLink(_user.id, _user.apiToken)}}" rel=tooltip title="Google Calendar"><i class=icon-calendar></i></a>
@@ -62,7 +63,7 @@ div(ng-controller='TasksCtrl')
// Todo Tabs
div(ng-if='list.type=="todo"', ng-class='{"tabbable tabs-below": list.type=="todo"}')
button.task-action-btn.tile.spacious.bright(ng-show='_showCompleted', x-bind='click:clearCompleted') Clear Completed
button.task-action-btn.tile.spacious.bright(ng-show='list.showCompleted', ng-click='clearCompleted()') Clear Completed
// remaining/completed tabs
ul.nav.nav-tabs
li(ng-class='{active: !list.showCompleted}')
+1 -1
View File
@@ -24,7 +24,7 @@ li(ng-repeat='task in user[list.type + "s"]', class='task {{taskClasses(task,use
a(ng-click='remove(task)', tooltip='Delete')
i.icon-trash
// chart
a(ng-show='task.history', x-bind='click:toggleChart', data-id='{{task.id}}', tooltip='Progress')
a(ng-show='task.history', x-bind='click:toggleChart', ng-click='notPorted()', data-id='{{task.id}}', tooltip='Progress')
i.icon-signal
// notes
span.task-notes(ng-show='task.notes', popover-trigger='mouseenter', popover-placement='left', popover='{{task.notes}}', popover-title='{{task.text}}')