(Re-)implement default avatar using user initials

We use a embedded svg to scale the initials text to its container
size. The user is free to overwrite its initials in the profile form.
This commit is contained in:
Maxime Quandalle 2015-06-10 17:10:32 +02:00
parent 0b6c229b6c
commit 765b0168ea
6 changed files with 91 additions and 43 deletions

View file

@ -218,22 +218,24 @@ $popupWidth = 300px
.pop-over-list
padding-top: 8px
.mini-profile-info
margin-top: 8px
min-height: 56px
position: relative
.miniprofile-header
margin-top: 8px
min-height: 56px
position: relative
.member-large
position: absolute
top: 2px
left: 2px
.member
position: absolute
top: 2px
left: 2px
height: 50px
width: @height
.info
margin: 0 0 0 64px
word-wrap: break-word
.info
margin: 0 0 0 64px
word-wrap: break-word
h3 a
text-decoration: none
h3 a
text-decoration: none
&:hover
text-decoration: underline
&:hover
text-decoration: underline

View file

@ -47,13 +47,15 @@ template(name="labelsWidget")
i.fa.fa-plus
template(name="memberPopup")
.board-member-menu: .mini-profile-info
+userAvatar(user=user)
.info
h3.bottom
.js-profile
= user.profile.name
p.quiet.bottom @#{user.username}
.board-member-menu
.miniprofile-header
+userAvatar(userId=user._id)
.info
h3.bottom
.js-profile
= user.profile.name
p.quiet.bottom @#{user.username}
if currentUser.isBoardMember
ul.pop-over-list
li

View file

@ -1,15 +1,22 @@
template(name="userAvatar")
.member.js-member(title="{{userData.profile.fullname}} ({{userData.username}})")
a.member.js-member(title="{{userData.profile.fullname}} ({{userData.username}})")
if userData.profile.avatarUrl
img.avatar.avatar-image(src=userData.profile.avatarUrl)
else
+userAvatarInitials(userId=userData._id)
if showStatus
span.member-presence-status(class=presenceStatusClassName)
span.member-type(class=memberType)
template(name="userAvatarInitials")
svg.avatar.avatar-initials(viewBox="0 0 {{viewPortWidth}} 15")
text(x="0" y="13")= initials
template(name="userPopup")
.board-member-menu
.mini-profile-info
+userAvatar(user=user)
+userAvatar(userId=user._id)
.info
h3.bottom
a.js-profile(href="{{pathFor route='Profile' username=user.username}}")= user.profile.name
@ -25,8 +32,8 @@ template(name="changeAvatarPopup")
ul.pop-over-list
each uploadedAvatars
li: a.js-select-avatar
.member: .avatar
img.avatar-image(src="{{url avatarUrlOptions}}")
.member
img.avatar.avatar-image(src="{{url avatarUrlOptions}}")
| Uploaded avatar
if isSelected
i.fa.fa-check
@ -36,6 +43,13 @@ template(name="changeAvatarPopup")
| Delete
| -
= original.name
li: a.js-select-initials
.member
+userAvatarInitials(userId=currentUser._id)
| Initials
if noAvatarUrl
i.fa.fa-check
p.sub-name Default avatar
input.hide.js-upload-avatar-input(accept="image/*;capture=camera" type="file")
button.full.js-upload-avatar
i.fa.fa-upload

View file

@ -26,6 +26,18 @@ Template.userAvatar.helpers({
}
});
Template.userAvatarInitials.helpers({
initials: function() {
var user = Users.findOne(this.userId);
return user && user.getInitials();
},
viewPortWidth: function() {
var user = Users.findOne(this.userId);
return (user && user.getInitials().length || 1) * 12;
}
});
BlazeComponent.extendComponent({
template: function() {
return 'changeAvatarPopup';
@ -49,6 +61,12 @@ BlazeComponent.extendComponent({
return avatarUrl === currentAvatarUrl;
},
noAvatarUrl: function() {
var userProfile = Meteor.user().profile;
var avatarUrl = userProfile && userProfile.avatarUrl;
return ! avatarUrl;
},
setAvatar: function(avatarUrl) {
Meteor.users.update(Meteor.userId(), {
$set: {
@ -84,6 +102,9 @@ BlazeComponent.extendComponent({
var avatarUrl = this.currentData().url(this.avatarUrlOptions());
this.setAvatar(avatarUrl);
},
'click .js-select-initials': function() {
this.setAvatar('');
},
'click .js-delete-avatar': function() {
Avatars.remove(this.currentData()._id);
}

View file

@ -5,11 +5,11 @@ avatar-radius = 50%
.member
border-radius: 3px
display: block
position: relative
float: left
height: 30px
width: @height
margin: 0 4px 4px 0
position: relative
cursor: pointer
user-select: none
z-index: 1
@ -17,26 +17,20 @@ avatar-radius = 50%
border-radius: avatar-radius
.avatar
height: 100%
width: @height
display: flex
align-items: center
justify-content: center
overflow: hidden
border-radius: avatar-radius
.avatar-initials
font-weight: bold
max-width: 100%
max-height: 100%
font-size: 14px
line-height: 200%
&.avatar-initials
height: 70%
width: @height
padding: 15%
background-color: #dbdbdb
color: #444444
position: absolute
.avatar-image
max-width: 100%
max-height: 100%
&.avatar-image
height: 100%
width: @height
.member-presence-status
background-color: #b3b3b3

View file

@ -31,13 +31,28 @@ Users.helpers({
return _.where(board.members, {userId: this._id})[0].isAdmin;
},
getInitials: function() {
var profile = this.profile || {};
if (profile.initials)
return profile.initials;
else if (profile.fullname) {
return _.reduce(profile.fullname.split(/\s+/), function(memo, word) {
return memo + word[0];
}, '').toUpperCase();
} else {
return this.pseudo[0].toUpperCase();
}
},
toggleBoardStar: function(boardId) {
var queryType = Meteor.user().hasStarred(boardId) ? '$pull' : '$addToSet';
var queryType = this.hasStarred(boardId) ? '$pull' : '$addToSet';
var query = {};
query[queryType] = {
'profile.starredBoards': boardId
};
Meteor.users.update(Meteor.userId(), query);
Meteor.users.update(this._id, query);
}
});