diff --git a/karma.conf.js b/karma.conf.js index 9f5fe99f30..3cc261a9eb 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -72,21 +72,7 @@ module.exports = function(config) { "website/public/js/directives/task-focus.directive.js", "website/public/js/directives/when-scrolled.directive.js", - "website/public/js/controllers/authCtrl.js", - "website/public/js/controllers/memberModalCtrl.js", - "website/public/js/controllers/menuCtrl.js", - "website/public/js/controllers/notificationCtrl.js", - "website/public/js/controllers/rootCtrl.js", - "website/public/js/controllers/settingsCtrl.js", - "website/public/js/controllers/headerCtrl.js", - "website/public/js/controllers/tasksCtrl.js", - "website/public/js/controllers/filtersCtrl.js", - "website/public/js/controllers/userCtrl.js", - "website/public/js/controllers/groupsCtrl.js", - "website/public/js/controllers/inventoryCtrl.js", - "website/public/js/controllers/footerCtrl.js", - "website/public/js/controllers/challengesCtrl.js", - "website/public/js/controllers/hallCtrl.js", + "website/public/js/controllers/*.js", 'test/spec/mocks/**/*.js', 'test/spec/specHelper.js', 'test/spec/**/*.js' diff --git a/website/public/js/controllers/autoCompleteCtrl.js b/website/public/js/controllers/autoCompleteCtrl.js new file mode 100644 index 0000000000..ac9c03aa54 --- /dev/null +++ b/website/public/js/controllers/autoCompleteCtrl.js @@ -0,0 +1,73 @@ +'use strict'; + +habitrpg.controller('AutocompleteCtrl', ['$scope', '$timeout', 'Groups', 'User', 'InputCaret', function ($scope,$timeout,Groups,User,InputCaret) { + $scope.clearUserlist = function() { + $scope.response = []; + $scope.usernames = []; + } + + $scope.filterUser = function(msg) { + if (!$scope.query || !msg.user) { + return false; + } + + // Ignore casing when checking for username + var user = msg.user.toLowerCase(); + var text = $scope.query.text.toLowerCase(); + + return user.indexOf(text) == 0; + } + + $scope.performCompletion = function(msg) { + $scope.autoComplete(msg); + $scope.query = null; + } + + $scope.addNewUser = function(user) { + if($.inArray(user.user,$scope.usernames) == -1) { + user.username = user.user; + $scope.usernames.push(user.user); + $scope.response.push(user); + } + } + + $scope.clearUserlist(); + + $scope.chatChanged = function(newvalue,oldvalue){ + if($scope.group && $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); + + $scope.caretChanged = function(newCaretPos) { + var relativeelement = $('.chat-form div:first'); + var textarea = $('.chat-form textarea'); + var userlist = $('.list-at-user'); + var offset = { + x: textarea.offset().left - relativeelement.offset().left, + y: textarea.offset().top - relativeelement.offset().top, + }; + if(relativeelement) { + var caretOffset = InputCaret.getPosition(textarea); + userlist.css({ + left: caretOffset.left + offset.x, + top: caretOffset.top + offset.y + 16 + }); + } + } + + $scope.updateTimer = false; + + $scope.$watch(function () { return $scope.caretPos; },function(newCaretPos) { + if($scope.updateTimer){ + $timeout.cancel($scope.updateTimer) + } + $scope.updateTimer = $timeout(function(){ + $scope.caretChanged(newCaretPos); + },$scope.watchDelay) + }); + }]); diff --git a/website/public/js/controllers/chatCtrl.js b/website/public/js/controllers/chatCtrl.js new file mode 100644 index 0000000000..693775579d --- /dev/null +++ b/website/public/js/controllers/chatCtrl.js @@ -0,0 +1,139 @@ +'use strict'; + +habitrpg.controller('ChatCtrl', ['$scope', 'Groups', 'Chat', 'User', '$http', 'ApiUrl', 'Notification', 'Members', '$rootScope', 'Analytics', + function($scope, Groups, Chat, User, $http, ApiUrl, Notification, Members, $rootScope, Analytics){ + $scope.message = {content:''}; + $scope._sending = false; + + $scope.isUserMentioned = function(user, message) { + if(message.hasOwnProperty("highlight")) + return message.highlight; + message.highlight = false; + var messagetext = message.text.toLowerCase(); + var username = user.profile.name; + var mentioned = messagetext.indexOf(username.toLowerCase()); + var pattern = username+"([^\w]|$){1}"; + if(mentioned > -1) { + var preceedingchar = messagetext.substring(mentioned-1,mentioned); + if(mentioned == 0 || preceedingchar.trim() == '' || preceedingchar == '@'){ + var regex = new RegExp(pattern,'i'); + message.highlight = regex.test(messagetext); + } + } + return message.highlight; + } + + $scope.postChat = function(group, message){ + if (_.isEmpty(message) || $scope._sending) return; + $scope._sending = true; + var previousMsg = (group.chat && group.chat[0]) ? group.chat[0].id : false; + Chat.utils.postChat({gid: group._id, message:message, previousMsg: previousMsg}, undefined, function(data){ + if(data.chat){ + group.chat = data.chat; + }else if(data.message){ + group.chat.unshift(data.message); + } + $scope.message.content = ''; + $scope._sending = false; + if (group.type == 'party') { + Analytics.updateUser({'partyID':group.id,'partySize':group.memberCount}); + } + if (group.privacy == 'public'){ + Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'group chat','groupType':group.type,'privacy':group.privacy,'groupName':group.name,'message':message}); + } else { + Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'group chat','groupType':group.type,'privacy':group.privacy}); + } + }, function(err){ + $scope._sending = false; + }); + } + + $scope.deleteChatMessage = function(group, message){ + if(message.uuid === User.user.id || (User.user.backer && User.user.contributor.admin)){ + var previousMsg = (group.chat && group.chat[0]) ? group.chat[0].id : false; + if(confirm('Are you sure you want to delete this message?')){ + Chat.utils.deleteChatMessage({gid:group._id, messageId:message.id, previousMsg:previousMsg}, undefined, function(data){ + if(data.chat) group.chat = data.chat; + + var i = _.findIndex(group.chat, {id: message.id}); + if(i !== -1) group.chat.splice(i, 1); + }); + } + } + } + + $scope.likeChatMessage = function(group,message) { + if (message.uuid == User.user._id) + return Notification.text(window.env.t('foreverAlone')); + if (!message.likes) message.likes = {}; + if (message.likes[User.user._id]) { + delete message.likes[User.user._id]; + } else { + message.likes[User.user._id] = true; + } + Chat.utils.like({ gid:group._id, messageId:message.id }, undefined); + } + + $scope.flagChatMessage = function(groupId,message) { + if(!message.flags) message.flags = {}; + if(message.flags[User.user._id]) + Notification.text(window.env.t('abuseAlreadyReported')); + else { + $scope.abuseObject = message; + $scope.groupId = groupId; + Members.selectMember(message.uuid, function(){ + $rootScope.openModal('abuse-flag',{ + controller:'MemberModalCtrl', + scope: $scope + }); + }); + } + }; + + $scope.copyToDo = function(message) { + var taskNotes = env.t("messageWroteIn", { + user: message.uuid == 'system' + ? 'system' + : '[' + message.user + '](' + env.BASE_URL + '/static/front/#?memberId=' + message.uuid + ')', + group: '[' + $scope.group.name + '](' + window.location.href + ')' + }); + + var newScope = $scope.$new(); + newScope.text = message.text; + newScope.notes = taskNotes; + + $rootScope.openModal('copyChatToDo',{ + controller:'CopyMessageModalCtrl', + scope: newScope + }); + }; + + $scope.sync = function(group){ + if(group.type == 'party') { + group.$syncParty(); // Syncs the whole party, not just 15 members + } else { + group.$get(); + } + // When the user clicks fetch recent messages we need to update + // that the user has seen the new messages + Chat.seenMessage(group._id); + } + + // List of Ordering options for the party members list + $scope.partyOrderChoices = { + 'level': window.env.t('sortLevel'), + 'random': window.env.t('sortRandom'), + 'pets': window.env.t('sortPets'), + 'habitrpg_date_joined' : window.env.t('sortHabitrpgJoined'), + 'party_date_joined': window.env.t('sortJoined'), + 'habitrpg_last_logged_in': window.env.t('sortHabitrpgLastLoggedIn'), + 'name': window.env.t('sortName'), + 'backgrounds': window.env.t('sortBackgrounds'), + }; + + $scope.partyOrderAscendingChoices = { + 'ascending': window.env.t('ascendingSort'), + 'descending': window.env.t('descendingSort') + } + + }]); diff --git a/website/public/js/controllers/copyMessageModalCtrl.js b/website/public/js/controllers/copyMessageModalCtrl.js new file mode 100644 index 0000000000..60d07ec152 --- /dev/null +++ b/website/public/js/controllers/copyMessageModalCtrl.js @@ -0,0 +1,17 @@ +'use strict'; + +habitrpg.controller("CopyMessageModalCtrl", ['$scope', 'User', 'Notification', + function($scope, User, Notification){ + $scope.saveTodo = function() { + var newTask = { + text: $scope.text, + type: 'todo', + notes: $scope.notes + }; + + User.user.ops.addTask({body:newTask}); + Notification.text(window.env.t('messageAddedAsToDo')); + + $scope.$close(); + } + }]); diff --git a/website/public/js/controllers/groupsCtrl.js b/website/public/js/controllers/groupsCtrl.js index 79365e0835..ce666d9bf7 100644 --- a/website/public/js/controllers/groupsCtrl.js +++ b/website/public/js/controllers/groupsCtrl.js @@ -115,487 +115,4 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', ' }); } - }]) - - .controller('InviteToGroupCtrl', ['$scope', 'User', 'Groups', 'injectedGroup', '$http', 'Notification', function($scope, User, Groups, injectedGroup, $http, Notification){ - $scope.group = injectedGroup; - - $scope.inviter = User.user.profile.name; - $scope.emails = [{name:"",email:""},{name:"",email:""}]; - $scope.invitees = {uuid:""}; - - $scope.inviteNewUsers = function(inviteMethod) { - if (!$scope.group._id) { - group.create($scope.newGroup, function() { - _inviteByMethod(inviteMethod); - }); - } else { - _inviteByMethod(inviteMethod); - } - }; - - function _inviteByMethod(inviteMethod) { - if (inviteMethod === 'email') { - Groups.Group.invite({gid: $scope.group._id}, {inviter: $scope.inviter, emails: $scope.emails}, function(){ - Notification.text(window.env.t('invitationsSent')); - $scope.emails = [{name:'',email:''},{name:'',email:''}]; - }, function(){ - $scope.emails = [{name:'',email:''},{name:'',email:''}]; - }); - } - else if (inviteMethod === 'uuid') { - Groups.Group.invite({gid: $scope.group._id}, {uuids: [$scope.invitees.uuid]}, function(){ - Notification.text(window.env.t('invitationsSent')); - $scope.invitees = {uuid:""}; - }, function(){ - $scope.invitees = {uuid:""}; - }); - } - else { - return console.log('Invalid invite method.') - } - } - - - }]) - - .controller('AutocompleteCtrl', ['$scope', '$timeout', 'Groups', 'User', 'InputCaret', function ($scope,$timeout,Groups,User,InputCaret) { - $scope.clearUserlist = function() { - $scope.response = []; - $scope.usernames = []; - } - - $scope.filterUser = function(msg) { - if (!$scope.query || !msg.user) { - return false; - } - - // Ignore casing when checking for username - var user = msg.user.toLowerCase(); - var text = $scope.query.text.toLowerCase(); - - return user.indexOf(text) == 0; - } - - $scope.performCompletion = function(msg) { - $scope.autoComplete(msg); - $scope.query = null; - } - - $scope.addNewUser = function(user) { - if($.inArray(user.user,$scope.usernames) == -1) { - user.username = user.user; - $scope.usernames.push(user.user); - $scope.response.push(user); - } - } - - $scope.clearUserlist(); - - $scope.chatChanged = function(newvalue,oldvalue){ - if($scope.group && $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); - - $scope.caretChanged = function(newCaretPos) { - var relativeelement = $('.chat-form div:first'); - var textarea = $('.chat-form textarea'); - var userlist = $('.list-at-user'); - var offset = { - x: textarea.offset().left - relativeelement.offset().left, - y: textarea.offset().top - relativeelement.offset().top, - }; - if(relativeelement) { - var caretOffset = InputCaret.getPosition(textarea); - userlist.css({ - left: caretOffset.left + offset.x, - top: caretOffset.top + offset.y + 16 - }); - } - } - - $scope.updateTimer = false; - - $scope.$watch(function () { return $scope.caretPos; },function(newCaretPos) { - if($scope.updateTimer){ - $timeout.cancel($scope.updateTimer) - } - $scope.updateTimer = $timeout(function(){ - $scope.caretChanged(newCaretPos); - },$scope.watchDelay) - }); - }]) - - .controller('ChatCtrl', ['$scope', 'Groups', 'Chat', 'User', '$http', 'ApiUrl', 'Notification', 'Members', '$rootScope', 'Analytics', - function($scope, Groups, Chat, User, $http, ApiUrl, Notification, Members, $rootScope, Analytics){ - $scope.message = {content:''}; - $scope._sending = false; - - $scope.isUserMentioned = function(user, message) { - if(message.hasOwnProperty("highlight")) - return message.highlight; - message.highlight = false; - var messagetext = message.text.toLowerCase(); - var username = user.profile.name; - var mentioned = messagetext.indexOf(username.toLowerCase()); - var pattern = username+"([^\w]|$){1}"; - if(mentioned > -1) { - var preceedingchar = messagetext.substring(mentioned-1,mentioned); - if(mentioned == 0 || preceedingchar.trim() == '' || preceedingchar == '@'){ - var regex = new RegExp(pattern,'i'); - message.highlight = regex.test(messagetext); - } - } - return message.highlight; - } - - $scope.postChat = function(group, message){ - if (_.isEmpty(message) || $scope._sending) return; - $scope._sending = true; - var previousMsg = (group.chat && group.chat[0]) ? group.chat[0].id : false; - Chat.utils.postChat({gid: group._id, message:message, previousMsg: previousMsg}, undefined, function(data){ - if(data.chat){ - group.chat = data.chat; - }else if(data.message){ - group.chat.unshift(data.message); - } - $scope.message.content = ''; - $scope._sending = false; - if (group.type == 'party') { - Analytics.updateUser({'partyID':group.id,'partySize':group.memberCount}); - } - if (group.privacy == 'public'){ - Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'group chat','groupType':group.type,'privacy':group.privacy,'groupName':group.name,'message':message}); - } else { - Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'group chat','groupType':group.type,'privacy':group.privacy}); - } - }, function(err){ - $scope._sending = false; - }); - } - - $scope.deleteChatMessage = function(group, message){ - if(message.uuid === User.user.id || (User.user.backer && User.user.contributor.admin)){ - var previousMsg = (group.chat && group.chat[0]) ? group.chat[0].id : false; - if(confirm('Are you sure you want to delete this message?')){ - Chat.utils.deleteChatMessage({gid:group._id, messageId:message.id, previousMsg:previousMsg}, undefined, function(data){ - if(data.chat) group.chat = data.chat; - - var i = _.findIndex(group.chat, {id: message.id}); - if(i !== -1) group.chat.splice(i, 1); - }); - } - } - } - - $scope.likeChatMessage = function(group,message) { - if (message.uuid == User.user._id) - return Notification.text(window.env.t('foreverAlone')); - if (!message.likes) message.likes = {}; - if (message.likes[User.user._id]) { - delete message.likes[User.user._id]; - } else { - message.likes[User.user._id] = true; - } - Chat.utils.like({ gid:group._id, messageId:message.id }, undefined); - } - - $scope.flagChatMessage = function(groupId,message) { - if(!message.flags) message.flags = {}; - if(message.flags[User.user._id]) - Notification.text(window.env.t('abuseAlreadyReported')); - else { - $scope.abuseObject = message; - $scope.groupId = groupId; - Members.selectMember(message.uuid, function(){ - $rootScope.openModal('abuse-flag',{ - controller:'MemberModalCtrl', - scope: $scope - }); - }); - } - }; - - $scope.copyToDo = function(message) { - var taskNotes = env.t("messageWroteIn", { - user: message.uuid == 'system' - ? 'system' - : '[' + message.user + '](' + env.BASE_URL + '/static/front/#?memberId=' + message.uuid + ')', - group: '[' + $scope.group.name + '](' + window.location.href + ')' - }); - - var newScope = $scope.$new(); - newScope.text = message.text; - newScope.notes = taskNotes; - - $rootScope.openModal('copyChatToDo',{ - controller:'CopyMessageModalCtrl', - scope: newScope - }); - }; - - $scope.sync = function(group){ - if(group.type == 'party') { - group.$syncParty(); // Syncs the whole party, not just 15 members - } else { - group.$get(); - } - // When the user clicks fetch recent messages we need to update - // that the user has seen the new messages - Chat.seenMessage(group._id); - } - - // List of Ordering options for the party members list - $scope.partyOrderChoices = { - 'level': window.env.t('sortLevel'), - 'random': window.env.t('sortRandom'), - 'pets': window.env.t('sortPets'), - 'habitrpg_date_joined' : window.env.t('sortHabitrpgJoined'), - 'party_date_joined': window.env.t('sortJoined'), - 'habitrpg_last_logged_in': window.env.t('sortHabitrpgLastLoggedIn'), - 'name': window.env.t('sortName'), - 'backgrounds': window.env.t('sortBackgrounds'), - }; - - $scope.partyOrderAscendingChoices = { - 'ascending': window.env.t('ascendingSort'), - 'descending': window.env.t('descendingSort') - } - - }]) - - .controller("GuildsCtrl", ['$scope', 'Groups', 'User', 'Challenges', '$rootScope', '$state', '$location', '$compile', 'Analytics', - function($scope, Groups, User, Challenges, $rootScope, $state, $location, $compile, Analytics) { - $scope.groups = { - guilds: Groups.myGuilds(), - "public": Groups.publicGuilds() - } - - $scope.type = 'guild'; - $scope.text = window.env.t('guild'); - var newGroup = function(){ - return new Groups.Group({type:'guild', privacy:'private'}); - } - $scope.newGroup = newGroup() - $scope.create = function(group){ - if (User.user.balance < 1) - return $rootScope.openModal('buyGems', {track:"Gems > Create Group"}); - - if (confirm(window.env.t('confirmGuild'))) { - group.$save(function(saved){ - if (saved.privacy == 'public') {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':true,'groupType':'guild','privacy':saved.privacy,'groupName':saved.name})} - else {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':true,'groupType':'guild','privacy':saved.privacy})} - $rootScope.hardRedirect('/#/options/groups/guilds/' + saved._id); - }); - } - } - - $scope.join = function(group){ - // If we're accepting an invitation, we don't have the actual group object, but a faux group object (for performance - // purposes) {id, name}. Let's trick ngResource into thinking we have a group, so we can call the same $join - // function (server calls .attachGroup(), which finds group by _id and handles this properly) - if (group.id && !group._id) { - group = new Groups.Group({_id:group.id}); - } - - group.$join(function(joined){ - if (joined.privacy == 'public') {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':false,'groupType':'guild','privacy':joined.privacy,'groupName':joined.name})} - else {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':false,'groupType':'guild','privacy':joined.privacy})} - $rootScope.hardRedirect('/#/options/groups/guilds/' + joined._id); - }) - } - - $scope.leave = function(keep) { - if (keep == 'cancel') { - $scope.selectedGroup = undefined; - $scope.popoverEl.popover('destroy'); - } else { - Groups.Group.leave({gid: $scope.selectedGroup._id, keep:keep}, undefined, function(){ - $rootScope.hardRedirect('/#/options/groups/guilds'); - }); - } - } - - $scope.clickLeave = function(group, $event){ - $scope.selectedGroup = group; - $scope.popoverEl = $($event.target); - var html, title; - Challenges.Challenge.query(function(challenges) { - challenges = _.pluck(_.filter(challenges, function(c) { - return c.group._id == group._id; - }), '_id'); - if (_.intersection(challenges, User.user.challenges).length > 0) { - html = $compile( - '' + window.env.t('removeTasks') + '
\n' + window.env.t('keepTasks') + '
\n' + window.env.t('cancel') + '
' - )($scope); - title = window.env.t('leaveGroupCha'); - } else { - html = $compile( - '' + window.env.t('confirm') + '
\n' + window.env.t('cancel') + '
' - )($scope); - title = window.env.t('leaveGroup') - } - $scope.popoverEl.popover('destroy').popover({ - html: true, - placement: 'top', - trigger: 'manual', - title: title, - content: html - }).popover('show'); - }); - } - - $scope.reject = function(guild){ - var i = _.findIndex(User.user.invitations.guilds, {id:guild.id}); - if (~i){ - User.user.invitations.guilds.splice(i, 1); - User.set({'invitations.guilds':User.user.invitations.guilds}); - } - } - } - ]) - - .controller("PartyCtrl", ['$rootScope','$scope','Groups','Chat','User','Challenges','$state','$compile','Analytics','Quests', - function($rootScope,$scope,Groups,Chat,User,Challenges,$state,$compile,Analytics,Quests) { - $scope.type = 'party'; - $scope.text = window.env.t('party'); - $scope.group = $rootScope.party = Groups.party(); - $scope.newGroup = new Groups.Group({type:'party'}); - $scope.inviteOrStartParty = Groups.inviteOrStartParty; - $scope.questInit = Quests.questInit; - - if ($state.is('options.social.party')) { - $scope.group.$syncParty(); // Sync party automatically when navigating to party page - } - - Chat.seenMessage($scope.group._id); - - $scope.create = function(group){ - if (!group.name) group.name = env.t('possessiveParty', {name: User.user.profile.name}); - group.$save(function(){ - Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':true,'groupType':'party','privacy':'private'}); - Analytics.updateUser({'partyID':group.id,'partySize':1}); - $rootScope.hardRedirect('/#/options/groups/party'); - }); - }; - - $scope.join = function(party){ - var group = new Groups.Group({_id: party.id, name: party.name}); - group.$join(function(){ - Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':false,'groupType':'party','privacy':'private'}); - Analytics.updateUser({'partyID':party.id}); - $rootScope.hardRedirect('/#/options/groups/party'); - }); - }; - - // TODO: refactor guild and party leave into one function - $scope.leave = function(keep) { - if (keep == 'cancel') { - $scope.selectedGroup = undefined; - $scope.popoverEl.popover('destroy'); - } else { - Groups.Group.leave({gid: $scope.selectedGroup._id, keep:keep}, undefined, function(){ - Analytics.updateUser({'partySize':null,'partyID':null}); - $rootScope.hardRedirect('/#/options/groups/party'); - }); - } - }; - - // TODO: refactor guild and party clickLeave into one function - $scope.clickLeave = function(group, $event){ - $scope.selectedGroup = group; - $scope.popoverEl = $($event.target); - var html, title; - Challenges.Challenge.query(function(challenges) { - challenges = _.pluck(_.filter(challenges, function(c) { - return c.group._id == group._id; - }), '_id'); - if (_.intersection(challenges, User.user.challenges).length > 0) { - html = $compile( - '' + window.env.t('removeTasks') + '
\n' + window.env.t('keepTasks') + '
\n' + window.env.t('cancel') + '
' - )($scope); - title = window.env.t('leavePartyCha'); - } else { - html = $compile( - '' + window.env.t('confirm') + '
\n' + window.env.t('cancel') + '
' - )($scope); - title = window.env.t('leaveParty'); - } - $scope.popoverEl.popover('destroy').popover({ - html: true, - placement: 'top', - trigger: 'manual', - title: title, - content: html - }).popover('show'); - }); - }; - - $scope.clickStartQuest = function(){ - var hasQuests = _.find(User.user.items.quests, function(quest) { - return quest > 0; - }); - - if (hasQuests){ - $rootScope.openModal("ownedQuests", { controller:"InventoryCtrl" }); - } else { - $rootScope.$state.go('options.inventory.quests'); - } - }; - - $scope.reject = function(){ - //User.user.invitations.party = undefined; - User.set({'invitations.party':{}}); - } - - $scope.questCancel = function(party){ - if (!confirm(window.env.t('sureCancel'))) return; - Groups.questCancel(party); - } - - $scope.questAbort = function(party){ - if (!confirm(window.env.t('sureAbort'))) return; - if (!confirm(window.env.t('doubleSureAbort'))) return; - Groups.questAbort(party); - } - - $scope.questAccept = function(party){ - Groups.questAccept(party); - }; - - $scope.questReject = function(party){ - Groups.questReject(party); - } - } - ]) - - .controller("TavernCtrl", ['$scope', 'Groups', 'User', - function($scope, Groups, User) { - $scope.group = Groups.tavern(); - $scope.toggleUserTier = function($event) { - $($event.target).next().toggle(); - } - } - ]) - - .controller("CopyMessageModalCtrl", ['$scope', 'User', 'Notification', - function($scope, User, Notification){ - $scope.saveTodo = function() { - var newTask = { - text: $scope.text, - type: 'todo', - notes: $scope.notes - }; - - User.user.ops.addTask({body:newTask}); - Notification.text(window.env.t('messageAddedAsToDo')); - - $scope.$close(); - } - } - ]); + }]); diff --git a/website/public/js/controllers/guildsCtrl.js b/website/public/js/controllers/guildsCtrl.js new file mode 100644 index 0000000000..020ebbe956 --- /dev/null +++ b/website/public/js/controllers/guildsCtrl.js @@ -0,0 +1,92 @@ +'use strict'; + +habitrpg.controller("GuildsCtrl", ['$scope', 'Groups', 'User', 'Challenges', '$rootScope', '$state', '$location', '$compile', 'Analytics', + function($scope, Groups, User, Challenges, $rootScope, $state, $location, $compile, Analytics) { + $scope.groups = { + guilds: Groups.myGuilds(), + "public": Groups.publicGuilds() + } + + $scope.type = 'guild'; + $scope.text = window.env.t('guild'); + var newGroup = function(){ + return new Groups.Group({type:'guild', privacy:'private'}); + } + $scope.newGroup = newGroup() + $scope.create = function(group){ + if (User.user.balance < 1) + return $rootScope.openModal('buyGems', {track:"Gems > Create Group"}); + + if (confirm(window.env.t('confirmGuild'))) { + group.$save(function(saved){ + if (saved.privacy == 'public') {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':true,'groupType':'guild','privacy':saved.privacy,'groupName':saved.name})} + else {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':true,'groupType':'guild','privacy':saved.privacy})} + $rootScope.hardRedirect('/#/options/groups/guilds/' + saved._id); + }); + } + } + + $scope.join = function(group){ + // If we're accepting an invitation, we don't have the actual group object, but a faux group object (for performance + // purposes) {id, name}. Let's trick ngResource into thinking we have a group, so we can call the same $join + // function (server calls .attachGroup(), which finds group by _id and handles this properly) + if (group.id && !group._id) { + group = new Groups.Group({_id:group.id}); + } + + group.$join(function(joined){ + if (joined.privacy == 'public') {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':false,'groupType':'guild','privacy':joined.privacy,'groupName':joined.name})} + else {Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':false,'groupType':'guild','privacy':joined.privacy})} + $rootScope.hardRedirect('/#/options/groups/guilds/' + joined._id); + }) + } + + $scope.leave = function(keep) { + if (keep == 'cancel') { + $scope.selectedGroup = undefined; + $scope.popoverEl.popover('destroy'); + } else { + Groups.Group.leave({gid: $scope.selectedGroup._id, keep:keep}, undefined, function(){ + $rootScope.hardRedirect('/#/options/groups/guilds'); + }); + } + } + + $scope.clickLeave = function(group, $event){ + $scope.selectedGroup = group; + $scope.popoverEl = $($event.target); + var html, title; + Challenges.Challenge.query(function(challenges) { + challenges = _.pluck(_.filter(challenges, function(c) { + return c.group._id == group._id; + }), '_id'); + if (_.intersection(challenges, User.user.challenges).length > 0) { + html = $compile( + '' + window.env.t('removeTasks') + '
\n' + window.env.t('keepTasks') + '
\n' + window.env.t('cancel') + '
' + )($scope); + title = window.env.t('leaveGroupCha'); + } else { + html = $compile( + '' + window.env.t('confirm') + '
\n' + window.env.t('cancel') + '
' + )($scope); + title = window.env.t('leaveGroup') + } + $scope.popoverEl.popover('destroy').popover({ + html: true, + placement: 'top', + trigger: 'manual', + title: title, + content: html + }).popover('show'); + }); + } + + $scope.reject = function(guild){ + var i = _.findIndex(User.user.invitations.guilds, {id:guild.id}); + if (~i){ + User.user.invitations.guilds.splice(i, 1); + User.set({'invitations.guilds':User.user.invitations.guilds}); + } + } + } + ]); diff --git a/website/public/js/controllers/inviteToGroupCtrl.js b/website/public/js/controllers/inviteToGroupCtrl.js new file mode 100644 index 0000000000..9ab7230026 --- /dev/null +++ b/website/public/js/controllers/inviteToGroupCtrl.js @@ -0,0 +1,41 @@ +"use strict"; + +habitrpg.controller('InviteToGroupCtrl', ['$scope', 'User', 'Groups', 'injectedGroup', '$http', 'Notification', function($scope, User, Groups, injectedGroup, $http, Notification) { + $scope.group = injectedGroup; + + $scope.inviter = User.user.profile.name; + $scope.emails = [{name:"",email:""},{name:"",email:""}]; + $scope.invitees = {uuid:""}; + + $scope.inviteNewUsers = function(inviteMethod) { + if (!$scope.group._id) { + group.create($scope.newGroup, function() { + _inviteByMethod(inviteMethod); + }); + } else { + _inviteByMethod(inviteMethod); + } + }; + + function _inviteByMethod(inviteMethod) { + if (inviteMethod === 'email') { + Groups.Group.invite({gid: $scope.group._id}, {inviter: $scope.inviter, emails: $scope.emails}, function(){ + Notification.text(window.env.t('invitationsSent')); + $scope.emails = [{name:'',email:''},{name:'',email:''}]; + }, function(){ + $scope.emails = [{name:'',email:''},{name:'',email:''}]; + }); + } + else if (inviteMethod === 'uuid') { + Groups.Group.invite({gid: $scope.group._id}, {uuids: [$scope.invitees.uuid]}, function(){ + Notification.text(window.env.t('invitationsSent')); + $scope.invitees = {uuid:""}; + }, function(){ + $scope.invitees = {uuid:""}; + }); + } + else { + return console.log('Invalid invite method.') + } + } + }]); diff --git a/website/public/js/controllers/partyCtrl.js b/website/public/js/controllers/partyCtrl.js new file mode 100644 index 0000000000..ca179a5c71 --- /dev/null +++ b/website/public/js/controllers/partyCtrl.js @@ -0,0 +1,115 @@ +'use strict'; + +habitrpg.controller("PartyCtrl", ['$rootScope','$scope','Groups','Chat','User','Challenges','$state','$compile','Analytics','Quests', + function($rootScope,$scope,Groups,Chat,User,Challenges,$state,$compile,Analytics,Quests) { + $scope.type = 'party'; + $scope.text = window.env.t('party'); + $scope.group = $rootScope.party = Groups.party(); + $scope.newGroup = new Groups.Group({type:'party'}); + $scope.inviteOrStartParty = Groups.inviteOrStartParty; + $scope.questInit = Quests.questInit; + + if ($state.is('options.social.party')) { + $scope.group.$syncParty(); // Sync party automatically when navigating to party page + } + + Chat.seenMessage($scope.group._id); + + $scope.create = function(group){ + if (!group.name) group.name = env.t('possessiveParty', {name: User.user.profile.name}); + group.$save(function(){ + Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':true,'groupType':'party','privacy':'private'}); + Analytics.updateUser({'partyID':group.id,'partySize':1}); + $rootScope.hardRedirect('/#/options/groups/party'); + }); + }; + + $scope.join = function(party){ + var group = new Groups.Group({_id: party.id, name: party.name}); + group.$join(function(){ + Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'join group','owner':false,'groupType':'party','privacy':'private'}); + Analytics.updateUser({'partyID':party.id}); + $rootScope.hardRedirect('/#/options/groups/party'); + }); + }; + + // TODO: refactor guild and party leave into one function + $scope.leave = function(keep) { + if (keep == 'cancel') { + $scope.selectedGroup = undefined; + $scope.popoverEl.popover('destroy'); + } else { + Groups.Group.leave({gid: $scope.selectedGroup._id, keep:keep}, undefined, function(){ + Analytics.updateUser({'partySize':null,'partyID':null}); + $rootScope.hardRedirect('/#/options/groups/party'); + }); + } + }; + + // TODO: refactor guild and party clickLeave into one function + $scope.clickLeave = function(group, $event){ + $scope.selectedGroup = group; + $scope.popoverEl = $($event.target); + var html, title; + Challenges.Challenge.query(function(challenges) { + challenges = _.pluck(_.filter(challenges, function(c) { + return c.group._id == group._id; + }), '_id'); + if (_.intersection(challenges, User.user.challenges).length > 0) { + html = $compile( + '' + window.env.t('removeTasks') + '
\n' + window.env.t('keepTasks') + '
\n' + window.env.t('cancel') + '
' + )($scope); + title = window.env.t('leavePartyCha'); + } else { + html = $compile( + '' + window.env.t('confirm') + '
\n' + window.env.t('cancel') + '
' + )($scope); + title = window.env.t('leaveParty'); + } + $scope.popoverEl.popover('destroy').popover({ + html: true, + placement: 'top', + trigger: 'manual', + title: title, + content: html + }).popover('show'); + }); + }; + + $scope.clickStartQuest = function(){ + var hasQuests = _.find(User.user.items.quests, function(quest) { + return quest > 0; + }); + + if (hasQuests){ + $rootScope.openModal("ownedQuests", { controller:"InventoryCtrl" }); + } else { + $rootScope.$state.go('options.inventory.quests'); + } + }; + + $scope.reject = function(){ + //User.user.invitations.party = undefined; + User.set({'invitations.party':{}}); + } + + $scope.questCancel = function(party){ + if (!confirm(window.env.t('sureCancel'))) return; + Groups.questCancel(party); + } + + $scope.questAbort = function(party){ + if (!confirm(window.env.t('sureAbort'))) return; + if (!confirm(window.env.t('doubleSureAbort'))) return; + Groups.questAbort(party); + } + + $scope.questAccept = function(party){ + Groups.questAccept(party); + }; + + $scope.questReject = function(party){ + Groups.questReject(party); + } + } + ]); diff --git a/website/public/js/controllers/tavernCtrl.js b/website/public/js/controllers/tavernCtrl.js new file mode 100644 index 0000000000..995fa22ad0 --- /dev/null +++ b/website/public/js/controllers/tavernCtrl.js @@ -0,0 +1,10 @@ +'use strict'; + +habitrpg.controller("TavernCtrl", ['$scope', 'Groups', 'User', + function($scope, Groups, User) { + $scope.group = Groups.tavern(); + $scope.toggleUserTier = function($event) { + $($event.target).next().toggle(); + } + } + ]);