From 226900f0400afd6be8da0465aca1bce26afc9338 Mon Sep 17 00:00:00 2001 From: Simon Backx Date: Thu, 30 Nov 2023 16:14:36 +0100 Subject: [PATCH] Allow custom reply-to addresses for self-hosters and allow empty values (#19200) fixes GRO-105 The newsletter value is mapped to an empty value when shown to the users, this matches the backend behaviour. When entering an empty value, this is stored internally as 'newsletter'. The replyToInput component now uses its own state for the input value. This avoids weird issues when the rendered value changes, e.g. when entering the text 'support' or 'newsletter' in the field. --- .../newsletters/NewsletterDetailModal.tsx | 122 +++++++++++------- .../src/utils/newsletterEmails.ts | 2 +- 2 files changed, 76 insertions(+), 48 deletions(-) diff --git a/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx b/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx index 093ab07c8f..4fdeaa5bc7 100644 --- a/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx +++ b/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx @@ -1,6 +1,6 @@ import NewsletterPreview from './NewsletterPreview'; import NiceModal, {useModal} from '@ebay/nice-modal-react'; -import React, {useEffect, useMemo, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import useFeatureFlag from '../../../../hooks/useFeatureFlag'; import useSettingGroup from '../../../../hooks/useSettingGroup'; import validator from 'validator'; @@ -16,6 +16,78 @@ import {renderReplyToEmail, renderSenderEmail} from '../../../../utils/newslette import {textColorForBackgroundColor} from '@tryghost/color-utils'; import {useGlobalData} from '../../../providers/GlobalDataProvider'; +const ReplyToEmailField: React.FC<{ + newsletter: Newsletter; + updateNewsletter: (fields: Partial) => void; + errors: ErrorMessages; + validate: () => void; + clearError: (field: string) => void; +}> = ({newsletter, updateNewsletter, errors, clearError, validate}) => { + const {settings, config} = useGlobalData(); + const [defaultEmailAddress, supportEmailAddress] = getSettingValues(settings, ['default_email_address', 'support_email_address']); + const newEmailAddressesFlag = useFeatureFlag('newEmailAddresses'); + + // When editing the senderReplyTo, we use a state, so we don't cause jumps when the 'rendering' method decides to change the value + // Because 'newsletter' 'support' or an empty value can be mapped to a default value, we don't want those changes to happen when entering text + const [senderReplyTo, setSenderReplyTo] = useState(renderReplyToEmail(newsletter, config, supportEmailAddress, defaultEmailAddress) || ''); + + let newsletterAddress = renderSenderEmail(newsletter, config, defaultEmailAddress); + const replyToEmails = useMemo(() => [ + {label: `Newsletter address (${newsletterAddress})`, value: 'newsletter'}, + {label: `Support address (${supportEmailAddress})`, value: 'support'} + ], [newsletterAddress, supportEmailAddress]); + + useEffect(() => { + if (!isManagedEmail(config) && !newEmailAddressesFlag) { + // Autocorrect invalid values + const foundValue = replyToEmails.find(option => option.value === newsletter.sender_reply_to); + if (!foundValue) { + updateNewsletter({sender_reply_to: 'newsletter'}); + } + } + }, [config, replyToEmails, updateNewsletter, newsletter.sender_reply_to, newEmailAddressesFlag]); + + const onChange = useCallback((e: React.ChangeEvent) => { + setSenderReplyTo(e.target.value); + updateNewsletter({sender_reply_to: e.target.value || 'newsletter'}); + }, [updateNewsletter, setSenderReplyTo]); + + // Self-hosters, or legacy Pro users + if (!isManagedEmail(config) && !newEmailAddressesFlag) { + // Only allow some choices + return ( + option.value === newsletter.sender_reply_to)} - title="Reply-to email" - onSelect={option => updateNewsletter({sender_reply_to: option?.value})} - /> - ); - } - - const replyToRequired = !hasSendingDomain(config); - // Pro users without custom sending domains - return ( - updateNewsletter({sender_reply_to: e.target.value})} - onKeyDown={() => clearError('sender_reply_to')} - /> - ); - }; - const tabs: Tab[] = [ { id: 'generalSettings', @@ -237,7 +265,7 @@ const Sidebar: React.FC<{
updateNewsletter({sender_name: e.target.value})} /> {renderSenderEmailField()} - {renderReplyToEmailField()} +
{ if (newsletter.sender_reply_to === 'newsletter') { - if (isManagedEmail(config) && hasSendingDomain(config)) { + if (isManagedEmail(config) || !!config.labs.newEmailAddresses) { // No reply-to set // sender_reply_to currently doesn't allow empty values, we need to set it to 'newsletter' return '';