git merge Merge branch 'develop' of https://github.com/HabitRPG/habitrpg into translations

This commit is contained in:
Matteo Pagliazzi 2013-11-12 14:54:17 +01:00
commit 7eaed0348f
13 changed files with 150 additions and 51 deletions

View file

@ -33,7 +33,8 @@
"BrowserQuest": "https://github.com/mozilla/BrowserQuest.git",
"github-buttons": "git://github.com/mdo/github-buttons.git",
"marked": "~0.2.9",
"JavaScriptButtons": "git://github.com/paypal/JavaScriptButtons.git#master"
"JavaScriptButtons": "git://github.com/paypal/JavaScriptButtons.git#master",
"Angular-At-Directive": "git://github.com/scarletsky/Angular-At-Directive.git#master"
},
"resolutions": {
"jquery": "~2.0.3",

View file

@ -0,0 +1,15 @@
// This migration has already been run in the past. It's vital to fix these users presently, but we need to find
// out why task values are ever getting in as NaN. My guess is API PUT /tasks/:tid routes
db.users.find({},{habits:1,dailys:1,todos:1,rewards:1}).forEach(function(user){
_.each(['habits','dailys','todos','rewards'], function(type){
_.each(user[type], function(task){
task.value = +task.value;
if (_.isNaN(task.value)) {
task.value = 0;
print(user._id);
}
})
})
db.users.update({_id:user._id}, {$set:{habits: user.habits, dailys: user.dailys, todos: user.todos, rewards: user.rewards}});
});

View file

@ -54,4 +54,4 @@ menu
.well.limited-edition
padding: 5px
margin: 0px
margin: 25px 0 0

View file

@ -57,4 +57,38 @@
margin: 5px
.option-group .option-time
padding: 0px 5px
padding: 0px 5px
// Autocomplete [TODO] make this nicer
.list-at-user {
width: 100%;
max-width: 120px;
position: absolute;
background: white;
border: 1px solid #a4a4a4;
z-index: 10;
margin-left: -435px;
margin-top: -355px;
}
.list-at-user li {
line-height:14px;
border-bottom: 1px solid #a4a4a4;
list-style-type: none;
}
.list-at-user li:hover {
cursor: pointer;
background: #b9dff4;
}
.list-at-user li span {
margin: 2px;
font-size: 11.844px;
margin-left: 5px;
display: inline-block;
}
.list-cur {
background: #b9dff4;
}

View file

@ -3,7 +3,7 @@
window.habitrpg = angular.module('habitrpg',
['ngResource', 'ngSanitize', 'userServices', 'groupServices', 'memberServices', 'challengeServices',
'sharedServices', 'authServices', 'notificationServices', 'guideServices',
'ui.bootstrap', 'ui.keypress', 'ui.router', 'chieffancypants.loadingBar'])
'ui.bootstrap', 'ui.keypress', 'ui.router', 'chieffancypants.loadingBar', 'At'])
// @see https://github.com/angular-ui/ui-router/issues/110 and https://github.com/HabitRPG/habitrpg/issues/1705
// temporary hack until they have a better solution

View file

@ -7,34 +7,13 @@ habitrpg.controller("ChallengesCtrl", ['$scope', 'User', 'Challenges', 'Notifica
Groups.Group.query({type:'party,guilds,tavern'}, function(groups){
$scope.groups = groups;
$scope.search = {
group: _.reduce(groups, function(m,g){m[g._id]=true;return m;}, {})
group: _.transform(groups, function(m,g){m[g._id]=true;})
};
});
// FIXME $scope.challenges needs to be resolved first (see app.js)
$scope.challenges = Challenges.Challenge.query();
// we should fix this, that's pretty brittle
// $scope.$watch('search', function(search){
// if (!search) $scope.filteredChallenges = $scope.challenges;
// $scope.filteredChallenges = $filter('filter')($scope.challenges, function(chal) {
// return (search.group[chal.group._id] &&
// (typeof search._isMember == 'undefined' || search._isMember == chal._isMember));
// })
// })
// TODO probably better to use $watch above, to avoid this being calculated on every digest cycle
$scope.filterChallenges = function(chal){
return (!$scope.search) ? true :
($scope.search.group[chal.group._id] &&
(typeof $scope.search._isMember == 'undefined' || $scope.search._isMember == chal._isMember));
}
$scope.$watch('newChallenge.group', function(gid){
if (!gid) return;
var group = _.find($scope.groups, {_id:gid});
$scope.maxPrize = User.user.balance*4 + ((group && group.balance && group.leader==User.user._id) ? group.balance*4 : 0);
if (gid == 'habitrpg') $scope.newChallenge.prize = 1;
})
// override score() for tasks listed in challenges-editing pages, so that nothing happens
$scope.score = function(){}
@ -216,4 +195,37 @@ habitrpg.controller("ChallengesCtrl", ['$scope', 'User', 'Challenges', 'Notifica
}).popover('show');
}
//------------------------------------------------------------
// Filtering
//------------------------------------------------------------
// $scope.$watch('search', function(search){
// if (!search) $scope.filteredChallenges = $scope.challenges;
// $scope.filteredChallenges = $filter('filter')($scope.challenges, function(chal) {
// return (search.group[chal.group._id] &&
// (typeof search._isMember == 'undefined' || search._isMember == chal._isMember));
// })
// })
// TODO probably better to use $watch above, to avoid this being calculated on every digest cycle
$scope.filterChallenges = function(chal){
return (!$scope.search) ? true :
($scope.search.group[chal.group._id] &&
(typeof $scope.search._isMember == 'undefined' || $scope.search._isMember == chal._isMember));
}
$scope.$watch('newChallenge.group', function(gid){
if (!gid) return;
var group = _.find($scope.groups, {_id:gid});
$scope.maxPrize = User.user.balance*4 + ((group && group.balance && group.leader==User.user._id) ? group.balance*4 : 0);
if (gid == 'habitrpg') $scope.newChallenge.prize = 1;
})
$scope.selectAll = function(){
$scope.search.group = _.transform($scope.groups, function(m,g){m[g._id] = true});
}
$scope.selectNone = function(){
$scope.search.group = _.transform($scope.groups, function(m,g){m[g._id] = false});
}
}]);

