From ee70d2dd1e66f8ffcea9537445a6209eb9a340c4 Mon Sep 17 00:00:00 2001 From: Oluwaseun Olorunsola Date: Mon, 4 Jul 2022 17:38:15 +0100 Subject: [PATCH] Implement polling and reconfirmation This will poll the server every certain interval (15s) for the email address and stop polling if the email is Authorized or the modal is closed or after a certain period of time (2 hours) MAILPOET-4300 --- .../common/authorize_sender_email_modal.tsx | 87 ++++++++++++++++--- mailpoet/lib/API/JSON/v1/Settings.php | 2 +- mailpoet/lib/Services/Bridge/API.php | 2 +- 3 files changed, 79 insertions(+), 12 deletions(-) diff --git a/mailpoet/assets/js/src/common/authorize_sender_email_modal.tsx b/mailpoet/assets/js/src/common/authorize_sender_email_modal.tsx index 5869169fa3..a08145b4c9 100644 --- a/mailpoet/assets/js/src/common/authorize_sender_email_modal.tsx +++ b/mailpoet/assets/js/src/common/authorize_sender_email_modal.tsx @@ -1,9 +1,14 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import ReactStringReplace from 'react-string-replace'; import PropTypes from 'prop-types'; +import moment from 'moment'; import { MailPoet } from 'mailpoet'; import { Modal } from 'common/modal/modal'; -import { Loader } from 'common'; +import { Button, Loader } from 'common'; + +const SET_INTERVAL_SECONDS = 15; + +const STOP_POLLING_AFTER = 2; // hours type ApiActionType = 'create' | 'confirm'; @@ -31,22 +36,75 @@ type Props = { }; function AuthorizeSenderEmailModal({ senderEmail, onRequestClose }: Props) { - const [apiResponseType, setApiResponseType] = useState(null); + const [createEmailApiResponse, setCreateEmailApiResponse] = + useState(null); + const [confirmEmailApiResponse, setConfirmEmailApiResponse] = + useState(null); + const [showLoader, setShowLoader] = useState(true); + const setIntervalId = useRef(); + const setIntervalStopTime = useRef(); const senderEmailAddress = String(senderEmail).toLowerCase(); useEffect(() => { if (!senderEmailAddress) { - return; + return null; } + const clearCurrentInterval = (intervalID: NodeJS.Timeout) => { + clearInterval(intervalID); + }; + + const executeAction = () => { + const currentIntervalId = setIntervalId.current; + const currentIntervalStopTime = setIntervalStopTime.current; + + if (currentIntervalStopTime && Date.now() >= currentIntervalStopTime) { + // stop polling after 2 hours + clearCurrentInterval(currentIntervalId); + return; + } + + makeApiRequest(senderEmailAddress, 'confirm') + .then((res) => { + const response = Boolean(res?.data?.isAuthorized); + + if (response) { + clearCurrentInterval(currentIntervalId); + setCreateEmailApiResponse(null); + setShowLoader(false); + setConfirmEmailApiResponse(true); + } + }) + .catch(() => { + // + }); + }; + makeApiRequest(senderEmailAddress) .then((res) => { - setApiResponseType(Boolean(res?.data)); + const response = Boolean(res?.data); + setCreateEmailApiResponse(response); + setShowLoader(response); + if (response) { + // if pending or already authorized perform the check ahead + executeAction(); + } }) .catch(() => { - setApiResponseType(false); + setCreateEmailApiResponse(false); + setShowLoader(false); }); + + clearCurrentInterval(setIntervalId.current); + setIntervalStopTime.current = moment() + .add(STOP_POLLING_AFTER, 'hours') + .valueOf(); + + const invervalID = setInterval(executeAction, 1000 * SET_INTERVAL_SECONDS); + setIntervalId.current = invervalID; + + return () => clearCurrentInterval(invervalID); }, [senderEmailAddress]); return ( @@ -58,7 +116,7 @@ function AuthorizeSenderEmailModal({ senderEmail, onRequestClose }: Props) { onRequestClose={onRequestClose} contentClassName="authorize-sender-email-modal" > - {apiResponseType && ( + {createEmailApiResponse && (

{ReactStringReplace( MailPoet.I18n.t('authorizeSenderEmailModalDescription'), @@ -69,12 +127,21 @@ function AuthorizeSenderEmailModal({ senderEmail, onRequestClose }: Props) { )}

)} - - {apiResponseType === false && ( + {createEmailApiResponse === false && (

{MailPoet.I18n.t('authorizeSenderEmailMessageError')}

)} - + {showLoader && } + + {confirmEmailApiResponse && ( + <> +

{MailPoet.I18n.t('authorizeSenderEmailMessageSuccess')}

+ + + )} ); } diff --git a/mailpoet/lib/API/JSON/v1/Settings.php b/mailpoet/lib/API/JSON/v1/Settings.php index eec0f306b5..ba140d0aab 100644 --- a/mailpoet/lib/API/JSON/v1/Settings.php +++ b/mailpoet/lib/API/JSON/v1/Settings.php @@ -198,7 +198,7 @@ class Settings extends APIEndpoint { } /** - * Makes POST request to Bridge endpoint to add email to user email authorization list + * Create POST request to Bridge endpoint to add email to user email authorization list */ public function authorizeSenderEmailAddress($data = []) { $emailAddress = $data['email'] ?? null; diff --git a/mailpoet/lib/Services/Bridge/API.php b/mailpoet/lib/Services/Bridge/API.php index 8241f3b75d..54ed1470ed 100644 --- a/mailpoet/lib/Services/Bridge/API.php +++ b/mailpoet/lib/Services/Bridge/API.php @@ -193,7 +193,7 @@ class API { if (!$isSuccess) { $logData = [ 'code' => $code, - 'error' => is_wp_error($result) ? $result->get_error_message() : null, + 'error' => is_wp_error($result) ? $result->get_error_message() : $this->wp->wpRemoteRetrieveBody($result), ]; $this->loggerFactory->getLogger(LoggerFactory::TOPIC_BRIDGE)->error('CreateAuthorizedEmailAddress API call failed.', $logData); }