mirror of https://github.com/wekan/wekan
The user is now able to upload an avatar, and pick one in a list. This functionality should eventually be abstracted in a community package but we still need to work on a great public API. We rely on collectionFS to manage uploaded avatars. We also removed bengott:avatar which was trying to solve the wrong problem (namely displaying the avatar, which is as simple as displaying an image), and not a avatar system as it should be. Gravatar support is coming (back) soon. We may also want to have a list of default fun avatars the user can choose instead of uploading its own one.pull/188/head
parent
98d7278d08
commit
46cc691534
@ -1,22 +1,42 @@ |
||||
template(name="userAvatar") |
||||
.member.js-member(class="{{class}}" title="{{userData.profile.name}} ({{userData.username}})") |
||||
+avatar(user=userData size=size) |
||||
.member.js-member(title="{{userData.profile.fullname}} ({{userData.username}})") |
||||
if userData.profile.avatarUrl |
||||
img.avatar.avatar-image(src=userData.profile.avatarUrl) |
||||
if showStatus |
||||
span.member-presence-status(class=presenceStatusClassName) |
||||
span.member-type(class=memberType) |
||||
|
||||
|
||||
template(name="userPopup") |
||||
.board-member-menu |
||||
.mini-profile-info |
||||
+userAvatar(user=user) |
||||
.info |
||||
h3.bottom |
||||
a.js-profile(href="{{ pathFor route='Profile' username=user.username }}")= user.profile.name |
||||
p.quiet.bottom @{{ user.username }} |
||||
.info |
||||
h3.bottom |
||||
a.js-profile(href="{{pathFor route='Profile' username=user.username}}")= user.profile.name |
||||
p.quiet.bottom @{{ user.username }} |
||||
|
||||
template(name="memberName") |
||||
a.inline-object.js-show-mem-menu(href="{{ pathFor route='Profile' username=user.username }}") |
||||
= user.profile.name |
||||
a.js-show-mem-menu(href="{{pathFor route='Profile' username=user.username}}") |
||||
= user.profile.fullname |
||||
if username |
||||
| ({{ user.username }}) |
||||
|
||||
template(name="changeAvatarPopup") |
||||
ul.pop-over-list |
||||
each uploadedAvatars |
||||
li: a.js-select-avatar |
||||
.member: .avatar |
||||
img.avatar-image(src="{{url avatarUrlOptions}}") |
||||
| Uploaded avatar |
||||
if isSelected |
||||
i.fa.fa-check |
||||
p.sub-name |
||||
unless isSelected |
||||
a.js-delete-avatar |
||||
| Delete |
||||
| - |
||||
= original.name |
||||
input.hide.js-upload-avatar-input(accept="image/*;capture=camera" type="file") |
||||
button.full.js-upload-avatar |
||||
i.fa.fa-upload |
||||
| Upload an avatar |
||||
|
@ -1,79 +0,0 @@ |
||||
<template name='profile'> |
||||
{{ # if profile }} |
||||
<div class="tabbed-pane-header"> |
||||
<div class="tabbed-pane-header-wrapper clearfix"> |
||||
<a class="tabbed-pane-header-image profile-image ed js-change-avatar-profile" href="#"> |
||||
{{> userAvatar user=profile size="large"}} |
||||
</a> |
||||
<div class="tabbed-pane-header-details"> |
||||
<div class="js-current-details"> |
||||
<div class="tabbed-pane-header-details-name"> |
||||
<h1 class="inline"> {{ profile.profile.name }} </h1> |
||||
<p class="window-title-extra quiet"> @{{ profile.username }} </p> |
||||
</div> |
||||
<div class="tabbed-pane-header-details-content"> |
||||
<p>{{ profile.profile.bio }}</p> |
||||
</div> |
||||
<div class="tabbed-pane-header-details-content"></div> |
||||
</div> |
||||
{{ > profileEditForm }} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{{ else }} |
||||
{{ > message label='user-profile-not-found' }} |
||||
{{ /if }} |
||||
</template> |
||||
|
||||
<template name="settings"> |
||||
{{ > profile profile=currentUser }} |
||||
<div class="tabbed-pane-main-col clearfix"> |
||||
<div class="tabbed-pane-main-col-loading hide js-loading-page"> |
||||
<span class="tabbed-pane-main-col-loading-spinner spinner"></span> |
||||
</div> |
||||
<div class="tabbed-pane-main-col-wrapper js-content"> |
||||
<div class="window-module clearfix"> |
||||
<div class="window-module-title"> |
||||
<h3>{{_ "account-details"}}</h3> |
||||
</div> |
||||
<a class="big-link js-change-name-and-bio" href="#"> |
||||
<span class="text">{{_ 'change-name-initials-bio'}}</span> |
||||
</a> |
||||
<a class="big-link js-change-avatar" href="#"> |
||||
<span class="text">{{_ 'change-avatar'}}</span> |
||||
</a> |
||||
<a class="big-link js-change-password" href="#"> |
||||
<span class="text">{{_ 'change-password'}}</span> |
||||
</a> |
||||
<a class="big-link js-change-email" href="#"> |
||||
<span class="text">{{_ 'change-email'}}</span> |
||||
</a> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<template name="profileEditForm"> |
||||
{{#if $eq currentUser.username profile.username }} |
||||
{{# if session 'ProfileEditForm' }} |
||||
<form id="ProfileEditForm" class="js-profile-form"> |
||||
<p class="error js-profile-form-error hide"></p> |
||||
<label>{{_ "username"}}</label> |
||||
<input type="text" id="username" value="{{ profile.username }}" disabled> |
||||
<label>{{_ "fullname"}}</label> |
||||
<input type="text" id="name" value="{{ profile.profile.name }}"> |
||||
<label> |
||||
{{_ "bio"}} <span class="quiet">({{_ 'optional'}})</span> |
||||
</label> |
||||
<textarea id="bio">{{ profile.profile.bio }}</textarea> |
||||
<input type="submit" class="primary wide js-submit-profile" value="{{_ 'save'}}"> |
||||
<input type="button" class="js-cancel-edit-profile" value="{{_ 'cancel'}}"> |
||||
</form> |
||||
{{ else }} |
||||
<a class="button-link tabbed-pane-header-details-edit js-edit-profile" href="#"> |
||||
<span class="icon-sm fa fa-pencil"></span> |
||||
{{_ "edit-profile"}} |
||||
</a> |
||||
{{ /if }} |
||||
{{ /if }} |
||||
</template> |
@ -1,31 +0,0 @@ |
||||
Template.profileEditForm.events({ |
||||
'click .js-edit-profile': function() { |
||||
Session.set('ProfileEditForm', true); |
||||
}, |
||||
'click .js-cancel-edit-profile': function() { |
||||
Session.set('ProfileEditForm', false); |
||||
}, |
||||
'submit #ProfileEditForm': function(evt, t) { |
||||
var name = t.find('#name').value; |
||||
var bio = t.find('#bio').value; |
||||
|
||||
// trim and update
|
||||
if ($.trim(name)) { |
||||
Users.update(this.profile()._id, { |
||||
$set: { |
||||
'profile.name': name, |
||||
'profile.bio': bio |
||||
} |
||||
}, function() { |
||||
|
||||
// update complete close profileEditForm
|
||||
Session.set('ProfileEditForm', false); |
||||
}); |
||||
} |
||||
evt.preventDefault(); |
||||
} |
||||
}); |
||||
|
||||
Template.memberName.events({ |
||||
'click .js-show-mem-menu': Popup.open('user') |
||||
}); |
@ -1,3 +0,0 @@ |
||||
Avatar.options = { |
||||
fallbackType: 'initials' |
||||
}; |
@ -0,0 +1,27 @@ |
||||
Avatars = new FS.Collection('avatars', { |
||||
stores: [ |
||||
new FS.Store.GridFS('avatars') |
||||
], |
||||
filter: { |
||||
maxSize: 32000, |
||||
allow: { |
||||
contentTypes: ['image/*'] |
||||
} |
||||
} |
||||
}); |
||||
|
||||
var isOwner = function(userId, file) { |
||||
return userId && userId === file.userId; |
||||
}; |
||||
|
||||
Avatars.allow({ |
||||
insert: isOwner, |
||||
update: isOwner, |
||||
remove: isOwner, |
||||
download: function() { return true; }, |
||||
fetch: ['userId'] |
||||
}); |
||||
|
||||
Avatars.files.before.insert(function(userId, doc) { |
||||
doc.userId = userId; |
||||
}); |
@ -0,0 +1,3 @@ |
||||
Meteor.publish('my-avatars', function() { |
||||
return Avatars.find({ userId: this.userId }); |
||||
}); |
Loading…
Reference in new issue