Merge pull request #1515 from mailpoet/in-app-welcome-emails
In app announcement for free welcome emails [MALPOET-1525]
This commit is contained in:
@@ -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 |
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -53,7 +53,10 @@ class Setting extends Model {
|
|||||||
),
|
),
|
||||||
'analytics' => array(
|
'analytics' => array(
|
||||||
'enabled' => false,
|
'enabled' => false,
|
||||||
)
|
),
|
||||||
|
'in_app_announcements' => [
|
||||||
|
'displayed' => []
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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. They’ll appreciate the extra touch.'),
|
||||||
}) %>
|
}) %>
|
||||||
<% endblock %>
|
<% endblock %>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user