solve conflict

This commit is contained in:
Matteo Pagliazzi
2013-11-08 17:05:03 +01:00
22 changed files with 266 additions and 83 deletions

View File

@@ -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}});
});

View File

@@ -26,15 +26,28 @@
label label
margin-right:5px margin-right:5px
.label-elite .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 background-color: #077409
color: black color: white
.label-champion .label-contributor-5, .label-contributor-6
background-color: #125BA2 background-color: #125BA2
color: white color: white
.label-royal .label-contributor-7
background-color: #7313B4 background-color: #7313B4
color: white color: white
.label-contributor-8
background-color: #ff8000
color: white
.label-npc
background-color: indianred
color: white
#market-tab #market-tab
position relative position relative

View File

@@ -146,6 +146,13 @@ window.habitrpg = angular.module('habitrpg',
templateUrl: "partials/options.settings.html" 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)); var settings = JSON.parse(localStorage.getItem(STORAGE_SETTINGS_ID));
if (settings && settings.auth) { if (settings && settings.auth) {
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8'; $httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8';

View File

@@ -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;
})
}
}])

View File

@@ -101,7 +101,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
} }
$scope.deleteChatMessage = function(group, message){ $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; 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){ Groups.Group.deleteChatMessage({gid:group._id, messageId:message.id, previousMsg:previousMsg}, undefined, function(data){
if(data.chat) group.chat = data.chat; if(data.chat) group.chat = data.chat;
@@ -116,22 +116,6 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
group.$get(); 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', .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.user.flags.rest = !User.user.flags.rest;
User.log({op:'set',data:{'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();
}
} }
]) ])

View File

@@ -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.charts = {};
$rootScope.toggleChart = function(id, task) { $rootScope.toggleChart = function(id, task) {
var history = [], matrix, data, chart, options; var history = [], matrix, data, chart, options;

View File

@@ -64,7 +64,7 @@ habitrpg.controller('SettingsCtrl',
if(value === true){ if(value === true){
$scope.restoreValues.stats = angular.copy(User.user.stats); $scope.restoreValues.stats = angular.copy(User.user.stats);
$scope.restoreValues.items = angular.copy(User.user.items); $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};
} }
}) })

View File

