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 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/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/controllers/groupsCtrl.js b/public/js/controllers/groupsCtrl.js index bd372d4c7c..5f6bd6e115 100644 --- a/public/js/controllers/groupsCtrl.js +++ b/public/js/controllers/groupsCtrl.js @@ -101,7 +101,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)){ var previousMsg = (group.chat && group.chat[0]) ? group.chat[0].id : false; Groups.Group.deleteChatMessage({gid:group._id, messageId:message.id, previousMsg:previousMsg}, undefined, function(data){ if(data.chat) group.chat = data.chat; @@ -116,22 +116,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', @@ -249,5 +233,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/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/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/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 cac0aec29f..ed1d7e1507 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,28 @@ 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"}); + 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'); + 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 @@ -199,8 +221,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) @@ -219,9 +241,12 @@ api.postChat = function(req, res, next) { group.save(function(err, saved){ if (err) return res.json(500, {err:err}); +<<<<<<< HEAD if(!chatUpdated) return res.json({message: saved.chat[0]}); +======= +>>>>>>> 06d1f77ce584840f8a0c3b9222709d8ca467af64 res.json({chat: saved.chat}); }); } @@ -233,7 +258,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!"}) var lastClientMsg = req.query.previousMsg; diff --git a/src/models/user.js b/src/models/user.js index f6af2060b1..cfd6b133bd 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': {}}, @@ -78,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/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 diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index e4cf11084e..ab58c7fb3b 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -23,8 +23,11 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html') img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') 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') \ No newline at end of file + menu + 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') \ No newline at end of file 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/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/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 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}} 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 + + diff --git a/views/shared/modals/members.jade b/views/shared/modals/members.jade index 715dc295d7..2f5f1ae43e 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 @@ -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 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