mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-25 09:03:12 +03:00
✨ Added email stats overview to member details page (#1795)
refs https://github.com/TryGhost/Ghost/issues/12461 - Added "Emails received", "Emails opened", and "Avg. open rate" to member details - Adjusted visual display of avatar, name and email. Made email a mailto link - Rearranged Name and Email fields to reduce height - Changed height of the notes textarea Co-authored-by: Kevin Ansfield <kevin@lookingsideways.co.uk>
This commit is contained in:
parent
ffe0f84700
commit
ecfb77b980
@ -1,22 +1,84 @@
|
||||
<div class="flex items-stretch mt2">
|
||||
<div class="flex-auto br4 shadow-1 bg-grouped-table mt2 flex flex-column justify-between items-stretch gh-member-settings-primary mr6">
|
||||
<div class="pa5 pb0 pt4">
|
||||
<GhFormGroup @errors={{this.member.errors}} @hasValidated={{this.member.hasValidated}} @property="name" @classNames="max-width">
|
||||
<label for="member-name">Name</label>
|
||||
<GhTextInput @id="member-name" @name="name" @value={{this.scratchMember.name}} @tabindex="1"
|
||||
@focus-out={{action "setProperty" "name" this.scratchMember.name}} />
|
||||
<GhErrorMessage @errors={{member.errors}} @property="name" />
|
||||
</GhFormGroup>
|
||||
<div>
|
||||
<div class="flex items-center pa5 pb3 pt6">
|
||||
{{#if (or this.member.name this.member.email)}}
|
||||
<GhMemberAvatar
|
||||
@member={{this.member}}
|
||||
@sizeClass={{if this.member.name 'f-subheadline fw4 lh-zero tracked-1' 'f-headline fw4 lh-zero tracked-1'}}
|
||||
@containerClass="w20 h20 mr4 gh-member-detail-avatar"
|
||||
/>
|
||||
{{else}}
|
||||
<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>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div>
|
||||
<h3 class="f2 fw6 ma0 pa0">
|
||||
{{or this.member.name this.member.email}}
|
||||
</h3>
|
||||
<p class="f7 pa0 ma0 midlightgrey-d1">
|
||||
{{#if (and this.member.name this.member.email)}}
|
||||
<span class="darkgrey fw5"><a href="mailto:{{this.member.email}}">{{this.member.email}}</a></span>
|
||||
{{/if}}
|
||||
</p>
|
||||
{{#unless this.member.isNew}}
|
||||
<p class="f7 pa0 ma0 midgrey-d1 {{if this.member.name "nudge-bottom--2"}}">
|
||||
{{#if this.member.geolocation}}
|
||||
{{#if (eq this.member.geolocation.country_code "US")}}
|
||||
{{this.member.geolocation.region}}, US
|
||||
{{else}}
|
||||
{{this.member.geolocation.country}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
Unknown location
|
||||
{{/if}}
|
||||
– Created on {{moment-format @member.createdAtUTC "D MMM YYYY"}}
|
||||
</p>
|
||||
{{/unless}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<GhFormGroup @errors={{this.member.errors}} @hasValidated={{this.member.hasValidated}} @property="email" @classNames="max-width">
|
||||
<label for="member-email">Email</label>
|
||||
<GhTextInput @value={{this.scratchMember.email}} @id="member-email" @name="email" @tabindex="2"
|
||||
@autocapitalize="off" @autocorrect="off" @autocomplete="off"
|
||||
@focus-out={{action "setProperty" "email" this.scratchMember.email}} />
|
||||
<GhErrorMessage @errors={{this.member.errors}} @property="email" />
|
||||
</GhFormGroup>
|
||||
<div class="flex mb5 pa5 pt3 pb5 bb b--whitegrey">
|
||||
<div class="flex-auto flex flex-column justify-center items-start">
|
||||
<div class="f7 midgrey-d1">Emails received</div>
|
||||
<div class="f2 fw6">{{@member.emailCount}}</div>
|
||||
</div>
|
||||
<div class="flex-auto flex flex-column justify-center items-start">
|
||||
<div class="f7 midgrey-d1">Emails opened</div>
|
||||
<div class="f2 fw6">{{@member.emailOpenedCount}}</div>
|
||||
</div>
|
||||
<div class="flex-auto flex flex-column justify-center items-start">
|
||||
<div class="f7 midgrey-d1">Avg. open rate</div>
|
||||
<div class="f2 fw6">
|
||||
{{#if (is-empty @member.emailOpenRate)}}
|
||||
<span data-tooltip="Insufficient data available">–</span>
|
||||
{{else}}
|
||||
{{@member.emailOpenRate}}%
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<GhFormGroup @errors={{this.member.errors}} @hasValidated={{this.member.hasValidated}} @property="name" @classNames="max-width pl5">
|
||||
<label for="member-name">Name</label>
|
||||
<GhTextInput @id="member-name" @name="name" @value={{this.scratchMember.name}} @tabindex="1"
|
||||
@focus-out={{action "setProperty" "name" this.scratchMember.name}} />
|
||||
<GhErrorMessage @errors={{member.errors}} @property="name" />
|
||||
</GhFormGroup>
|
||||
|
||||
<GhFormGroup @errors={{this.member.errors}} @hasValidated={{this.member.hasValidated}} @property="email" @classNames="max-width pl4 pr5">
|
||||
<label for="member-email">Email</label>
|
||||
<GhTextInput @value={{this.scratchMember.email}} @id="member-email" @name="email" @tabindex="2"
|
||||
@autocapitalize="off" @autocorrect="off" @autocomplete="off"
|
||||
@focus-out={{action "setProperty" "email" this.scratchMember.email}} />
|
||||
<GhErrorMessage @errors={{this.member.errors}} @property="email" />
|
||||
</GhFormGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pa5 pt5 pb6 bt b--whitegrey">
|
||||
|
||||
<div class="pa5 pb6 bt b--whitegrey">
|
||||
<GhFormGroup @classNames="gh-members-subscribed-checkbox mb0">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
@ -34,8 +96,9 @@
|
||||
</GhFormGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-auto br4 shadow-1 bg-grouped-table mt2 flex flex-column items-stretch gh-member-settings-secondary">
|
||||
<div class="pa5 pt4">
|
||||
<div class="pa5 pt6 pb6">
|
||||
<GhFormGroup>
|
||||
<label for="label-input">Labels</label>
|
||||
<GhMemberLabelInput @member={{this.member}} @triggerId="label-input" />
|
||||
|
@ -15,6 +15,8 @@ export default Model.extend(ValidationEngine, {
|
||||
labels: hasMany('label', {embedded: 'always', async: false}),
|
||||
comped: attr('boolean', {defaultValue: false}),
|
||||
geolocation: attr('json-string'),
|
||||
emailCount: attr('number'),
|
||||
emailOpenedCount: attr('number'),
|
||||
emailOpenRate: attr('number'),
|
||||
|
||||
ghostPaths: service(),
|
||||
|
@ -396,7 +396,7 @@ textarea.gh-member-details-textarea {
|
||||
max-width: 100%;
|
||||
min-width: auto;
|
||||
min-height: 50px;
|
||||
height: 98px;
|
||||
height: 156px;
|
||||
}
|
||||
|
||||
.gh-member-info-icon {
|
||||
|
@ -89,6 +89,12 @@ input {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.form-group.pa5 {
|
||||
max-width: 100%;
|
||||
padding-left: calc(var(--grid-size) * 5);
|
||||
padding-right: calc(var(--grid-size) * 5);
|
||||
}
|
||||
|
||||
.form-group.mb0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
@ -26,44 +26,6 @@
|
||||
</GhCanvasHeader>
|
||||
|
||||
<form class="mb10 member-basic-info-form">
|
||||
<div class="flex items-center mb10 bt b--lightgrey-d1 pt8">
|
||||
{{#if (or this.member.name this.member.email)}}
|
||||
<GhMemberAvatar
|
||||
@member={{this.member}}
|
||||
@sizeClass={{if this.member.name 'f-subheadline fw4 lh-zero tracked-1' 'f-headline fw4 lh-zero tracked-1'}}
|
||||
@containerClass="w20 h20 mr4 gh-member-detail-avatar"
|
||||
/>
|
||||
{{else}}
|
||||
<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>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div>
|
||||
<h3 class="f2 fw6 ma0 pa0">
|
||||
{{or this.member.name this.member.email}}
|
||||
</h3>
|
||||
<p class="f7 pa0 ma0 midlightgrey-d1">
|
||||
{{#if (and this.member.name this.member.email)}}
|
||||
<span class="darkgrey fw5">{{this.member.email}}</span>
|
||||
{{/if}}
|
||||
</p>
|
||||
{{#unless this.member.isNew}}
|
||||
<p class="f7 pa0 ma0 midgrey-d1 {{if this.member.name "nudge-bottom--2"}}">
|
||||
{{#if this.member.geolocation}}
|
||||
{{#if (eq this.member.geolocation.country_code "US")}}
|
||||
{{this.member.geolocation.region}}, US
|
||||
{{else}}
|
||||
{{this.member.geolocation.country}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
Unknown location
|
||||
{{/if}}
|
||||
– Created on {{this.subscribedAt}}
|
||||
</p>
|
||||
{{/unless}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<GhMemberSettingsForm
|
||||
@member={{this.member}}
|
||||
@scratchMember={{this.scratchMember}}
|
||||
|
Loading…
Reference in New Issue
Block a user