@@ -11,6 +11,8 @@ angular.module('memberServices', ['ngResource']).
var Member = $resource(API_URL + '/api/v1/members/:uid', {uid:'@_id'}); var Member = $resource(API_URL + '/api/v1/members/:uid', {uid:'@_id'});
var memberServices = { var memberServices = {
Member: Member,
members: members, members: members,
/** /**

View File

@@ -52,7 +52,8 @@
"js/controllers/inventoryCtrl.js", "js/controllers/inventoryCtrl.js",
"js/controllers/marketCtrl.js", "js/controllers/marketCtrl.js",
"js/controllers/footerCtrl.js", "js/controllers/footerCtrl.js",
"js/controllers/challengesCtrl.js" "js/controllers/challengesCtrl.js",
"js/controllers/adminCtrl.js"
], ],
"css": [ "css": [
"bower_components/bootstrap/docs/assets/css/bootstrap.css", "bower_components/bootstrap/docs/assets/css/bootstrap.css",

View File

@@ -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 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 nameFields = 'profile.name';
var challengeFields = '_id name'; var challengeFields = '_id name';
var guildPopulate = {path: 'members', select: nameFields, options: {limit: 15} }; 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 * Fetch groups list. This no longer returns party or tavern, as those can be requested indivdually
* as /groups/party or /groups/tavern * as /groups/party or /groups/tavern
@@ -199,8 +221,8 @@ api.postChat = function(req, res, next) {
var message = { var message = {
id: helpers.uuid(), id: helpers.uuid(),
uuid: user._id, uuid: user._id,
contributor: user.backer && user.backer.contributor, contributor: user.contributor && user.contributor.toObject(),
npc: user.backer && user.backer.npc, backer: user.backer && user.backer.toObject(),
text: req.query.message, // FIXME this should be body, but ngResource is funky text: req.query.message, // FIXME this should be body, but ngResource is funky
user: user.profile.name, user: user.profile.name,
timestamp: +(new Date) timestamp: +(new Date)
@@ -219,9 +241,12 @@ api.postChat = function(req, res, next) {
group.save(function(err, saved){ group.save(function(err, saved){
if (err) return res.json(500, {err:err}); if (err) return res.json(500, {err:err});
<<<<<<< HEAD
if(!chatUpdated) return res.json({message: saved.chat[0]}); if(!chatUpdated) return res.json({message: saved.chat[0]});
=======
>>>>>>> 06d1f77ce584840f8a0c3b9222709d8ca467af64
res.json({chat: saved.chat}); 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(!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!"}) return res.json(401, {err: "Not authorized to delete this message!"})
var lastClientMsg = req.query.previousMsg; var lastClientMsg = req.query.previousMsg;

View File

@@ -54,12 +54,18 @@ var UserSchema = new Schema({
backer: { backer: {
tier: Number, tier: Number,
admin: Boolean, //admin: Boolean, // FIXME migrate to contributor.admin
npc: String, npc: String,
contributor: String, //contributor: String, // FIXME migrate to contributor.text
tokensApplied: Boolean 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, balance: Number,
filters: {type: Schema.Types.Mixed, 'default': {}}, filters: {type: Schema.Types.Mixed, 'default': {}},
@@ -78,7 +84,8 @@ var UserSchema = new Schema({
rewrite: {type: Boolean, 'default': true}, rewrite: {type: Boolean, 'default': true},
partyEnabled: Boolean, // FIXME do we need this? partyEnabled: Boolean, // FIXME do we need this?
petsEnabled: {type: Boolean, 'default': false}, 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: { history: {
exp: Array, // [{date: Date, value: Number}], // big peformance issues if these are defined exp: Array, // [{date: Date, value: Number}], // big peformance issues if these are defined

View File

@@ -80,6 +80,7 @@ router["delete"]('/groups/:gid/chat/:messageId', auth.auth, groups.attachGroup,
/* Members */ /* Members */
router.get('/members/:uid', groups.getMember); router.get('/members/:uid', groups.getMember);
router.post('/members/:uid', auth.auth, groups.updateMember); // only for admins
// Market // Market
router.post('/market/buy', auth.auth, user.marketBuy); router.post('/market/buy', auth.auth, user.marketBuy);

28
views/options/admin.jade Normal file
View File

@@ -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.&nbsp;
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

View File

@@ -2,6 +2,7 @@ include ./profile
include ./social/index include ./social/index
include ./inventory/index include ./inventory/index
include ./settings include ./settings
include ./admin
script(id='partials/options.html', type="text/ng-template") script(id='partials/options.html', type="text/ng-template")
.grid .grid
@@ -26,6 +27,10 @@ script(id='partials/options.html', type="text/ng-template")
a(ui-sref='options.settings') a(ui-sref='options.settings')
i.icon-wrench i.icon-wrench
| Settings | 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-content
.tab-pane.active .tab-pane.active

View File

@@ -24,7 +24,10 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html')
h4 Rare Pets h4 Rare Pets
menu menu
div(ng-if='hasPet("Wolf", "Veteran")') div
button(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", "Veteran")', 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(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(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')

View File

@@ -1,5 +1,5 @@
form(ng-submit='postChat(group,_chatMessage)') 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 //FIXME ng-model makes this painfully slow! using jquery for now, which is really non-angular-like
.control-group.option-large .control-group.option-large
textarea.chat-textarea.option-content(style='height:6em;', ui-keypress='{13:"postChat(group,_chatMessage)"}', ng-model='_chatMessage') textarea.chat-textarea.option-content(style='height:6em;', ui-keypress='{13:"postChat(group,_chatMessage)"}', ng-model='_chatMessage')

View File

@@ -1,10 +1,10 @@
li(ng-repeat='message in group.chat', ng-class='{highlight: indexOf(message.text, user.profile.name)}') 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='{{nameTagClasses(message)}}', tooltip='{{message.contributor}}', ng-click='clickMember(message.uuid, true)') a.label.chat-message(class='label-contributor-{{message.contributor.level}}', ng-class='{"label-npc": message.backer.npc}', ng-click='clickMember(message.uuid, true)')
| {{message.user}} span(tooltip='{{contribText(message.contributor, message.backer)}}') {{message.user}}&nbsp;
span | &nbsp;
span(ng-bind-html="message.text | linky:'_blank'") - span(ng-bind-html="message.text | linky:'_blank'")
span | &nbsp;-&nbsp;
span.muted.time span.muted.time
| {{relativeDate(message.timestamp, _currentTime) + ' '}} | {{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') i.icon-remove(tooltip='Delete')

View File

@@ -18,44 +18,90 @@
span(ng-hide='user.flags.rest') Rest In The Inn span(ng-hide='user.flags.rest') Rest In The Inn
.alert.alert-info(ng-show='user.flags.rest') .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. | 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(style='position: relative;top: auto;left: auto;right: auto;margin: 0 auto 20px;z-index: 1;max-width: 100%;')
.modal-header .modal-header
h3 Resources h3 Resources
.modal-body .modal-body
ul.unstyled table.table.table-striped
li tr
h4 td
a(target='_blank', href='http://community.habitrpg.com/forums/lfg') LFG Posts a(target='_blank', href='http://community.habitrpg.com/forums/lfg') LFG Posts
li tr
h4 td
a(target='_blank', href='http://www.youtube.com/watch?feature=player_embedded&v=cT5ghzZFfao') Tutorial a(target='_blank', href='http://www.youtube.com/watch?feature=player_embedded&v=cT5ghzZFfao') Tutorial
li tr
h4 td
a(target='_blank', href='http://community.habitrpg.com/faq-page') FAQ a(target='_blank', href='http://community.habitrpg.com/faq-page') FAQ
li tr
h4 td
a(target='_blank', href='http://community.habitrpg.com/node/280') Report a Problem a(target='_blank', href='http://community.habitrpg.com/node/280') Report a Problem
li tr
h4 td
a(target='_blank', href='https://trello.com/board/habitrpg/50e5d3684fe3a7266b0036d6') Request a Feature a(target='_blank', href='https://trello.com/board/habitrpg/50e5d3684fe3a7266b0036d6') Request a Feature
li tr
h4 td
a(target='_blank', href='http://community.habitrpg.com/forum') Community Forum 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.
<span class='achievement achievement-firefox'></span> When your <strong>first</strong> 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.
<span class='shop_armor_7 shop-sprite item-img'></span> When your <strong>second</strong> submission is deployed, you will receive the <strong>Crystal Armor</strong>. As a bounty for your great work, you will also receive <strong>2 Gems</strong>.
tr
td
a.label.label-contributor-3(ng-click='toggleUserTier($event)') Elite (3-4)
div(style='display:none;')
p.
<span class='shop_head_7 shop-sprite item-img'></span> When your <strong>third</strong> submission is deployed, you will receive the <strong>Crystal Helmet</strong>. As a bounty for your great work, you will also receive <strong>2 Gems</strong>.
hr
p.
<span class='shop_weapon_8 shop-sprite item-img'></span> When your <strong>fourth</strong> submission is deployed, you will receive the <strong>Crystal Sword</strong>. As a bounty for your great work, you will also receive <strong>2 Gems</strong>.
tr
td
a.label.label-contributor-5(ng-click='toggleUserTier($event)') Champion (5-6)
div(style='display:none;')
p.
<span class='shop_shield_7 shop-sprite item-img'></span> When your <em>fifth</em> submission is deployed, you will receive the <strong>Crystal Shield</strong>! As a bounty for your great work, you will also receive <strong>2 Gems</strong>.
hr
p.
<div class='Pet-Dragon-Hydra pull-left'></div> When your <em>sixth</em> submission is deployed, you will receive a <strong>Hydra Pet</strong>. As a bounty for your great work, you will also receive <strong>2 Gems</strong>.
tr
td
a.label.label-contributor-7(ng-click='toggleUserTier($event)') Legendary (7)
div(style='display:none;')
p.
When your <em>seventh</em> submission is deployed, you will receive <strong>2 Gems</strong> 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 include ./challenge-box
.span8(ng-controller='ChatCtrl') .span8(ng-controller='ChatCtrl')
h3 Tavern Talk 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. <a href='http://community.habitrpg.com/node/280' target='_blank'>Follow these instructions</a> instead.
ul.unstyled.tavern-chat ul.unstyled.tavern-chat
include ./chat-message include ./chat-message

View File

@@ -3,11 +3,11 @@ figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile
span(ng-class='{zzz:profile.flags.rest}') span(ng-class='{zzz:profile.flags.rest}')
span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}')
span(class='{{profile.preferences.gender}}_hair_{{profile.preferences.hair}}') 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='{{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("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.tier)}}') span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}')
span(class='{{equipped("weapon",profile.items.weapon,profile.preferences,profile.backer.tier)}}') span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}')
// FIXME handle @minimal, this might have to be a directive // 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') 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}} .avatar-level Lvl {{profile.stats.lvl}}