View file

@ -79,6 +79,32 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
}
])
.controller('AutocompleteCtrl', ['$scope', 'Groups', 'User', function ($scope,Groups,User) {
$scope.clearUserlist = function() {
$scope.response = [];
$scope.usernames = [];
}
$scope.addNewUser = function(user) {
if($.inArray(user.user,$scope.usernames) == -1) {
$scope.usernames.push(user.user);
$scope.response.push(user);
}
}
$scope.clearUserlist();
$scope.chatChanged = function(newvalue,oldvalue){
if($scope.group.chat && $scope.group.chat.length > 0){
for(var i = 0; i < $scope.group.chat.length; i++) {
$scope.addNewUser($scope.group.chat[i]);
}
}
}
$scope.$watch('group.chat',$scope.chatChanged);
}])
.controller('ChatCtrl', ['$scope', 'Groups', 'User', function($scope, Groups, User){
$scope._chatMessage = '';
$scope._sending = false;

View file

@ -13,6 +13,8 @@
"bower_components/angular-ui/build/angular-ui.js",
"bower_components/angular-ui-utils/modules/keypress/keypress.js",
"bower_components/angular-loading-bar/build/loading-bar.js",
"bower_components/Angular-At-Directive/src/at.js",
"bower_components/Angular-At-Directive/src/caret.js",
"bower_components/bootstrap/docs/assets/js/bootstrap.js",
"bower_components/angular-bootstrap/ui-bootstrap.js",

View file

@ -67,12 +67,18 @@ api.get = function(req, res) {
api.getMember = function(req, res) {
var cid = req.params.cid, uid = req.params.uid;
var elMatch = {$elemMatch:{'challenge.id':cid}};
// TMK we can't use $elemMatch (which would make things much cleaner) @see http://goo.gl/MxmWdQ & http://goo.gl/Iku44w
// Revert back to 9fbb45c to see the $elemMatch solution
User.findById(uid)
.select({'profile.name':1, habits:elMatch, dailys:elMatch, rewards:elMatch, todos:elMatch})
.select('profile.name habits dailys rewards todos')
.exec(function(err, member){
if(err) return res.json(500, {err:err});
if (!member) return res.json(404, {err: 'Member '+uid+' for challenge '+cid+' not found'});
_.each(['habits','dailys','todos', 'rewards'], function(type){
member[type] = _.filter(member[type], function(task){
return task.challenge && task.challenge.id && task.challenge.id == cid;
});
});
res.json(member);
})
}

View file

@ -57,21 +57,16 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template')
button.btn.btn-small.btn-primary(ng-hide='user.purchased.skin.eb052b && user.purchased.skin.f69922 && user.purchased.skin.f5d70f && user.purchased.skin.0ff591 && user.purchased.skin.2b43f6 && user.purchased.skin.d7a9f7 && user.purchased.skin.800ed0 && user.purchased.skin.rainbow', ng-click='unlock(["skin.eb052b", "skin.f69922", "skin.f5d70f", "skin.0ff591", "skin.2b43f6", "skin.d7a9f7", "skin.800ed0", "skin.rainbow"])') Unlock Set - 5<span class="Pet_Currency_Gem1x inline-gems"/>
// Special Events
div.well.limited-edition
.label.label-info.pull-right(popover='Available for purchase until November 10th (but permanently in your options if purchased).', popover-title='Limited Edition', popover-placement='right', popover-trigger='mouseenter')
| Limited Edition&nbsp;
i.icon.icon-question-sign
h5.
Spooky Skins - 2<span class="Pet_Currency_Gem1x inline-gems"/>/skin
//menu(label='Spooky Skins (2 Gems / skin)')
// restore to d4df481 to see purchasing + "limited edition" code
div(ng-if='user.purchased.skin.monster || user.purchased.skin.pumpkin || user.purchased.skin.skeleton || user.purchased.skin.zombie || user.purchased.skin.ghost || user.purchased.skin.shadow')
h5 Spooky Skins
menu
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_monster', ng-class='{locked: !user.purchased.skin.monster}', ng-click='unlock("skin.monster")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_pumpkin', ng-class='{locked: !user.purchased.skin.pumpkin}', ng-click='unlock("skin.pumpkin")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_skeleton', ng-class='{locked: !user.purchased.skin.skeleton}', ng-click='unlock("skin.skeleton")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_zombie', ng-class='{locked: !user.purchased.skin.zombie}', ng-click='unlock("skin.zombie")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_ghost', ng-class='{locked: !user.purchased.skin.ghost}', ng-click='unlock("skin.ghost")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_shadow', ng-class='{locked: !user.purchased.skin.shadow}', ng-click='unlock("skin.shadow")')
button.btn.btn-small.btn-primary(ng-hide='user.purchased.skin.monster && user.purchased.skin.pumpkin && user.purchased.skin.skeleton && user.purchased.skin.zombie && user.purchased.skin.ghost && user.purchased.skin.shadow', ng-click='unlock(["skin.monster", "skin.pumpkin", "skin.skeleton", "skin.zombie", "skin.ghost", "skin.shadow"])') Unlock Set - 5<span class="Pet_Currency_Gem1x inline-gems"/>
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_monster', ng-if='user.purchased.skin.monster', ng-click='unlock("skin.monster")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_pumpkin', ng-if='user.purchased.skin.pumpkin', ng-click='unlock("skin.pumpkin")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_skeleton', ng-if='user.purchased.skin.skeleton', ng-click='unlock("skin.skeleton")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_zombie', ng-if='user.purchased.skin.zombie', ng-click='unlock("skin.zombie")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_ghost', ng-if='user.purchased.skin.ghost', ng-click='unlock("skin.ghost")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_shadow', ng-if='user.purchased.skin.shadow', ng-click='unlock("skin.shadow")')
script(id='partials/options.profile.stats.html', type='text/ng-template')
.row-fluid

View file

@ -9,12 +9,12 @@ script(type='text/ng-template', id='partials/options.social.challenges.detail.cl
script(type='text/ng-template', id='partials/options.social.challenges.detail.member.html')
.modal.wide-modal
.modal-header
button.close(type='button', ng-click='$state.go("^")', aria-hidden='true') ×
h3 {{obj.profile.name}}
.modal-body
habitrpg-tasks(main=false)
.modal-footer
a.btn(ng-click='$state.go("^")') Close
button.close(type='button', ng-click='$state.go("^")', aria-hidden='true') ×
h3 {{obj.profile.name}}
.modal-body
habitrpg-tasks(main=false)
.modal-footer
a.btn(ng-click='$state.go("^")') Close
script(type='text/ng-template', id='partials/options.social.challenges.detail.html')
// Edit button
@ -61,6 +61,10 @@ script(type='text/ng-template', id='partials/options.social.challenges.html')
.span2.well#challenges-filters
h3 Filter:
h4 Groups
ul.unstyled
a.btn.btn-mini.pull-left(ng-click='selectAll()') All
a.btn.btn-mini(ng-click='selectNone()') None
br
label.checkbox(ng-repeat='group in groups')
input(type='checkbox', ng-model='search.group[group._id]')
| {{group.name}}

View file

@ -1,8 +1,12 @@
form(ng-submit='postChat(group,_chatMessage)')
.-options
//FIXME ng-model makes this painfully slow! using jquery for now, which is really non-angular-like
.control-group.option-large
textarea.chat-textarea.option-content(style='height:6em;', ui-keypress='{13:"postChat(group,_chatMessage)"}', ng-model='_chatMessage')
.control-group.option-large(ng-controller='AutocompleteCtrl')
textarea.chat-textarea.option-content(style='height:6em;', ui-keypress='{13:"postChat(group,_chatMessage)"}', ng-model='_chatMessage', flag='@', at-user, auto-complete)
span.user-list(ng-show='!isAtListHidden', auto-follow='true')
ul.list-at-user
li(ng-repeat='user in users | filter:query.text | limitTo: 5', ng-click='autoComplete(user)')
span.username.label(class='label-contributor-{{user.contributor.level}}') {{user.user}}
table.pull-right
tr
td

View file

@ -1,4 +1,4 @@
// @TODO ui:connectionAlert
//.header-wrap(ng-controller='HeaderCtrl', data-spy="affix", data-offset-top="148")
.header-wrap(ng-controller='HeaderCtrl')
a.label.undo-button(x-bind='click:undo', ng-show='_undo') Undo
div(ng-if='!user.preferences.hideHeader')