diff --git a/ghost/admin/app/components/gh-posts-list-item.hbs b/ghost/admin/app/components/gh-posts-list-item.hbs index 85477a9604..e4b60a7688 100644 --- a/ghost/admin/app/components/gh-posts-list-item.hbs +++ b/ghost/admin/app/components/gh-posts-list-item.hbs @@ -1,4 +1,8 @@ -
  • +
  • {{#if @post.isFeatured}} {{svg-jar "star-filled" class="fill-blue w3 h3"}} @@ -17,21 +21,48 @@ in {{@post.primaryTag.name}} {{/if}} - {{#if (eq @post.email.status "submitted")}} - • Sent to {{gh-pluralize @post.email.emailCount "member"}} - {{/if}} + • {{gh-format-post-time @post.updatedAtUTC draft=true}} - {{#if @post.isScheduled}} - – Will be published {{this.scheduledText}} - {{/if}}

    + {{#if (eq @post.displayName "post")}} + +
    + {{#if (or @post.email @post.willEmail)}} + {{#if (eq @post.email.status "submitted")}} + + {{@post.email.emailCount}} + {{gh-pluralize @post.email.emailCount "send"}} + + {{/if}} + {{/if}} +
    +
    + {{/if}} + + {{#if (eq @post.displayName "post")}} + + {{#if (and @post.email.trackOpens (eq @post.email.status "submitted"))}} +
    + + {{#if this.isHovered}} + {{@post.email.openedCount}} + {{else}} + {{@post.email.openRate}}%  + {{/if}} + + {{@post.email.openRate}}% opens +
    + {{/if}} +
    + {{/if}} +
    {{#if @post.isScheduled}} - + Scheduled {{/if}} @@ -47,30 +78,6 @@ Published {{/if}} - - {{#if this.session.user.isOwnerOrAdmin}} - {{#if (or @post.email (and @post.isScheduled this.sendEmailWhenPublished))}} - {{#if (eq @post.email.status "failed")}} - - {{svg-jar "send-email" class="stroke-red"}} - - {{else}} - {{#if @post.isScheduled}} - - {{svg-jar "send-email" class="stroke-green-d2"}} - - {{else}} - - {{svg-jar "send-email" class="stroke-midgrey"}} - - {{/if}} - {{/if}} - {{/if}} - {{/if}}
    - - - {{gh-format-post-time @post.updatedAtUTC draft=true}} -
  • \ No newline at end of file diff --git a/ghost/admin/app/components/gh-posts-list-item.js b/ghost/admin/app/components/gh-posts-list-item.js index f47c1fe190..0ae51fef56 100644 --- a/ghost/admin/app/components/gh-posts-list-item.js +++ b/ghost/admin/app/components/gh-posts-list-item.js @@ -1,11 +1,15 @@ import Component from '@glimmer/component'; +import {action} from '@ember/object'; import {formatPostTime} from 'ghost-admin/helpers/gh-format-post-time'; import {inject as service} from '@ember/service'; +import {tracked} from '@glimmer/tracking'; export default class GhPostsListItemComponent extends Component { @service session; @service settings; + @tracked isHovered = false; + get authorNames() { return this.args.post.authors.map(author => author.name || author.email).join(', '); } @@ -19,10 +23,6 @@ export default class GhPostsListItemComponent extends Component { let {post} = this.args; let text = []; - if (post.emailRecipientFilter && post.emailRecipientFilter !== 'none') { - text.push(`and sent to ${post.emailRecipientFilter} members`); - } - let formattedTime = formatPostTime( post.publishedAtUTC, {timezone: this.settings.get('timezone'), scheduled: true} @@ -31,4 +31,14 @@ export default class GhPostsListItemComponent extends Component { return text.join(' '); } + + @action + mouseOver() { + this.isHovered = true; + } + + @action + mouseLeave() { + this.isHovered = false; + } } diff --git a/ghost/admin/app/models/email.js b/ghost/admin/app/models/email.js index bc55890818..06d35afe10 100644 --- a/ghost/admin/app/models/email.js +++ b/ghost/admin/app/models/email.js @@ -1,8 +1,8 @@ import Model, {attr, belongsTo} from '@ember-data/model'; +import {computed} from '@ember/object'; import {equal} from '@ember/object/computed'; export default Model.extend({ - emailCount: attr('number'), error: attr('string'), html: attr('string'), plaintext: attr('string'), @@ -11,6 +11,14 @@ export default Model.extend({ subject: attr('string'), submittedAtUTC: attr('moment-utc'), uuid: attr('string'), + recipientFilter: attr('string'), + + emailCount: attr('number', {defaultValue: 0}), + deliveredCount: attr('number', {defaultValue: 0}), + openedCount: attr('number', {defaultValue: 0}), + failedCount: attr('number', {defaultValue: 0}), + + trackOpens: attr('boolean'), createdAtUTC: attr('moment-utc'), createdBy: attr('string'), @@ -22,6 +30,16 @@ export default Model.extend({ isSuccess: equal('status', 'submitted'), isFailure: equal('status', 'failed'), + openRate: computed('emailCount', 'openedCount', function () { + let {emailCount, openedCount} = this; + + if (emailCount === 0) { + return 0; + } + + return Math.round(openedCount / emailCount * 100); + }), + retry() { return this.store.adapterFor('email').retry(this); } diff --git a/ghost/admin/app/models/post.js b/ghost/admin/app/models/post.js index f148807775..c951d0e368 100644 --- a/ghost/admin/app/models/post.js +++ b/ghost/admin/app/models/post.js @@ -149,6 +149,10 @@ export default Model.extend(Comparable, ValidationEngine, { internalTags: filterBy('tags', 'isInternal', true), isScheduled: equal('status', 'scheduled'), + willEmail: computed('emailRecipientFilter', function () { + return this.emailRecipientFilter !== 'none'; + }), + previewUrl: computed('uuid', 'ghostPaths.url', 'config.blogUrl', function () { let blogUrl = this.get('config.blogUrl'); let uuid = this.uuid; diff --git a/ghost/admin/app/styles/layouts/content.css b/ghost/admin/app/styles/layouts/content.css index 220fac9d85..925e281d3c 100644 --- a/ghost/admin/app/styles/layouts/content.css +++ b/ghost/admin/app/styles/layouts/content.css @@ -160,12 +160,13 @@ padding-left: 10px; } -.gh-posts-status-header { - width: 160px; +.gh-posts-sends-header, +.gh-posts-opens-header { + width: 120px; } -.gh-posts-lastupdate-header { - width: 160px; +.gh-posts-status-header { + width: 140px; } .gh-post-list-title { @@ -179,7 +180,9 @@ } .gh-post-list-updated, -.gh-post-list-author { +.gh-post-list-author, +.gh-post-list-recipients, +.gh-post-list-opens { color: var(--middarkgrey); font-size: 1.3rem; } @@ -201,7 +204,7 @@ color: var(--middarkgrey); } -.gh-schedule-time { +.gh-schedule-plan { color: var(--green-d1); } @@ -219,6 +222,10 @@ margin-right: 3px; } +.gh-content-email-stats-mobile { + display: none; +} + .gh-content-status-draft, .gh-content-status-published, .gh-content-status-scheduled, @@ -340,9 +347,10 @@ padding: 20px 28px 4px; } - .gh-post-list-status { + .gh-post-list-status, + .gh-post-list-recipients, + .gh-post-list-opens { display: inline-block; - order: 3; border: none; padding: 0 4px 20px 28px; font-size: 1.3rem; @@ -352,9 +360,21 @@ text-overflow: ellipsis; } + .gh-post-list-status { + order: 3; + } + + .gh-post-list-recipients { + order: 4; + } + + .gh-post-list-opens { + order: 5; + } + .gh-post-list-updated { display: inline-block; - order: 4; + order: 6; border: none; padding: 0 4px 20px; font-size: 1.3rem; @@ -366,7 +386,7 @@ .gh-post-list-author { display: inline-block; - order: 5; + order: 7; border: none; padding: 0 4px 20px 0; font-size: 1.3rem; @@ -385,6 +405,14 @@ display: none; } + .gh-content-email-stats { + display: none; + } + + .gh-content-email-stats-mobile { + display: inherit; + } + .post-header { justify-content: flex-end; min-height: 120px; diff --git a/ghost/admin/app/templates/pages.hbs b/ghost/admin/app/templates/pages.hbs index 84ef649414..e23529f30c 100644 --- a/ghost/admin/app/templates/pages.hbs +++ b/ghost/admin/app/templates/pages.hbs @@ -33,7 +33,6 @@
    {{!--Favorite indicator column: no header--}}
    Title
    Status
    -
    Last update
    {{/if}} diff --git a/ghost/admin/app/templates/posts.hbs b/ghost/admin/app/templates/posts.hbs index fd17a7ac77..f4144e3295 100644 --- a/ghost/admin/app/templates/posts.hbs +++ b/ghost/admin/app/templates/posts.hbs @@ -32,8 +32,9 @@
  • {{!--Favorite indicator column: no header--}}
    Title
    +
    Sends
    +
    Opens
    Status
    -
    Last update
  • {{/if}}