Refactor emails segments into separate components
[MAILPOET-3224]
This commit is contained in:
@@ -1,24 +1,14 @@
|
|||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React from 'react';
|
||||||
import MailPoet from 'mailpoet';
|
import MailPoet from 'mailpoet';
|
||||||
import { assign, compose, find } from 'lodash/fp';
|
|
||||||
|
|
||||||
import APIErrorsNotice from 'notices/api_errors_notice';
|
|
||||||
import Select from 'common/form/react_select/react_select';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EmailFormItem,
|
EmailFormItem,
|
||||||
OnFilterChange,
|
OnFilterChange,
|
||||||
SegmentTypes,
|
SegmentTypes,
|
||||||
SelectOption,
|
EmailActionTypes,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { SegmentFormData } from '../segment_form_data';
|
|
||||||
|
|
||||||
enum EmailActionTypes {
|
import { EmailStatisticsFields } from './email_statistics';
|
||||||
OPENED = 'opened',
|
|
||||||
NOT_OPENED = 'notOpened',
|
|
||||||
CLICKED = 'clicked',
|
|
||||||
NOT_CLICKED = 'notClicked',
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EmailSegmentOptions = [
|
export const EmailSegmentOptions = [
|
||||||
{ value: 'opened', label: MailPoet.I18n.t('emailActionOpened'), group: SegmentTypes.Email },
|
{ value: 'opened', label: MailPoet.I18n.t('emailActionOpened'), group: SegmentTypes.Email },
|
||||||
@@ -38,98 +28,14 @@ export function validateEmail(formItems: EmailFormItem): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldDisplayLinks = (itemAction: string, itemNewsletterId?: string): boolean => (
|
|
||||||
(
|
|
||||||
(itemAction === EmailActionTypes.CLICKED)
|
|
||||||
|| (itemAction === EmailActionTypes.NOT_CLICKED)
|
|
||||||
)
|
|
||||||
&& (itemNewsletterId != null)
|
|
||||||
);
|
|
||||||
|
|
||||||
const newsletterOptions = SegmentFormData.newslettersList?.map((newsletter) => {
|
|
||||||
const sentAt = (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet');
|
|
||||||
return {
|
|
||||||
label: `${newsletter.subject} (${sentAt})`,
|
|
||||||
value: newsletter.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onChange: OnFilterChange;
|
onChange: OnFilterChange;
|
||||||
item: EmailFormItem;
|
item: EmailFormItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EmailFields: React.FunctionComponent<Props> = ({ onChange, item }) => {
|
export const EmailFields: React.FunctionComponent<Props> = ({ onChange, item }) => (
|
||||||
const [errors, setErrors] = useState([]);
|
<EmailStatisticsFields
|
||||||
const [links, setLinks] = useState<SelectOption[]>([]);
|
item={item}
|
||||||
const [loadingLinks, setLoadingLinks] = useState<boolean>(false);
|
onChange={onChange}
|
||||||
|
/>
|
||||||
function loadLinks(newsletterId: string): void {
|
);
|
||||||
setErrors([]);
|
|
||||||
setLoadingLinks(true);
|
|
||||||
MailPoet.Ajax.post({
|
|
||||||
api_version: MailPoet.apiVersion,
|
|
||||||
endpoint: 'newsletter_links',
|
|
||||||
action: 'get',
|
|
||||||
data: { newsletterId },
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
const { data } = response;
|
|
||||||
const loadedLinks = data.map((link) => ({
|
|
||||||
value: link.id,
|
|
||||||
label: link.url,
|
|
||||||
}));
|
|
||||||
setLoadingLinks(false);
|
|
||||||
setLinks(loadedLinks);
|
|
||||||
})
|
|
||||||
.fail((response) => {
|
|
||||||
setErrors(response.errors);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadLinksCB = useCallback(() => {
|
|
||||||
if (!shouldDisplayLinks(item.action, item.newsletter_id)) return;
|
|
||||||
setLinks([]);
|
|
||||||
loadLinks(item.newsletter_id);
|
|
||||||
}, [item.action, item.newsletter_id]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
loadLinksCB();
|
|
||||||
}, [loadLinksCB, item.action, item.newsletter_id]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{(errors.length > 0 && (
|
|
||||||
<APIErrorsNotice errors={errors} />
|
|
||||||
))}
|
|
||||||
|
|
||||||
<Select
|
|
||||||
isFullWidth
|
|
||||||
placeholder={MailPoet.I18n.t('selectNewsletterPlaceholder')}
|
|
||||||
options={newsletterOptions}
|
|
||||||
value={find(['value', item.newsletter_id], newsletterOptions)}
|
|
||||||
onChange={(option: SelectOption): void => compose([
|
|
||||||
onChange,
|
|
||||||
assign(item),
|
|
||||||
])({ newsletter_id: option.value })}
|
|
||||||
automationId="segment-email"
|
|
||||||
/>
|
|
||||||
{(loadingLinks && (MailPoet.I18n.t('loadingDynamicSegmentItems')))}
|
|
||||||
{
|
|
||||||
(!!links.length && shouldDisplayLinks(item.action, item.newsletter_id))
|
|
||||||
&& (
|
|
||||||
<Select
|
|
||||||
isFullWidth
|
|
||||||
placeholder={MailPoet.I18n.t('selectLinkPlaceholder')}
|
|
||||||
options={links}
|
|
||||||
value={find(['value', item.link_id], links)}
|
|
||||||
onChange={(option: SelectOption): void => compose([
|
|
||||||
onChange,
|
|
||||||
assign(item),
|
|
||||||
])({ link_id: option.value })}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
@@ -0,0 +1,109 @@
|
|||||||
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
|
import MailPoet from 'mailpoet';
|
||||||
|
import { assign, compose, find } from 'lodash/fp';
|
||||||
|
|
||||||
|
import APIErrorsNotice from 'notices/api_errors_notice';
|
||||||
|
import Select from 'common/form/react_select/react_select';
|
||||||
|
import {
|
||||||
|
EmailActionTypes,
|
||||||
|
EmailFormItem,
|
||||||
|
OnFilterChange,
|
||||||
|
SelectOption,
|
||||||
|
} from '../types';
|
||||||
|
import { SegmentFormData } from '../segment_form_data';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
onChange: OnFilterChange;
|
||||||
|
item: EmailFormItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shouldDisplayLinks = (itemAction: string, itemNewsletterId?: string): boolean => (
|
||||||
|
(
|
||||||
|
(itemAction === EmailActionTypes.CLICKED)
|
||||||
|
|| (itemAction === EmailActionTypes.NOT_CLICKED)
|
||||||
|
)
|
||||||
|
&& (itemNewsletterId != null)
|
||||||
|
);
|
||||||
|
|
||||||
|
const newsletterOptions = SegmentFormData.newslettersList?.map((newsletter) => {
|
||||||
|
const sentAt = (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet');
|
||||||
|
return {
|
||||||
|
label: `${newsletter.subject} (${sentAt})`,
|
||||||
|
value: newsletter.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const EmailStatisticsFields: React.FunctionComponent<Props> = ({ onChange, item }) => {
|
||||||
|
const [errors, setErrors] = useState([]);
|
||||||
|
const [links, setLinks] = useState<SelectOption[]>([]);
|
||||||
|
const [loadingLinks, setLoadingLinks] = useState<boolean>(false);
|
||||||
|
|
||||||
|
function loadLinks(newsletterId: string): void {
|
||||||
|
setErrors([]);
|
||||||
|
setLoadingLinks(true);
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
api_version: MailPoet.apiVersion,
|
||||||
|
endpoint: 'newsletter_links',
|
||||||
|
action: 'get',
|
||||||
|
data: { newsletterId },
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
const { data } = response;
|
||||||
|
const loadedLinks = data.map((link) => ({
|
||||||
|
value: link.id,
|
||||||
|
label: link.url,
|
||||||
|
}));
|
||||||
|
setLoadingLinks(false);
|
||||||
|
setLinks(loadedLinks);
|
||||||
|
})
|
||||||
|
.fail((response) => {
|
||||||
|
setErrors(response.errors);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadLinksCB = useCallback(() => {
|
||||||
|
if (!shouldDisplayLinks(item.action, item.newsletter_id)) return;
|
||||||
|
setLinks([]);
|
||||||
|
loadLinks(item.newsletter_id);
|
||||||
|
}, [item.action, item.newsletter_id]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadLinksCB();
|
||||||
|
}, [loadLinksCB, item.action, item.newsletter_id]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{(errors.length > 0 && (
|
||||||
|
<APIErrorsNotice errors={errors} />
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Select
|
||||||
|
isFullWidth
|
||||||
|
placeholder={MailPoet.I18n.t('selectNewsletterPlaceholder')}
|
||||||
|
options={newsletterOptions}
|
||||||
|
value={find(['value', item.newsletter_id], newsletterOptions)}
|
||||||
|
onChange={(option: SelectOption): void => compose([
|
||||||
|
onChange,
|
||||||
|
assign(item),
|
||||||
|
])({ newsletter_id: option.value })}
|
||||||
|
automationId="segment-email"
|
||||||
|
/>
|
||||||
|
{(loadingLinks && (MailPoet.I18n.t('loadingDynamicSegmentItems')))}
|
||||||
|
{
|
||||||
|
(!!links.length && shouldDisplayLinks(item.action, item.newsletter_id))
|
||||||
|
&& (
|
||||||
|
<Select
|
||||||
|
isFullWidth
|
||||||
|
placeholder={MailPoet.I18n.t('selectLinkPlaceholder')}
|
||||||
|
options={links}
|
||||||
|
value={find(['value', item.link_id], links)}
|
||||||
|
onChange={(option: SelectOption): void => compose([
|
||||||
|
onChange,
|
||||||
|
assign(item),
|
||||||
|
])({ link_id: option.value })}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@@ -4,6 +4,14 @@ export enum SegmentTypes {
|
|||||||
WooCommerce = 'woocommerce',
|
WooCommerce = 'woocommerce',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum EmailActionTypes {
|
||||||
|
OPENS_ABSOLUTE_COUNT = 'opensAbsoluteCount',
|
||||||
|
OPENED = 'opened',
|
||||||
|
NOT_OPENED = 'notOpened',
|
||||||
|
CLICKED = 'clicked',
|
||||||
|
NOT_CLICKED = 'notClicked',
|
||||||
|
}
|
||||||
|
|
||||||
export interface SelectOption {
|
export interface SelectOption {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
Reference in New Issue
Block a user