diff --git a/common/locales/en/groups.json b/common/locales/en/groups.json index 6e5e0915d8..ce6a86e786 100644 --- a/common/locales/en/groups.json +++ b/common/locales/en/groups.json @@ -116,5 +116,8 @@ "sendGiftFromBalance": "From Balance", "sendGiftPurchase": "Purchase", "sendGiftMessagePlaceholder": "Personal message (optional)", - "sendGiftSubscription": "<%= months %> Month(s): $<%= price %>" + "sendGiftSubscription": "<%= months %> Month(s): $<%= price %>", + "inviteFriends": "Invite Friends", + "startAParty": "Start a Party", + "addToParty": "Add someone to your party" } diff --git a/common/locales/en/settings.json b/common/locales/en/settings.json index a1eb6ce215..26c252902b 100644 --- a/common/locales/en/settings.json +++ b/common/locales/en/settings.json @@ -118,5 +118,7 @@ "resubscribe": "Resubscribe", "promoCode": "Promo Code", "promoCodeApplied": "Promo Code Applied! Check your inventory", - "promoPlaceholder": "Enter Promotion Code" + "promoPlaceholder": "Enter Promotion Code", + "couponText": "We sometimes have events and give out coupon codes for special gear. (eg, those who stop by our Wondercon booth)", + "displayInviteToPartyWhenPartyIs1": "Display Invite To Party button when party has 1 member." } diff --git a/test/spec/headerCtrlSpec.js b/test/spec/headerCtrlSpec.js new file mode 100644 index 0000000000..4060519fde --- /dev/null +++ b/test/spec/headerCtrlSpec.js @@ -0,0 +1,56 @@ +'use strict'; + +describe('Header Controller', function() { + var scope, ctrl, user, $location, $rootScope; + + beforeEach(function() { + module(function($provide) { + $provide.value('User', {}); + }); + + inject(function(_$rootScope_, _$controller_, _$location_){ + user = specHelper.newUser(); + user._id = "unique-user-id" + + scope = _$rootScope_.$new(); + $rootScope = _$rootScope_; + + $location = _$location_; + + // Load RootCtrl to ensure shared behaviors are loaded + _$controller_('RootCtrl', {$scope: scope, User: {user: user}}); + + ctrl = _$controller_('HeaderCtrl', {$scope: scope, User: {user: user}}); + }); + }); + + context('inviteOrStartParty', function(){ + beforeEach(function(){ + sinon.stub($location, 'path'); + sinon.stub($rootScope, 'openModal'); + }); + + afterEach(function(){ + $location.path.restore(); + $rootScope.openModal.restore(); + }); + + it('redirects to party page if user does not have a party', function(){ + var group = {}; + scope.inviteOrStartParty(group); + + expect($location.path).to.be.calledWith("/options/groups/party"); + expect($rootScope.openModal).to.not.be.called; + }); + + it('Opens invite-friends modal if user has a party', function(){ + var group = { + type: 'party' + }; + scope.inviteOrStartParty(group); + + expect($rootScope.openModal).to.be.calledOnce; + expect($location.path).to.not.be.called; + }); + }); +}); diff --git a/website/public/css/header.styl b/website/public/css/header.styl index e9cd485114..a1169843ce 100644 --- a/website/public/css/header.styl +++ b/website/public/css/header.styl @@ -98,7 +98,7 @@ @media (min-width: 70em) .site-header width: 70% - + // this is a wrapper for avatars in the header // inside this is the actual `herobox` module @@ -125,7 +125,7 @@ hrpg-label-color-mixin(darken($color-herobox, 16.18%)) width: 2.618em text-align:center - margin-right: 0.618em + margin-right: 0.618em .meter position: relative overflow: hidden @@ -161,7 +161,7 @@ white-space: nowrap &.value right: 0.382em - + // boss.jade only [class^="quest_"] + & min-width: 220px @@ -172,4 +172,8 @@ header .hero-stats background-color: darken($color-herobox, 4%) border-right: 1px solid darken($color-herobox, 12%) - \ No newline at end of file + +button.party-invite + right: 10px; + position: absolute; + top: 55px; diff --git a/website/public/js/controllers/headerCtrl.js b/website/public/js/controllers/headerCtrl.js index 9424eca81d..89db3dc18c 100644 --- a/website/public/js/controllers/headerCtrl.js +++ b/website/public/js/controllers/headerCtrl.js @@ -1,7 +1,7 @@ "use strict"; -habitrpg.controller("HeaderCtrl", ['$scope', 'Groups', 'User', - function($scope, Groups, User) { +habitrpg.controller("HeaderCtrl", ['$scope', 'Groups', 'User', '$location', '$rootScope', + function($scope, Groups, User, $location, $rootScope) { $scope.Math = window.Math; $scope.user = User.user; @@ -16,6 +16,19 @@ habitrpg.controller("HeaderCtrl", ['$scope', 'Groups', 'User', $scope.$watch('user.party.orderAscending', triggerResort); }); + $scope.inviteOrStartParty = function(group) { + if (group.type === "party") { + $rootScope.openModal('invite-friends', { + controller:'InviteToGroupCtrl', + resolve: { + injectedGroup: function(){ return group; } + } + }); + } else { + $location.path("/options/groups/party"); + } + } + function resortParty() { var result = _.sortBy( _.filter($scope.party.members, function(member){ diff --git a/website/src/models/user.js b/website/src/models/user.js index d2a8204d5d..0fe8eec6ff 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -321,6 +321,7 @@ var UserSchema = new Schema({ advancedCollapsed: {type: Boolean, 'default': false}, toolbarCollapsed: {type:Boolean, 'default':false}, background: String, + displayInviteToPartyWhenPartyIs1: { type:Boolean, 'default':true}, webhooks: {type: Schema.Types.Mixed, 'default': {}}, // For this fields make sure to use strict comparison when searching for falsey values (=== false) // As users who didn't login after these were introduced may have them undefined/null diff --git a/website/views/options/settings.jade b/website/views/options/settings.jade index c25d4a054f..053efa17da 100644 --- a/website/views/options/settings.jade +++ b/website/views/options/settings.jade @@ -66,6 +66,10 @@ script(type='text/ng-template', id='partials/options.settings.settings.html') label input(type='checkbox', ng-model='user.preferences.dailyDueDefaultView', ng-change='set({"preferences.dailyDueDefaultView": user.preferences.dailyDueDefaultView?true: false})') span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('dailyDueDefaultViewPop'))=env.t('dailyDueDefaultView') + .checkbox(ng-if='party.memberCount === 1') + label + input(type='checkbox', ng-model='user.preferences.displayInviteToPartyWhenPartyIs1', ng-change='set({"preferences.displayInviteToPartyWhenPartyIs1": user.preferences.displayInviteToPartyWhenPartyIs1 ? true : false})') + span.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('displayInviteToPartyWhenPartyIs1'))=env.t('displayInviteToPartyWhenPartyIs1') // button.btn.btn-default(ng-click='showTour()', popover-placement='right', popover-trigger='mouseenter', popover=env.t('restartTour'))= env.t('showTour') button.btn.btn-default(ng-click='showBailey()', popover-trigger='mouseenter', popover-placement='right', popover=env.t('showBaileyPop'))= env.t('showBailey') button.btn.btn-default(ng-click='openRestoreModal()', popover-trigger='mouseenter', popover-placement='right', popover=env.t('fixValPop'))= env.t('fixVal') diff --git a/website/views/options/social/group.jade b/website/views/options/social/group.jade index 850694e7e4..9c35139c58 100644 --- a/website/views/options/social/group.jade +++ b/website/views/options/social/group.jade @@ -60,7 +60,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter .panel-heading h3.panel-title =env.t('members') - button.pull-right.btn.btn-primary(ng-click="openInviteModal(group)")=env.t('inviteFriends') + button.pull-right.btn.btn-primary(ng-click="openInviteModal(group)")=env.t("inviteFriends") .panel-body.modal-fixed-height div.form-group(ng-if='::group.type=="party"') p=env.t('partyList') diff --git a/website/views/shared/header/header.jade b/website/views/shared/header/header.jade index 4fc7cb3c03..3fe3006e56 100644 --- a/website/views/shared/header/header.jade +++ b/website/views/shared/header/header.jade @@ -32,5 +32,8 @@ // party span(ng-controller='PartyCtrl') + button.party-invite.pull-right.btn.btn-primary(ng-click="inviteOrStartParty(group)", + ng-if="(!party.members || party.memberCount === 1) && user.preferences.displayInviteToPartyWhenPartyIs1", + popover="{{!party.members ? env.t('startAParty') : env.t('addToParty')}}", popover-placement="left", popover-trigger="mouseenter")=env.t("inviteFriends") .herobox-wrap(ng-repeat='profile in partyMinusSelf') +herobox()