From bc24fa8130638b7b7f30aefbaf07db9df15b3693 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 23 Aug 2015 22:38:55 -0500 Subject: [PATCH] Add front end button to leave quest --- common/locales/en/quests.json | 2 ++ test/server_side/controllers/groups.test.js | 7 ++--- test/spec/controllers/partyCtrlSpec.js | 31 ++++++++++++++++++- test/spec/services/groupServicesSpec.js | 20 ++++++++++-- website/public/js/controllers/partyCtrl.js | 9 ++++++ website/public/js/services/groupServices.js | 10 +++++- website/src/controllers/groups.js | 2 +- website/views/options/social/group.jade | 4 +-- .../options/social/quests/questActive.jade | 4 ++- 9 files changed, 77 insertions(+), 12 deletions(-) diff --git a/common/locales/en/quests.json b/common/locales/en/quests.json index 80c8a7f561..27e45d5c9a 100644 --- a/common/locales/en/quests.json +++ b/common/locales/en/quests.json @@ -37,6 +37,8 @@ "bossColl1": "To collect items, do your positive tasks. Quest items drop just like normal items; however, you won't see the drops until the next day, then everything you've found will be tallied up and contributed to the pile.", "bossColl2": "Only participants can collect items and share in the quest loot.", "abort": "Abort", + "leaveQuest": "Leave Quest", + "sureLeave": "Are you sure you want to leave the active quest? All your quest progress will be lost.", "questOwner": "Quest Owner", "questOwnerNotInPendingQuest": "The quest owner has left the quest and can no longer begin it. It is recommended that you cancel it now. The quest owner will retain possession of the quest scroll.", "questOwnerNotInRunningQuest": "The quest owner has left the quest. You can abort the quest if you need to. You can also allow it to keep running and all remaining participants will receive the quest rewards when the quest finishes.", diff --git a/test/server_side/controllers/groups.test.js b/test/server_side/controllers/groups.test.js index 4d735e7c71..59fc4d0f9c 100644 --- a/test/server_side/controllers/groups.test.js +++ b/test/server_side/controllers/groups.test.js @@ -54,8 +54,7 @@ describe('Groups Controller', function() { group: group, user: user }, - json: sinon.stub(), - send: sinon.stub() + json: sinon.stub() }; req = { }; @@ -125,8 +124,8 @@ describe('Groups Controller', function() { it('sends back 201 on success', function() { groupsController.questLeave(req, res); - expect(res.send).to.be.calledOnce; - expect(res.send).to.be.calledWith(201); + expect(res.json).to.be.calledOnce; + expect(res.json).to.be.calledWith(201); }); }); }); diff --git a/test/spec/controllers/partyCtrlSpec.js b/test/spec/controllers/partyCtrlSpec.js index 4a08689bc3..5e0d693c98 100644 --- a/test/spec/controllers/partyCtrlSpec.js +++ b/test/spec/controllers/partyCtrlSpec.js @@ -71,7 +71,7 @@ describe("Party Controller", function() { cancelSpy.should.have.been.calledOnce; }); - it('does not call Groups.questCancel when alert box is confirmed', function() { + it('does not call Groups.questCancel when alert box is not confirmed', function() { windowSpy = sandbox.stub(window, "confirm", function(){return false}); scope.questCancel(party); @@ -128,6 +128,35 @@ describe("Party Controller", function() { }); }); + describe('#questLeave', function() { + var party, leaveSpy, windowSpy; + + beforeEach(function() { + party = {}; + sandbox.stub(rootScope, 'hardRedirect'); + leaveSpy = sandbox.stub(groups, 'questLeave').returns({ + then: sandbox.stub().yields() + }); + }); + + it('calls Groups.questLeave when alert box is confirmed', function() { + windowSpy = sandbox.stub(window, "confirm").returns(true); + + scope.questLeave(party); + windowSpy.should.have.been.calledOnce; + windowSpy.should.have.been.calledWith(window.env.t('sureLeave')); + leaveSpy.should.have.been.calledOnce; + }); + + it('does not call Groups.questLeave when alert box is not confirmed', function() { + windowSpy = sandbox.stub(window, "confirm").returns(false); + + scope.questLeave(party); + windowSpy.should.have.been.calledOnce; + leaveSpy.should.not.have.been.calledOnce; + }); + }); + describe('clickStartQuest', function() { beforeEach(function() { sandbox.stub(rootScope, 'openModal'); diff --git a/test/spec/services/groupServicesSpec.js b/test/spec/services/groupServicesSpec.js index 0a4534c0c6..67e8fe5aae 100644 --- a/test/spec/services/groupServicesSpec.js +++ b/test/spec/services/groupServicesSpec.js @@ -53,7 +53,8 @@ describe('groupServices', function() { $questAccept: successPromise, $questReject: successPromise, $questCancel: successPromise, - $questAbort: successPromise + $questAbort: successPromise, + $questLeave: successPromise } var failPromise = function() { @@ -68,7 +69,8 @@ describe('groupServices', function() { $questAccept: failPromise, $questReject: failPromise, $questCancel: failPromise, - $questAbort: failPromise + $questAbort: failPromise, + $questLeave: failPromise } beforeEach(function() { @@ -135,5 +137,19 @@ describe('groupServices', function() { console.log.should.have.been.calledWith('fail'); }); }); + + describe('questLeave', function() { + it('syncs user if $questLeave succeeds', function() { + groups.questLeave(successParty); + user.sync.should.have.been.calledOnce; + console.log.should.not.have.been.called; + }); + + it('does not sync user if $questLeave fails', function() { + groups.questLeave(failParty); + user.sync.should.not.have.been.calledOnce; + console.log.should.have.been.calledWith('fail'); + }); + }); }); }); diff --git a/website/public/js/controllers/partyCtrl.js b/website/public/js/controllers/partyCtrl.js index 0e565d62c6..ee183dbb0b 100644 --- a/website/public/js/controllers/partyCtrl.js +++ b/website/public/js/controllers/partyCtrl.js @@ -114,6 +114,15 @@ habitrpg.controller("PartyCtrl", ['$rootScope','$scope','Groups','Chat','User',' Groups.questAbort(party); } + $scope.questLeave = function(party){ + if (!confirm(window.env.t('sureLeave'))) return; + + Groups.questLeave(party) + .then(function() { + $rootScope.hardRedirect('/#/options/groups/party'); + }); + } + $scope.questAccept = function(party){ Groups.questAccept(party); }; diff --git a/website/public/js/services/groupServices.js b/website/public/js/services/groupServices.js index fd736985ce..7bf866fca1 100644 --- a/website/public/js/services/groupServices.js +++ b/website/public/js/services/groupServices.js @@ -42,7 +42,8 @@ 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'} + questAbort: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questAbort'}, + questLeave: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questLeave'} }); function _syncUser() { @@ -98,6 +99,12 @@ .then(_syncUser, _logError); } + function questLeave(party) { + Analytics.updateUser({'partyID':party.id,'partySize':party.memberCount}); + return party.$questLeave() + .then(_syncUser, _logError); + } + function inviteOrStartParty(group) { if (group.type === "party" || $location.$$path === "/options/groups/party") { group.type = 'party'; @@ -121,6 +128,7 @@ questAccept: questAccept, questReject: questReject, questAbort: questAbort, + questLeave: questLeave, questCancel: questCancel, inviteOrStartParty: inviteOrStartParty, diff --git a/website/src/controllers/groups.js b/website/src/controllers/groups.js index 4a2a1e588f..2b5c8fdd69 100644 --- a/website/src/controllers/groups.js +++ b/website/src/controllers/groups.js @@ -1095,6 +1095,6 @@ api.questLeave = function(req, res, next) { group.save(function(err, result) { if (err) return next(err); - res.send(201); + return res.json(201, group); }); } diff --git a/website/views/options/social/group.jade b/website/views/options/social/group.jade index a19d3e979d..eb49e8b493 100644 --- a/website/views/options/social/group.jade +++ b/website/views/options/social/group.jade @@ -71,8 +71,8 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter button.pull-right.btn.btn-primary(ng-click="openInviteModal(group)")=env.t("inviteFriends") .panel-body.modal-fixed-height - h4(ng-show='group.memberCount === 1 && group.type === "party"')=env.t('partyEmpty') - table.table.table-striped(ng-show='group.memberCount > 1 || group.type !== "party"' bindonce='group') + h4(ng-show='::group.memberCount === 1 && group.type === "party"')=env.t('partyEmpty') + table.table.table-striped(ng-show='::group.memberCount > 1 || group.type !== "party"' bindonce='group') tr(ng-repeat='member in group.members track by member._id') td.media // allow leaders to ban members diff --git a/website/views/options/social/quests/questActive.jade b/website/views/options/social/quests/questActive.jade index 52d2be421e..510eefd5a9 100644 --- a/website/views/options/social/quests/questActive.jade +++ b/website/views/options/social/quests/questActive.jade @@ -20,5 +20,7 @@ div(ng-if='group.quest.active==true') include ./ianQuestInfo unless tavern - button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfRunningQuest(group.quest.leader,group))', + button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfRunningQuest(group.quest.leader,group))', ng-click='questAbort(party)')=env.t('abort') + button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader!=user._id && isMemberOfRunningQuest(user._id,group))', + ng-click='questLeave(party)')=env.t('leaveQuest')