Merge pull request #1515 from mailpoet/in-app-welcome-emails

In app announcement for free welcome emails [MALPOET-1525]
This commit is contained in:
Michelle Shull
2018-09-20 11:29:24 -04:00
committed by GitHub
7 changed files with 136 additions and 24 deletions

View File

@@ -26,3 +26,16 @@
100% 100%
-moz-box-shadow: 0 0 0 0 rgba(255, 83, 1, 0) -moz-box-shadow: 0 0 0 0 rgba(255, 83, 1, 0)
box-shadow: 0 0 0 0 rgba(255, 83, 1, 0) box-shadow: 0 0 0 0 rgba(255, 83, 1, 0)
.mailpoet_in_app_announcement_free_welcome_emails
text-align: center
h2
font-size: 28px
img
width: 640px
margin-top: -20px
.mailpoet_in_app_announcement_free_welcome_emails_dot
position: relative
top: -3px
left: 8px

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View File

@@ -1,25 +1,80 @@
import React from 'react'; import React from 'react';
import MailPoet from 'mailpoet';
import InAppAnnouncementDot from './in_app_announcement_dot.jsx'; import InAppAnnouncementDot from './in_app_announcement_dot.jsx';
const InAppAnnouncement = (props) => { class InAppAnnouncement extends React.Component {
if (props.newUser !== null && constructor(props) {
window.mailpoet_is_new_user !== props.newUser super(props);
) { this.saveDisplayed = this.saveDisplayed.bind(this);
return null;
this.state = {
announcementsSettings: window.mailpoet_in_app_announcements || null,
};
} }
if (props.validUntil < (new Date().getTime() / 1000)) { saveDisplayed() {
return null; const settings = Object.assign({}, this.state.announcementsSettings);
settings.displayed.push(this.props.showOnlyOnceSlug);
return MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'settings',
action: 'set',
data: { in_app_announcements: settings },
}).always(() => (this.setState({ announcementsSettings: settings })));
} }
return ( render() {
<InAppAnnouncementDot if (this.props.showToNewUser !== null &&
className={props.className} window.mailpoet_is_new_user !== this.props.showToNewUser
width={props.width} ) {
height={props.height} return null;
> }
{props.children}
</InAppAnnouncementDot>); if (this.props.validUntil !== null
&& this.props.validUntil < new Date()
) {
return null;
}
if (this.props.showToPremiumUser !== null &&
window.mailpoet_premium_active !== this.props.showToPremiumUser
) {
return null;
}
if (this.props.showOnlyOnceSlug &&
this.state.announcementsSettings.displayed.includes(this.props.showOnlyOnceSlug)
) {
return null;
}
return (
<InAppAnnouncementDot
className={this.props.className}
width={this.props.width}
height={this.props.height}
onUserTrigger={() => {
if (!this.props.showOnlyOnceSlug) { return; }
this.saveDisplayed();
}}
>
{this.props.children}
</InAppAnnouncementDot>
);
}
}
const validateBooleanWithWindowDependency = (props, propName, componentName, windowProperty) => {
const propValue = props[propName];
if (propValue !== null && propValue !== true && propValue !== false) {
return new Error(`Invalid property in ${componentName}. newUser must be of type boolean`);
}
if (propValue !== null && typeof window[windowProperty] === 'undefined') {
return new Error(
`Missing data for evaluation of ${componentName} display condition. ${propName} requires window.${windowProperty}`
);
}
return null;
}; };
InAppAnnouncement.propTypes = { InAppAnnouncement.propTypes = {
@@ -27,14 +82,27 @@ InAppAnnouncement.propTypes = {
height: React.PropTypes.string, height: React.PropTypes.string,
className: React.PropTypes.string, className: React.PropTypes.string,
children: React.PropTypes.element.isRequired, children: React.PropTypes.element.isRequired,
validUntil: React.PropTypes.number, validUntil: React.PropTypes.instanceOf(Date),
newUser: (props, propName, componentName) => { showToNewUser: (props, propName, componentName) => (
validateBooleanWithWindowDependency(props, propName, componentName, 'mailpoet_is_new_user')
),
showToPremiumUser: (props, propName, componentName) => (
validateBooleanWithWindowDependency(props, propName, componentName, 'mailpoet_premium_active')
),
showOnlyOnceSlug: (props, propName, componentName) => {
const propValue = props[propName]; const propValue = props[propName];
if (propValue !== null && propValue !== true && propValue !== false) { if (propValue !== null && typeof propValue !== 'string') {
return new Error(`Invalid property in ${componentName}. newUser must be of type boolean`); return new Error(`Invalid property in ${componentName}. ${propName} must be of type string`);
} }
if (typeof window.mailpoet_is_new_user === 'undefined') { if (propValue === null) {
return new Error(`Missing data for evaluation of ${componentName} display condition. ${propName} requires window.mailpoet_is_new_user`); return null;
}
if (
typeof window.mailpoet_in_app_announcements === 'undefined'
) {
return new Error(
`Missing data for evaluation of ${componentName} display condition. ${propName} requires window.mailpoet_in_app_announcements`
);
} }
return null; return null;
}, },
@@ -45,7 +113,9 @@ InAppAnnouncement.defaultProps = {
height: '600px', height: '600px',
className: null, className: null,
validUntil: null, validUntil: null,
newUser: null, showToNewUser: null,
showToPremiumUser: null,
showOnlyOnceSlug: null,
}; };
module.exports = InAppAnnouncement; module.exports = InAppAnnouncement;

View File

@@ -14,21 +14,24 @@ const InAppAnnouncementDot = props => (
width: props.width, width: props.width,
height: props.height, height: props.height,
}); });
if (props.onUserTrigger) props.onUserTrigger();
}} }}
/> />
); );
InAppAnnouncementDot.propTypes = { InAppAnnouncementDot.propTypes = {
children: React.PropTypes.element.isRequired,
width: React.PropTypes.string, width: React.PropTypes.string,
height: React.PropTypes.string, height: React.PropTypes.string,
className: React.PropTypes.string, className: React.PropTypes.string,
children: React.PropTypes.element.isRequired, onUserTrigger: React.PropTypes.func,
}; };
InAppAnnouncementDot.defaultProps = { InAppAnnouncementDot.defaultProps = {
width: 'auto', width: 'auto',
height: 'auto', height: 'auto',
className: null, className: null,
onUserTrigger: null,
}; };
module.exports = InAppAnnouncementDot; module.exports = InAppAnnouncementDot;

