Split component for email statistics segment filter configuration
There was a lot of conditional functionality related only to open statistics. Splitting the component into two improves readability. [MAILPOET-3951]
This commit is contained in:
committed by
Veljko V
parent
a6e93f93ff
commit
7abb04d12e
@@ -8,7 +8,8 @@ import {
|
||||
SegmentTypes, WordpressRoleFormItem,
|
||||
} from '../types';
|
||||
|
||||
import { EmailStatisticsFields } from './email_statistics';
|
||||
import { EmailOpenStatisticsFields } from './email_statistics_opens';
|
||||
import { EmailClickStatisticsFields } from './email_statistics_clicks';
|
||||
import { EmailOpensAbsoluteCountFields } from './email_opens_absolute_count';
|
||||
|
||||
export const EmailSegmentOptions = [
|
||||
@@ -37,7 +38,8 @@ export function validateEmail(formItems: EmailFormItem): boolean {
|
||||
(formItems.action !== EmailActionTypes.OPENS_ABSOLUTE_COUNT)
|
||||
&& (formItems.action !== EmailActionTypes.MACHINE_OPENS_ABSOLUTE_COUNT)
|
||||
) {
|
||||
return (!!formItems.newsletter_id) // old segments this can be removed after MAILPOET-3951
|
||||
return (!!formItems.newsletter_id) // EmailActionTypes.CLICKED
|
||||
// EmailActionTypes.OPENED, EmailActionTypes.MACHINE_OPENED
|
||||
|| (
|
||||
Array.isArray(formItems.newsletters)
|
||||
&& formItems.newsletters.length > 0
|
||||
@@ -54,10 +56,10 @@ export function validateEmail(formItems: EmailFormItem): boolean {
|
||||
const componentsMap = {
|
||||
[EmailActionTypes.OPENS_ABSOLUTE_COUNT]: EmailOpensAbsoluteCountFields,
|
||||
[EmailActionTypes.MACHINE_OPENS_ABSOLUTE_COUNT]: EmailOpensAbsoluteCountFields,
|
||||
[EmailActionTypes.CLICKED]: EmailStatisticsFields,
|
||||
[EmailActionTypes.NOT_CLICKED]: EmailStatisticsFields,
|
||||
[EmailActionTypes.OPENED]: EmailStatisticsFields,
|
||||
[EmailActionTypes.MACHINE_OPENED]: EmailStatisticsFields,
|
||||
[EmailActionTypes.CLICKED]: EmailClickStatisticsFields,
|
||||
[EmailActionTypes.NOT_CLICKED]: EmailClickStatisticsFields,
|
||||
[EmailActionTypes.OPENED]: EmailOpenStatisticsFields,
|
||||
[EmailActionTypes.MACHINE_OPENED]: EmailOpenStatisticsFields,
|
||||
[EmailActionTypes.CLICKED_ANY]: null,
|
||||
};
|
||||
|
||||
|
@@ -1,201 +0,0 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import MailPoet from 'mailpoet';
|
||||
import { filter, find, map } from 'lodash/fp';
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
|
||||
import APIErrorsNotice from 'notices/api_errors_notice';
|
||||
import ReactSelect from 'common/form/react_select/react_select';
|
||||
import Select from 'common/form/select/select';
|
||||
import { Grid } from 'common/grid';
|
||||
import {
|
||||
AnyValueTypes,
|
||||
EmailActionTypes,
|
||||
EmailFormItem,
|
||||
SelectOption,
|
||||
WindowNewslettersList,
|
||||
} from '../types';
|
||||
|
||||
const shouldDisplayLinks = (itemAction: string, itemNewsletterId?: string): boolean => (
|
||||
(
|
||||
(itemAction === EmailActionTypes.CLICKED)
|
||||
|| (itemAction === EmailActionTypes.NOT_CLICKED)
|
||||
)
|
||||
&& (itemNewsletterId != null)
|
||||
);
|
||||
|
||||
type Props = {
|
||||
filterIndex: number;
|
||||
}
|
||||
|
||||
export const EmailStatisticsFields: React.FunctionComponent<Props> = ({ filterIndex }) => {
|
||||
const segment: EmailFormItem = useSelect(
|
||||
(select) => select('mailpoet-dynamic-segments-form').getSegmentFilter(filterIndex),
|
||||
[filterIndex]
|
||||
);
|
||||
|
||||
const { updateSegmentFilter, updateSegmentFilterFromEvent } = useDispatch('mailpoet-dynamic-segments-form');
|
||||
|
||||
const newslettersList: WindowNewslettersList = useSelect(
|
||||
(select) => select('mailpoet-dynamic-segments-form').getNewslettersList(),
|
||||
[]
|
||||
);
|
||||
|
||||
const [errors, setErrors] = useState([]);
|
||||
const [links, setLinks] = useState<SelectOption[]>([]);
|
||||
const [loadingLinks, setLoadingLinks] = useState<boolean>(false);
|
||||
|
||||
const newsletterOptions = newslettersList?.map((newsletter) => {
|
||||
const sentAt = (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet');
|
||||
return {
|
||||
label: newsletter.subject,
|
||||
tag: sentAt,
|
||||
value: Number(newsletter.id),
|
||||
};
|
||||
});
|
||||
|
||||
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(segment.action, segment.newsletter_id)) return;
|
||||
setLinks([]);
|
||||
loadLinks(segment.newsletter_id);
|
||||
}, [segment.action, segment.newsletter_id]);
|
||||
|
||||
useEffect(() => {
|
||||
loadLinksCB();
|
||||
if (
|
||||
(segment.action === EmailActionTypes.OPENED)
|
||||
&& (
|
||||
(segment.operator !== AnyValueTypes.ANY)
|
||||
&& (segment.operator !== AnyValueTypes.ALL)
|
||||
&& (segment.operator !== AnyValueTypes.NONE)
|
||||
)
|
||||
) {
|
||||
updateSegmentFilter({ operator: AnyValueTypes.ANY }, filterIndex);
|
||||
}
|
||||
}, [
|
||||
loadLinksCB,
|
||||
segment.action,
|
||||
segment.newsletter_id,
|
||||
segment.operator,
|
||||
filterIndex,
|
||||
updateSegmentFilter,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{(errors.length > 0 && (
|
||||
<APIErrorsNotice errors={errors} />
|
||||
))}
|
||||
{
|
||||
((segment.action === EmailActionTypes.OPENED))
|
||||
&& (
|
||||
<Grid.CenteredRow>
|
||||
<Select
|
||||
key="select"
|
||||
isFullWidth
|
||||
value={segment.operator}
|
||||
onChange={(e) => {
|
||||
updateSegmentFilterFromEvent('operator', filterIndex, e);
|
||||
}}
|
||||
>
|
||||
<option value={AnyValueTypes.ANY}>{MailPoet.I18n.t('anyOf')}</option>
|
||||
<option value={AnyValueTypes.ALL}>{MailPoet.I18n.t('allOf')}</option>
|
||||
<option value={AnyValueTypes.NONE}>{MailPoet.I18n.t('noneOf')}</option>
|
||||
</Select>
|
||||
</Grid.CenteredRow>
|
||||
)
|
||||
}
|
||||
{
|
||||
// this condition is temporary,
|
||||
// when MAILPOET-3951 is implemented this select will be in all segments
|
||||
((segment.action === EmailActionTypes.OPENED))
|
||||
&& (
|
||||
<Grid.CenteredRow>
|
||||
<ReactSelect
|
||||
dimension="small"
|
||||
isFullWidth
|
||||
isMulti
|
||||
placeholder={MailPoet.I18n.t('selectNewsletterPlaceholder')}
|
||||
options={newsletterOptions}
|
||||
automationId="segment-email"
|
||||
value={
|
||||
filter(
|
||||
(option) => {
|
||||
if (!segment.newsletters) return undefined;
|
||||
const newsletterId = option.value;
|
||||
return segment.newsletters.indexOf(newsletterId) !== -1;
|
||||
},
|
||||
newsletterOptions
|
||||
)
|
||||
}
|
||||
onChange={(options: SelectOption[]): void => {
|
||||
updateSegmentFilter(
|
||||
{ newsletters: map('value', options) },
|
||||
filterIndex
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Grid.CenteredRow>
|
||||
)
|
||||
}
|
||||
{
|
||||
((segment.action !== EmailActionTypes.OPENED))
|
||||
&& (
|
||||
<Grid.CenteredRow>
|
||||
<ReactSelect
|
||||
dimension="small"
|
||||
isFullWidth
|
||||
placeholder={MailPoet.I18n.t('selectNewsletterPlaceholder')}
|
||||
options={newsletterOptions}
|
||||
value={find(['value', segment.newsletter_id], newsletterOptions)}
|
||||
onChange={(option: SelectOption): void => {
|
||||
updateSegmentFilter({ newsletter_id: option.value }, filterIndex);
|
||||
}}
|
||||
automationId="segment-email"
|
||||
/>
|
||||
</Grid.CenteredRow>
|
||||
)
|
||||
}
|
||||
{(loadingLinks && (MailPoet.I18n.t('loadingDynamicSegmentItems')))}
|
||||
{
|
||||
(!!links.length && shouldDisplayLinks(segment.action, segment.newsletter_id))
|
||||
&& (
|
||||
<div>
|
||||
<ReactSelect
|
||||
dimension="small"
|
||||
isFullWidth
|
||||
placeholder={MailPoet.I18n.t('selectLinkPlaceholder')}
|
||||
options={links}
|
||||
value={find(['value', Number(segment.link_id)], links)}
|
||||
onChange={(option: SelectOption): void => {
|
||||
updateSegmentFilter({ link_id: option.value }, filterIndex);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
@@ -0,0 +1,121 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import MailPoet from 'mailpoet';
|
||||
import { find } from 'lodash/fp';
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
|
||||
import APIErrorsNotice from 'notices/api_errors_notice';
|
||||
import ReactSelect from 'common/form/react_select/react_select';
|
||||
import { Grid } from 'common/grid';
|
||||
import {
|
||||
EmailFormItem,
|
||||
SelectOption,
|
||||
WindowNewslettersList,
|
||||
} from '../types';
|
||||
|
||||
const shouldDisplayLinks = (itemNewsletterId?: string): boolean => (!!itemNewsletterId);
|
||||
|
||||
type Props = {
|
||||
filterIndex: number;
|
||||
}
|
||||
|
||||
export const EmailClickStatisticsFields: React.FunctionComponent<Props> = ({ filterIndex }) => {
|
||||
const segment: EmailFormItem = useSelect(
|
||||
(select) => select('mailpoet-dynamic-segments-form').getSegmentFilter(filterIndex),
|
||||
[filterIndex]
|
||||
);
|
||||
|
||||
const { updateSegmentFilter } = useDispatch('mailpoet-dynamic-segments-form');
|
||||
|
||||
const newslettersList: WindowNewslettersList = useSelect(
|
||||
(select) => select('mailpoet-dynamic-segments-form').getNewslettersList(),
|
||||
[]
|
||||
);
|
||||
|
||||
const [errors, setErrors] = useState([]);
|
||||
const [links, setLinks] = useState<SelectOption[]>([]);
|
||||
const [loadingLinks, setLoadingLinks] = useState<boolean>(false);
|
||||
|
||||
const newsletterOptions = newslettersList?.map((newsletter) => {
|
||||
const sentAt = (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet');
|
||||
return {
|
||||
label: newsletter.subject,
|
||||
tag: sentAt,
|
||||
value: Number(newsletter.id),
|
||||
};
|
||||
});
|
||||
|
||||
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(segment.newsletter_id)) return;
|
||||
setLinks([]);
|
||||
loadLinks(segment.newsletter_id);
|
||||
}, [segment.newsletter_id]);
|
||||
|
||||
useEffect(() => {
|
||||
loadLinksCB();
|
||||
}, [
|
||||
loadLinksCB,
|
||||
segment.newsletter_id,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{(errors.length > 0 && (
|
||||
<APIErrorsNotice errors={errors} />
|
||||
))}
|
||||
<Grid.CenteredRow>
|
||||
<ReactSelect
|
||||
dimension="small"
|
||||
isFullWidth
|
||||
placeholder={MailPoet.I18n.t('selectNewsletterPlaceholder')}
|
||||
options={newsletterOptions}
|
||||
value={find(['value', segment.newsletter_id], newsletterOptions)}
|
||||
onChange={(option: SelectOption): void => {
|
||||
updateSegmentFilter({ newsletter_id: option.value }, filterIndex);
|
||||
}}
|
||||
automationId="segment-email"
|
||||
/>
|
||||
</Grid.CenteredRow>
|
||||
{(loadingLinks && (MailPoet.I18n.t('loadingDynamicSegmentItems')))}
|
||||
{
|
||||
(!!links.length && shouldDisplayLinks(segment.newsletter_id))
|
||||
&& (
|
||||
<div>
|
||||
<ReactSelect
|
||||
dimension="small"
|
||||
isFullWidth
|
||||
placeholder={MailPoet.I18n.t('selectLinkPlaceholder')}
|
||||
options={links}
|
||||
value={find(['value', Number(segment.link_id)], links)}
|
||||
onChange={(option: SelectOption): void => {
|
||||
updateSegmentFilter({ link_id: option.value }, filterIndex);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
@@ -0,0 +1,100 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import MailPoet from 'mailpoet';
|
||||
import { filter, map } from 'lodash/fp';
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
|
||||
import ReactSelect from 'common/form/react_select/react_select';
|
||||
import Select from 'common/form/select/select';
|
||||
import { Grid } from 'common/grid';
|
||||
import {
|
||||
AnyValueTypes,
|
||||
EmailFormItem,
|
||||
SelectOption,
|
||||
WindowNewslettersList,
|
||||
} from '../types';
|
||||
|
||||
type Props = {
|
||||
filterIndex: number;
|
||||
}
|
||||
|
||||
export const EmailOpenStatisticsFields: React.FunctionComponent<Props> = ({ filterIndex }) => {
|
||||
const segment: EmailFormItem = useSelect(
|
||||
(select) => select('mailpoet-dynamic-segments-form').getSegmentFilter(filterIndex),
|
||||
[filterIndex]
|
||||
);
|
||||
|
||||
const { updateSegmentFilter, updateSegmentFilterFromEvent } = useDispatch('mailpoet-dynamic-segments-form');
|
||||
|
||||
const newslettersList: WindowNewslettersList = useSelect(
|
||||
(select) => select('mailpoet-dynamic-segments-form').getNewslettersList(),
|
||||
[]
|
||||
);
|
||||
|
||||
const newsletterOptions = newslettersList?.map((newsletter) => {
|
||||
const sentAt = (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet');
|
||||
return {
|
||||
label: newsletter.subject,
|
||||
tag: sentAt,
|
||||
value: Number(newsletter.id),
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if ((segment.operator !== AnyValueTypes.ANY)
|
||||
&& (segment.operator !== AnyValueTypes.ALL)
|
||||
&& (segment.operator !== AnyValueTypes.NONE)
|
||||
) {
|
||||
updateSegmentFilter({ operator: AnyValueTypes.ANY }, filterIndex);
|
||||
}
|
||||
}, [
|
||||
segment.newsletter_id,
|
||||
segment.operator,
|
||||
filterIndex,
|
||||
updateSegmentFilter,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid.CenteredRow>
|
||||
<Select
|
||||
key="select"
|
||||
isFullWidth
|
||||
value={segment.operator}
|
||||
onChange={(e) => {
|
||||
updateSegmentFilterFromEvent('operator', filterIndex, e);
|
||||
}}
|
||||
>
|
||||
<option value={AnyValueTypes.ANY}>{MailPoet.I18n.t('anyOf')}</option>
|
||||
<option value={AnyValueTypes.ALL}>{MailPoet.I18n.t('allOf')}</option>
|
||||
<option value={AnyValueTypes.NONE}>{MailPoet.I18n.t('noneOf')}</option>
|
||||
</Select>
|
||||
</Grid.CenteredRow>
|
||||
<Grid.CenteredRow>
|
||||
<ReactSelect
|
||||
dimension="small"
|
||||
isFullWidth
|
||||
isMulti
|
||||
placeholder={MailPoet.I18n.t('selectNewsletterPlaceholder')}
|
||||
options={newsletterOptions}
|
||||
automationId="segment-email"
|
||||
value={
|
||||
filter(
|
||||
(option) => {
|
||||
if (!segment.newsletters) return undefined;
|
||||
const newsletterId = option.value;
|
||||
return segment.newsletters.indexOf(newsletterId) !== -1;
|
||||
},
|
||||
newsletterOptions
|
||||
)
|
||||
}
|
||||
onChange={(options: SelectOption[]): void => {
|
||||
updateSegmentFilter(
|
||||
{ newsletters: map('value', options) },
|
||||
filterIndex
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Grid.CenteredRow>
|
||||
</>
|
||||
);
|
||||
};
|
Reference in New Issue
Block a user