Display the last newsletter step for the re-engagement email
[MAILPOET-3763]
This commit is contained in:
@@ -8,6 +8,7 @@ import StandardNewsletterFields from 'newsletters/send/standard.jsx';
|
|||||||
import NotificationNewsletterFields from 'newsletters/send/notification.jsx';
|
import NotificationNewsletterFields from 'newsletters/send/notification.jsx';
|
||||||
import WelcomeNewsletterFields from 'newsletters/send/welcome.jsx';
|
import WelcomeNewsletterFields from 'newsletters/send/welcome.jsx';
|
||||||
import AutomaticEmailFields from 'newsletters/send/automatic.jsx';
|
import AutomaticEmailFields from 'newsletters/send/automatic.jsx';
|
||||||
|
import { ReEngagementNewsletterFields } from 'newsletters/send/re_engagement';
|
||||||
import HelpTooltip from 'help-tooltip.jsx';
|
import HelpTooltip from 'help-tooltip.jsx';
|
||||||
import jQuery from 'jquery';
|
import jQuery from 'jquery';
|
||||||
import Background from 'common/background/background';
|
import Background from 'common/background/background';
|
||||||
@@ -68,6 +69,7 @@ class NewsletterSend extends React.Component {
|
|||||||
switch (newsletter.type) {
|
switch (newsletter.type) {
|
||||||
case 'notification': return NotificationNewsletterFields;
|
case 'notification': return NotificationNewsletterFields;
|
||||||
case 'welcome': return WelcomeNewsletterFields;
|
case 'welcome': return WelcomeNewsletterFields;
|
||||||
|
case 're_engagement': return ReEngagementNewsletterFields;
|
||||||
case 'automatic':
|
case 'automatic':
|
||||||
if (automaticEmails[newsletter.options.group]) {
|
if (automaticEmails[newsletter.options.group]) {
|
||||||
return AutomaticEmailFields;
|
return AutomaticEmailFields;
|
||||||
|
192
assets/js/src/newsletters/send/re_engagement.tsx
Normal file
192
assets/js/src/newsletters/send/re_engagement.tsx
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import MailPoet from 'mailpoet';
|
||||||
|
import { assoc, find, map } from 'lodash/fp';
|
||||||
|
|
||||||
|
import { Scheduling } from '../types/re_engagement/scheduling';
|
||||||
|
import GATrackingField from './ga_tracking';
|
||||||
|
import SenderField from './sender_address_field';
|
||||||
|
|
||||||
|
interface ReengagementWindow extends Window {
|
||||||
|
settings: {
|
||||||
|
deactivate_subscriber_after_inactive_days: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare let window: ReengagementWindow;
|
||||||
|
|
||||||
|
interface onValueChangeParam {
|
||||||
|
target: {
|
||||||
|
name: string,
|
||||||
|
value: {
|
||||||
|
afterTimeNumber: number|string,
|
||||||
|
afterTimeType: string,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
item: {
|
||||||
|
options: {
|
||||||
|
afterTimeNumber: number|string,
|
||||||
|
afterTimeType: string,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onValueChange: (val: onValueChangeParam) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function FormReEngagementScheduling(props: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Scheduling
|
||||||
|
afterTimeNumber={props.item.options.afterTimeNumber.toString()}
|
||||||
|
afterTimeType={props.item.options.afterTimeType}
|
||||||
|
inactiveSubscribersPeriod={
|
||||||
|
Number(window.settings.deactivate_subscriber_after_inactive_days)
|
||||||
|
}
|
||||||
|
updateAfterTimeNumber={(value) => {
|
||||||
|
props.onValueChange({
|
||||||
|
target: {
|
||||||
|
name: 'options',
|
||||||
|
value: assoc('afterTimeNumber', value, props.item.options),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
updateAfterTimeType={(value) => {
|
||||||
|
props.onValueChange({
|
||||||
|
target: {
|
||||||
|
name: 'options',
|
||||||
|
value: assoc('afterTimeType', value, props.item.options),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
{
|
||||||
|
name: 'email-header',
|
||||||
|
label: null,
|
||||||
|
tip: null,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'subject',
|
||||||
|
customLabel: MailPoet.I18n.t('subjectLabel'),
|
||||||
|
className: 'mailpoet-form-field-subject',
|
||||||
|
placeholder: MailPoet.I18n.t('subjectLine'),
|
||||||
|
tooltip: MailPoet.I18n.t('subjectLineTip'),
|
||||||
|
type: 'text',
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true,
|
||||||
|
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError'),
|
||||||
|
maxLength: 250,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'preheader',
|
||||||
|
customLabel: MailPoet.I18n.t('preheaderLabel'),
|
||||||
|
className: 'mailpoet-form-field-preheader',
|
||||||
|
placeholder: MailPoet.I18n.t('preheaderLine'),
|
||||||
|
// ignore for now until the MailPoet object is refactored to typescript
|
||||||
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||||
|
tooltip: `${MailPoet.I18n.t('preheaderLineTip1')} ${MailPoet.I18n.t('preheaderLineTip2')}`,
|
||||||
|
type: 'textarea',
|
||||||
|
validation: {
|
||||||
|
maxLength: 250,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'options',
|
||||||
|
type: 'reactComponent',
|
||||||
|
component: FormReEngagementScheduling,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'segments',
|
||||||
|
label: MailPoet.I18n.t('segments'),
|
||||||
|
tip: MailPoet.I18n.t('segmentsTip'),
|
||||||
|
type: 'selection',
|
||||||
|
placeholder: MailPoet.I18n.t('selectSegmentPlaceholder'),
|
||||||
|
id: 'mailpoet_segments',
|
||||||
|
api_version: MailPoet.apiVersion,
|
||||||
|
endpoint: 'segments',
|
||||||
|
multiple: true,
|
||||||
|
filter: function filter(segment) {
|
||||||
|
return !segment.deleted_at;
|
||||||
|
},
|
||||||
|
getLabel: function getLabel(segment) {
|
||||||
|
return segment.name;
|
||||||
|
},
|
||||||
|
getCount: function getCount(segment) {
|
||||||
|
return parseInt(segment.subscribers, 10).toLocaleString();
|
||||||
|
},
|
||||||
|
transformChangedValue: function transformChangedValue(segmentIds) {
|
||||||
|
const allSegments = this.getItems();
|
||||||
|
return map((id) => find((segment) => segment.id === id, allSegments), segmentIds);
|
||||||
|
},
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true,
|
||||||
|
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sender',
|
||||||
|
label: MailPoet.I18n.t('sender'),
|
||||||
|
tip: MailPoet.I18n.t('senderTip'),
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'sender_name',
|
||||||
|
type: 'text',
|
||||||
|
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sender_address',
|
||||||
|
type: 'reactComponent',
|
||||||
|
component: SenderField,
|
||||||
|
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true,
|
||||||
|
'data-parsley-type': 'email',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'reply-to',
|
||||||
|
label: MailPoet.I18n.t('replyTo'),
|
||||||
|
tip: MailPoet.I18n.t('replyToTip'),
|
||||||
|
inline: true,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'reply_to_name',
|
||||||
|
type: 'text',
|
||||||
|
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'reply_to_address',
|
||||||
|
type: 'text',
|
||||||
|
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
|
||||||
|
validation: {
|
||||||
|
'data-parsley-type': 'email',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
GATrackingField,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const ReEngagementNewsletterFields = {
|
||||||
|
// ignore for now until we refactor the forms to typescript
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
getFields() {
|
||||||
|
return fields;
|
||||||
|
},
|
||||||
|
getSendButtonOptions(): { value: string } {
|
||||||
|
return {
|
||||||
|
value: MailPoet.I18n.t('activate'),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
@@ -12,8 +12,8 @@ interface Props {
|
|||||||
afterTimeNumber: string;
|
afterTimeNumber: string;
|
||||||
afterTimeType: string;
|
afterTimeType: string;
|
||||||
inactiveSubscribersPeriod: number;
|
inactiveSubscribersPeriod: number;
|
||||||
updateAfterTimeNumber: (string) => void;
|
updateAfterTimeNumber: (arg: string) => void;
|
||||||
updateAfterTimeType: (string) => void;
|
updateAfterTimeType: (arg: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Scheduling({
|
export function Scheduling({
|
||||||
|
Reference in New Issue
Block a user