refactor(services): move to a single "habitrpg" module for services /

directives / filters
This commit is contained in:
Tyler Renelle 2015-01-17 18:43:37 -07:00
parent 90c7142da5
commit 2306b7c572
19 changed files with 646 additions and 661 deletions

View file

@ -1,9 +1,7 @@
"use strict";
window.habitrpg = angular.module('habitrpg',
['ngResource', 'ngSanitize', 'userServices', 'groupServices', 'memberServices', 'challengeServices',
'authServices', 'notificationServices', 'guideServices', 'authCtrl', 'paymentServices',
'ui.bootstrap', 'ui.keypress', 'ui.router', 'chieffancypants.loadingBar', 'At', 'infinite-scroll', 'ui.select2', 'angular.filter'])
['authCtrl', 'ui.bootstrap', 'ui.keypress', 'ui.router', 'chieffancypants.loadingBar', 'At', 'infinite-scroll', 'ui.select2', 'angular.filter', 'ngResource'])
// @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

@ -5,8 +5,8 @@
*/
angular.module('authCtrl', [])
.controller("AuthCtrl", ['$scope', '$rootScope', 'User', '$http', '$location', '$window','ApiUrlService', '$modal',
function($scope, $rootScope, User, $http, $location, $window, ApiUrlService, $modal) {
.controller("AuthCtrl", ['$scope', '$rootScope', 'User', '$http', '$location', '$window','ApiUrl', '$modal',
function($scope, $rootScope, User, $http, $location, $window, ApiUrl, $modal) {
$scope.logout = function() {
localStorage.clear();
@ -36,7 +36,7 @@ angular.module('authCtrl', [])
if ($scope.registrationForm.$invalid) {
return;
}
var url = ApiUrlService.get() + "/api/v2/register";
var url = ApiUrl.get() + "/api/v2/register";
if($rootScope.selectedLanguage) url = url + '?lang=' + $rootScope.selectedLanguage.code;
$http.post(url, $scope.registerVals).success(function(data, status, headers, config) {
runAuth(data.id, data.apiToken);
@ -48,7 +48,7 @@ angular.module('authCtrl', [])
username: $scope.loginUsername || $('#login-tab input[name="username"]').val(),
password: $scope.loginPassword || $('#login-tab input[name="password"]').val()
};
$http.post(ApiUrlService.get() + "/api/v2/user/auth/local", data)
$http.post(ApiUrl.get() + "/api/v2/user/auth/local", data)
.success(function(data, status, headers, config) {
runAuth(data.id, data.token);
}).error(errorAlert);
@ -70,7 +70,7 @@ angular.module('authCtrl', [])
if(email == null || email.length == 0) {
alert(window.env.t('invalidEmail'));
} else {
$http.post(ApiUrlService.get() + '/api/v2/user/reset-password', {email:email})
$http.post(ApiUrl.get() + '/api/v2/user/reset-password', {email:email})
.success(function(){
alert(window.env.t('newPassSent'));
})
@ -120,7 +120,7 @@ angular.module('authCtrl', [])
$scope.socialLogin = function(network){
hello(network).login({scope:'email'}).then(function(auth){
$http.post(ApiUrlService.get() + "/api/v2/user/auth/social", auth)
$http.post(ApiUrl.get() + "/api/v2/user/auth/social", auth)
.success(function(data, status, headers, config) {
runAuth(data.id, data.token);
}).error(errorAlert);

View file

@ -1,108 +1,108 @@
"use strict";
(typeof habitrpg !== 'undefined' ? habitrpg : habitrpgStatic)
.controller("FooterCtrl", ['$scope', '$rootScope', 'User', '$http', 'Notification', 'ApiUrlService',
function($scope, $rootScope, User, $http, Notification, ApiUrlService) {
angular.module('habitrpg').controller("FooterCtrl",
['$scope', '$rootScope', 'User', '$http', 'Notification', 'ApiUrl',
function($scope, $rootScope, User, $http, Notification, ApiUrl) {
if(typeof habitrpg === "undefined"){
$scope.languages = env.avalaibleLanguages;
$scope.selectedLanguage = _.find(env.avalaibleLanguages, {code: env.language.code});
if(typeof habitrpg === "undefined"){
$scope.languages = env.avalaibleLanguages;
$scope.selectedLanguage = _.find(env.avalaibleLanguages, {code: env.language.code});
$rootScope.selectedLanguage = $scope.selectedLanguage;
$scope.changeLang = function(){
window.location = '?lang='+$scope.selectedLanguage.code;
}
$rootScope.selectedLanguage = $scope.selectedLanguage;
$scope.changeLang = function(){
window.location = '?lang='+$scope.selectedLanguage.code;
}
}
/**
External Scripts
JS files not needed right away (google charts) or entirely optional (analytics)
Each file gets loaded async via $.getScript, so it doesn't bog page-load
*/
$scope.deferredScripts = function(){
// Stripe
$.getScript('//checkout.stripe.com/v2/checkout.js');
// Google Analytics, only in production
if (window.env.NODE_ENV === 'production') {
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', window.env.GA_ID, {userId:User.user._id});
ga('require', 'displayfeatures');
ga('send', 'pageview');
}
/**
External Scripts
JS files not needed right away (google charts) or entirely optional (analytics)
Each file gets loaded async via $.getScript, so it doesn't bog page-load
*/
$scope.deferredScripts = function(){
// Scripts only for desktop
if (!window.env.IS_MOBILE) {
// Add This
//$.getScript("//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4"); //FIXME why isn't this working when here? instead it's now in <head>
var addthisServices = 'facebook,twitter,googleplus,tumblr,'+window.env.BASE_URL.replace('https://','').replace('http://','');
window.addthis_config = {
ui_click: true,
services_custom:{
name: "Download",
url: window.env.BASE_URL+"/export/avatar-"+User.user._id+".png",
icon: window.env.BASE_URL+"/favicon.ico"
},
services_expanded:addthisServices,
services_compact:addthisServices
};
// Stripe
$.getScript('//checkout.stripe.com/v2/checkout.js');
// Google Analytics, only in production
if (window.env.NODE_ENV === 'production') {
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', window.env.GA_ID, {userId:User.user._id});
ga('require', 'displayfeatures');
ga('send', 'pageview');
}
// Scripts only for desktop
if (!window.env.IS_MOBILE) {
// Add This
//$.getScript("//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4"); //FIXME why isn't this working when here? instead it's now in <head>
var addthisServices = 'facebook,twitter,googleplus,tumblr,'+window.env.BASE_URL.replace('https://','').replace('http://','');
window.addthis_config = {
ui_click: true,
services_custom:{
name: "Download",
url: window.env.BASE_URL+"/export/avatar-"+User.user._id+".png",
icon: window.env.BASE_URL+"/favicon.ico"
},
services_expanded:addthisServices,
services_compact:addthisServices
};
// Google Charts
$.getScript("//www.google.com/jsapi", function() {
google.load("visualization", "1", {
packages: ["corechart"],
callback: function() {}
});
// Google Charts
$.getScript("//www.google.com/jsapi", function() {
google.load("visualization", "1", {
packages: ["corechart"],
callback: function() {}
});
}
});
}
}
/**
* Debug functions. Note that the server route for gems is only available if process.env.DEBUG=true
*/
if (_.contains(['development','test'],window.env.NODE_ENV)) {
$scope.setHealthLow = function(){
User.set({
'stats.hp': 1
});
}
$scope.addMissedDay = function(){
if (!confirm("Are you sure you want to reset the day?")) return;
var dayBefore = moment(User.user.lastCron).subtract(1, 'days').toDate();
User.set({'lastCron': dayBefore});
Notification.text('-1 day, remember to refresh');
}
$scope.addTenGems = function(){
$http.post(ApiUrlService.get() + '/api/v2/user/addTenGems').success(function(){
User.log({});
})
}
$scope.addGold = function(){
User.set({
'stats.gp': User.user.stats.gp + 500,
});
}
$scope.addLevelsAndGold = function(){
User.set({
'stats.exp': User.user.stats.exp + 10000,
'stats.gp': User.user.stats.gp + 10000,
'stats.mp': User.user.stats.mp + 10000
});
}
$scope.addOneLevel = function(){
User.set({
'stats.exp': User.user.stats.exp + (Math.round(((Math.pow(User.user.stats.lvl, 2) * 0.25) + (10 * User.user.stats.lvl) + 139.75) / 10) * 10)
});
}
$scope.addBossQuestProgressUp = function(){
User.set({
'party.quest.progress.up': User.user.party.quest.progress.up + 1000
});
}
/**
* Debug functions. Note that the server route for gems is only available if process.env.DEBUG=true
*/
if (_.contains(['development','test'],window.env.NODE_ENV)) {
$scope.setHealthLow = function(){
User.set({
'stats.hp': 1
});
}
}])
$scope.addMissedDay = function(){
if (!confirm("Are you sure you want to reset the day?")) return;
var dayBefore = moment(User.user.lastCron).subtract(1, 'days').toDate();
User.set({'lastCron': dayBefore});
Notification.text('-1 day, remember to refresh');
}
$scope.addTenGems = function(){
$http.post(ApiUrl.get() + '/api/v2/user/addTenGems').success(function(){
User.log({});
})
}
$scope.addGold = function(){
User.set({
'stats.gp': User.user.stats.gp + 500,
});
}
$scope.addLevelsAndGold = function(){
User.set({
'stats.exp': User.user.stats.exp + 10000,
'stats.gp': User.user.stats.gp + 10000,
'stats.mp': User.user.stats.mp + 10000
});
}
$scope.addOneLevel = function(){
User.set({
'stats.exp': User.user.stats.exp + (Math.round(((Math.pow(User.user.stats.lvl, 2) * 0.25) + (10 * User.user.stats.lvl) + 139.75) / 10) * 10)
});
}
$scope.addBossQuestProgressUp = function(){
User.set({
'party.quest.progress.up': User.user.party.quest.progress.up + 1000
});
}
}
}])

View file

@ -211,7 +211,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
});
}])
.controller('ChatCtrl', ['$scope', 'Groups', 'User', '$http', 'ApiUrlService', 'Notification', 'Members', '$rootScope', function($scope, Groups, User, $http, ApiUrlService, Notification, Members, $rootScope){
.controller('ChatCtrl', ['$scope', 'Groups', 'User', '$http', 'ApiUrl', 'Notification', 'Members', '$rootScope', function($scope, Groups, User, $http, ApiUrl, Notification, Members, $rootScope){
$scope.message = {content:''};
$scope._sending = false;
@ -275,7 +275,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
}
//Chat.Chat.like({gid:group._id,mid:message.id});
$http.post(ApiUrlService.get() + '/api/v2/groups/' + group._id + '/chat/' + message.id + '/like');
$http.post(ApiUrl.get() + '/api/v2/groups/' + group._id + '/chat/' + message.id + '/like');
}
$scope.flagChatMessage = function(groupId,message) {

View file

@ -1,8 +1,8 @@
"use strict";
habitrpg.controller("HallHeroesCtrl", ['$scope', '$rootScope', 'User', 'Notification', 'ApiUrlService', '$resource',
function($scope, $rootScope, User, Notification, ApiUrlService, $resource) {
var Hero = $resource(ApiUrlService.get() + '/api/v2/hall/heroes/:uid', {uid:'@_id'});
habitrpg.controller("HallHeroesCtrl", ['$scope', '$rootScope', 'User', 'Notification', 'ApiUrl', '$resource',
function($scope, $rootScope, User, Notification, ApiUrl, $resource) {
var Hero = $resource(ApiUrl.get() + '/api/v2/hall/heroes/:uid', {uid:'@_id'});
$scope.hero = undefined;
$scope.loadHero = function(uuid){
$scope.hero = Hero.get({uid:uuid});
@ -19,9 +19,9 @@ habitrpg.controller("HallHeroesCtrl", ['$scope', '$rootScope', 'User', 'Notifica
$scope.heroes = Hero.query();
}]);
habitrpg.controller("HallPatronsCtrl", ['$scope', '$rootScope', 'User', 'Notification', 'ApiUrlService', '$resource',
function($scope, $rootScope, User, Notification, ApiUrlService, $resource) {
var Patron = $resource(ApiUrlService.get() + '/api/v2/hall/patrons/:uid', {uid:'@_id'});
habitrpg.controller("HallPatronsCtrl", ['$scope', '$rootScope', 'User', 'Notification', 'ApiUrl', '$resource',
function($scope, $rootScope, User, Notification, ApiUrl, $resource) {
var Patron = $resource(ApiUrl.get() + '/api/v2/hall/patrons/:uid', {uid:'@_id'});
var page = 0;
$scope.patrons = [];

View file

@ -3,8 +3,8 @@
/* Make user and settings available for everyone through root scope.
*/
habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups', 'Shared', 'Content', '$modal', '$timeout', 'ApiUrlService', 'Payments',
function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups, Shared, Content, $modal, $timeout, ApiUrlService, Payments) {
habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups', 'Shared', 'Content', '$modal', '$timeout', 'ApiUrl', 'Payments',
function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups, Shared, Content, $modal, $timeout, ApiUrl, Payments) {
var user = User.user;
var initSticky = _.once(function(){
@ -221,7 +221,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
$scope.spell = null;
$rootScope.applyingAction = false;
$http.post(ApiUrlService.get() + '/api/v2/user/class/cast/'+spell.key+'?targetType='+type+'&targetId='+targetId)
$http.post(ApiUrl.get() + '/api/v2/user/class/cast/'+spell.key+'?targetType='+type+'&targetId='+targetId)
.success(function(){
var msg = window.env.t('youCast', {spell: spell.text()});
switch (type) {

View file

@ -2,8 +2,8 @@
// Make user and settings available for everyone through root scope.
habitrpg.controller('SettingsCtrl',
['$scope', 'User', '$rootScope', '$http', 'ApiUrlService', 'Guide', '$location', '$timeout', 'Notification', 'Shared',
function($scope, User, $rootScope, $http, ApiUrlService, Guide, $location, $timeout, Notification, Shared) {
['$scope', 'User', '$rootScope', '$http', 'ApiUrl', 'Guide', '$location', '$timeout', 'Notification', 'Shared',
function($scope, User, $rootScope, $http, ApiUrl, Guide, $location, $timeout, Notification, Shared) {
// FIXME we have this re-declared everywhere, figure which is the canonical version and delete the rest
// $scope.auth = function (id, token) {
@ -81,7 +81,7 @@ habitrpg.controller('SettingsCtrl',
if (!changeUser.newUsername || !changeUser.password) {
return alert(window.env.t('fillAll'));
}
$http.post(ApiUrlService.get() + '/api/v2/user/change-username', changeUser)
$http.post(ApiUrl.get() + '/api/v2/user/change-username', changeUser)
.success(function(){
alert(window.env.t('usernameSuccess'));
$scope.changeUser = {};
@ -95,7 +95,7 @@ habitrpg.controller('SettingsCtrl',
if (!changePass.oldPassword || !changePass.newPassword || !changePass.confirmNewPassword) {
return alert(window.env.t('fillAll'));
}
$http.post(ApiUrlService.get() + '/api/v2/user/change-password', changePass)
$http.post(ApiUrl.get() + '/api/v2/user/change-password', changePass)
.success(function(data, status, headers, config){
if (data.err) return alert(data.err);
alert(window.env.t('passSuccess'));
@ -132,7 +132,7 @@ habitrpg.controller('SettingsCtrl',
}
$scope['delete'] = function(){
$http['delete'](ApiUrlService.get() + '/api/v2/user')
$http['delete'](ApiUrl.get() + '/api/v2/user')
.success(function(res, code){
if (res.err) return alert(res.err);
localStorage.clear();
@ -141,14 +141,14 @@ habitrpg.controller('SettingsCtrl',
}
$scope.enterCoupon = function(code) {
$http.post(ApiUrlService.get() + '/api/v2/user/coupon/' + code).success(function(res,code){
$http.post(ApiUrl.get() + '/api/v2/user/coupon/' + code).success(function(res,code){
if (code!==200) return;
User.sync();
Notification.text('Coupon applied! Check your inventory');
});
}
$scope.generateCodes = function(codes){
$http.post(ApiUrlService.get() + '/api/v2/coupons/generate/'+codes.event+'?count='+(codes.count || 1))
$http.post(ApiUrl.get() + '/api/v2/coupons/generate/'+codes.event+'?count='+(codes.count || 1))
.success(function(res,code){
$scope._codes = {};
if (code!==200) return;
@ -183,7 +183,7 @@ habitrpg.controller('SettingsCtrl',
}
$scope.applyCoupon = function(coupon){
$http.get(ApiUrlService.get() + '/api/v2/coupons/valid-discount/'+coupon)
$http.get(ApiUrl.get() + '/api/v2/coupons/valid-discount/'+coupon)
.success(function(){
Notification.text("Coupon applied!");
var subs = $scope.Content.subscriptionBlocks;

View file

@ -1,7 +1,7 @@
"use strict";
habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','Notification', '$http', 'ApiUrlService', '$timeout', 'Shared',
function($scope, $rootScope, $location, User, Notification, $http, ApiUrlService, $timeout, Shared) {
habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','Notification', '$http', 'ApiUrl', '$timeout', 'Shared',
function($scope, $rootScope, $location, User, Notification, $http, ApiUrl, $timeout, Shared) {
$scope.obj = User.user; // used for task-lists
$scope.user = User.user;
@ -88,7 +88,7 @@ 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(ApiUrlService.get() + '/api/v2/user/tasks/' + task.id + '/unlink?keep=' + keep)
$http.post(ApiUrl.get() + '/api/v2/user/tasks/' + task.id + '/unlink?keep=' + keep)
.success(function(){
User.log({});
});

View file

@ -7,98 +7,94 @@
var facebook = {}
angular.module('authServices', ['userServices']).
factory('Facebook',
['$http', '$location', 'User', 'ApiUrlService',
function($http, $location, User, ApiUrlService) {
//TODO FB.init({appId: '${section.parameters['facebook.app.id']}', status: true, cookie: true, xfbml: true});
var auth, user = User.user;
angular.module('habitrpg').factory('Facebook',
['$http', '$location', 'User', 'ApiUrl',
function($http, $location, User, ApiUrl) {
//TODO FB.init({appId: '${section.parameters['facebook.app.id']}', status: true, cookie: true, xfbml: true});
var auth, user = User.user;
facebook.handleStatusChange = function(session) {
if (session.authResponse) {
facebook.handleStatusChange = function(session) {
if (session.authResponse) {
FB.api('/me', {
fields: 'name, picture, email'
}, function(response) {
console.log(response.error)
if (!response.error) {
FB.api('/me', {
fields: 'name, picture, email'
}, function(response) {
console.log(response.error)
if (!response.error) {
var data = {
name: response.name,
facebook_id: response.id,
email: response.email
}
$http.post(ApiUrlService.get() + '/api/v2/user/auth/facebook', data).success(function(data, status, headers, config) {
User.authenticate(data.id, data.token, function(err) {
if (!err) {
alert(window.env.t('loginSuccess'));
$location.path("/habit");
}
});
}).error(function(response) {
console.log('error')
})
} else {
alert('napaka')
var data = {
name: response.name,
facebook_id: response.id,
email: response.email
}
//clearAction();
});
} else {
document.body.className = 'not_connected';
$http.post(ApiUrl.get() + '/api/v2/user/auth/facebook', data).success(function(data, status, headers, config) {
User.authenticate(data.id, data.token, function(err) {
if (!err) {
alert(window.env.t('loginSuccess'));
$location.path("/habit");
}
});
}).error(function(response) {
console.log('error')
})
} else {
alert('napaka')
}
//clearAction();
}
});
} else {
document.body.className = 'not_connected';
//clearAction();
}
return {
authUser: function() {
FB.Event.subscribe('auth.statusChange', facebook.handleStatusChange);
},
getAuth: function() {
return auth;
},
login: function() {
FB.login(null, {
scope: 'email'
});
},
logout: function() {
FB.logout(function(response) {
window.location.reload();
});
}
}
}
])
return {
authUser: function() {
FB.Event.subscribe('auth.statusChange', facebook.handleStatusChange);
},
getAuth: function() {
return auth;
},
login: function() {
FB.login(null, {
scope: 'email'
});
},
logout: function() {
FB.logout(function(response) {
window.location.reload();
});
}
}
}])
.factory('LocalAuth',
['$http', 'User',
function($http, User) {
var auth,
user = User.user;
['$http', 'User',
function($http, User) {
var auth,
user = User.user;
return {
getAuth: function() {
return auth;
},
return {
getAuth: function() {
return auth;
},
login: function() {
user.id = '';
user.apiToken = '';
User.authenticate();
return;
login: function() {
user.id = '';
user.apiToken = '';
User.authenticate();
return;
},
logout: function() {}
}
},
logout: function() {}
}
]);
}]);

View file

@ -4,24 +4,23 @@
* Services that persists and retrieves user from localStorage.
*/
angular.module('challengeServices', ['ngResource']).
factory('Challenges', ['ApiUrlService', '$resource', 'User', '$q', 'Members',
function(ApiUrlService, $resource, User, $q, Members) {
var Challenge = $resource(ApiUrlService.get() + '/api/v2/challenges/:cid',
{cid:'@_id'},
{
//'query': {method: "GET", isArray:false}
join: {method: "POST", url: ApiUrlService.get() + '/api/v2/challenges/:cid/join'},
leave: {method: "POST", url: ApiUrlService.get() + '/api/v2/challenges/:cid/leave'},
close: {method: "POST", params: {uid:''}, url: ApiUrlService.get() + '/api/v2/challenges/:cid/close'},
getMember: {method: "GET", url: ApiUrlService.get() + '/api/v2/challenges/:cid/member/:uid'}
});
angular.module('habitrpg').factory('Challenges',
['ApiUrl', '$resource',
function(ApiUrl, $resource) {
var Challenge = $resource(ApiUrl.get() + '/api/v2/challenges/:cid',
{cid:'@_id'},
{
//'query': {method: "GET", isArray:false}
join: {method: "POST", url: ApiUrl.get() + '/api/v2/challenges/:cid/join'},
leave: {method: "POST", url: ApiUrl.get() + '/api/v2/challenges/:cid/leave'},
close: {method: "POST", params: {uid:''}, url: ApiUrl.get() + '/api/v2/challenges/:cid/close'},
getMember: {method: "GET", url: ApiUrl.get() + '/api/v2/challenges/:cid/member/:uid'}
});
//var challenges = [];
//var challenges = [];
return {
Challenge: Challenge
//challenges: challenges
}
}
]);
return {
Challenge: Challenge
//challenges: challenges
}
}]);

View file

@ -4,76 +4,74 @@
* Services that persists and retrieves user from localStorage.
*/
angular.module('groupServices', ['ngResource', 'challengeServices']).
factory('Groups', ['ApiUrlService', '$resource', '$q', '$http', 'User', 'Challenges',
function(ApiUrlService, $resource, $q, $http, User, Challenges) {
var Group = $resource(ApiUrlService.get() + '/api/v2/groups/:gid',
{gid:'@_id', messageId: '@_messageId'},
{
get: {
method: "GET",
isArray:false,
// Wrap challenges as ngResource so they have functions like $leave or $join
transformResponse: function(data, headers) {
data = angular.fromJson(data);
_.each(data && data.challenges, function(c) {
angular.extend(c, Challenges.Challenge.prototype);
});
return data;
}
},
postChat: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/chat'},
deleteChatMessage: {method: "DELETE", url: ApiUrlService.get() + '/api/v2/groups/:gid/chat/:messageId'},
flagChatMessage: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/chat/:messageId/flag'},
clearFlagCount: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/chat/:messageId/clearflags'},
join: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/join'},
leave: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/leave'},
invite: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/invite'},
removeMember: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/removeMember'},
questAccept: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/questAccept'},
questReject: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/questReject'},
questCancel: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/questCancel'},
questAbort: {method: "POST", url: ApiUrlService.get() + '/api/v2/groups/:gid/questAbort'}
angular.module('habitrpg').factory('Groups',
['ApiUrl', '$resource', '$q', '$http', 'User', 'Challenges',
function(ApiUrl, $resource, $q, $http, User, Challenges) {
var Group = $resource(ApiUrl.get() + '/api/v2/groups/:gid',
{gid:'@_id', messageId: '@_messageId'},
{
get: {
method: "GET",
isArray:false,
// Wrap challenges as ngResource so they have functions like $leave or $join
transformResponse: function(data, headers) {
data = angular.fromJson(data);
_.each(data && data.challenges, function(c) {
angular.extend(c, Challenges.Challenge.prototype);
});
// Defer loading everything until they're requested
var data = {party: undefined, myGuilds: undefined, publicGuilds: undefined, tavern: undefined};
return {
party: function(cb){
if (!data.party) return (data.party = Group.get({gid: 'party'}, cb));
return (cb) ? cb(party) : data.party;
},
publicGuilds: function(){
//TODO combine these as {type:'guilds,public'} and create a $filter() to separate them
if (!data.publicGuilds) data.publicGuilds = Group.query({type:'public'});
return data.publicGuilds;
},
myGuilds: function(){
if (!data.myGuilds) data.myGuilds = Group.query({type:'guilds'});
return data.myGuilds;
},
tavern: function(){
if (!data.tavern) data.tavern = Group.get({gid:'habitrpg'});
return data.tavern;
},
// On enter, set chat message to "seen"
seenMessage: function(gid){
$http.post(ApiUrlService.get() + '/api/v2/groups/'+gid+'/chat/seen');
if (User.user.newMessages) delete User.user.newMessages[gid];
},
// Pass reference to party, myGuilds, publicGuilds, tavern; inside data in order to
// be able to modify them directly (otherwise will be stick with cached version)
data: data,
Group: Group
return data;
}
}
])
},
postChat: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/chat'},
deleteChatMessage: {method: "DELETE", url: ApiUrl.get() + '/api/v2/groups/:gid/chat/:messageId'},
flagChatMessage: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/chat/:messageId/flag'},
clearFlagCount: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/chat/:messageId/clearflags'},
join: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/join'},
leave: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/leave'},
invite: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/invite'},
removeMember: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/removeMember'},
questAccept: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questAccept'},
questReject: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questReject'},
questCancel: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questCancel'},
questAbort: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questAbort'}
});
// Defer loading everything until they're requested
var data = {party: undefined, myGuilds: undefined, publicGuilds: undefined, tavern: undefined};
return {
party: function(cb){
if (!data.party) return (data.party = Group.get({gid: 'party'}, cb));
return (cb) ? cb(party) : data.party;
},
publicGuilds: function(){
//TODO combine these as {type:'guilds,public'} and create a $filter() to separate them
if (!data.publicGuilds) data.publicGuilds = Group.query({type:'public'});
return data.publicGuilds;
},
myGuilds: function(){
if (!data.myGuilds) data.myGuilds = Group.query({type:'guilds'});
return data.myGuilds;
},
tavern: function(){
if (!data.tavern) data.tavern = Group.get({gid:'habitrpg'});
return data.tavern;
},
// On enter, set chat message to "seen"
seenMessage: function(gid){
$http.post(ApiUrl.get() + '/api/v2/groups/'+gid+'/chat/seen');
if (User.user.newMessages) delete User.user.newMessages[gid];
},
// Pass reference to party, myGuilds, publicGuilds, tavern; inside data in order to
// be able to modify them directly (otherwise will be stick with cached version)
data: data,
Group: Group
}
}])
/**
* TODO Get this working. Make ChatService it's own ngResource, so we can update chat without having to sync the whole
* group object (expensive). Also so we can add chat-specific routes

View file

@ -4,219 +4,217 @@
* Services for each tour step when you unlock features
*/
angular.module('guideServices', []).
factory('Guide', ['$rootScope', 'User', '$timeout', function($rootScope, User, $timeout) {
/**
* Init and show the welcome tour. Note we do it listening to a $rootScope broadcasted 'userLoaded' message,
* this because we need to determine whether to show the tour *after* the user has been pulled from the server,
* otherwise it's always start off as true, and then get set to false later
*/
$rootScope.$on('userUpdated', initTour);
function initTour(){
if (User.user.flags.showTour === false) return;
var tourSteps = [
{
element: ".main-herobox",
title: window.env.t('welcomeHabit'),
content: window.env.t('welcomeHabitT1') + " <a href='http://www.kickstarter.com/profile/1823740484' target='_blank'>Justin</a>, " + window.env.t('welcomeHabitT2'),
}, {
element: ".main-herobox",
title: window.env.t('yourAvatar'),
content: window.env.t('yourAvatarText'),
}, {
element: ".main-herobox",
title: window.env.t('avatarCustom'),
content: window.env.t('avatarCustomText'),
}, {
element: "#bars",
title: window.env.t('hitPoints'),
content: window.env.t('hitPointsText'),
}, {
element: "#bars",
title: window.env.t('expPoints'),
content: window.env.t('expPointsText'),
}, {
element: "ul.habits",
title: window.env.t('typeGoals'),
content: window.env.t('typeGoalsText'),
placement: "top"
}, {
element: "ul.habits",
title: window.env.t('habits'),
content: window.env.t('tourHabits'),
placement: "top"
}, {
element: "ul.dailys",
title: window.env.t('dailies'),
content: window.env.t('tourDailies'),
placement: "top"
}, {
element: "ul.todos",
title: window.env.t('todos'),
content: window.env.t('tourTodos'),
placement: "top"
}, {
element: "ul.main-list.rewards",
title: window.env.t('rewards'),
content: window.env.t('tourRewards'),
placement: "top"
}, {
element: "ul.habits li:first-child",
title: window.env.t('hoverOver'),
content: window.env.t('hoverOverText'),
placement: "right"
}, {
element: "ul.habits li:first-child",
title: window.env.t('unlockFeatures'),
content: window.env.t('unlockFeaturesT1') + " <a href='http://habitrpg.wikia.com' target='_blank'>" + window.env.t('habitWiki') + "</a> " + window.env.t('unlockFeaturesT2'),
placement: "right"
}
];
_.each(tourSteps, function(step){
if (env.worldDmg.guide) {
step.content = "<div><div class='npc_justin_broken float-left'></div>" + step.content + "</div>";
} else {
step.content = "<div><div class='npc_justin float-left'></div>" + step.content + "</div>";
}
});
$('.main-herobox').popover('destroy');
var tour = new Tour({
template: "<div class='popover'>" +
"<div class='arrow'></div><h3 class='popover-title'></h3><div class='popover-content'></div>" +
"<div class='popover-navigation'><div class='btn-group'>" +
"<button class='btn btn-sm btn-default' data-role='prev'>&laquo;</button>" +
"<button class='btn btn-sm btn-default' data-role='next'>&raquo;</button>" +
"<button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button></div>" +
"<button class='btn btn-sm btn-default' data-role='end'>" + window.env.t('endTour') + "</button></div></div>",
onEnd: function(){
User.set({'flags.showTour': false});
}
});
tourSteps.forEach(function(step) {
tour.addStep(_.defaults(step, {html: true}));
});
tour.restart(); // Tour doesn't quite mesh with our handling of flags.showTour, just restart it on page load
//tour.start(true);
};
var alreadyShown = function(before, after) {
return !(!before && after === true);
};
var showPopover = function(selector, title, html, placement) {
if (!placement) placement = 'bottom';
$(selector).popover('destroy');
var button = "<button class='btn btn-sm btn-default' onClick=\"$('" + selector + "').popover('hide');return false;\">" + window.env.t('close') + "</button>";
angular.module('habitrpg').factory('Guide',
['$rootScope', 'User', '$timeout',
function($rootScope, User, $timeout) {
/**
* Init and show the welcome tour. Note we do it listening to a $rootScope broadcasted 'userLoaded' message,
* this because we need to determine whether to show the tour *after* the user has been pulled from the server,
* otherwise it's always start off as true, and then get set to false later
*/
$rootScope.$on('userUpdated', initTour);
function initTour(){
if (User.user.flags.showTour === false) return;
var tourSteps = [
{
element: ".main-herobox",
title: window.env.t('welcomeHabit'),
content: window.env.t('welcomeHabitT1') + " <a href='http://www.kickstarter.com/profile/1823740484' target='_blank'>Justin</a>, " + window.env.t('welcomeHabitT2'),
}, {
element: ".main-herobox",
title: window.env.t('yourAvatar'),
content: window.env.t('yourAvatarText'),
}, {
element: ".main-herobox",
title: window.env.t('avatarCustom'),
content: window.env.t('avatarCustomText'),
}, {
element: "#bars",
title: window.env.t('hitPoints'),
content: window.env.t('hitPointsText'),
}, {
element: "#bars",
title: window.env.t('expPoints'),
content: window.env.t('expPointsText'),
}, {
element: "ul.habits",
title: window.env.t('typeGoals'),
content: window.env.t('typeGoalsText'),
placement: "top"
}, {
element: "ul.habits",
title: window.env.t('habits'),
content: window.env.t('tourHabits'),
placement: "top"
}, {
element: "ul.dailys",
title: window.env.t('dailies'),
content: window.env.t('tourDailies'),
placement: "top"
}, {
element: "ul.todos",
title: window.env.t('todos'),
content: window.env.t('tourTodos'),
placement: "top"
}, {
element: "ul.main-list.rewards",
title: window.env.t('rewards'),
content: window.env.t('tourRewards'),
placement: "top"
}, {
element: "ul.habits li:first-child",
title: window.env.t('hoverOver'),
content: window.env.t('hoverOverText'),
placement: "right"
}, {
element: "ul.habits li:first-child",
title: window.env.t('unlockFeatures'),
content: window.env.t('unlockFeaturesT1') + " <a href='http://habitrpg.wikia.com' target='_blank'>" + window.env.t('habitWiki') + "</a> " + window.env.t('unlockFeaturesT2'),
placement: "right"
}
];
_.each(tourSteps, function(step){
if (env.worldDmg.guide) {
html = "<div><div class='npc_justin_broken float-left'></div>" + html + '<br/>' + button + '</div>';
step.content = "<div><div class='npc_justin_broken float-left'></div>" + step.content + "</div>";
} else {
html = "<div><div class='npc_justin float-left'></div>" + html + '<br/>' + button + '</div>';
step.content = "<div><div class='npc_justin float-left'></div>" + step.content + "</div>";
}
$(selector).popover({
title: title,
placement: placement,
trigger: 'manual',
html: true,
content: html
}).popover('show');
};
$rootScope.$watch('user.flags.customizationsNotification', function(after, before) {
if (alreadyShown(before, after)) return;
showPopover('.main-herobox', window.env.t('customAvatar'), window.env.t('customAvatarText'), 'bottom');
});
$rootScope.$watch('user.flags.itemsEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
var html = window.env.t('storeUnlockedText');
showPopover('div.rewards', window.env.t('storeUnlocked'), html, 'left');
});
$rootScope.$watch('user.flags.partyEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
var html = window.env.t('partySysText');
showPopover('.user-menu', window.env.t('partySys'), html, 'bottom');
});
$rootScope.$watch('user.flags.dropsEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
var eggs = User.user.items.eggs || {};
if (!eggs) {
eggs['Wolf'] = 1; // This is also set on the server
$('.main-herobox').popover('destroy');
var tour = new Tour({
template: "<div class='popover'>" +
"<div class='arrow'></div><h3 class='popover-title'></h3><div class='popover-content'></div>" +
"<div class='popover-navigation'><div class='btn-group'>" +
"<button class='btn btn-sm btn-default' data-role='prev'>&laquo;</button>" +
"<button class='btn btn-sm btn-default' data-role='next'>&raquo;</button>" +
"<button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button></div>" +
"<button class='btn btn-sm btn-default' data-role='end'>" + window.env.t('endTour') + "</button></div></div>",
onEnd: function(){
User.set({'flags.showTour': false});
}
$rootScope.openModal('dropsEnabled');
});
$rootScope.$watch('user.flags.rebirthEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
$rootScope.openModal('rebirthEnabled');
tourSteps.forEach(function(step) {
tour.addStep(_.defaults(step, {html: true}));
});
tour.restart(); // Tour doesn't quite mesh with our handling of flags.showTour, just restart it on page load
//tour.start(true);
};
var alreadyShown = function(before, after) {
return !(!before && after === true);
};
var showPopover = function(selector, title, html, placement) {
if (!placement) placement = 'bottom';
$(selector).popover('destroy');
var button = "<button class='btn btn-sm btn-default' onClick=\"$('" + selector + "').popover('hide');return false;\">" + window.env.t('close') + "</button>";
if (env.worldDmg.guide) {
html = "<div><div class='npc_justin_broken float-left'></div>" + html + '<br/>' + button + '</div>';
} else {
html = "<div><div class='npc_justin float-left'></div>" + html + '<br/>' + button + '</div>';
}
$(selector).popover({
title: title,
placement: placement,
trigger: 'manual',
html: true,
content: html
}).popover('show');
};
$rootScope.$watch('user.flags.customizationsNotification', function(after, before) {
if (alreadyShown(before, after)) return;
showPopover('.main-herobox', window.env.t('customAvatar'), window.env.t('customAvatarText'), 'bottom');
});
$rootScope.$watch('user.flags.itemsEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
var html = window.env.t('storeUnlockedText');
showPopover('div.rewards', window.env.t('storeUnlocked'), html, 'left');
});
$rootScope.$watch('user.flags.partyEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
var html = window.env.t('partySysText');
showPopover('.user-menu', window.env.t('partySys'), html, 'bottom');
});
$rootScope.$watch('user.flags.dropsEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
var eggs = User.user.items.eggs || {};
if (!eggs) {
eggs['Wolf'] = 1; // This is also set on the server
}
$rootScope.openModal('dropsEnabled');
});
$rootScope.$watch('user.flags.rebirthEnabled', function(after, before) {
if (alreadyShown(before, after)) return;
$rootScope.openModal('rebirthEnabled');
});
/**
* Classes Tour
*/
function classesTour(){
/**
* Classes Tour
*/
function classesTour(){
// TODO notice my hack-job `onShow: _.once()` functions. Without these, the syncronous path redirects won't properly handle showing tour
var tourSteps = [
{
path: '/#/options/inventory/equipment',
onShow: _.once(function(tour){
$timeout(function(){tour.goTo(0)});
}),
element: '.equipment-tab',
title: window.env.t('classGear'),
content: window.env.t('classGearText', {klass: User.user.stats.class})
},
{
path: '/#/options/profile/stats',
onShow: _.once(function(tour){
$timeout(function(){tour.goTo(1)});
}),
element: ".allocate-stats",
title: window.env.t('stats'),
content: window.env.t('classStats'),
}, {
element: ".auto-allocate",
title: window.env.t('autoAllocate'),
placement: 'left',
content: window.env.t('autoAllocateText'),
}, {
element: ".meter.mana",
title: window.env.t('spells'),
content: window.env.t('spellsText') + " <a target='_blank' href='http://habitrpg.wikia.com/wiki/Todos'>" + window.env.t('toDo') + "</a>."
}, {
orphan: true,
title: window.env.t('readMore'),
content: window.env.t('moreClass') + " <a href='http://habitrpg.wikia.com/wiki/Class_System' target='_blank'>Wikia</a>."
}
];
_.each(tourSteps, function(step){
if (env.worldDmg.guide) {
step.content = "<div><div class='npc_justin_broken float-left'></div>" + step.content + "</div>";
} else {
step.content = "<div><div class='npc_justin float-left'></div>" + step.content + "</div>";
}
});
$('.allocate-stats').popover('destroy');
var tour = new Tour({
// TODO notice my hack-job `onShow: _.once()` functions. Without these, the syncronous path redirects won't properly handle showing tour
var tourSteps = [
{
path: '/#/options/inventory/equipment',
onShow: _.once(function(tour){
$timeout(function(){tour.goTo(0)});
}),
element: '.equipment-tab',
title: window.env.t('classGear'),
content: window.env.t('classGearText', {klass: User.user.stats.class})
},
{
path: '/#/options/profile/stats',
onShow: _.once(function(tour){
$timeout(function(){tour.goTo(1)});
}),
element: ".allocate-stats",
title: window.env.t('stats'),
content: window.env.t('classStats'),
}, {
element: ".auto-allocate",
title: window.env.t('autoAllocate'),
placement: 'left',
content: window.env.t('autoAllocateText'),
}, {
element: ".meter.mana",
title: window.env.t('spells'),
content: window.env.t('spellsText') + " <a target='_blank' href='http://habitrpg.wikia.com/wiki/Todos'>" + window.env.t('toDo') + "</a>."
}, {
orphan: true,
title: window.env.t('readMore'),
content: window.env.t('moreClass') + " <a href='http://habitrpg.wikia.com/wiki/Class_System' target='_blank'>Wikia</a>."
}
];
_.each(tourSteps, function(step){
if (env.worldDmg.guide) {
step.content = "<div><div class='npc_justin_broken float-left'></div>" + step.content + "</div>";
} else {
step.content = "<div><div class='npc_justin float-left'></div>" + step.content + "</div>";
}
});
$('.allocate-stats').popover('destroy');
var tour = new Tour({
// onEnd: function(){
// User.set({'flags.showTour': false});
// }
});
tourSteps.forEach(function(step) {
tour.addStep(_.defaults(step, {html: true}));
});
tour.restart(); // Tour doesn't quite mesh with our handling of flags.showTour, just restart it on page load
//tour.start(true);
};
});
tourSteps.forEach(function(step) {
tour.addStep(_.defaults(step, {html: true}));
});
tour.restart(); // Tour doesn't quite mesh with our handling of flags.showTour, just restart it on page load
//tour.start(true);
};
return {
initTour: initTour,
classesTour: classesTour
};
}
]);
return {
initTour: initTour,
classesTour: classesTour
};
}]);

View file

@ -4,85 +4,84 @@
* Services that persists and retrieves user from localStorage.
*/
angular.module('memberServices', ['ngResource', 'sharedServices']).
factory('Members', ['$rootScope', 'Shared', 'ApiUrlService', '$resource',
function($rootScope, Shared, ApiUrlService, $resource) {
var members = {};
var Member = $resource(ApiUrlService.get() + '/api/v2/members/:uid', {uid:'@_id'});
var memberServices = {
angular.module('habitrpg').factory('Members',
['$rootScope', 'Shared', 'ApiUrl', '$resource',
function($rootScope, Shared, ApiUrl, $resource) {
var members = {};
var Member = $resource(ApiUrl.get() + '/api/v2/members/:uid', {uid:'@_id'});
var memberServices = {
Member: Member,
Member: Member,
members: members,
members: members,
/**
* Allows us to lazy-load party / group / public members throughout the application.
* @param obj - either a group or an individual member. If it's a group, we lazy-load all of its members.
*/
populate: function(obj){
/**
* Allows us to lazy-load party / group / public members throughout the application.
* @param obj - either a group or an individual member. If it's a group, we lazy-load all of its members.
*/
populate: function(obj){
function populateGroup(group){
_.each(group.members, function(member){
// meaning `populate('members')` wasn't run on the server, so we're getting the "in-database" form of
// the members array, which is just a list of IDs - not the populated objects
if (_.isString(member)) return;
function populateGroup(group){
_.each(group.members, function(member){
// meaning `populate('members')` wasn't run on the server, so we're getting the "in-database" form of
// the members array, which is just a list of IDs - not the populated objects
if (_.isString(member)) return;
// lazy-load
members[member._id] = member;
})
}
// lazy-load
members[member._id] = member;
})
}
// Array of groups
if (_.isArray(obj)) {
if (obj[0] && obj[0].members) {
_.each(obj, function(group){
populateGroup(group);
})
}
// Individual Group
} else if (obj.members)
populateGroup(obj);
// individual Member
if (obj._id) {
members[obj._id] = obj;
}
},
selectedMember: undefined,
/**
* Once users are populated, we fetch them throughout the application (eg, modals). This
* either gets them or fetches if not available
* @param uid
*/
selectMember: function(uid, cb) {
var self = this;
// Fetch from cache if we can. For guild members, only their uname will have been fetched on initial load,
// check if they have full fields (eg, check profile.items and an item inside
// because sometimes profile.items exists but it's empty like when user is fetched for party
// and then for guild)
// and if not, fetch them
if (members[uid] && members[uid].items && members[uid].items.weapon) {
Shared.wrap(members[uid],false);
self.selectedMember = members[uid];
cb();
} else {
Member.get({uid: uid}, function(member){
self.populate(member); // lazy load for later
Shared.wrap(member,false);
self.selectedMember = members[member._id];
cb();
});
}
}
// Array of groups
if (_.isArray(obj)) {
if (obj[0] && obj[0].members) {
_.each(obj, function(group){
populateGroup(group);
})
}
$rootScope.$on('userUpdated', function(event, user){
memberServices.populate(user);
})
// Individual Group
} else if (obj.members)
populateGroup(obj);
return memberServices;
// individual Member
if (obj._id) {
members[obj._id] = obj;
}
]);
},
selectedMember: undefined,
/**
* Once users are populated, we fetch them throughout the application (eg, modals). This
* either gets them or fetches if not available
* @param uid
*/
selectMember: function(uid, cb) {
var self = this;
// Fetch from cache if we can. For guild members, only their uname will have been fetched on initial load,
// check if they have full fields (eg, check profile.items and an item inside
// because sometimes profile.items exists but it's empty like when user is fetched for party
// and then for guild)
// and if not, fetch them
if (members[uid] && members[uid].items && members[uid].items.weapon) {
Shared.wrap(members[uid],false);
self.selectedMember = members[uid];
cb();
} else {
Member.get({uid: uid}, function(member){
self.populate(member); // lazy load for later
Shared.wrap(member,false);
self.selectedMember = members[member._id];
cb();
});
}
}
}
$rootScope.$on('userUpdated', function(event, user){
memberServices.populate(user);
})
return memberServices;
}]);

View file

@ -1,85 +1,84 @@
/**
Set up "+1 Exp", "Level Up", etc notifications
*/
angular.module("notificationServices", [])
.factory("Notification", [function() {
var stack_topright = {"dir1": "down", "dir2": "left", "spacing1": 15, "spacing2": 15, "firstpos1": 60};
function notify(html, type, icon) {
var notice = $.pnotify({
type: type || 'warning', //('info', 'text', 'warning', 'success', 'gp', 'xp', 'hp', 'lvl', 'death', 'mp', 'crit')
text: html,
opacity: 1,
addclass: 'alert-' + type,
delay: 7000,
hide: (type == 'error') ? false : true,
mouse_reset: false,
width: "250px",
stack: stack_topright,
icon: icon || false
}).click(function() { notice.pnotify_remove() });
};
angular.module("habitrpg").factory("Notification",
[function() {
var stack_topright = {"dir1": "down", "dir2": "left", "spacing1": 15, "spacing2": 15, "firstpos1": 60};
function notify(html, type, icon) {
var notice = $.pnotify({
type: type || 'warning', //('info', 'text', 'warning', 'success', 'gp', 'xp', 'hp', 'lvl', 'death', 'mp', 'crit')
text: html,
opacity: 1,
addclass: 'alert-' + type,
delay: 7000,
hide: (type == 'error') ? false : true,
mouse_reset: false,
width: "250px",
stack: stack_topright,
icon: icon || false
}).click(function() { notice.pnotify_remove() });
};
/**
Show "+ 5 {gold_coin} 3 {silver_coin}"
*/
function coins(money) {
var absolute, gold, silver;
absolute = Math.abs(money);
gold = Math.floor(absolute);
silver = Math.floor((absolute - gold) * 100);
if (gold && silver > 0) {
return "" + gold + " <span class='notification-icon shop_gold'></span> " + silver + " <span class='notification-icon shop_silver'></span>";
} else if (gold > 0) {
return "" + gold + " <span class='notification-icon shop_gold'></span>";
} else if (silver > 0) {
return "" + silver + " <span class='notification-icon shop_silver'></span>";
}
};
var sign = function(number){
return number?number<0?'-':'+':'+';
/**
Show "+ 5 {gold_coin} 3 {silver_coin}"
*/
function coins(money) {
var absolute, gold, silver;
absolute = Math.abs(money);
gold = Math.floor(absolute);
silver = Math.floor((absolute - gold) * 100);
if (gold && silver > 0) {
return "" + gold + " <span class='notification-icon shop_gold'></span> " + silver + " <span class='notification-icon shop_silver'></span>";
} else if (gold > 0) {
return "" + gold + " <span class='notification-icon shop_gold'></span>";
} else if (silver > 0) {
return "" + silver + " <span class='notification-icon shop_silver'></span>";
}
};
var round = function(number){
return Math.abs(number.toFixed(1));
}
return {
coins: coins,
hp: function(val) {
// don't show notifications if user dead
notify(sign(val) + " " + round(val) + " " + window.env.t('hp'), 'hp', 'glyphicon glyphicon-heart');
},
exp: function(val) {
if (val < -50) return; // don't show when they level up (resetting their exp)
notify(sign(val) + " " + round(val) + " " + window.env.t('xp'), 'xp', 'glyphicon glyphicon-star');
},
gp: function(val, bonus) {
notify(sign(val) + " " + coins(val - bonus), 'gp');
},
text: function(val){
if (val) {
notify(val, 'info');
}
},
lvl: function(){
notify(window.env.t('levelUp'), 'lvl', 'glyphicon glyphicon-chevron-up');
},
error: function(error){
notify(error, "danger", 'glyphicon glyphicon-exclamation-sign');
},
mp: function(val) {
notify(sign(val) + " " + round(val) + " " + window.env.t('mp'), 'mp', 'glyphicon glyphicon-fire');
},
crit: function(val) {
notify(window.env.t('critBonus') + Math.round(val) + "%", 'crit', 'glyphicon glyphicon-certificate');
},
streak: function(val) {
notify(window.env.t('streakName') + ': ' + val, 'streak', 'glyphicon glyphicon-repeat');
},
drop: function(val) {
notify(val, 'drop', 'glyphicon glyphicon-gift');
}
};
var sign = function(number){
return number?number<0?'-':'+':'+';
}
]);
var round = function(number){
return Math.abs(number.toFixed(1));
}
return {
coins: coins,
hp: function(val) {
// don't show notifications if user dead
notify(sign(val) + " " + round(val) + " " + window.env.t('hp'), 'hp', 'glyphicon glyphicon-heart');
},
exp: function(val) {
if (val < -50) return; // don't show when they level up (resetting their exp)
notify(sign(val) + " " + round(val) + " " + window.env.t('xp'), 'xp', 'glyphicon glyphicon-star');
},
gp: function(val, bonus) {
notify(sign(val) + " " + coins(val - bonus), 'gp');
},
text: function(val){
if (val) {
notify(val, 'info');
}
},
lvl: function(){
notify(window.env.t('levelUp'), 'lvl', 'glyphicon glyphicon-chevron-up');
},
error: function(error){
notify(error, "danger", 'glyphicon glyphicon-exclamation-sign');
},
mp: function(val) {
notify(sign(val) + " " + round(val) + " " + window.env.t('mp'), 'mp', 'glyphicon glyphicon-fire');
},
crit: function(val) {
notify(window.env.t('critBonus') + Math.round(val) + "%", 'crit', 'glyphicon glyphicon-certificate');
},
streak: function(val) {
notify(window.env.t('streakName') + ': ' + val, 'streak', 'glyphicon glyphicon-repeat');
},
drop: function(val) {
notify(val, 'drop', 'glyphicon glyphicon-gift');
}
};
}]);

View file

@ -1,6 +1,6 @@
'use strict';
angular.module('paymentServices',[]).factory('Payments',
angular.module('habitrpg').factory('Payments',
['$rootScope', 'User', '$http', 'Content',
function($rootScope, User, $http, Content) {
var Payments = {};

View file

@ -4,12 +4,10 @@
* Services that expose habitrpg-shared
*/
angular.module('sharedServices', []).
factory('Shared', [function () {
return window.habitrpgShared;
}
]).
factory('Content', ['Shared', function (Shared) {
return Shared.content;
}
]);
angular.module('habitrpg')
.factory('Shared', [function () {
return window.habitrpgShared;
}])
.factory('Content', ['Shared', function (Shared) {
return Shared.content;
}]);

View file

@ -1,6 +1,6 @@
"use strict";
window.habitrpgStatic = angular.module('habitrpgStatic', ['notificationServices', 'userServices', 'chieffancypants.loadingBar', 'authCtrl', 'ui.bootstrap'])
window.habitrpg = angular.module('habitrpg', ['chieffancypants.loadingBar', 'authCtrl', 'ui.bootstrap'])
.constant("API_URL", "")
.constant("STORAGE_USER_ID", 'habitrpg-user')
.constant("STORAGE_SETTINGS_ID", 'habit-mobile-settings')

View file

@ -1,7 +1,7 @@
//-Trick needed to pass 'env' to ./layout
block vars
doctype html
html(ng-app='habitrpgStatic')
html(ng-app='habitrpg')
head
block extraHead

View file

@ -1,6 +1,6 @@
block vars
doctype html
html(ng-app='habitrpgStatic')
html(ng-app='habitrpg')
head
block title