mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
[#1465] add member modals back in. Not all info is present, just a bit more
work. Can now click guild & tavern members! does lazy-loading of members so we don't have to load all their information at once
This commit is contained in:
@@ -38,13 +38,13 @@ module.exports = function(grunt) {
|
||||
'public/js/services/sharedServices.js',
|
||||
'public/js/services/userServices.js',
|
||||
'public/js/services/groupServices.js',
|
||||
'public/js/services/memberServices.js',
|
||||
|
||||
'public/js/filters/filters.js',
|
||||
|
||||
'public/js/directives/directives.js',
|
||||
|
||||
'public/js/controllers/authCtrl.js',
|
||||
'public/js/controllers/characterCtrl.js',
|
||||
'public/js/controllers/menuCtrl.js',
|
||||
'public/js/controllers/notificationCtrl.js',
|
||||
'public/js/controllers/rootCtrl.js',
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha test/api.mocha.coffee",
|
||||
"start": "grunt run:dev",
|
||||
"postinstall": "./node_modules/bower/bin/bower install -f"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
window.habitrpg = angular.module('habitrpg',
|
||||
['ngRoute', 'ngResource', 'ngSanitize', 'userServices', 'groupServices', 'sharedServices', 'authServices', 'notificationServices', 'ui.bootstrap', 'ui.keypress'])
|
||||
['ngRoute', 'ngResource', 'ngSanitize', 'userServices', 'groupServices', 'memberServices', 'sharedServices', 'authServices', 'notificationServices', 'ui.bootstrap', 'ui.keypress'])
|
||||
|
||||
.constant("API_URL", "")
|
||||
.constant("STORAGE_USER_ID", 'habitrpg-user')
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The character controller:
|
||||
*
|
||||
*/
|
||||
|
||||
habitrpg.controller('CharacterCtrl',
|
||||
['$scope', '$location', 'User',
|
||||
function($scope, $location, User) {
|
||||
|
||||
$scope.user = User.user;
|
||||
|
||||
$scope.equipped = function(user, type) {
|
||||
var tier = (user.backer && user.backer.tier)
|
||||
return window.habitrpgShared.helpers.equipped(type, user.items[type], user.preferences, tier);
|
||||
}
|
||||
|
||||
$scope.$watch('user.tasks', function(){
|
||||
$scope.hpPercent = function(hp) {
|
||||
return (hp / 50) * 100;
|
||||
}
|
||||
|
||||
$scope.expPercent = function(exp, level) {
|
||||
return (exp / window.habitrpgShared.algos.tnl(level)) * 100;
|
||||
}
|
||||
})
|
||||
|
||||
$scope.floor = Math.floor;
|
||||
$scope.count = function(arr) {
|
||||
return _.size(arr);
|
||||
}
|
||||
$scope.tnl = window.habitrpgShared.algos.tnl;
|
||||
|
||||
$scope.showUserAvatar = function() {
|
||||
$('.userAvatar').show()
|
||||
}
|
||||
|
||||
}
|
||||
]);
|
||||
@@ -1,17 +1,38 @@
|
||||
"use strict";
|
||||
|
||||
habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'API_URL', '$q', 'User',
|
||||
function($scope, $rootScope, Groups, $http, API_URL, $q, User) {
|
||||
habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'API_URL', '$q', 'User', 'Members', '$location',
|
||||
function($scope, $rootScope, Groups, $http, API_URL, $q, User, Members, $location) {
|
||||
|
||||
$scope.isMember = function(user, group){
|
||||
return ~(group.members.indexOf(user._id));
|
||||
}
|
||||
|
||||
$scope.groups = Groups.groups;
|
||||
// ------ Loading ------
|
||||
|
||||
$scope.groups = Groups.groups;
|
||||
$scope.fetchGuilds = Groups.fetchGuilds;
|
||||
$scope.fetchTavern = Groups.fetchTavern;
|
||||
|
||||
// ------ Modals ------
|
||||
|
||||
$scope.clickMember = function(uid) {
|
||||
if (User.user._id == uid) {
|
||||
if ($location.path() == '/tasks') {
|
||||
$location.path('/options');
|
||||
} else {
|
||||
$location.path('/tasks');
|
||||
}
|
||||
} else {
|
||||
// We need the member information up top here, but then we pass it down to the modal controller
|
||||
// down below. Better way of handling this?
|
||||
debugger
|
||||
Members.selectMember(uid);
|
||||
$rootScope.modals.member = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ------ Invites ------
|
||||
|
||||
$scope.invitee = '';
|
||||
$scope.invite = function(group, uuid){
|
||||
group.$invite({uuid:uuid}, function(){
|
||||
@@ -22,6 +43,15 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
|
||||
}
|
||||
])
|
||||
|
||||
.controller("MemberModalCtrl", ['$scope', '$rootScope', 'Members',
|
||||
function($scope, $rootScope, Members) {
|
||||
// We watch Members.selectedMember because it's asynchronously set, so would be a hassle to handle updates here
|
||||
$scope.$watch( function() { return Members.selectedMember; }, function (member) {
|
||||
$scope.profile = member;
|
||||
});
|
||||
}
|
||||
])
|
||||
|
||||
.controller('ChatCtrl', ['$scope', 'Groups', 'User', function($scope, Groups, User){
|
||||
$scope._chatMessage = '';
|
||||
$scope.postChat = function(group, message){
|
||||
|
||||
@@ -6,17 +6,4 @@ habitrpg.controller("UserAvatarCtrl", ['$scope', '$location', 'User',
|
||||
$scope.hideUserAvatar = function() {
|
||||
$(".userAvatar").hide();
|
||||
};
|
||||
|
||||
$scope.clickAvatar = function(profile) {
|
||||
if (User.user.id == profile.id) {
|
||||
if ($location.path() == '/tasks') {
|
||||
$location.path('/options');
|
||||
} else {
|
||||
$location.path('/tasks');
|
||||
}
|
||||
} else {
|
||||
//TODO show party member modal
|
||||
//$("#avatar-modal-#{uid}").modal('show')
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
|
||||
angular.module('groupServices', ['ngResource']).
|
||||
factory('Groups', ['API_URL', '$resource', 'User', '$q',
|
||||
function(API_URL, $resource, User, $q) {
|
||||
factory('Groups', ['API_URL', '$resource', 'User', '$q', 'Members',
|
||||
function(API_URL, $resource, User, $q, Members) {
|
||||
var Group = $resource(API_URL + '/api/v1/groups/:gid',
|
||||
{gid:'@_id'},
|
||||
{
|
||||
@@ -34,6 +34,7 @@ angular.module('groupServices', ['ngResource']).
|
||||
// But we don't defer triggering Party, since we always need it for the header if nothing else
|
||||
Group.query({type:'party'}, function(_groups){
|
||||
partyQ.resolve(_groups[0]);
|
||||
Members.populate(_groups[0]);
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -42,10 +43,12 @@ angular.module('groupServices', ['ngResource']).
|
||||
$('#loading-indicator').show();
|
||||
Group.query({type:'guilds'}, function(_groups){
|
||||
guildsQ.resolve(_groups);
|
||||
Members.populate(_groups);
|
||||
$('#loading-indicator').hide();
|
||||
})
|
||||
Group.query({type:'public'}, function(_groups){
|
||||
publicQ.resolve(_groups);
|
||||
Members.populate(_groups);
|
||||
})
|
||||
}),
|
||||
|
||||
@@ -54,6 +57,7 @@ angular.module('groupServices', ['ngResource']).
|
||||
Group.query({type:'tavern'}, function(_groups){
|
||||
$('#loading-indicator').hide();
|
||||
tavernQ.resolve(_groups[0]);
|
||||
Members.populate(_groups[0]);
|
||||
})
|
||||
}),
|
||||
|
||||
|
||||
73
public/js/services/memberServices.js
Normal file
73
public/js/services/memberServices.js
Normal file
@@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Services that persists and retrieves user from localStorage.
|
||||
*/
|
||||
|
||||
angular.module('memberServices', ['ngResource']).
|
||||
factory('Members', ['API_URL', '$resource',
|
||||
function(API_URL, $resource) {
|
||||
var members = {};
|
||||
var Member = $resource(API_URL + '/api/v1/members/:uid', {uid:'@_id'});
|
||||
return {
|
||||
|
||||
members: members,
|
||||
|
||||
/**
|
||||
* Allows us to lazy-load party / group / public members throughout the application.
|
||||
* @param obj - either a group or an individual member. If it's a group, we lazy-load all of its members.
|
||||
*/
|
||||
populate: function(obj){
|
||||
|
||||
function populateGroup(group){
|
||||
_.each(group.members, function(member){
|
||||
// meaning `populate('members')` wasn't run on the server, so we're getting the "in-database" form of
|
||||
// the members array, which is just a list of IDs - not the populated objects
|
||||
if (_.isString(member)) return;
|
||||
|
||||
// lazy-load
|
||||
if (!members[member._id]) members[member._id] = member;
|
||||
})
|
||||
}
|
||||
|
||||
// Array of groups
|
||||
if (_.isArray(obj)) {
|
||||
if (obj[0] && obj[0].members) {
|
||||
_.each(obj, function(group){
|
||||
populateGroup(group);
|
||||
})
|
||||
}
|
||||
|
||||
// Individual Group
|
||||
} else if (obj.members)
|
||||
populateGroup(obj);
|
||||
|
||||
// individual Member
|
||||
if (obj._id) {
|
||||
if (!members[obj._id]) {
|
||||
members[obj._id] = obj;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
selectedMember: undefined,
|
||||
|
||||
/**
|
||||
* Once users are populated, we fetch them throughout the application (eg, modals). This
|
||||
* either gets them or fetches if not available
|
||||
* @param uid
|
||||
*/
|
||||
selectMember: function(uid) {
|
||||
var self = this;
|
||||
if (members[uid]) {
|
||||
self.selectedMember = members[uid];
|
||||
} else {
|
||||
Member.get({uid: uid}, function(member){
|
||||
self.populate(member); // lazy load for later
|
||||
self.selectedMember = members[member._id];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
@@ -19,6 +19,14 @@ var api = module.exports;
|
||||
var usernameFields = 'auth.local.username auth.facebook.displayName auth.facebook.givenName auth.facebook.familyName auth.facebook.name';
|
||||
var partyFields = 'profile preferences items stats achievements party backer flags.rest ' + usernameFields;
|
||||
|
||||
api.getMember = function(req, res) {
|
||||
User.findById(req.params.uid).select(partyFields).exec(function(err, user){
|
||||
if (err) return res.json(500,{err:err});
|
||||
if (!user) return res.json(400,{err:'User not found'});
|
||||
res.json(user);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get groups. If req.query.type privided, returned as an array (so ngResource can use). If not, returned as
|
||||
* object {guilds, public, party, tavern}. req.query.type can be comma-separated `type=guilds,party`
|
||||
|
||||
@@ -64,6 +64,9 @@ router.post('/groups/:gid/chat', auth.auth, groups.attachGroup, groups.postChat)
|
||||
//PUT /groups/:gid/chat/:messageId
|
||||
//DELETE /groups/:gid/chat/:messageId
|
||||
|
||||
/* Members */
|
||||
router.get('/members/:uid', groups.getMember);
|
||||
|
||||
// Market
|
||||
router.post('/market/buy', auth.auth, user.marketBuy);
|
||||
|
||||
|
||||
@@ -52,13 +52,13 @@ html
|
||||
script(type='text/javascript', src='/js/services/sharedServices.js')
|
||||
script(type='text/javascript', src='/js/services/userServices.js')
|
||||
script(type='text/javascript', src='/js/services/groupServices.js')
|
||||
script(type='text/javascript', src='/js/services/memberServices.js')
|
||||
|
||||
script(type='text/javascript', src='/js/filters/filters.js')
|
||||
|
||||
script(type='text/javascript', src='/js/directives/directives.js')
|
||||
|
||||
script(type='text/javascript', src='/js/controllers/authCtrl.js')
|
||||
script(type='text/javascript', src='/js/controllers/characterCtrl.js')
|
||||
script(type='text/javascript', src='/js/controllers/menuCtrl.js')
|
||||
script(type='text/javascript', src='/js/controllers/notificationCtrl.js')
|
||||
script(type='text/javascript', src='/js/controllers/rootCtrl.js')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
li(ng-repeat='message in group.chat', ng-class='{highlight: message.text.indexOf(username(user.auth,user.profile.name)) != -1}')
|
||||
span.label.chat-message(class='{{nameTagClasses(message)}}', tooltip='{{message.contributor}}')
|
||||
a.label.chat-message(class='{{nameTagClasses(message)}}', tooltip='{{message.contributor}}', ng-click='clickMember(message.uuid)')
|
||||
| {{message.user}}
|
||||
span
|
||||
span(ng-bind-html="message.text | linky:'_blank'") -
|
||||
|
||||
@@ -1,68 +1,66 @@
|
||||
div#groups-controller(ng-controller='GroupsCtrl')
|
||||
// FIXME note, due to https://github.com/angular-ui/bootstrap/issues/783 we can't use nested angular-bootstrap tabs
|
||||
// Subscribe to that ticket & change this when they fix
|
||||
|
||||
// FIXME note, due to https://github.com/angular-ui/bootstrap/issues/783 we can't use nested angular-bootstrap tabs
|
||||
// Subscribe to that ticket & change this when they fix
|
||||
ul.nav.nav-tabs
|
||||
li.active
|
||||
a(data-target='#groups-party', data-toggle='tab') Party
|
||||
li
|
||||
a(data-target='#groups-guilds', data-toggle='tab', ng-click='fetchGuilds()') Guilds
|
||||
|
||||
ul.nav.nav-tabs
|
||||
li.active
|
||||
a(data-target='#groups-party', data-toggle='tab') Party
|
||||
li
|
||||
a(data-target='#groups-guilds', data-toggle='tab', ng-click='fetchGuilds()') Guilds
|
||||
.tab-content(ng-controller='PartyCtrl')
|
||||
#groups-party.tab-pane.active
|
||||
div(ng-show='group._id')
|
||||
include ./group
|
||||
div(ng-hide='group._id')
|
||||
div(ng-show='user.invitations.party')
|
||||
// #with required for the accept/reject buttons
|
||||
// {#with _user.invitations.party as :party}
|
||||
h2 You're Invited To {{user.invitations.party.name}}
|
||||
a.btn.btn-success(data-type='party', ng-click='join(user.invitations.party)') Accept
|
||||
a.btn.btn-danger(ng-click='reject(group)') Reject
|
||||
// {/}
|
||||
div(ng-hide='user.invitations.party', ng-controller='PartyCtrl')
|
||||
h2 Create A Party
|
||||
p
|
||||
| You are not in a party. You can either create one and invite friends, or if you want to join an existing party, have them enter:
|
||||
pre.prettyprint.
|
||||
{{user.id}}
|
||||
include ./create-group
|
||||
|
||||
.tab-content(ng-controller='PartyCtrl')
|
||||
#groups-party.tab-pane.active
|
||||
div(ng-show='group._id')
|
||||
#groups-guilds.tab-pane(ng-controller='GuildsCtrl')
|
||||
ul.nav.nav-tabs
|
||||
li.active
|
||||
a(data-target='#groups-public-guilds', data-toggle='tab') Public Guilds
|
||||
li(ng-repeat='group in groups.guilds')
|
||||
a(data-target='#groups-guild-{{group._id}}', data-toggle='tab') {{group.name}}
|
||||
li
|
||||
a(data-target='#groups-create-guild', data-toggle='tab') Create Guild
|
||||
.tab-content
|
||||
.tab-pane.active#groups-public-guilds
|
||||
div(ng-repeat='invitation in user.invitations.guilds')
|
||||
h3 You're Invited To {{invitation.name}}
|
||||
a.btn.btn-success(data-type='guild', ng-click='join(group)') Accept
|
||||
a.btn.btn-danger(x-bind='click:rejectInvitation') Reject
|
||||
// Public Groups
|
||||
.options-group.option-large.whatever-options
|
||||
input.option-content(type='text',ng-model='guildSearch', placeholder='Search')
|
||||
table.table.table-striped
|
||||
tr(ng-repeat='group in groups.public | filter:guildSearch')
|
||||
td
|
||||
ul.pull-right.challenge-accordion-header-specs
|
||||
li {{group.members.length}} member(s)
|
||||
li
|
||||
// join / leave
|
||||
a.btn.btn-small.btn-danger(ng-show='isMember(user, group)', ng-click='leave(group)')
|
||||
i.icon-ban-circle
|
||||
| Leave
|
||||
a.btn.btn-small.btn-success(ng-hide='isMember(user, group)', ng-click='join(group)')
|
||||
i.icon-ok
|
||||
| Join
|
||||
h4 {{group.name}}
|
||||
p {{group.description}}
|
||||
.tab-pane(id='groups-guild-{{group._id}}', ng-repeat='group in groups.guilds')
|
||||
include ./group
|
||||
div(ng-hide='group._id')
|
||||
div(ng-show='user.invitations.party')
|
||||
// #with required for the accept/reject buttons
|
||||
// {#with _user.invitations.party as :party}
|
||||
h2 You're Invited To {{user.invitations.party.name}}
|
||||
a.btn.btn-success(data-type='party', ng-click='join(user.invitations.party)') Accept
|
||||
a.btn.btn-danger(ng-click='reject(group)') Reject
|
||||
// {/}
|
||||
div(ng-hide='user.invitations.party', ng-controller='PartyCtrl')
|
||||
h2 Create A Party
|
||||
p
|
||||
| You are not in a party. You can either create one and invite friends, or if you want to join an existing party, have them enter:
|
||||
pre.prettyprint.
|
||||
{{user.id}}
|
||||
include ./create-group
|
||||
|
||||
#groups-guilds.tab-pane(ng-controller='GuildsCtrl')
|
||||
ul.nav.nav-tabs
|
||||
li.active
|
||||
a(data-target='#groups-public-guilds', data-toggle='tab') Public Guilds
|
||||
li(ng-repeat='group in groups.guilds')
|
||||
a(data-target='#groups-guild-{{group._id}}', data-toggle='tab') {{group.name}}
|
||||
li
|
||||
a(data-target='#groups-create-guild', data-toggle='tab') Create Guild
|
||||
.tab-content
|
||||
.tab-pane.active#groups-public-guilds
|
||||
div(ng-repeat='invitation in user.invitations.guilds')
|
||||
h3 You're Invited To {{invitation.name}}
|
||||
a.btn.btn-success(data-type='guild', ng-click='join(group)') Accept
|
||||
a.btn.btn-danger(x-bind='click:rejectInvitation') Reject
|
||||
// Public Groups
|
||||
.options-group.option-large.whatever-options
|
||||
input.option-content(type='text',ng-model='guildSearch', placeholder='Search')
|
||||
table.table.table-striped
|
||||
tr(ng-repeat='group in groups.public | filter:guildSearch')
|
||||
td
|
||||
ul.pull-right.challenge-accordion-header-specs
|
||||
li {{group.members.length}} member(s)
|
||||
li
|
||||
// join / leave
|
||||
a.btn.btn-small.btn-danger(ng-show='isMember(user, group)', ng-click='leave(group)')
|
||||
i.icon-ban-circle
|
||||
| Leave
|
||||
a.btn.btn-small.btn-success(ng-hide='isMember(user, group)', ng-click='join(group)')
|
||||
i.icon-ok
|
||||
| Join
|
||||
h4 {{group.name}}
|
||||
p {{group.description}}
|
||||
.tab-pane(id='groups-guild-{{group._id}}', ng-repeat='group in groups.guilds')
|
||||
include ./group
|
||||
|
||||
.tab-pane#groups-create-guild
|
||||
include ./create-group
|
||||
.tab-pane#groups-create-guild
|
||||
include ./create-group
|
||||
@@ -1,4 +1,4 @@
|
||||
figure.herobox(ng-click='clickAvatar(profile)', data-name='{{username(profile.auth, profile.profile.name)}}', ng-class='{isUser: profile.id==user.id, hasPet: profile.items.pet}', data-level='{{profile.stats.lvl}}', data-uid='{{profile.id}}', rel='popover', data-placement='bottom', data-trigger='hover', data-html='true', data-content="<div ng-hide='profile.id == user.id'> <div class='progress progress-danger' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.hp, 50)}}%;'></div> </div> <div class='progress progress-warning' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.exp, tnl(profile.stats.lvl))}}%;'></div> </div> <div>Level: {{profile.stats.lvl}}</div> <div>GP: {{profile.stats.gp | number:0}}</div> <div>{{count(profile.items.pets)}} / 90 Pets Found</div> </div>")
|
||||
figure.herobox(ng-click='clickMember(profile._id)', data-name='{{username(profile.auth, profile.profile.name)}}', ng-class='{isUser: profile.id==user.id, hasPet: profile.items.pet}', data-level='{{profile.stats.lvl}}', data-uid='{{profile.id}}', rel='popover', data-placement='bottom', data-trigger='hover', data-html='true', data-content="<div ng-hide='profile.id == user.id'> <div class='progress progress-danger' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.hp, 50)}}%;'></div> </div> <div class='progress progress-warning' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.exp, tnl(profile.stats.lvl))}}%;'></div> </div> <div>Level: {{profile.stats.lvl}}</div> <div>GP: {{profile.stats.gp | number:0}}</div> <div>{{count(profile.items.pets)}} / 90 Pets Found</div> </div>")
|
||||
.character-sprites
|
||||
span(ng-class='{zzz:profile.flags.rest}')
|
||||
span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}')
|
||||
|
||||
@@ -4,4 +4,5 @@ include ./reroll
|
||||
include ./death
|
||||
include ./new-stuff
|
||||
include ./why-ads
|
||||
include ./more-gems
|
||||
include ./more-gems
|
||||
include ./members
|
||||
@@ -1,40 +1,27 @@
|
||||
{{#each _membersArray as :member}}
|
||||
<app:modals:modal modalId="avatar-modal-{{:member.id}}">
|
||||
<app:avatar:profile profile={{_members[:member.id]}} />
|
||||
<div ng-controller="MemberModalCtrl">
|
||||
<div modal="modals.member">
|
||||
<app:avatar:profile />
|
||||
|
||||
<!-- see above -->
|
||||
<profile:>
|
||||
<h2 class='profile-modal-header'>{{username(@profile.auth, @profile.profile.name)}}</h2>
|
||||
<!-- see above -->
|
||||
<h2 class='profile-modal-header'>{{username(profile.auth, profile.profile.name)}}</h2>
|
||||
<hr/>
|
||||
<div class='row-fluid'>
|
||||
<div class='span6'>
|
||||
{{#if @profile.profile.imageUrl}}
|
||||
<img src="{{@profile.profile.imageUrl}}" />
|
||||
{{/}}
|
||||
{{#if @profile.profile.blurb}}
|
||||
<p>{{@profile.profile.blurb}}</p>
|
||||
{{/}}
|
||||
{{#if @profile.profile.websites}}
|
||||
<ul>
|
||||
{{#each @profile.profile.websites as :website}}
|
||||
<li>{{:website}}</li>
|
||||
{{/}}
|
||||
<img ng-show='profile.profile.imageUrl' ng-src="{{profile.profile.imageUrl}}" />
|
||||
<p ng-show="profile.profile.blurb">{{profile.profile.blurb}}</p>
|
||||
<ul ng-show="profile.profile.websites">
|
||||
<li ng-repeat="website in profile.profile.websites">{{website}}</li>
|
||||
</ul>
|
||||
{{/}}
|
||||
<h3>Stats</h3>
|
||||
<app:avatar:profile-stats profile={{@profile}} />
|
||||
<app:avatar:profile-stats profile={{profile}} />
|
||||
</div>
|
||||
<div class='span6'>
|
||||
<h3>Achievements</h3>
|
||||
<app:avatar:achievements profile={{@profile}} />
|
||||
|
||||
<app:avatar:achievements profile={{profile}} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<@footer>
|
||||
<button data-dismiss="modal" class="btn btn-success">Ok</button>
|
||||
</@footer>
|
||||
</app:modals:modal>
|
||||
{{/}}
|
||||
<footer>
|
||||
<button data-dismiss="modal" class="btn btn-success">Ok</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
21
views/shared/modals/members.jade
Normal file
21
views/shared/modals/members.jade
Normal file
@@ -0,0 +1,21 @@
|
||||
div(ng-controller='MemberModalCtrl')
|
||||
div(modal='modals.member')
|
||||
//-.modal-header
|
||||
h3 username
|
||||
.modal-body
|
||||
h2.profile-modal-header {{username(profile.auth, profile.profile.name)}}
|
||||
app:avatar:profile
|
||||
hr
|
||||
.row-fluid
|
||||
.span6
|
||||
img(ng-show='profile.profile.imageUrl', ng-src='{{profile.profile.imageUrl}}')
|
||||
p(ng-show='profile.profile.blurb') {{profile.profile.blurb}}
|
||||
ul(ng-show='profile.profile.websites')
|
||||
li(ng-repeat='website in profile.profile.websites') {{website}}
|
||||
h3 Stats
|
||||
app:avatar:profile-stats
|
||||
.span6
|
||||
h3 Achievements
|
||||
app:avatar:achievements
|
||||
.modal-footer
|
||||
button.btn.btn-default(ng-click='modals.member = false') Ok
|
||||
Reference in New Issue
Block a user