Added email track clicks column and cleaned up frontend checks (#15501)

fixes https://github.com/TryGhost/Team/issues/2008

- New column that stores email click tracking at the time it was created
- Improved frontend side checks for when to show analytics
This commit is contained in:
Simon Backx 2022-09-29 16:42:45 +02:00 committed by GitHub
parent 22a75ba144
commit 0cd0fc838d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 65 additions and 33 deletions

View File

@ -117,7 +117,7 @@
{{!-- Opened / Signups column --}} {{!-- Opened / Signups column --}}
<LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="permalink gh-list-data gh-post-list-opens"> <LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="permalink gh-list-data gh-post-list-opens">
{{#if (and @post.email (not-eq this.settings.membersSignupAccess "none") (not-eq this.settings.editorDefaultEmailRecipients "disabled") (not this.session.user.isContributor) (or @post.isSent @post.isPublished) this.settings.emailTrackOpens @post.email.trackOpens this.feature.emailAnalytics (eq @post.displayName "post"))}} {{#if @post.showEmailOpenAnalytics }}
<LinkTo @route="members" @query={{hash filterParam=(concat "opened_emails.post_id:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isOpenStatHovered) true)}} {{on "mouseleave" (fn (mut this.isOpenStatHovered) false)}}> <LinkTo @route="members" @query={{hash filterParam=(concat "opened_emails.post_id:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isOpenStatHovered) true)}} {{on "mouseleave" (fn (mut this.isOpenStatHovered) false)}}>
<span class="gh-content-email-stats-value"> <span class="gh-content-email-stats-value">
{{#if this.isHovered}} {{#if this.isHovered}}
@ -130,9 +130,7 @@
opened opened
</span> </span>
</LinkTo> </LinkTo>
{{/if}} {{else if (and @post.isPage @post.showAttributionAnalytics) }}
{{#if (and this.feature.memberAttribution (not-eq this.settings.membersSignupAccess "none") (and @post.isPage) (not this.session.user.isContributor)) }}
<LinkTo @route="members" @query={{hash filterParam=(concat "signup:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isOpenStatHovered) true)}} {{on "mouseleave" (fn (mut this.isOpenStatHovered) false)}}> <LinkTo @route="members" @query={{hash filterParam=(concat "signup:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isOpenStatHovered) true)}} {{on "mouseleave" (fn (mut this.isOpenStatHovered) false)}}>
<span class="gh-content-email-stats-value"> <span class="gh-content-email-stats-value">
{{@post.count.signups}} {{@post.count.signups}}
@ -146,7 +144,7 @@
{{!-- Clicked / Conversions column --}} {{!-- Clicked / Conversions column --}}
<LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="permalink gh-list-data gh-post-list-clicks"> <LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="permalink gh-list-data gh-post-list-clicks">
{{#if (and @post.email (not-eq this.settings.membersSignupAccess "none") (not-eq this.settings.editorDefaultEmailRecipients "disabled") (not this.session.user.isContributor) (or @post.isSent @post.isPublished) this.settings.emailTrackClicks this.feature.emailAnalytics)}} {{#if @post.showEmailClickAnalytics }}
<LinkTo @route="members" @query={{hash filterParam=(concat "clicked_links.post_id:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isClickStatHovered) true)}} {{on "mouseleave" (fn (mut this.isClickStatHovered) false)}}> <LinkTo @route="members" @query={{hash filterParam=(concat "clicked_links.post_id:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isClickStatHovered) true)}} {{on "mouseleave" (fn (mut this.isClickStatHovered) false)}}>
<span class="gh-content-email-stats-value"> <span class="gh-content-email-stats-value">
{{#if this.isHovered}} {{#if this.isHovered}}
@ -159,9 +157,7 @@
clicked clicked
</span> </span>
</LinkTo> </LinkTo>
{{/if}} {{else if (and @post.isPage @post.showPaidAttributionAnalytics) }}
{{#if (and this.feature.memberAttribution (not-eq this.settings.membersSignupAccess "none") (and @post.isPage) (not this.session.user.isContributor)) }}
<LinkTo @route="members" @query={{hash filterParam=(concat "conversion:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isClickStatHovered) true)}} {{on "mouseleave" (fn (mut this.isClickStatHovered) false)}}> <LinkTo @route="members" @query={{hash filterParam=(concat "conversion:[" @post.id "]") }} class="flex flex-column gh-post-row-event" {{on "mouseover" (fn (mut this.isClickStatHovered) true)}} {{on "mouseleave" (fn (mut this.isClickStatHovered) false)}}>
<span class="gh-content-email-stats-value"> <span class="gh-content-email-stats-value">
{{@post.count.paid_conversions}} {{@post.count.paid_conversions}}
@ -176,7 +172,7 @@
{{!-- Button column --}} {{!-- Button column --}}
<LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="permalink gh-list-data gh-post-list-button"> <LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="permalink gh-list-data gh-post-list-button">
<div class="gh-list-data-inner"> <div class="gh-list-data-inner">
{{#if this.isAnalytics}} {{#if @post.hasAnalyticsPage }}
<LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="gh-post-list-cta stats {{if this.isHovered "is-hovered"}}" title=""> <LinkTo @route={{this.routeForLink}} @models={{this.modelsForLink}} class="gh-post-list-cta stats {{if this.isHovered "is-hovered"}}" title="">
{{svg-jar "stats" title=""}} {{svg-jar "stats" title=""}}
</LinkTo> </LinkTo>

View File

@ -24,10 +24,6 @@ export default class PostsListItemClicks extends Component {
return text.join(' '); return text.join(' ');
} }
get isAnalytics() {
return this.args.post.hasAnalytics;
}
get routeForLink() { get routeForLink() {
if (this.isAnalytics) { if (this.isAnalytics) {
return 'posts.analytics'; return 'posts.analytics';

View File

@ -52,7 +52,7 @@
</LinkTo> </LinkTo>
</div> </div>
{{#if (and this.post.email.trackOpens this.settings.emailTrackOpens) }} {{#if this.post.showEmailOpenAnalytics }}
<div class="gh-post-analytics-item"> <div class="gh-post-analytics-item">
<LinkTo @route="members" @query={{hash filterParam=(concat "opened_emails.post_id:[" this.post.id "]") }}> <LinkTo @route="members" @query={{hash filterParam=(concat "opened_emails.post_id:[" this.post.id "]") }}>
<h3>{{this.post.email.openRate}}<sup>%</sup></h3> <h3>{{this.post.email.openRate}}<sup>%</sup></h3>
@ -61,7 +61,7 @@
</div> </div>
{{/if}} {{/if}}
{{#if this.settings.emailTrackClicks}} {{#if this.post.showEmailClickAnalytics }}
<div class="gh-post-analytics-item"> <div class="gh-post-analytics-item">
<LinkTo @route="members" @query={{hash filterParam=(concat "clicked_links.post_id:[" this.post.id "]") }}> <LinkTo @route="members" @query={{hash filterParam=(concat "clicked_links.post_id:[" this.post.id "]") }}>
<h3>{{this.post.clickRate}}<sup>%</sup></h3> <h3>{{this.post.clickRate}}<sup>%</sup></h3>
@ -71,7 +71,7 @@
{{/if}} {{/if}}
{{/if}} {{/if}}
{{#if (and (feature 'memberAttribution') (not this.post.emailOnly)) }} {{#if this.post.showAttributionAnalytics }}
<div class="gh-post-analytics-item"> <div class="gh-post-analytics-item">
<LinkTo @route="members" @query={{hash filterParam=(concat "signup:[" this.post.id "]") }}> <LinkTo @route="members" @query={{hash filterParam=(concat "signup:[" this.post.id "]") }}>
<h3>{{format-number this.post.count.signups}}</h3> <h3>{{format-number this.post.count.signups}}</h3>
@ -79,7 +79,7 @@
</LinkTo> </LinkTo>
</div> </div>
{{#if this.membersUtils.paidMembersEnabled}} {{#if this.post.showPaidAttributionAnalytics }}
<div class="gh-post-analytics-item"> <div class="gh-post-analytics-item">
<LinkTo @route="members" @query={{hash filterParam=(concat "conversion:[" this.post.id "]") }}> <LinkTo @route="members" @query={{hash filterParam=(concat "conversion:[" this.post.id "]") }}>
<h3>{{format-number this.post.count.paid_conversions}}</h3> <h3>{{format-number this.post.count.paid_conversions}}</h3>

View File

@ -119,11 +119,11 @@ export default class Analytics extends Component {
} }
get showLinks() { get showLinks() {
return this.settings.get('emailTrackClicks') && (this.post.isSent || (this.post.isPublished && this.post.email)); return this.post.showEmailClickAnalytics;
} }
get showSources() { get showSources() {
return this.feature.get('sourceAttribution') && !this.membersUtils.isMembersInviteOnly && !this.post.emailOnly; return this.feature.get('sourceAttribution') && this.post.showAttributionAnalytics;
} }
get isLoaded() { get isLoaded() {

View File

@ -19,6 +19,7 @@ export default Model.extend({
failedCount: attr('number', {defaultValue: 0}), failedCount: attr('number', {defaultValue: 0}),
trackOpens: attr('boolean'), trackOpens: attr('boolean'),
trackClicks: attr('boolean'),
createdAtUTC: attr('moment-utc'), createdAtUTC: attr('moment-utc'),
createdBy: attr('string'), createdBy: attr('string'),

View File

@ -73,6 +73,7 @@ export default Model.extend(Comparable, ValidationEngine, {
ghostPaths: service(), ghostPaths: service(),
clock: service(), clock: service(),
settings: service(), settings: service(),
membersUtils: service(),
displayName: 'post', displayName: 'post',
validationType: 'post', validationType: 'post',
@ -182,20 +183,44 @@ export default Model.extend(Comparable, ValidationEngine, {
return this.isScheduled && !!this.newsletter && !this.email; return this.isScheduled && !!this.newsletter && !this.email;
}), }),
hasAnalytics: computed('isPost', 'isSent', 'isPublished', 'email', function () { showEmailOpenAnalytics: computed('isPost', 'isSent', 'isPublished', 'email', function () {
return this.isPost return this.isPost
&& !this.session.user.isContributor && !this.session.user.isContributor
&& this.settings.get('membersSignupAccess') !== 'none' && this.settings.get('membersSignupAccess') !== 'none'
&& this.settings.get('editorDefaultEmailRecipients') !== 'disabled'
&& (this.isSent || this.isPublished)
&& this.email
&& this.email.trackOpens
&& this.settings.get('emailTrackOpens');
}),
showEmailClickAnalytics: computed('isPost', 'isSent', 'isPublished', 'email', function () {
return this.isPost
&& !this.session.user.isContributor
&& this.settings.get('membersSignupAccess') !== 'none'
&& this.settings.get('editorDefaultEmailRecipients') !== 'disabled'
&& (this.isSent || this.isPublished)
&& this.email
&& this.email.trackClicks
&& this.settings.get('emailTrackClicks');
}),
showAttributionAnalytics: computed('isPage', 'emailOnly', 'isPublished', 'membersUtils.isMembersInviteOnly', function () {
return (this.isPage || !this.emailOnly)
&& this.isPublished
&& this.feature.get('memberAttribution')
&& !this.membersUtils.isMembersInviteOnly
&& !this.session.user.isContributor;
}),
showPaidAttributionAnalytics: computed.and('showAttributionAnalytics', 'membersUtils.paidMembersEnabled'),
hasAnalyticsPage: computed('isPost', 'showEmailOpenAnalytics', 'showEmailClickAnalytics', 'showAttributionAnalytics', function () {
return this.isPost
&& ( && (
( this.showEmailOpenAnalytics
// We have clicks or opens data || this.showEmailClickAnalytics
(this.isSent || (this.isPublished && this.email)) || this.showAttributionAnalytics
&& (this.settings.get('emailTrackClicks') || this.settings.get('emailTrackOpens'))
)
|| (
// We have attribution data for pubished posts
this.isPublished && this.feature.get('memberAttribution')
)
); );
}), }),

View File

@ -0,0 +1,7 @@
const {createAddColumnMigration} = require('../../utils');
module.exports = createAddColumnMigration('emails', 'track_clicks', {
type: 'bool',
nullable: false,
defaultTo: false
});

View File

@ -723,6 +723,7 @@ module.exports = {
html: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true}, html: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
plaintext: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true}, plaintext: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
track_opens: {type: 'bool', nullable: false, defaultTo: false}, track_opens: {type: 'bool', nullable: false, defaultTo: false},
track_clicks: {type: 'bool', nullable: false, defaultTo: false},
submitted_at: {type: 'dateTime', nullable: false}, submitted_at: {type: 'dateTime', nullable: false},
newsletter_id: {type: 'string', maxlength: 24, nullable: true, references: 'newsletters.id'}, newsletter_id: {type: 'string', maxlength: 24, nullable: true, references: 'newsletters.id'},
created_at: {type: 'dateTime', nullable: false}, created_at: {type: 'dateTime', nullable: false},

View File

@ -10,6 +10,7 @@ const Email = ghostBookshelf.Model.extend({
status: 'pending', status: 'pending',
recipient_filter: 'status:-free', recipient_filter: 'status:-free',
track_opens: false, track_opens: false,
track_clicks: false,
delivered_count: 0, delivered_count: 0,
opened_count: 0, opened_count: 0,
failed_count: 0 failed_count: 0

View File

@ -239,6 +239,7 @@ const addEmail = async (postModel, options) => {
plaintext: emailData.plaintext, plaintext: emailData.plaintext,
submitted_at: moment().toDate(), submitted_at: moment().toDate(),
track_opens: !!settingsCache.get('email_track_opens'), track_opens: !!settingsCache.get('email_track_opens'),
track_clicks: !!settingsCache.get('email_track_clicks'),
recipient_filter: emailRecipientFilter, recipient_filter: emailRecipientFilter,
newsletter_id: newsletter.id newsletter_id: newsletter.id
}, knexOptions); }, knexOptions);

View File

@ -22,6 +22,7 @@ Object {
"status": "submitted", "status": "submitted",
"subject": "You got mailed!", "subject": "You got mailed!",
"submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"track_clicks": false,
"track_opens": false, "track_opens": false,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
@ -45,6 +46,7 @@ Object {
"status": "failed", "status": "failed",
"subject": "You got mailed! Again!", "subject": "You got mailed! Again!",
"submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"track_clicks": false,
"track_opens": false, "track_opens": false,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
@ -67,7 +69,7 @@ exports[`Emails API Can browse emails 2: [headers] 1`] = `
Object { Object {
"access-control-allow-origin": "http://127.0.0.1:2369", "access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "1243", "content-length": "1285",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding", "vary": "Accept-Version, Origin, Accept-Encoding",
@ -97,6 +99,7 @@ Object {
"status": "submitted", "status": "submitted",
"subject": "You got mailed!", "subject": "You got mailed!",
"submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"track_clicks": false,
"track_opens": false, "track_opens": false,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
@ -109,7 +112,7 @@ exports[`Emails API Can read an email 2: [headers] 1`] = `
Object { Object {
"access-control-allow-origin": "http://127.0.0.1:2369", "access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "561", "content-length": "582",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding", "vary": "Accept-Version, Origin, Accept-Encoding",
@ -139,6 +142,7 @@ Object {
"status": "pending", "status": "pending",
"subject": "You got mailed! Again!", "subject": "You got mailed! Again!",
"submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "submitted_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"track_clicks": false,
"track_opens": false, "track_opens": false,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
@ -151,7 +155,7 @@ exports[`Emails API Can retry a failed email 2: [headers] 1`] = `
Object { Object {
"access-control-allow-origin": "http://127.0.0.1:2369", "access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "607", "content-length": "628",
"content-type": "application/json; charset=utf-8", "content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding", "vary": "Accept-Version, Origin, Accept-Encoding",

View File

@ -35,7 +35,7 @@ const validateRouteSettings = require('../../../../../core/server/services/route
*/ */
describe('DB version integrity', function () { describe('DB version integrity', function () {
// Only these variables should need updating // Only these variables should need updating
const currentSchemaHash = '999d625400e6d87efe0fd66e6bda4059'; const currentSchemaHash = '2a59debcacc1e3dc0b15e2f729ca4bdb';
const currentFixturesHash = '8cf221f0ed930ac1fe8030a58e60d64b'; const currentFixturesHash = '8cf221f0ed930ac1fe8030a58e60d64b';
const currentSettingsHash = '2978a5684a2d5fcf089f61f5d368a0c0'; const currentSettingsHash = '2978a5684a2d5fcf089f61f5d368a0c0';
const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01'; const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01';