From d2af7a442ac44fb06002d2173d4898f86842469b Mon Sep 17 00:00:00 2001 From: Shane Lister Date: Sat, 26 Oct 2013 19:56:18 -0700 Subject: [PATCH 01/12] Add Contributor Only Pet Choice This PR https://github.com/HabitRPG/habitrpg-shared/pull/33 should completed before this one. --- views/options/pets.jade | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/views/options/pets.jade b/views/options/pets.jade index 80d8b1a899..8ff2f45c4d 100644 --- a/views/options/pets.jade +++ b/views/options/pets.jade @@ -26,4 +26,7 @@ div(ng-if='hasPet("Wolf", "Veteran")') button(class="pet-button Pet-Wolf-Veteran", ng-class='{active: isCurrentPet("Wolf", "Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') div(ng-if='hasPet("Wolf", "Cerberus")') - button(class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') \ No newline at end of file + button(class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') + div(ng-if='hasPet("Hydra")') + button(class="pet-button Pet-Hydra", ng-class='{active: isCurrentPet("Hydra")}', ng-click='choosePet("Hydra")', tooltip='Hydra Pet') + From d7b24883b4fb04d25a5d82171f0c82b9b5f74ad3 Mon Sep 17 00:00:00 2001 From: Shane Lister Date: Sun, 27 Oct 2013 19:21:40 -0700 Subject: [PATCH 02/12] Update pets.jade --- views/options/pets.jade | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/views/options/pets.jade b/views/options/pets.jade index 8ff2f45c4d..61c6cf4956 100644 --- a/views/options/pets.jade +++ b/views/options/pets.jade @@ -23,10 +23,8 @@ h4 Rare Pets menu - div(ng-if='hasPet("Wolf", "Veteran")') - button(class="pet-button Pet-Wolf-Veteran", ng-class='{active: isCurrentPet("Wolf", "Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') - div(ng-if='hasPet("Wolf", "Cerberus")') - button(class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') - div(ng-if='hasPet("Hydra")') - button(class="pet-button Pet-Hydra", ng-class='{active: isCurrentPet("Hydra")}', ng-click='choosePet("Hydra")', tooltip='Hydra Pet') + div(ng-if='hasPet("Wolf", "Veteran") || hasPet("Wolf", "Cerberus") || hasPet("Dragon", "Hydra")') + button(ng-if='hasPet("Wolf", "Veteran")', class="pet-button Pet-Wolf-Veteran", ng-class='{active: isCurrentPet("Wolf", "Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') + button(ng-if='hasPet("Wolf", "Cerberus")', class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') + button(ng-if='hasPet("Dragon", "Hydra")', class="pet-button Pet-Dragon-Hydra", ng-class='{active: isCurrentPet("Dragon", "Hydra")}', ng-click='choosePet("Dragon", "Hydra")', tooltip='Hydra Pet') From afcd2b38036c27f59ceead7645f4c8abd1d3c4c2 Mon Sep 17 00:00:00 2001 From: Shane Lister Date: Wed, 30 Oct 2013 23:10:03 -0700 Subject: [PATCH 03/12] Rare Pets Layout Shows rare pets header always. Shows golden missing rare pet graphic if Hydra not obtained with link to how to obtain it. --- views/options/pets.jade | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/views/options/pets.jade b/views/options/pets.jade index 61c6cf4956..b0ed9562e5 100644 --- a/views/options/pets.jade +++ b/views/options/pets.jade @@ -21,10 +21,12 @@ button(class="pet-button pet-not-owned", ng-hide='hasPet(pet.name, potion.name)') img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') - h4 Rare Pets +h4 Rare Pets menu - div(ng-if='hasPet("Wolf", "Veteran") || hasPet("Wolf", "Cerberus") || hasPet("Dragon", "Hydra")') + div button(ng-if='hasPet("Wolf", "Veteran")', class="pet-button Pet-Wolf-Veteran", ng-class='{active: isCurrentPet("Wolf", "Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') button(ng-if='hasPet("Wolf", "Cerberus")', class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') button(ng-if='hasPet("Dragon", "Hydra")', class="pet-button Pet-Dragon-Hydra", ng-class='{active: isCurrentPet("Dragon", "Hydra")}', ng-click='choosePet("Dragon", "Hydra")', tooltip='Hydra Pet') - + a(target='_blank', href='https://github.com/HabitRPG/habitrpg/wiki/Contributing') + button(ng-if='!hasPet("Dragon", "Hydra")', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') + img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') From d679fa1e62e15cb66d7fa9ea75142c4fce416f49 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 6 Nov 2013 15:49:41 -0800 Subject: [PATCH 04/12] contrib: add Admin page to update contributor status. Start migrating from User.backer => User.contributor --- public/js/app.js | 7 +++++++ public/js/controllers/adminCtrl.js | 16 ++++++++++++++++ public/js/services/memberServices.js | 2 ++ public/manifest.json | 3 ++- src/controllers/groups.js | 20 +++++++++++++++++++- src/models/user.js | 10 ++++++++-- src/routes/api.js | 1 + views/options/admin.jade | 28 ++++++++++++++++++++++++++++ views/options/index.jade | 5 +++++ 9 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 public/js/controllers/adminCtrl.js create mode 100644 views/options/admin.jade diff --git a/public/js/app.js b/public/js/app.js index 2e6b74e018..cdb890c820 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -146,6 +146,13 @@ window.habitrpg = angular.module('habitrpg', templateUrl: "partials/options.settings.html" }) + // Options > Settings + .state('options.admin', { + url: "/admin", + controller: 'AdminCtrl', + templateUrl: "partials/options.admin.html" + }) + var settings = JSON.parse(localStorage.getItem(STORAGE_SETTINGS_ID)); if (settings && settings.auth) { $httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8'; diff --git a/public/js/controllers/adminCtrl.js b/public/js/controllers/adminCtrl.js new file mode 100644 index 0000000000..33059d5d86 --- /dev/null +++ b/public/js/controllers/adminCtrl.js @@ -0,0 +1,16 @@ +"use strict"; + +habitrpg.controller("AdminCtrl", ['$scope', '$rootScope', 'User', 'Members', 'Notification', + function($scope, $rootScope, User, Members, Notification) { + $scope.profile = undefined; + $scope.loadUser = function(uuid){ + $scope.profile = Members.Member.get({uid:uuid}); + } + $scope.save = function(profile) { + profile.$save(function(){ + Notification.text("User updated"); + $scope.profile = undefined; + $scope._uuid = undefined; + }) + } + }]) \ No newline at end of file diff --git a/public/js/services/memberServices.js b/public/js/services/memberServices.js index f969bb336c..3b375eca65 100644 --- a/public/js/services/memberServices.js +++ b/public/js/services/memberServices.js @@ -11,6 +11,8 @@ angular.module('memberServices', ['ngResource']). var Member = $resource(API_URL + '/api/v1/members/:uid', {uid:'@_id'}); var memberServices = { + Member: Member, + members: members, /** diff --git a/public/manifest.json b/public/manifest.json index f2540082fe..ee6d559b95 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -52,7 +52,8 @@ "js/controllers/inventoryCtrl.js", "js/controllers/marketCtrl.js", "js/controllers/footerCtrl.js", - "js/controllers/challengesCtrl.js" + "js/controllers/challengesCtrl.js", + "js/controllers/adminCtrl.js" ], "css": [ "bower_components/bootstrap/docs/assets/css/bootstrap.css", diff --git a/src/controllers/groups.js b/src/controllers/groups.js index 39e62b330e..57ad9df379 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -17,7 +17,7 @@ var api = module.exports; */ var itemFields = 'items.armor items.head items.shield items.weapon items.currentPet items.pets'; // TODO just send down count(items.pets) for better performance -var partyFields = 'profile preferences stats achievements party backer flags.rest auth.timestamps ' + itemFields; +var partyFields = 'profile preferences stats achievements party backer contributor balance flags.rest auth.timestamps ' + itemFields; var nameFields = 'profile.name'; var challengeFields = '_id name'; var guildPopulate = {path: 'members', select: nameFields, options: {limit: 15} }; @@ -46,6 +46,24 @@ api.getMember = function(req, res) { }) } +api.updateMember = function(req, res) { + var user = res.locals.user; + if (!(user.contributor && user.contributor.admin)) return res.json(401, {err:"You don't have access to save this user"}); + async.waterfall([ + function(cb){ + User.findById(req.params.uid, cb); + }, + function(member, cb){ + if (!member) return res.json(404, {err: "User not found"}); + _.merge(member, _.pick(req.body, ['contributor', 'balance'])); + member.save(cb); + } + ], function(err, saved){ + if (err) return res.json(500,{err:err}); + res.json(204); + }) +} + /** * Fetch groups list. This no longer returns party or tavern, as those can be requested indivdually * as /groups/party or /groups/tavern diff --git a/src/models/user.js b/src/models/user.js index f6af2060b1..eea15b64c1 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -54,12 +54,18 @@ var UserSchema = new Schema({ backer: { tier: Number, - admin: Boolean, + //admin: Boolean, // FIXME migrate to contributor.admin npc: String, - contributor: String, + //contributor: String, // FIXME migrate to contributor.text tokensApplied: Boolean }, + contributor: { + level: Number, // 1-7, see https://trello.com/c/wkFzONhE/277-contributor-gear + admin: Boolean, + text: String, // Artisan, Friend, Blacksmith, etc + }, + balance: Number, filters: {type: Schema.Types.Mixed, 'default': {}}, diff --git a/src/routes/api.js b/src/routes/api.js index 757ad4b8cd..6ee338f3f6 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -80,6 +80,7 @@ router["delete"]('/groups/:gid/chat/:messageId', auth.auth, groups.attachGroup, /* Members */ router.get('/members/:uid', groups.getMember); +router.post('/members/:uid', auth.auth, groups.updateMember); // only for admins // Market router.post('/market/buy', auth.auth, user.marketBuy); diff --git a/views/options/admin.jade b/views/options/admin.jade new file mode 100644 index 0000000000..aded591834 --- /dev/null +++ b/views/options/admin.jade @@ -0,0 +1,28 @@ +script(id='partials/options.admin.html', type="text/ng-template") + form.form-horizontal(ng-submit='loadUser(_uuid)') + .-options + .option-group.option-large + input.option-content(type='text', ng-model='_uuid', placeholder='UUID') + button.btn(type='submit') Load User + form.form-horizontal(ng-show='profile', ng-submit='save(profile)') + h3 {{profile.profile.name}} + h4 Contributor Status + .-options + .control-group.option-large + input.option-content(type='text', ng-model='profile.contributor.text', placeholder='Contributor Title (eg, "Blacksmith")') + .control-group.option-medium + input.option-content(type='number', step="any", ng-model='profile.contributor.level') + span.input-suffix Contrib Level + br + small [1-7] this determines which items, pets, and mounts are available. Also determines name-tag coloring.  + a(target='_blank', href='https://trello.com/c/wkFzONhE/277-contributor-gear') More details. + .control-group.option-medium + input.option-content(type='number', step="any", ng-model='profile.balance') + span.input-suffix $ (Gems/4) + .control-group.option-medium + label.checkbox + input(type='checkbox', ng-model='profile.contributor.admin') + | Admin + // h4 Backer Status + // Add backer stuff like tier, disable adds, etcs + button.btn-primary(type='submit') Save \ No newline at end of file diff --git a/views/options/index.jade b/views/options/index.jade index e5a10f7865..7b987ce013 100644 --- a/views/options/index.jade +++ b/views/options/index.jade @@ -2,6 +2,7 @@ include ./profile include ./social/index include ./inventory/index include ./settings +include ./admin script(id='partials/options.html', type="text/ng-template") .grid @@ -26,6 +27,10 @@ script(id='partials/options.html', type="text/ng-template") a(ui-sref='options.settings') i.icon-wrench | Settings + li(ng-class="{ active: $state.includes('options.admin') }", ng-if='user.contributor.admin') + a(ui-sref='options.admin') + i.icon-cog + | Admin .tab-content .tab-pane.active From 8646783aa1fcb56ffcfd71d1dc6edbc42e018ff8 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 6 Nov 2013 17:16:17 -0800 Subject: [PATCH 05/12] contrib: equipped functions to use habitrpg-shared@959024d --- views/shared/header/avatar.jade | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index d4846cffc5..0fcb8096a4 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -3,11 +3,11 @@ figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile span(ng-class='{zzz:profile.flags.rest}') span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') span(class='{{profile.preferences.gender}}_hair_{{profile.preferences.hair}}') - span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer.tier)}}') + span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}') span(class='{{profile.preferences.gender}}_head_0', ng-hide='profile.preferences.showHelm') - span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer.tier)}}', ng-show='profile.preferences.showHelm') - span(class='{{equipped("shield",profile.items.shield,profile.preferences,profile.backer.tier)}}') - span(class='{{equipped("weapon",profile.items.weapon,profile.preferences,profile.backer.tier)}}') + span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer, profile.contributor)}}', ng-show='profile.preferences.showHelm') + span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}') + span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}') // FIXME handle @minimal, this might have to be a directive span.current-pet(class='Pet-{{profile.items.currentPet.name}}-{{profile.items.currentPet.modifier}}', ng-show='profile.items.currentPet && !minimal') .avatar-level Lvl {{profile.stats.lvl}} From f61c35975ae59a6987a6daa8de26c12751dbb949 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 6 Nov 2013 17:47:00 -0800 Subject: [PATCH 06/12] contrib: award profile Dragon-Hydra if admin sets level >= 6 --- src/controllers/groups.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/controllers/groups.js b/src/controllers/groups.js index 57ad9df379..88c286bac5 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -56,6 +56,9 @@ api.updateMember = function(req, res) { function(member, cb){ if (!member) return res.json(404, {err: "User not found"}); _.merge(member, _.pick(req.body, ['contributor', 'balance'])); + if (!member.items.pets) member.items.pets = []; + var i = member.items.pets.indexOf('Dragon-Hydra'); + if (!~i && member.contributor.level >= 6) member.items.pets.push('Dragon-Hydra'); member.save(cb); } ], function(err, saved){ From 962cf9a3be10df167f41967b9f8caa2e4aee0f4c Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 7 Nov 2013 11:24:38 -0800 Subject: [PATCH 07/12] contrib: add name-tag colors based on contributor level --- public/css/game-pane.styl | 31 ++++++++++++++++++------- public/js/controllers/groupsCtrl.js | 18 +------------- public/js/controllers/rootCtrl.js | 10 ++++++++ src/controllers/groups.js | 7 +++--- views/options/social/chat-message.jade | 14 +++++------ views/shared/modals/members.jade | 2 +- views/shared/profiles/achievements.jade | 12 +++++----- 7 files changed, 50 insertions(+), 44 deletions(-) diff --git a/public/css/game-pane.styl b/public/css/game-pane.styl index 0a60fa1f9d..086e922734 100644 --- a/public/css/game-pane.styl +++ b/public/css/game-pane.styl @@ -26,15 +26,28 @@ label margin-right:5px - .label-elite - background-color: #077409 - color: black - .label-champion - background-color: #125BA2 - color: white - .label-royal - background-color: #7313B4 - color: white + .own-message + border-left: 4px solid #333 + padding-left: 2px + +// Name tags +.label-contributor-1, .label-contributor-2 + background-color: #333; +.label-contributor-3, .label-contributor-4 + background-color: #077409 + color: white +.label-contributor-5, .label-contributor-6 + background-color: #125BA2 + color: white +.label-contributor-7 + background-color: #7313B4 + color: white +.label-contributor-8 + background-color: #ff8000 + color: white +.label-npc + background-color: indianred + color: white #market-tab position relative diff --git a/public/js/controllers/groupsCtrl.js b/public/js/controllers/groupsCtrl.js index dddb4ac628..ec0afc3475 100644 --- a/public/js/controllers/groupsCtrl.js +++ b/public/js/controllers/groupsCtrl.js @@ -96,7 +96,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A } $scope.deleteChatMessage = function(group, message){ - if(message.uuid === User.user.id || (User.user.backer && User.user.backer.admin)){ + if(message.uuid === User.user.id || (User.user.backer && User.user.contributor.admin)){ Groups.Group.deleteChatMessage({gid: group._id, messageId: message.id}, undefined, function(){ var i = _.indexOf(group.chat, message); if(i !== -1) group.chat.splice(i, 1); @@ -108,22 +108,6 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A group.$get(); } - $scope.nameTagClasses = function(message){ - if (!message) return; // fixme what's triggering this? - if (message.contributor) { - if (message.contributor.match(/npc/i) || message.contributor.match(/royal/i)) { - return 'label-royal'; - } else if (message.contributor.match(/champion/i)) { - return 'label-champion'; - } else if (message.contributor.match(/elite/i)) { - return 'label-success'; //elite - } - } - if (message.uuid == User.user.id) { - return 'label-inverse'; //self - } - } - }]) .controller("GuildsCtrl", ['$scope', 'Groups', 'User', '$rootScope', '$state', '$location', diff --git a/public/js/controllers/rootCtrl.js b/public/js/controllers/rootCtrl.js index bf8ce25de4..eab96974a5 100644 --- a/public/js/controllers/rootCtrl.js +++ b/public/js/controllers/rootCtrl.js @@ -75,6 +75,16 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ }); } + $scope.contribText = function(contrib, backer){ + if (!contrib && !backer) return; + if (backer && backer.npc) return backer.npc; + var l = contrib && contrib.level; + if (l && l > 0) { + var level = (l < 3) ? 'Friend' : (l < 5) ? 'Elite' : (l < 7) ? 'Champion' : (l < 8) ? 'Legendary' : 'Heroic'; + return level + ' ' + contrib.text; + } + } + $rootScope.charts = {}; $rootScope.toggleChart = function(id, task) { var history = [], matrix, data, chart, options; diff --git a/src/controllers/groups.js b/src/controllers/groups.js index 88c286bac5..4fd3db2ab6 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -220,8 +220,8 @@ api.postChat = function(req, res, next) { var message = { id: helpers.uuid(), uuid: user._id, - contributor: user.backer && user.backer.contributor, - npc: user.backer && user.backer.npc, + contributor: user.contributor && user.contributor.toObject(), + backer: user.backer && user.backer.toObject(), text: req.query.message, // FIXME this should be body, but ngResource is funky user: user.profile.name, timestamp: +(new Date) @@ -237,7 +237,6 @@ api.postChat = function(req, res, next) { group.save(function(err, saved){ if (err) return res.json(500, {err:err}); - res.json({chat: saved.chat}); }); } @@ -249,7 +248,7 @@ api.deleteChatMessage = function(req, res){ if(!message) return res.json(404, {err: "Message not found!"}); - if(user._id !== message.uuid && !(user.backer && user.backer.admin)) + if(user._id !== message.uuid && !(user.backer && user.contributor.admin)) return res.json(401, {err: "Not authorized to delete this message!"}) Group.update({_id:group._id}, {$pull:{chat:{id: req.params.messageId}}}, function(err){ diff --git a/views/options/social/chat-message.jade b/views/options/social/chat-message.jade index af57fc283d..f1f70b729d 100644 --- a/views/options/social/chat-message.jade +++ b/views/options/social/chat-message.jade @@ -1,10 +1,10 @@ -li(ng-repeat='message in group.chat', ng-class='{highlight: indexOf(message.text, user.profile.name)}') - a.label.chat-message(class='{{nameTagClasses(message)}}', tooltip='{{message.contributor}}', ng-click='clickMember(message.uuid, true)') - | {{message.user}} - span - span(ng-bind-html="message.text | linky:'_blank'") - - span +li(ng-repeat='message in group.chat', ng-class='{highlight: indexOf(message.text, user.profile.name), "own-message": user._id == message.uuid}') + a.label.chat-message(class='label-contributor-{{message.contributor.level}}', ng-class='{"label-npc": message.backer.npc}', ng-click='clickMember(message.uuid, true)') + span(tooltip='{{contribText(message.contributor, message.backer)}}') {{message.user}}  + |   + span(ng-bind-html="message.text | linky:'_blank'") + |  -  span.muted.time | {{relativeDate(message.timestamp, _currentTime) + ' '}} - a(ng-show='user.backer.admin || message.uuid == user.id', ng-click='deleteChatMessage(group, message)') + a(ng-show='user.contributor.admin || message.uuid == user.id', ng-click='deleteChatMessage(group, message)') i.icon-remove(tooltip='Delete') diff --git a/views/shared/modals/members.jade b/views/shared/modals/members.jade index 715dc295d7..98e33c1458 100644 --- a/views/shared/modals/members.jade +++ b/views/shared/modals/members.jade @@ -3,7 +3,7 @@ div(ng-controller='MemberModalCtrl') .modal-header h3 span {{profile.profile.name}} - span(ng-show='profile.backer.contributor') - {{profile.backer.contributor}} + span(ng-if='profile.contributor.level') - {{contribText(profile.contributor, profile.backer)}} .modal-body .row-fluid .span6 diff --git a/views/shared/profiles/achievements.jade b/views/shared/profiles/achievements.jade index e85f222929..94ace40920 100644 --- a/views/shared/profiles/achievements.jade +++ b/views/shared/profiles/achievements.jade @@ -16,16 +16,16 @@ div(ng-if='profile.backer.npc') .achievement.achievement-helm h5 - span.label.label-master {{profile.backer.npc}} NPC + span.label.label-npc {{profile.backer.npc}} NPC small Backed the Kickstarter project at the maximum level! hr - div(ng-if='profile.backer.contributor || user._id == profile._id') - .achievement.achievement-firefox(ng-show='profile.backer.contributor') - div(ng-class='{muted: !profile.backer.contributor}') + div(ng-if='profile.contributor.level || user._id == profile._id') + .achievement.achievement-firefox(ng-if='profile.contributor.level') + div(ng-class='{muted: !profile.contributor.level}') h5 - span.label.label-inverse(ng-if='profile.backer.contributor') {{profile.backer.contributor}} - span.label(ng-if='!profile.backer.contributor') Contributor + span.label(ng-if='profile.contributor.level', class='label-contributor-{{profile.contributor.level}}') {{contribText(profile.contributor, profile.backer)}} + span.label(ng-if='!profile.contributor.level') Contributor small. Has contributed to HabitRPG (code, design, pixel art, legal advice, docs, etc). Want this badge? Fix a bug :) hr From a886c178b28d7a7f47ed71aa1928f7dda28f96e0 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 7 Nov 2013 12:47:33 -0800 Subject: [PATCH 08/12] contrib: add migration to help me start porting existing contribs --- .../20131107_from_backer_to_contributor.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 migrations/20131107_from_backer_to_contributor.js diff --git a/migrations/20131107_from_backer_to_contributor.js b/migrations/20131107_from_backer_to_contributor.js new file mode 100644 index 0000000000..d5a4ee851b --- /dev/null +++ b/migrations/20131107_from_backer_to_contributor.js @@ -0,0 +1,18 @@ +db.users.find({ + $or: [ + {'backer.admin':{$exists:1}}, + {'backer.contributor':{$exists:1}} + ] +},{backer:1}).forEach(function(user){ + user.contributor = {}; + user.contributor.admin = user.backer.admin; + delete user.backer.admin; + + // this isnt' the proper storage format, but I'm going to be going through the admin utility manually and setting things properly + if (user.backer.contributor) { + user.contributor.text = user.backer.contributor; + delete user.backer.contributor; + } + + db.users.update({_id:user._id}, {$set:{backer:user.backer, contributor:user.contributor}}); +}); \ No newline at end of file From 7fe4f31a162185aa86678570901b8666029cd983 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 7 Nov 2013 13:05:34 -0800 Subject: [PATCH 09/12] contrib: show profile._id in modal so admins can assign contrib status --- views/shared/modals/members.jade | 1 + 1 file changed, 1 insertion(+) diff --git a/views/shared/modals/members.jade b/views/shared/modals/members.jade index 98e33c1458..2f5f1ae43e 100644 --- a/views/shared/modals/members.jade +++ b/views/shared/modals/members.jade @@ -13,6 +13,7 @@ div(ng-controller='MemberModalCtrl') li(ng-repeat='website in profile.profile.websites') a(href='{{website}}', target='_blank') {{website}} ul.muted.unstyled(ng-if='profile.auth.timestamps', style='margin-top:10px;') + li {{profile._id}} li(ng-show='profile.auth.timestamps.created') - Member since {{timestamp(profile.auth.timestamps.created)}} - li(ng-show='profile.auth.timestamps.loggedin') - Last logged in {{timestamp(profile.auth.timestamps.loggedin)}} - h3 Stats From 7c94b4b6d3e2483209f7bbdc78948bf6e7eb1f42 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 7 Nov 2013 13:42:29 -0800 Subject: [PATCH 10/12] contrib: add contributor achievement modal --- src/controllers/groups.js | 1 + src/models/user.js | 3 ++- views/shared/modals/achievements.jade | 13 +++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/controllers/groups.js b/src/controllers/groups.js index 4fd3db2ab6..7d8a3faebe 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -59,6 +59,7 @@ api.updateMember = function(req, res) { if (!member.items.pets) member.items.pets = []; var i = member.items.pets.indexOf('Dragon-Hydra'); if (!~i && member.contributor.level >= 6) member.items.pets.push('Dragon-Hydra'); + if (member.contributor.level >= 1) member.flags.contributor = true; member.save(cb); } ], function(err, saved){ diff --git a/src/models/user.js b/src/models/user.js index eea15b64c1..cfd6b133bd 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -84,7 +84,8 @@ var UserSchema = new Schema({ rewrite: {type: Boolean, 'default': true}, partyEnabled: Boolean, // FIXME do we need this? petsEnabled: {type: Boolean, 'default': false}, - rest: {type: Boolean, 'default': false} // fixme - change to preferences.resting once we're off derby + rest: {type: Boolean, 'default': false}, // fixme - change to preferences.resting once we're off derby + contributor: Boolean }, history: { exp: Array, // [{date: Date, value: Number}], // big peformance issues if these are defined diff --git a/views/shared/modals/achievements.jade b/views/shared/modals/achievements.jade index f6eabcaa4e..56b9fa69dd 100644 --- a/views/shared/modals/achievements.jade +++ b/views/shared/modals/achievements.jade @@ -30,4 +30,17 @@ div(modal='modals.achievements.beastmaster') .modal-footer button.btn.btn-default.cancel(ng-click='modals.achievements.beastmaster = false') Ok +// Contributor +div(modal='user.flags.contributor') + .modal-header + h3 Contributor Achievement! + .modal-body + .NPC-Justin.float-left + p. + {{user.profile.name}}, you awesome person! You're now a level {{user.contributor.level}} contributor for pitching in to Habit. See Trello for what prizes you've earned for your contribution level. + + .modal-footer + button.btn.btn-default.cancel(ng-click='set("flags.contributor",false)') Ok + + From 4454cc502b5fd4bbccbff3560c708da6b9698da1 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 7 Nov 2013 14:22:56 -0800 Subject: [PATCH 11/12] contrib: only show contrib alert if they've gained, not lost --- src/controllers/groups.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/groups.js b/src/controllers/groups.js index 7d8a3faebe..3b266c510f 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -55,11 +55,11 @@ api.updateMember = function(req, res) { }, function(member, cb){ if (!member) return res.json(404, {err: "User not found"}); + if (req.body.contributor.level > (member.contributor && member.contributor.level || 0)) member.flags.contributor = true; _.merge(member, _.pick(req.body, ['contributor', 'balance'])); if (!member.items.pets) member.items.pets = []; var i = member.items.pets.indexOf('Dragon-Hydra'); if (!~i && member.contributor.level >= 6) member.items.pets.push('Dragon-Hydra'); - if (member.contributor.level >= 1) member.flags.contributor = true; member.save(cb); } ], function(err, saved){ From 06d1f77ce584840f8a0c3b9222709d8ca467af64 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 7 Nov 2013 17:24:49 -0800 Subject: [PATCH 12/12] contribu: cleanup tavern, add legend for contrib tiers --- public/js/controllers/groupsCtrl.js | 3 + public/js/controllers/settingsCtrl.js | 2 +- views/options/social/chat-box.jade | 2 +- views/options/social/tavern.jade | 94 ++++++++++++++++++++------- 4 files changed, 75 insertions(+), 26 deletions(-) diff --git a/public/js/controllers/groupsCtrl.js b/public/js/controllers/groupsCtrl.js index ec0afc3475..a7662423dd 100644 --- a/public/js/controllers/groupsCtrl.js +++ b/public/js/controllers/groupsCtrl.js @@ -225,5 +225,8 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A User.user.flags.rest = !User.user.flags.rest; User.log({op:'set',data:{'flags.rest':User.user.flags.rest}}); } + $scope.toggleUserTier = function($event) { + $($event.target).next().toggle(); + } } ]) diff --git a/public/js/controllers/settingsCtrl.js b/public/js/controllers/settingsCtrl.js index d3886f9d79..dec606770f 100644 --- a/public/js/controllers/settingsCtrl.js +++ b/public/js/controllers/settingsCtrl.js @@ -64,7 +64,7 @@ habitrpg.controller('SettingsCtrl', if(value === true){ $scope.restoreValues.stats = angular.copy(User.user.stats); $scope.restoreValues.items = angular.copy(User.user.items); - $scope.restoreValues.achievements = {streak: User.user.achievements.streak}; + $scope.restoreValues.achievements = {streak: User.user.achievements.streak || 0}; } }) diff --git a/views/options/social/chat-box.jade b/views/options/social/chat-box.jade index a62ee51f59..fde98515b5 100644 --- a/views/options/social/chat-box.jade +++ b/views/options/social/chat-box.jade @@ -1,5 +1,5 @@ form(ng-submit='postChat(group,_chatMessage)') - .whatever-options + .-options //FIXME ng-model makes this painfully slow! using jquery for now, which is really non-angular-like .control-group.option-large textarea.chat-textarea.option-content(style='height:6em;', ui-keypress='{13:"postChat(group,_chatMessage)"}', ng-model='_chatMessage') diff --git a/views/options/social/tavern.jade b/views/options/social/tavern.jade index f4ba422d0c..2075a8965f 100644 --- a/views/options/social/tavern.jade +++ b/views/options/social/tavern.jade @@ -18,44 +18,90 @@ span(ng-hide='user.flags.rest') Rest In The Inn .alert.alert-info(ng-show='user.flags.rest') | Whilst resting, your dailies are saved and aren't affected by day turn-over. Whether you check out tomorrow or in a week's time, you'll continue in the same state as when you checked in. + + // Resources .modal(style='position: relative;top: auto;left: auto;right: auto;margin: 0 auto 20px;z-index: 1;max-width: 100%;') .modal-header h3 Resources .modal-body - ul.unstyled - li - h4 + table.table.table-striped + tr + td a(target='_blank', href='http://community.habitrpg.com/forums/lfg') LFG Posts - li - h4 + tr + td a(target='_blank', href='http://www.youtube.com/watch?feature=player_embedded&v=cT5ghzZFfao') Tutorial - li - h4 + tr + td a(target='_blank', href='http://community.habitrpg.com/faq-page') FAQ - li - h4 + tr + td a(target='_blank', href='http://community.habitrpg.com/node/280') Report a Problem - li - h4 + tr + td a(target='_blank', href='https://trello.com/board/habitrpg/50e5d3684fe3a7266b0036d6') Request a Feature - li - h4 + tr + td a(target='_blank', href='http://community.habitrpg.com/forum') Community Forum + // Player Tiers + .modal(style='position: relative;top: auto;left: auto;right: auto;margin: 0 auto 20px;z-index: 1;max-width: 100%;') + .modal-header + h3 Player Tier Legend + .modal-body + small (click each for details) + table.table.table-striped + tr + td + a.label.label-contributor-1(ng-click='toggleUserTier($event)') Friend (1-2) + div(style='display:none;') + p. + When your first submission is deployed, you will receive the HabitRPG Contributor's badge. Your name in tavern chat will proudly display that you are a contributor. + hr + p. + When your second submission is deployed, you will receive the Crystal Armor. As a bounty for your great work, you will also receive 2 Gems. + tr + td + a.label.label-contributor-3(ng-click='toggleUserTier($event)') Elite (3-4) + div(style='display:none;') + p. + When your third submission is deployed, you will receive the Crystal Helmet. As a bounty for your great work, you will also receive 2 Gems. + hr + p. + When your fourth submission is deployed, you will receive the Crystal Sword. As a bounty for your great work, you will also receive 2 Gems. + + tr + td + a.label.label-contributor-5(ng-click='toggleUserTier($event)') Champion (5-6) + div(style='display:none;') + p. + When your fifth submission is deployed, you will receive the Crystal Shield! As a bounty for your great work, you will also receive 2 Gems. + hr + p. +
When your sixth submission is deployed, you will receive a Hydra Pet. As a bounty for your great work, you will also receive 2 Gems. + tr + td + a.label.label-contributor-7(ng-click='toggleUserTier($event)') Legendary (7) + div(style='display:none;') + p. + When your seventh submission is deployed, you will receive 2 Gems and become a member of the honored Contributor's Guild and be privy to the behind-the-scenes details of HabitRPG! + tr + td + a.label.label-contributor-8(ng-click='toggleUserTier($event)') Heroic + div(style='display:none;') + p This is HabitRPG staff or Staff-level Contributors + tr + td + a.label.label-npc(ng-click='toggleUserTier($event)') NPC + div(style='display:none;') + p Was a backer at the highest Kickstarter tier. + include ./challenge-box .span8(ng-controller='ChatCtrl') h3 Tavern Talk - .row-fluid - .span3 - ul.unstyled.buttonList - li - a.btn.btn-info(style='width:100%', target='_blank', href='http://community.habitrpg.com/faq-page') FAQ - li - a.btn.btn-info(style='width:100%', target='_blank', href='http://community.habitrpg.com/node/280') Report a Problem - li - a.btn.btn-info(style='width:100%', target='_blank', href='https://trello.com/board/habitrpg/50e5d3684fe3a7266b0036d6') Request a Feature - .span9 - include ./chat-box + include ./chat-box + small.alert.alert-info. + Note: if you're reporting a bug, the developers won't see it here. Follow these instructions instead. ul.unstyled.tavern-chat include ./chat-message