0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-03 23:00:14 -05:00

Added additional newsletter customisation settings (#13074)

refs https://github.com/TryGhost/Team/issues/793

New settings added for newsletter customisation options:

- `newsletter_header_image` - `null/"$url"`
- `newsletter_show_header_icon` - `"true/false"`
- `newsletter_show_header_title` - `"true/false"`
- `newsletter_title_alignment` - `"center/left"`
- `newsletter_title_font_category` - `"serif/sans_serif"`
- `newsletter_show_feature_image` - `"true/false"`

`newsletter_show_header` has been dropped because the same functionality can be achieved by setting both `newsletter_show_header_icon` and `newsletter_show_header_title` to `false`

---

- migration to convert and delete `newsletter_show_header` setting
- removed `newsletter_show_header` from default settings to ensure it doesn't get re-created
- replaced main labs template and template settings generation with the labs template
- deleted labs template
This commit is contained in:
Kevin Ansfield 2021-06-21 13:40:40 +01:00 committed by GitHub
parent acb0bd47af
commit 446993a905
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 178 additions and 1057 deletions

View file

@ -0,0 +1,123 @@
const logging = require('@tryghost/logging');
const {createTransactionalMigration} = require('../../utils');
const ObjectId = require('bson-objectid');
// newsletter_show_header = false ->
// newsletter_show_header_title = false
// newsletter_show_header_icon = false
//
// the default for both of the new settings is true so there's no need to migrate
// anything if previously showing the header
module.exports = createTransactionalMigration(
async function up(connection) {
const oldSetting = await connection('settings')
.where('key', 'newsletter_show_header')
.select(['value', 'created_by'])
.first();
if (!oldSetting) {
logging.info('Skipping migration of newsletter_show_header setting. Does not exist');
return;
}
if (oldSetting.value === 'false') {
logging.info('Migrating newsletter_show_header setting. Disabling title and logo');
const newSettingKeys = ['newsletter_show_header_title', 'newsletter_show_header_icon'];
const now = connection.raw('CURRENT_TIMESTAMP');
for (const settingKey of newSettingKeys) {
const existingSetting = await connection('settings').where('key', settingKey).first();
if (!existingSetting) {
// insert default setting - migrations are run before default settings are created
await connection('settings')
.insert({
id: ObjectId().toHexString(),
key: settingKey,
group: 'newsletter',
type: 'boolean',
value: 'true',
created_at: now,
updated_at: now,
created_by: oldSetting.created_by,
updated_by: oldSetting.created_by
});
}
}
await connection('settings')
.whereIn('key', ['newsletter_show_header_title', 'newsletter_show_header_icon'])
.update({value: 'false'});
} else {
logging.info('Skipping migration of newsletter_show_header setting. Matches new defaults');
}
logging.info('Deleting newsletter_show_header setting');
await connection('settings')
.where('key', 'newsletter_show_header')
.del();
},
async function down(connection) {
logging.info('Adding newsletter_show_header setting');
const oldSetting = await connection('settings')
.where('key', '=', 'newsletter_show_header')
.select('value')
.first();
const showTitle = await connection('settings')
.where('key', '=', 'newsletter_show_header_title')
.select(['value', 'created_by'])
.first();
const showIcon = await connection('settings')
.where('key', '=', 'newsletter_show_header_icon')
.select(['value', 'created_by'])
.first();
if (oldSetting) {
logging.warn('Skipping rollback of newsletter_show_header setting. Already exists');
} else {
const [{id: ownerId} = {id: 1}] = await connection('users')
.select('users.id')
.innerJoin(
'roles_users',
'users.id',
'roles_users.user_id'
)
.where(
'roles_users.role_id',
connection('roles').select('id').where('name', 'Owner')
);
let showHeader = 'true'; // default
if (showTitle && showIcon) {
showHeader = showTitle.value === 'false' && showIcon.value === 'false' ? 'false' : 'true';
}
const now = connection.raw('CURRENT_TIMESTAMP');
await connection('settings')
.insert({
id: ObjectId().toHexString(),
key: 'newsletter_show_header',
group: 'newsletter',
type: 'boolean',
value: showHeader,
created_at: now,
updated_at: now,
created_by: ownerId,
updated_by: ownerId
});
}
logging.info('Deleting newsletter_show_header_{title,icon} settings');
await connection('settings')
.whereIn('key', ['newsletter_show_header_title', 'newsletter_show_header_icon'])
.del();
}
);

View file

@ -463,19 +463,6 @@
},
"type": "boolean"
},
"newsletter_show_header": {
"defaultValue": "true",
"validations": {
"isEmpty": false,
"isIn": [
[
"true",
"false"
]
]
},
"type": "boolean"
},
"newsletter_header_image": {
"defaultValue": null,
"validations": {

View file

@ -1,8 +1,6 @@
const _ = require('lodash');
const juice = require('juice');
const template = require('./template');
const labsTemplate = require('./template-labs');
const config = require('../../../shared/config');
const settingsCache = require('../../services/settings/cache');
const labs = require('../../services/labs');
const urlUtils = require('../../../shared/url-utils');
@ -125,16 +123,6 @@ const parseReplacements = (email) => {
};
const getTemplateSettings = async () => {
return {
showSiteHeader: settingsCache.get('newsletter_show_header'),
bodyFontCategory: settingsCache.get('newsletter_body_font_category'),
showBadge: settingsCache.get('newsletter_show_badge'),
footerContent: settingsCache.get('newsletter_footer_content'),
accentColor: settingsCache.get('accent_color')
};
};
const getLabsTemplateSettings = async () => {
const templateSettings = {
headerImage: settingsCache.get('newsletter_header_image'),
showHeaderIcon: settingsCache.get('newsletter_show_header_icon') && settingsCache.get('icon'),
@ -244,11 +232,9 @@ const serialize = async (postModel, options = {isBrowserPreview: false, apiVersi
}
}
const useLabsTemplate = config.get('enableDeveloperExperiments');
const templateSettings = await (useLabsTemplate ? getLabsTemplateSettings() : getTemplateSettings());
const templateRenderer = useLabsTemplate ? labsTemplate : template;
const templateSettings = await getTemplateSettings();
let htmlTemplate = templateRenderer({post, site: getSite(), templateSettings});
let htmlTemplate = template({post, site: getSite(), templateSettings});
if (options.isBrowserPreview) {
const previewUnsubscribeUrl = createUnsubscribeUrl(null);

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
const iff = (cond, yes, no) => (cond ? yes : no);
module.exports = ({post, site, templateSettings}) => {
const date = new Date();
const hasFeatureImageCaption = templateSettings.labsFeatureImageMeta && templateSettings.showFeatureImage && post.feature_image && post.feature_image_caption;
return `<!doctype html>
<html>
@ -267,6 +268,10 @@ figure blockquote p {
font-size: 1em;
}
.header-image {
padding-top: 16px;
}
.site-icon {
padding-bottom: 10px;
padding-top: 20px;
@ -302,6 +307,12 @@ figure blockquote p {
font-weight: 600;
text-align: center;
}
.post-title-serif {
font-family: Georgia, serif;
}
.post-title-left {
text-align: left;
}
.post-title-link {
color: #15212A;
@ -309,6 +320,9 @@ figure blockquote p {
text-align: center;
margin-top: 50px;
}
.post-title-link-left {
text-align: left;
}
.post-meta,
.view-online {
@ -320,6 +334,9 @@ figure blockquote p {
text-transform: uppercase;
text-align: center;
}
.post-meta-left {
text-align: left;
}
.view-online {
text-align: right;
@ -336,6 +353,18 @@ figure blockquote p {
width: 100%;
}
.feature-image-with-caption {
padding-bottom: 10px;
}
.feature-image-caption {
width: 100%;
padding-bottom: 30px;
text-align: center;
font-size: 13px;
color: #738a94;
}
.post-content {
max-width: 600px !important;
font-family: Georgia, serif;
@ -877,19 +906,27 @@ ${ templateSettings.showBadge ? `
<td class="wrapper">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
${ templateSettings.headerImage ? `
<tr>
<td class="header-image" width="100%" align="center"><img src="${templateSettings.headerImage}"${templateSettings.headerImageWidth ? ` width="${templateSettings.headerImageWidth}"` : ''}></td>
</tr>
` : ''}
${ templateSettings.showSiteHeader ? `
${ templateSettings.showHeaderIcon || templateSettings.showHeaderTitle ? `
<tr>
<td class="site-info" width="100%" align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
${ site.iconUrl ? `
${ templateSettings.showHeaderIcon && site.iconUrl ? `
<tr>
<td class="site-icon"><a href="${site.url}"><img src="${site.iconUrl}" border="0"></a></td>
</tr>
` : ``}
${ templateSettings.showHeaderTitle ? `
<tr>
<td class="site-url"><div style="width: 100% !important;"><a href="${site.url}">${site.title}</a></div></td>
</tr>
` : ``}
</table>
</td>
</tr>
@ -897,13 +934,15 @@ ${ templateSettings.showBadge ? `
<tr>
<td class="post-title"><a href="${post.url}" class="post-title-link">${post.title}</a></td>
<td class="post-title ${templateSettings.titleFontCategory === 'serif' ? `post-title-serif` : `` } ${templateSettings.titleAlignment === 'left' ? `post-title-left` : ``}">
<a href="${post.url}" class="post-title-link ${templateSettings.titleAlignment === 'left' ? `post-title-link-left` : ``}">${post.title}</a>
</td>
</tr>
<tr>
<td align="center">
<td>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="post-meta">
<td class="post-meta ${templateSettings.titleAlignment === 'left' ? `post-meta-left` : ``}">
By ${post.authors}
${post.published_at}
<a href="${post.url}" class="view-online-link">View online </a>
@ -912,9 +951,14 @@ ${ templateSettings.showBadge ? `
</table>
</td>
</tr>
${post.feature_image ? `
${ templateSettings.showFeatureImage && post.feature_image ? `
<tr>
<td class="feature-image"><img src="${post.feature_image}"${post.feature_image_width ? ` width="${post.feature_image_width}"` : ''}></td>
<td class="feature-image ${hasFeatureImageCaption ? 'feature-image-with-caption' : ''}"><img src="${post.feature_image}"${post.feature_image_width ? ` width="${post.feature_image_width}"` : ''} alt="${post.feature_image_alt}"></td>
</tr>
` : ``}
${ hasFeatureImageCaption ? `
<tr>
<td class="feature-image-caption" align="center">${post.feature_image_caption}</td>
</tr>
` : ``}
<tr>

View file

@ -350,11 +350,6 @@ const defaultSettingsKeyTypes = [
type: 'boolean',
group: 'newsletter'
},
{
key: 'newsletter_show_header',
type: 'boolean',
group: 'newsletter'
},
{
key: 'newsletter_header_image',
type: 'string',

View file

@ -72,7 +72,6 @@ const defaultSettingsKeyTypes = [
{key: 'active_timezone', type: 'blog'},
{key: 'default_locale', type: 'blog'},
{key: 'newsletter_show_badge', type: 'newsletter'},
{key: 'newsletter_show_header', type: 'newsletter'},
{key: 'newsletter_header_image', type: 'newsletter'},
{key: 'newsletter_show_header_icon', type: 'newsletter'},
{key: 'newsletter_show_header_title', type: 'newsletter'},

View file

@ -76,7 +76,6 @@ const defaultSettingsKeyTypes = [
{key: 'default_locale', type: 'blog'},
{key: 'accent_color', type: 'blog'},
{key: 'newsletter_show_badge', type: 'newsletter'},
{key: 'newsletter_show_header', type: 'newsletter'},
{key: 'newsletter_header_image', type: 'newsletter'},
{key: 'newsletter_show_header_icon', type: 'newsletter'},
{key: 'newsletter_show_header_title', type: 'newsletter'},

View file

@ -191,7 +191,7 @@ describe('Exporter', function () {
// NOTE: if default settings changed either modify the settings keys blocklist or increase allowedKeysLength
// This is a reminder to think about the importer/exporter scenarios ;)
const allowedKeysLength = 84;
const allowedKeysLength = 83;
totalKeysLength.should.eql(SETTING_KEYS_BLOCKLIST.length + allowedKeysLength);
});
});

View file

@ -34,7 +34,7 @@ describe('DB version integrity', function () {
// Only these variables should need updating
const currentSchemaHash = 'ef13a18aee78222086ca864c16bde696';
const currentFixturesHash = '8671672598d2a62e53418c4b91aa79a3';
const currentSettingsHash = '9986400eb68ccb55173b181c2be4f94a';
const currentSettingsHash = 'dd0a0a08e66b252e7704bb7e346a8c20';
const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01';
// If this test is failing, then it is likely a change has been made that requires a DB version bump,