🎨 Added gravatars for member avatars (#1417)

no issue

- When an email has a valid gravatar handle it displays an image instead of initials for the member
- Introduces new {{gravatar}} helper which accepts an email as parameter and size/d as named parameters. The output is a URL to gravatar image
- Refactored usage of "splattribute" to explicit property. There was a need to duplicate class property usage in the component and doing that through splatttibute feature is unsafe as pointed ou here - https://github.com/TryGhost/Ghost-Admin/pull/1417#discussion_r351837584
This commit is contained in:
Naz Gargol 2019-12-03 18:10:47 +07:00 committed by GitHub
parent 6d2bc8fccc
commit 1df0e2b917
7 changed files with 61 additions and 7 deletions

View File

@ -14,7 +14,7 @@ const stringToHslColor = function (str, saturation, lightness) {
export default Component.extend({ export default Component.extend({
tagName: '', tagName: '',
containerClass: '',
member: null, member: null,
initialsClass: computed('sizeClass', function () { initialsClass: computed('sizeClass', function () {
return this.sizeClass || 'gh-member-list-avatar'; return this.sizeClass || 'gh-member-list-avatar';

View File

@ -0,0 +1,20 @@
import Helper from '@ember/component/helper';
import md5 from 'blueimp-md5';
import {isEmpty} from '@ember/utils';
import {inject as service} from '@ember/service';
export default Helper.extend({
config: service(),
compute([email], {size = 180, d = 'blank'}/*, hash*/) {
if (!this.get('config.useGravatar')) {
return;
}
if (!email || isEmpty(email)) {
return;
}
return `https://www.gravatar.com/avatar/${md5(email)}?s=${size}&d=${d}`;
}
});

View File

@ -1,10 +1,41 @@
/* Global /* Global
/* ----------------------------------------- */ /* ----------------------------------------- */
/* Members avatar
/* ----------------------------------------- */
.gh-member-gravatar {
position: relative;
}
.gh-member-avatar-label { .gh-member-avatar-label {
display: block; display: block;
color: #fff; color: #fff;
} }
.gh-member-avatar-image {
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
box-sizing: content-box;
background-position: center center;
background-size: cover;
border-radius: 100%;
}
.gh-member-initials {
border: none;
box-shadow: 0 0 0 1px var(--white);
}
.gh-member-detail-avatar .gh-member-initials {
box-shadow: 0 0 0 1px var(--main-bg-color);
}
/* Members list /* Members list
/* ----------------------------------------- */ /* ----------------------------------------- */

View File

@ -1,3 +1,6 @@
<div class="flex items-center justify-center br-100" style={{this.backgroundStyle}} ...attributes> <figure class="gh-member-gravatar {{this.containerClass}}">
<span class="gh-member-avatar-label {{this.initialsClass}}">{{this.initials}}</span> <div class="gh-member-initials flex items-center justify-center br-100 {{this.containerClass}}" style={{this.backgroundStyle}}>
</div> <span class="gh-member-avatar-label {{this.initialsClass}}">{{this.initials}}</span>
</div>
<img class="gh-member-avatar-image" src={{gravatar this.member.email size=180}} />
</figure>

View File

@ -1,6 +1,6 @@
<LinkTo @route="member" @model={{this.member}} title="Member details" class="gh-list-data gh-members-list-basic"> <LinkTo @route="member" @model={{this.member}} title="Member details" class="gh-list-data gh-members-list-basic">
<div class="flex items-center"> <div class="flex items-center">
<GhMemberAvatar @member={{member}} class="w9 h9 mr3" /> <GhMemberAvatar @member={{member}} @containerClass="w9 h9 mr3" />
<div> <div>
<h3 class="ma0 pa0 gh-members-list-name {{if (not member.name) "gh-members-name-noname"}}">{{this.displayName}}</h3> <h3 class="ma0 pa0 gh-members-list-name {{if (not member.name) "gh-members-name-noname"}}">{{this.displayName}}</h3>
{{#if this.name}} {{#if this.name}}

View File

@ -15,7 +15,7 @@
</section> </section>
</GhCanvasHeader> </GhCanvasHeader>
<div class="flex items-center mb10 bt b--lightgrey-d1 pt8"> <div class="flex items-center mb10 bt b--lightgrey-d1 pt8">
<GhMemberAvatar @member={{member}} @sizeClass={{if member.name 'f-subheadline fw4 lh-zero tracked-1' 'f-headline fw4 lh-zero tracked-1'}} class="w18 h18 mr4" /> <GhMemberAvatar @member={{member}} @sizeClass={{if member.name 'f-subheadline fw4 lh-zero tracked-1' 'f-headline fw4 lh-zero tracked-1'}} @containerClass="w18 h18 mr4 gh-member-detail-avatar" />
<div> <div>
<h3 class="f2 fw5 ma0 pa0"> <h3 class="f2 fw5 ma0 pa0">
{{or member.name member.email}} {{or member.name member.email}}

View File

@ -11,7 +11,7 @@
</GhCanvasHeader> </GhCanvasHeader>
<div class="flex items-center mb10 bt b--lightgrey-d1 pt8"> <div class="flex items-center mb10 bt b--lightgrey-d1 pt8">
{{#if (or member.name member.email)}} {{#if (or member.name member.email)}}
<GhMemberAvatar @member={{member}} @sizeClass={{if member.name 'f-subheadline fw4 lh-zero tracked-1' 'f-headline fw4 lh-zero tracked-1'}} class="w18 h18 mr4" /> <GhMemberAvatar @member={{member}} @sizeClass={{if member.name 'f-subheadline fw4 lh-zero tracked-1' 'f-headline fw4 lh-zero tracked-1'}} @containerClass="w18 h18 mr4" />
{{else}} {{else}}
<div class="flex items-center justify-center br-100 w18 h18 mr4 gh-new-member-avatar"> <div class="flex items-center justify-center br-100 w18 h18 mr4 gh-new-member-avatar">
<span class="gh-member-avatar-label f-subheadline fw4 lh-zero tracked-1">N</span> <span class="gh-member-avatar-label f-subheadline fw4 lh-zero tracked-1">N</span>