View File

@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router'; import { Link } from 'react-router';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import InAppAnnoucement from 'in_app_announcements/in_app_announcement.jsx';
const ListingHeading = () => ( const ListingHeading = () => (
<h1 className="title"> <h1 className="title">
@@ -17,6 +18,23 @@ const ListingHeading = () => (
> >
{MailPoet.I18n.t('new')} {MailPoet.I18n.t('new')}
</Link> </Link>
<InAppAnnoucement
className="mailpoet_in_app_announcement_free_welcome_emails_dot"
showToNewUser={false}
showToPremiumUser={false}
showOnlyOnceSlug="free_welcome_emails"
height="650px"
validUntil={new Date('2018-10-31')}
>
<div className="mailpoet_in_app_announcement_free_welcome_emails">
<h2>{MailPoet.I18n.t('freeWelcomeEmailsHeading')}</h2>
<img
src={window.mailpoet_free_welcome_emails_image}
alt={MailPoet.I18n.t('freeWelcomeEmailsHeading')}
/>
<p>{MailPoet.I18n.t('freeWelcomeEmailsParagraph')}</p>
</div>
</InAppAnnoucement>
</h1> </h1>
); );

View File

@@ -53,7 +53,10 @@ class Setting extends Model {
), ),
'analytics' => array( 'analytics' => array(
'enabled' => false, 'enabled' => false,
) ),
'in_app_announcements' => [
'displayed' => []
],
); );
} }

View File

@@ -17,6 +17,8 @@
var mailpoet_tracking_enabled = <%= json_encode(tracking_enabled) %>; var mailpoet_tracking_enabled = <%= json_encode(tracking_enabled) %>;
var mailpoet_premium_active = <%= json_encode(premium_plugin_active) %>; var mailpoet_premium_active = <%= json_encode(premium_plugin_active) %>;
var mailpoet_automatic_emails = <%= json_encode(automatic_emails) %>; var mailpoet_automatic_emails = <%= json_encode(automatic_emails) %>;
var mailpoet_in_app_announcements = mailpoet_settings.in_app_announcements;
var mailpoet_free_welcome_emails_image = '<%= image_url('in_app_announcements/hello-illustration-for-welcome-emails.png') %>';
<% set newUser = (is_new_user == true) ? 'true' : 'false' %> <% set newUser = (is_new_user == true) ? 'true' : 'false' %>
var mailpoet_is_new_user = <%= newUser %>; var mailpoet_is_new_user = <%= newUser %>;
</script> </script>
@@ -297,6 +299,9 @@
'introBack': _x('Back', 'A label on a button'), 'introBack': _x('Back', 'A label on a button'),
'introSkip': _x('Skip', 'A label on a button'), 'introSkip': _x('Skip', 'A label on a button'),
'introDone': _x('Done', 'A label on a button'), 'introDone': _x('Done', 'A label on a button'),
'freeWelcomeEmailsHeading': __('Welcome Emails are now free for everyone'),
'freeWelcomeEmailsParagraph': __('Say “Hello!” automatically to all your new subscribers. Theyll appreciate the extra touch.'),
}) %> }) %>
<% endblock %> <% endblock %>