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

Added newsletter customisation options (#1756)

no-issue

This adds three initial customisation options for newsletters:
  1. Show/Hide site title and logo
  2. Set font to serif/sans serif
  3. Display a publish with Ghost badge

This is the first step in allowing customisation of the look and feel of newsletters.

Co-authored-by: Rish <zrishabhgarg@gmail.com>
Co-authored-by: Peter Zimon <zimo@ghost.org>
This commit is contained in:
Peter Zimon 2020-11-12 15:45:22 +01:00 committed by GitHub
parent f68738ee62
commit 94581a87f8
10 changed files with 624 additions and 3 deletions

View file

@ -282,7 +282,17 @@
<div class="gh-setting-header">Email</div>
<section class="flex flex-column br3 shadow-1 bg-grouped-table mt1 pa5">
<div class="gh-setting-first">
<div class="gh-setting-first relative">
<div class="gh-setting-content">
<h4 class="gh-setting-title">Email design</h4>
<p class="gh-setting-desc pa0 ma0">Customize the look and feel of email newsletters</p>
</div>
<div class="gh-setting-action">
<button type="button" class="gh-btn" {{action (toggle "showEmailDesignSettings" this)}} data-test-toggle-membersFrom><span> Customize </span></button>
</div>
</div>
<div class="gh-setting">
<div class="gh-setting-content">
<h4 class="gh-setting-title">Email addresses</h4>
<p class="gh-setting-desc pa0 ma0">Contact information used for newsletters and member login emails</p>
@ -461,9 +471,19 @@
@close={{action "closePortalSettings"}}
@modifier="full-overlay portal-settings" />
{{/if}}
{{#if this.showLeaveSettingsModal}}
<GhFullscreenModal @modal="leave-settings"
@confirm={{action "leavePortalSettings"}}
@close={{action "closeLeaveSettingsModal"}}
@modifier="action wide" />
{{/if}}
{{#if this.showEmailDesignSettings}}
<GhFullscreenModal @modal="email-design-settings"
@model={{hash
openStripeSettings=(action "openStripeSettings")
}}
@close={{action "closeEmailDesignSettings"}}
@modifier="full-overlay portal-settings" />
{{/if}}

View file

@ -52,6 +52,7 @@ export default Component.extend({
showFromAddressConfirmation: false,
showSupportAddressConfirmation: false,
showPortalSettings: false,
showEmailDesignSettings: false,
stripePlanInvalidAmount: false,
_scratchStripeYearlyAmount: null,
_scratchStripeMonthlyAmount: null,
@ -164,6 +165,10 @@ export default Component.extend({
}
},
closeEmailDesignSettings() {
this.set('showEmailDesignSettings', false);
},
setDefaultContentVisibility(value) {
this.setDefaultContentVisibility(value);
},

View file

@ -0,0 +1,142 @@
<div class="modal-body modal-fullsettings">
<div class="modal-fullsettings-body">
<div class="modal-fullsettings-sidebar with-footer">
<div>
<h2 class="modal-fullsettings-topbar modal-fullsettings-heading">Email newsletter design</h2>
<fieldset class="modal-fullsettings-form">
<div class="modal-fullsettings-section first">
<GhFormGroup>
<h4 class="modal-fullsettings-title">Show publication icon and title</h4>
<div class="for-switch small">
<label
class="switch"
for="show-header"
>
<input
type="checkbox"
checked={{this.settings.newsletterShowHeader}}
id="show-header"
name="show-header"
onclick={{action "toggleShowHeader" value="target.checked"}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</GhFormGroup>
</div>
<div class="modal-fullsettings-section">
<GhFormGroup @classNames="vertical">
<h4 class="modal-fullsettings-title">Typography</h4>
<div class="modal-fullsettings-radiogroup">
<div class="gh-radio {{if (eq this.settings.newsletterBodyFontCategory "serif") "active"}}"
{{action "setTypography" "serif" on="click"}}
>
<div class="gh-radio-button"></div>
<div class="gh-radio-content">
<div class="gh-radio-label">Serif</div>
</div>
</div>
<div class="gh-radio {{if (eq this.settings.newsletterBodyFontCategory "sans_serif") "active"}}"
{{action "setTypography" "sans_serif" on="click"}}
>
<div class="gh-radio-button"></div>
<div class="gh-radio-content">
<div class="gh-radio-label">Sans-serif</div>
</div>
</div>
</div>
<p>Font style for the email body contents</p>
</GhFormGroup>
</div>
</fieldset>
</div>
<div class="modal-fullsettings-section gh-members-emailsettings-footer">
<GhFormGroup>
<div class="gh-members-emailsettings-promotelabel">
<span>{{svg-jar "heart"}}</span>
<div>
<h4 class="modal-fullsettings-title">Promote independent publishing</h4>
<p>Show youre a part of the indie publishing movement with a small badge in the footer</p>
</div>
</div>
<div class="for-switch small">
<label
class="switch"
for="promote-ghost"
>
<input
type="checkbox"
checked={{this.settings.newsletterShowBadge}}
id="promote-ghost"
name="promote-ghost"
onclick={{action "toggleBadge" value="target.checked"}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</GhFormGroup>
</div>
</div>
<div class="modal-fullsettings-main">
<div class="flex items-center justify-end w-100 modal-fullsettings-topbar">
<div class="flex items-center">
<button
class="gh-btn mr3"
{{action "closeModal"}}
{{!-- disable mouseDown so it doesn't trigger focus-out validations --}}
{{on "mousedown" (optional this.noop)}}
data-test-button="cancel-custom-view-form"
>
<span>Cancel</span>
</button>
<GhTaskButton
@buttonText="Save and close"
@successText="Saved"
@task={{this.saveTask}}
@idleClass="gh-btn-blue"
@class="gh-btn gh-btn-icon"
data-test-button="save-members-modal-setting"
/>
</div>
</div>
<div class="modal-fullsettings-preview-container">
<div class="gh-members-emailpreview-container">
<div class="gh-members-emailpreview-faux">
<p>
<span class="strong">Ghost Site</span> &lt;newsletters@ghostsite.com&gt;
</p>
<p><span class="dark">To:</span> Jamie Larson &lt;jamie@example.com&gt;</p>
</div>
<div class="gh-members-emailpreview-header {{if (not this.settings.newsletterShowHeader) "hide"}}">
<img src="https://static.ghost.org/v3.0.0/images/ghost-squircle.png" />
<h4>Ghost site</h4>
</div>
<div class="gh-members-emailpreview-title">
<h2>Email newsletter</h2>
<p>
<span>By Jamie Larson  Nov 5 2020  </span> <a href="javascript:">View online →</a>
</p>
</div>
<div class="gh-members-emailpreview-content {{if (eq this.settings.newsletterBodyFontCategory "sans_serif") "sans-serif"}}">
<p>This is where the contents of your newsletter go. Customise the appearance with the options in the sidebar.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras at auctor tellus, in accumsan magna. Sed vel magna velit. Vivamus commodo laoreet malesuada. Nullam efficitur augue et eros fermentum.</p>
</div>
<div class="gh-members-emailpreview-footer">
<div class="gh-members-emailpreview-footercontent">
{{this.footerText}}
</div>
<div class="gh-members-emailpreview-footersite">
<span>Ghost Site &copy; </span> <a href="javascript:">Unsubscribe</a>
</div>
</div>
<div class="gh-members-emailpreview-badge {{if (not this.settings.newsletterShowBadge) "hide"}}">
<a href="https://ghost.org" target="_blank" rel="noopener noreferrer"><svg viewBox="0 0 156 156"><g fill="none" fill-rule="evenodd"><rect fill="#15212B" width="156" height="156" rx="27"></rect><g transform="translate(36 36)" fill="#F6F8FA"><path d="M0 71.007A4.004 4.004 0 014 67h26a4 4 0 014 4.007v8.986A4.004 4.004 0 0130 84H4a4 4 0 01-4-4.007v-8.986zM50 71.007A4.004 4.004 0 0154 67h26a4 4 0 014 4.007v8.986A4.004 4.004 0 0180 84H54a4 4 0 01-4-4.007v-8.986z"></path><rect y="34" width="84" height="17" rx="4"></rect><path d="M0 4.007A4.007 4.007 0 014.007 0h41.986A4.003 4.003 0 0150 4.007v8.986A4.007 4.007 0 0145.993 17H4.007A4.003 4.003 0 010 12.993V4.007z"></path><rect x="67" width="17" height="17" rx="4"></rect></g></g></svg> <span>Publish with Ghost</span></a>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,47 @@
import ModalComponent from 'ghost-admin/components/modal-base';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
export default ModalComponent.extend({
settings: service(),
showHeader: true,
showSansSerif: false,
showBadge: true,
footerText: '',
init() {
this._super(...arguments);
},
actions: {
toggleShowHeader(showHeader) {
this.settings.set('newsletterShowHeader', showHeader);
},
setTypography(typography) {
if (typography === 'serif') {
this.settings.set('newsletterBodyFontCategory', 'serif');
} else {
this.settings.set('newsletterBodyFontCategory', 'sans_serif');
}
},
toggleBadge(showBadge) {
this.settings.set('newsletterShowBadge', showBadge);
},
confirm() {
return this.saveTask.perform();
},
leaveSettings() {
this.closeModal();
}
},
saveTask: task(function* () {
yield this.settings.save();
this.closeModal();
}).drop()
});

View file

@ -66,5 +66,11 @@ export default Model.extend(ValidationEngine, {
stripeConnectSecretKey: attr('string'),
stripeConnectLivemode: attr('boolean'),
stripeConnectDisplayName: attr('string'),
stripeConnectAccountId: attr('string')
stripeConnectAccountId: attr('string'),
/**
* Newsletter settings
*/
newsletterShowHeader: attr('boolean'),
newsletterBodyFontCategory: attr('string'),
newsletterShowBadge: attr('boolean')
});

View file

@ -27,7 +27,7 @@ export default Service.extend(_ProxyMixin, ValidationEngine, {
_loadSettings() {
if (!this._loadingPromise) {
this._loadingPromise = this.store
.queryRecord('setting', {group: 'site,theme,private,members,portal,email,amp,labs,slack,unsplash,views'})
.queryRecord('setting', {group: 'site,theme,private,members,portal,newsletter,email,amp,labs,slack,unsplash,views'})
.then((settings) => {
this._loadingPromise = null;
return settings;

View file

@ -165,6 +165,161 @@
}
/* Full screen setting modal with preview. Used in e.g. Portal
/* settings, Email design settings etc.
/* ---------------------------------------------------------- */
.modal-fullsettings {
height: 100%;
display: flex;
flex-direction: column;
}
.modal-fullsettings-body {
display: flex;
padding: 0;
flex-grow: 1;
}
.modal-fullsettings-body .form-group.space-l {
margin-bottom: 1.9em;
}
.modal-fullsettings-body .for-switch.small {
width: 36px !important;
height: 22px !important;
}
.modal-fullsettings-body .gh-select svg {
top: 19px;
right: 9px;
}
.modal-fullsettings-body .modal-footer {
margin-top: 28px;
}
.modal-fullsettings-sidebar {
display: flex;
flex-direction: column;
padding: 0px 24px 20px;
width: 342px;
}
.modal-fullsettings-sidebar.with-footer {
justify-content: space-between;
}
.modal-fullsettings-topbar {
height: 66px;
}
.modal-fullsettings-heading {
display: flex;
align-items: center;
font-size: 1.9rem;
font-weight: 600;
padding: 0 24px;
margin: 0 -24px 1px;
border-bottom: 1px solid var(--whitegrey);
}
.modal-fullsettings-form {
min-width: 292px;
}
.modal-fullsettings-section {
margin: 24px -24px;
padding: 0 24px;
}
.modal-fullsettings-section.first {
margin-top: 20px;
}
.modal-fullsettings-section.divider-top {
border-top: 1px solid var(--whitegrey);
padding-top: 16px;
}
.modal-fullsettings-sectionheading {
font-size: 1.2rem;
font-weight: 500;
color: var(--midlightgrey);
margin: 0 0 12px;
text-transform: uppercase;
letter-spacing: 0.2px;
}
.modal-fullsettings-section .form-group {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0;
margin-bottom: 0;
}
.modal-fullsettings-section .form-group p {
font-size: 1.25rem !important;
line-height: 1.4em;
}
.modal-fullsettings-section .form-group.vertical {
display: block;
}
.modal-fullsettings-section .form-group.vertical h4 {
margin-bottom: 8px;
}
.modal-fullsettings-section .form-group.vertical p {
margin-top: 8px;
}
.modal-fullsettings-section .gh-select select,
.modal-fullsettings-section textarea {
font-size: 1.4rem;
}
.modal-fullsettings-radiogroup {
margin: 18px 0 0;
}
.modal-fullsettings-radiogroup .gh-radio {
margin-bottom: 14px;
}
.modal-fullsettings-radiogroup .gh-radio:last-of-type {
margin-bottom: 12px;
}
.modal-fullsettings-radiogroup + p {
margin-top: 4px !important;
margin-bottom: 28px;
}
.modal-fullsettings-title {
font-size: 1.3rem;
font-weight: 600;
margin: 0 12px 0 0;
}
.modal-fullsettings-main {
display: flex;
flex-direction: column;
flex-grow: 1;
padding: 0 20px 20px;
border-left: 1px solid var(--whitegrey);
}
.modal-fullsettings-preview-container {
border: 1px solid var(--whitegrey);
border-radius: 5px;
overflow: hidden;
background: var(--whitegrey-l1);
height: calc(100vh - 150px);
overflow-y: scroll;
}
/* Content Modifiers
/* ---------------------------------------------------------- */

View file

@ -792,3 +792,247 @@ p.gh-members-import-errordetail:first-of-type {
padding: 4px;
}
}
/* Email newsletter design settings
/* -------------------------------------------------------- */
.gh-members-emailsettings-footer {
border-top: 1px solid var(--whitegrey);
padding-top: 20px;
margin-bottom: 4px;
}
.gh-members-emailsettings-footer .form-group {
align-items: flex-start;
}
.gh-members-emailsettings-promotelabel {
display: flex;
align-items: flex-start;
}
.gh-members-emailsettings-promotelabel svg {
width: 20px;
margin-right: 8px;
}
.gh-members-emailsettings-promotelabel svg path {
stroke: var(--red);
}
.gh-members-emailsettings-footer .for-switch {
margin-top: -2px;
}
.gh-members-emailpreview-container {
width: 100%;
max-width: 520px;
background: var(--white);
border-radius: 12px;
padding: 32px;
margin: 32px auto;
box-shadow:
0 0 0 1px rgba(0,0,0,0.02),
0 2.8px 2.2px rgba(0, 0, 0, 0.02),
0 6.7px 5.3px rgba(0, 0, 0, 0.028),
0 12.5px 10px rgba(0, 0, 0, 0.035),
0 22.3px 17.9px rgba(0, 0, 0, 0.042),
0 41.8px 33.4px rgba(0, 0, 0, 0.05),
0 100px 80px rgba(0, 0, 0, 0.07);
;
color: var(--blackgrey);
transform: scale(0.8);
transform-origin: top;
}
.gh-members-emailpreview-container a {
color: var(--midgrey);
text-decoration: underline;
}
.gh-members-emailpreview-faux {
margin: -32px -32px 16px;
padding: 16px 24px;
border-bottom: 1px solid var(--lightgrey-d1);
}
.gh-members-emailpreview-faux p {
margin: 0;
padding: 0;
color: var(--midlightgrey);
}
.gh-members-emailpreview-faux .strong {
font-size: 1.5rem;
font-weight: 500;
color: var(--darkgrey);
}
.gh-members-emailpreview-faux .dark {
color: var(--darkgrey);
}
.gh-members-emailpreview-header {
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 0;
border-bottom: 1px solid var(--whitegrey);
}
.gh-members-emailpreview-header.hide {
display: none;
}
.gh-members-emailpreview-header img {
width: 48px;
height: 48px;
}
.gh-members-emailpreview-header h4 {
text-align: center;
font-size: 1.6rem;
letter-spacing: -0.1px;
font-weight: 700;
text-transform: uppercase;
margin: 10px 0;
color: var(--blackgrey);
}
.gh-members-emailpreview-title {
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 0;
}
.gh-members-emailpreview-title h2 {
font-size: 4.2rem;
line-height: 1.1em;
font-weight: 600;
text-align: center;
margin: 0;
padding: 0 0 10px;
color: var(--blackgrey);
}
.gh-members-emailpreview-title p {
margin: 0;
padding: 0 0 10px;
white-space: nowrap;
font-size: 1.3rem;
line-height: 1;
letter-spacing: 0.2px;
text-transform: uppercase;
text-align: center;
color: var(--blackgrey);
}
.gh-members-emailpreview-title p span {
color: var(--midgrey);
}
.gh-members-emailpreview-title a {
text-decoration: none;
color: var(--blackgrey);
}
.gh-members-emailpreview-content {
padding-bottom: 20px;
border-bottom: 1px solid var(--whitegrey);
}
.gh-members-emailpreview-content p {
font-family: Georgia, serif;
font-size: 1.8rem;
line-height: 1.5em;
color: var(--darkgrey-l1);
max-width: 560px;
}
.gh-members-emailpreview-content.sans-serif p {
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;
font-size: 1.75rem;
line-height: 1.5em;
}
.gh-members-emailpreview-footer {
padding: 40px 0 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.gh-members-emailpreview-footercontent {
margin: 0 0 10px;
max-width: 380px;
font-size: 1.15rem;
text-align: center;
line-height: 1.4em;
color: var(--midgrey-l1);
}
.gh-members-emailpreview-footercontent p {
font-size: 1.15rem;
text-align: center;
line-height: 1.4em;
color: var(--midgrey-l1);
margin: 0;
padding: 0;
}
.gh-members-emailpreview-footercontent strong {
font-weight: 600;
}
.gh-members-emailpreview-footersite {
font-size: 1.15rem;
text-align: center;
color: var(--blackgrey);
}
.gh-members-emailpreview-footersite span {
color: var(--midgrey-l1);
}
.gh-members-emailpreview-badge {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 0 25px;
}
.gh-members-emailpreview-badge.hide {
display: none;
}
.gh-members-emailpreview-badge a {
display: inline-flex;
align-items: center;
padding: 6px 9px 6px 6px;
border: none;
font-size: 12px;
line-height: 12px;
letter-spacing: -.3px;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
font-weight: 600;
text-decoration: none;
color: #383838;
background: #fff;
border-radius: 5px;
box-shadow: 0 0 0 1px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.08);
cursor: pointer;
outline: none;
background: var(--white);
}
.gh-members-emailpreview-badge svg {
height: 16px;
width: 16px;
margin: 0 6px 0 0;
}
@media (min-height: 1070px) {
.gh-members-emailpreview-container {
transform: scale(0.9);
}
}

View file

@ -35,6 +35,7 @@
--black-80: rgba(40, 48, 52, 0.8);
--black-90: rgba(40, 48, 52, 0.9);
--blackgrey: #15212A;
--darkgrey: #343f44;
--middarkgrey: #54666D;
--midgrey: #738a94;

View file

@ -0,0 +1 @@
<svg width="26" height="24" viewBox="0 0 26 24" xmlns="http://www.w3.org/2000/svg"><title>heart</title><g stroke="#000" fill="none" fill-rule="evenodd"><path d="M23.651 5.357c-.878-1.717-2.269-2.728-4.173-3.034-1.904-.305-3.541.22-4.912 1.577L13 5.329 11.434 3.9c-1.371-1.356-3.009-1.881-4.913-1.575-1.904.306-3.295 1.317-4.172 3.035-1.222 2.42-.867 4.582 1.063 6.486L13 21.75l9.588-9.907c1.93-1.904 2.285-4.066 1.063-6.486z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/></g></svg>

After

Width:  |  Height:  |  Size: 503 B