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 WelcomeNewsletterFields from 'newsletters/send/welcome.jsx';
|
||||
import AutomaticEmailFields from 'newsletters/send/automatic.jsx';
|
||||
import { ReEngagementNewsletterFields } from 'newsletters/send/re_engagement';
|
||||
import HelpTooltip from 'help-tooltip.jsx';
|
||||
import jQuery from 'jquery';
|
||||
import Background from 'common/background/background';
|
||||
@@ -68,6 +69,7 @@ class NewsletterSend extends React.Component {
|
||||
switch (newsletter.type) {
|
||||
case 'notification': return NotificationNewsletterFields;
|
||||
case 'welcome': return WelcomeNewsletterFields;
|
||||
case 're_engagement': return ReEngagementNewsletterFields;
|
||||
case 'automatic':
|
||||
if (automaticEmails[newsletter.options.group]) {
|
||||
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;
|
||||
afterTimeType: string;
|
||||
inactiveSubscribersPeriod: number;
|
||||
updateAfterTimeNumber: (string) => void;
|
||||
updateAfterTimeType: (string) => void;
|
||||
updateAfterTimeNumber: (arg: string) => void;
|
||||
updateAfterTimeType: (arg: string) => void;
|
||||
}
|
||||
|
||||
export function Scheduling({
|
||||
|
Reference in New Issue
Block a user