api & rewrite: implement clear-completd at POST /api/v1/user/clear-completed
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
}]);
|
||||
|
||||
@@ -23,5 +23,8 @@ habitrpg.controller('SettingsCtrl',
|
||||
User.log({'op':'set', data:{'preferences.dayStart': dayStart}});
|
||||
}
|
||||
|
||||
$scope.reroll = function(){
|
||||
}
|
||||
|
||||
}
|
||||
]);
|
||||
|
||||
+141
-134
@@ -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'});
|
||||
}
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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}')
|
||||
|
||||
@@ -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}}')
|
||||
|
||||
Reference in New Issue
Block a user