diff --git a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email.tsx b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email.tsx index 9927c384c8..a2c138b4ca 100644 --- a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email.tsx +++ b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email.tsx @@ -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, }; diff --git a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics.tsx b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics.tsx deleted file mode 100644 index 8da6fb8208..0000000000 --- a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics.tsx +++ /dev/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 = ({ 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([]); - const [loadingLinks, setLoadingLinks] = useState(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 && ( - - ))} - { - ((segment.action === EmailActionTypes.OPENED)) - && ( - - - - ) - } - { - // this condition is temporary, - // when MAILPOET-3951 is implemented this select will be in all segments - ((segment.action === EmailActionTypes.OPENED)) - && ( - - { - 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 - ); - }} - /> - - ) - } - { - ((segment.action !== EmailActionTypes.OPENED)) - && ( - - { - updateSegmentFilter({ newsletter_id: option.value }, filterIndex); - }} - automationId="segment-email" - /> - - ) - } - {(loadingLinks && (MailPoet.I18n.t('loadingDynamicSegmentItems')))} - { - (!!links.length && shouldDisplayLinks(segment.action, segment.newsletter_id)) - && ( -
- { - updateSegmentFilter({ link_id: option.value }, filterIndex); - }} - /> -
- ) - } - - ); -}; diff --git a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_clicks.tsx b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_clicks.tsx new file mode 100644 index 0000000000..cc052c6d1b --- /dev/null +++ b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_clicks.tsx @@ -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 = ({ 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([]); + const [loadingLinks, setLoadingLinks] = useState(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 && ( + + ))} + + { + updateSegmentFilter({ newsletter_id: option.value }, filterIndex); + }} + automationId="segment-email" + /> + + {(loadingLinks && (MailPoet.I18n.t('loadingDynamicSegmentItems')))} + { + (!!links.length && shouldDisplayLinks(segment.newsletter_id)) + && ( +
+ { + updateSegmentFilter({ link_id: option.value }, filterIndex); + }} + /> +
+ ) + } + + ); +}; diff --git a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_opens.tsx b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_opens.tsx new file mode 100644 index 0000000000..e101617c6a --- /dev/null +++ b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_opens.tsx @@ -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 = ({ 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 ( + <> + + + + + { + 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 + ); + }} + /> + + + ); +};