View File

@@ -30,4 +30,17 @@ div(modal='modals.achievements.beastmaster')
.modal-footer .modal-footer
button.btn.btn-default.cancel(ng-click='modals.achievements.beastmaster = false') Ok 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 <a href='https://trello.com/c/wkFzONhE/277-contributor-gear' target='_blank'>Trello</a> for what prizes you've earned for your contribution level.
.modal-footer
button.btn.btn-default.cancel(ng-click='set("flags.contributor",false)') Ok

View File

@@ -3,7 +3,7 @@ div(ng-controller='MemberModalCtrl')
.modal-header .modal-header
h3 h3
span {{profile.profile.name}} 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 .modal-body
.row-fluid .row-fluid
.span6 .span6
@@ -13,6 +13,7 @@ div(ng-controller='MemberModalCtrl')
li(ng-repeat='website in profile.profile.websites') li(ng-repeat='website in profile.profile.websites')
a(href='{{website}}', target='_blank') {{website}} a(href='{{website}}', target='_blank') {{website}}
ul.muted.unstyled(ng-if='profile.auth.timestamps', style='margin-top:10px;') 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.created') - Member since {{timestamp(profile.auth.timestamps.created)}} -
li(ng-show='profile.auth.timestamps.loggedin') - Last logged in {{timestamp(profile.auth.timestamps.loggedin)}} - li(ng-show='profile.auth.timestamps.loggedin') - Last logged in {{timestamp(profile.auth.timestamps.loggedin)}} -
h3 Stats h3 Stats

