0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Added email feedback column (#15698)

closes TryGhost/Team#2159
- Added column to email table
- Hide the feedback tab on frontend depending on the column value

Co-authored-by: Daniel Lockyer <daniellockyer@fastmail.com>
This commit is contained in:
Elena Baidakova 2022-10-27 11:22:50 +04:00 committed by GitHub
parent 077ff89960
commit e3ab868b83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 41 additions and 23 deletions

View file

@ -85,23 +85,23 @@
/>
</tabs.tabPanel>
{{/if}}
{{/if}}
{{#if this.post.showAudienceFeedback }}
<tabs.tab>
<h3>{{svg-jar "analytics-tab-feedback-large"}}{{format-number this.post.count.positive_feedback}}</h3>
<p>{{svg-jar "analytics-tab-feedback"}}<span class="analytics-tab-label">Feedback<span class="analytics-tab-percentage">&nbsp;— {{this.post.sentiment}}%</span></span></p>
</tabs.tab>
{{#if this.post.isFeedbackEnabledForEmail }}
<tabs.tab>
<h3>{{svg-jar "analytics-tab-feedback-large"}}{{format-number this.post.count.positive_feedback}}</h3>
<p>{{svg-jar "analytics-tab-feedback"}}<span class="analytics-tab-label">Feedback<span class="analytics-tab-percentage">&nbsp;— {{this.post.sentiment}}%</span></span></p>
</tabs.tab>
<tabs.tabPanel>
<Posts::PostActivityFeed
@postId={{this.post.id}}
@eventType="feedback"
@data={{array this.post.count.positive_feedback this.post.count.negative_feedback}}
@positiveLink={{hash filterParam=(concat "(feedback.post_id:" this.post.id "+feedback.score:1)")}}
@negativeLink={{hash filterParam=(concat "(feedback.post_id:" this.post.id "+feedback.score:0)")}}
/>
</tabs.tabPanel>
<tabs.tabPanel>
<Posts::PostActivityFeed
@postId={{this.post.id}}
@eventType="feedback"
@data={{array this.post.count.positive_feedback this.post.count.negative_feedback}}
@positiveLink={{hash filterParam=(concat "(feedback.post_id:" this.post.id "+feedback.score:1)")}}
@negativeLink={{hash filterParam=(concat "(feedback.post_id:" this.post.id "+feedback.score:0)")}}
/>
</tabs.tabPanel>
{{/if}}
{{/if}}
{{#if this.post.showAttributionAnalytics }}

View file

@ -21,6 +21,8 @@ export default Model.extend({
trackOpens: attr('boolean'),
trackClicks: attr('boolean'),
feedbackEnabled: attr('boolean'),
createdAtUTC: attr('moment-utc'),
createdBy: attr('string'),
updatedAtUTC: attr('moment-utc'),

View file

@ -251,6 +251,8 @@ export default Model.extend(Comparable, ValidationEngine, {
return this.get('ghostPaths.url').join(blogUrl, previewKeyword, uuid);
}),
isFeedbackEnabledForEmail: computed.reads('email.feedbackEnabled'),
isPublic: computed('visibility', function () {
return this.visibility === 'public' ? true : false;
}),

View file

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

View file

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

View file

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

View file

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

View file

@ -81,7 +81,7 @@ exports[`Activity Feed API Can filter events by post id 2: [headers] 1`] = `
Object {
"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",
"content-length": "23031",
"content-length": "23206",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -401,7 +401,7 @@ exports[`Activity Feed API Returns email delivered events in activity feed 2: [h
Object {
"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",
"content-length": "1246",
"content-length": "1271",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -434,7 +434,7 @@ exports[`Activity Feed API Returns email opened events in activity feed 2: [head
Object {
"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",
"content-length": "1243",
"content-length": "1268",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -483,7 +483,7 @@ exports[`Activity Feed API Returns email sent events in activity feed 2: [header
Object {
"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",
"content-length": "5774",
"content-length": "5899",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",

View file

@ -10,6 +10,7 @@ Object {
"error": null,
"error_data": null,
"failed_count": 0,
"feedback_enabled": false,
"from": null,
"html": "<p>Look! I'm an email</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
@ -34,6 +35,7 @@ Object {
"error": "Everything went south",
"error_data": null,
"failed_count": 0,
"feedback_enabled": false,
"from": null,
"html": "<p>What's that? Another email!</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
@ -69,7 +71,7 @@ exports[`Emails API Can browse emails 2: [headers] 1`] = `
Object {
"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",
"content-length": "1285",
"content-length": "1335",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -87,6 +89,7 @@ Object {
"error": null,
"error_data": null,
"failed_count": 0,
"feedback_enabled": false,
"from": null,
"html": "<p>Look! I'm an email</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
@ -112,7 +115,7 @@ exports[`Emails API Can read an email 2: [headers] 1`] = `
Object {
"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",
"content-length": "582",
"content-length": "607",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -130,6 +133,7 @@ Object {
"error": "Everything went south",
"error_data": null,
"failed_count": 0,
"feedback_enabled": false,
"from": null,
"html": "<p>What's that? Another email!</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
@ -155,7 +159,7 @@ exports[`Emails API Can retry a failed email 2: [headers] 1`] = `
Object {
"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",
"content-length": "628",
"content-length": "653",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",

View file

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