View File

@@ -16,16 +16,16 @@
div(ng-if='profile.backer.npc') div(ng-if='profile.backer.npc')
.achievement.achievement-helm .achievement.achievement-helm
h5 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! small Backed the Kickstarter project at the maximum level!
hr hr
div(ng-if='profile.backer.contributor || user._id == profile._id') div(ng-if='profile.contributor.level || user._id == profile._id')
.achievement.achievement-firefox(ng-show='profile.backer.contributor') .achievement.achievement-firefox(ng-if='profile.contributor.level')
div(ng-class='{muted: !profile.backer.contributor}') div(ng-class='{muted: !profile.contributor.level}')
h5 h5
span.label.label-inverse(ng-if='profile.backer.contributor') {{profile.backer.contributor}} span.label(ng-if='profile.contributor.level', class='label-contributor-{{profile.contributor.level}}') {{contribText(profile.contributor, profile.backer)}}
span.label(ng-if='!profile.backer.contributor') Contributor span.label(ng-if='!profile.contributor.level') Contributor
small. small.
Has contributed to HabitRPG (code, design, pixel art, legal advice, docs, etc). Want this badge? Fix a bug :) Has contributed to HabitRPG (code, design, pixel art, legal advice, docs, etc). Want this badge? Fix a bug :)
hr hr