mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-30 22:34:01 -05:00
🐛 Fixed archived newsletters visible in Portal when email disabled (#21737)
ref ONC-225 - Ensures newsletter preferences are hidden in the Portal when email functionality is disabled. - Adds conditional logic in NewsletterManagement.js to check for the hasNewslettersEnabled prop. - Updates tests in AccountEmailPage.test.js and AccountHomePage.test.js to cover scenarios where newsletters are disabled. - Improves user experience by preventing the display of irrelevant settings when email is turned off.
This commit is contained in:
parent
011f6a71ed
commit
3233bae37c
7 changed files with 115 additions and 39 deletions
|
@ -77,9 +77,12 @@ function CommentsSection({updateCommentNotifications, isCommentsEnabled, enableC
|
|||
);
|
||||
}
|
||||
|
||||
function NewsletterPrefs({subscribedNewsletters, setSubscribedNewsletters}) {
|
||||
function NewsletterPrefs({subscribedNewsletters, setSubscribedNewsletters, hasNewslettersEnabled}) {
|
||||
const {site} = useContext(AppContext);
|
||||
const newsletters = getSiteNewsletters({site});
|
||||
if (!hasNewslettersEnabled) {
|
||||
return null;
|
||||
}
|
||||
return newsletters.map((newsletter) => {
|
||||
return (
|
||||
<NewsletterPrefSection
|
||||
|
@ -104,6 +107,7 @@ function ShowPaidMemberMessage({site, isPaid}) {
|
|||
}
|
||||
|
||||
export default function NewsletterManagement({
|
||||
hasNewslettersEnabled,
|
||||
notification,
|
||||
subscribedNewsletters,
|
||||
updateSubscribedNewsletters,
|
||||
|
@ -127,6 +131,7 @@ export default function NewsletterManagement({
|
|||
<div className='gh-portal-section flex'>
|
||||
<div className='gh-portal-list'>
|
||||
<NewsletterPrefs
|
||||
hasNewslettersEnabled={hasNewslettersEnabled}
|
||||
subscribedNewsletters={subscribedNewsletters}
|
||||
setSubscribedNewsletters={(updatedNewsletters) => {
|
||||
let newsletters = updatedNewsletters.map((d) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import AppContext from '../../AppContext';
|
||||
import {useContext, useEffect, useState} from 'react';
|
||||
import {isPaidMember, getSiteNewsletters} from '../../utils/helpers';
|
||||
import {isPaidMember, getSiteNewsletters, hasNewsletterSendingEnabled} from '../../utils/helpers';
|
||||
import {SYNTAX_I18NEXT} from '@doist/react-interpolate';
|
||||
import NewsletterManagement from '../common/NewsletterManagement';
|
||||
import Interpolate from '@doist/react-interpolate';
|
||||
|
@ -16,6 +16,7 @@ export default function AccountEmailPage() {
|
|||
const [hasInteracted, setHasInteracted] = useState(true);
|
||||
const siteNewsletters = getSiteNewsletters({site});
|
||||
|
||||
const hasNewslettersEnabled = hasNewsletterSendingEnabled({site});
|
||||
// Redirect to signin page if member is not available
|
||||
useEffect(() => {
|
||||
if (!member) {
|
||||
|
@ -90,6 +91,7 @@ export default function AccountEmailPage() {
|
|||
|
||||
return (
|
||||
<NewsletterManagement
|
||||
hasNewslettersEnabled={hasNewslettersEnabled}
|
||||
notification={newsletterUuid ? HeaderNotification : null}
|
||||
subscribedNewsletters={subscribedNewsletters}
|
||||
updateSubscribedNewsletters={(updatedNewsletters) => {
|
||||
|
|
|
@ -117,4 +117,21 @@ describe('Account Email Page', () => {
|
|||
const {mockOnActionFn} = setup({site: siteData, member: null});
|
||||
expect(mockOnActionFn).toHaveBeenCalledWith('switchPage', {page: 'signin'});
|
||||
});
|
||||
|
||||
test('newsletters are not visible when newsletters are disabled on the site but has comments enabled', async () => {
|
||||
const newsletterData = getNewslettersData({numOfNewsletters: 2});
|
||||
const siteData = getSiteData({
|
||||
newsletters: newsletterData,
|
||||
editorDefaultEmailRecipients: 'disabled',
|
||||
member: getMemberData({newsletters: newsletterData})
|
||||
});
|
||||
|
||||
const {getAllByTestId, getByText} = setup({site: siteData});
|
||||
const unsubscribeBtns = getAllByTestId(`toggle-wrapper`);
|
||||
|
||||
expect(getByText('Email preferences')).toBeInTheDocument();
|
||||
|
||||
expect(unsubscribeBtns).toHaveLength(1);
|
||||
expect(unsubscribeBtns[0].textContent).toContain('Get notified when someone replies to your comment');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {render, fireEvent} from '../../../utils/test-utils';
|
||||
import AccountHomePage from './AccountHomePage';
|
||||
import {site} from '../../../utils/fixtures';
|
||||
import {getSiteData} from '../../../utils/fixtures-generator';
|
||||
import {getSiteData, getNewslettersData} from '../../../utils/fixtures-generator';
|
||||
|
||||
const setup = (overrides) => {
|
||||
const {mockOnActionFn, ...utils} = render(
|
||||
|
@ -55,4 +55,30 @@ describe('Account Home Page', () => {
|
|||
expect(logoutBtn).toBeInTheDocument();
|
||||
expect(utils.queryByText('Email newsletter')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('newsletter settings is not visible when newsletters are disabled and comments are disabled', async () => {
|
||||
const siteData = getSiteData({
|
||||
editorDefaultEmailRecipients: 'disabled',
|
||||
commentsEnabled: 'off'
|
||||
});
|
||||
|
||||
const {utils} = setup({site: siteData});
|
||||
|
||||
expect(utils.queryByText('Email preferences')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Email preferences / settings is visible when newsletters are disabled and comments are enabled', async () => {
|
||||
const newsletterData = getNewslettersData({numOfNewsletters: 2});
|
||||
const siteData = getSiteData({
|
||||
newsletters: newsletterData,
|
||||
editorDefaultEmailRecipients: 'disabled',
|
||||
commentsEnabled: 'all'
|
||||
});
|
||||
|
||||
const {utils} = setup({site: siteData});
|
||||
|
||||
expect(utils.queryByText('Emails')).toBeInTheDocument();
|
||||
expect(utils.queryByText('Update your preferences')).toBeInTheDocument();
|
||||
expect(utils.queryByText('Newsletters')).not.toBeInTheDocument(); // there should be no sign of newsletters
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,6 +6,22 @@ import PaidAccountActions from './PaidAccountActions';
|
|||
import EmailNewsletterAction from './EmailNewsletterAction';
|
||||
import EmailPreferencesAction from './EmailPreferencesAction';
|
||||
|
||||
const shouldShowEmailPreferences = (site, member) => {
|
||||
return (
|
||||
hasMultipleNewsletters({site}) && hasNewsletterSendingEnabled({site}) ||
|
||||
hasCommentsEnabled({site}) ||
|
||||
isEmailSuppressed({member})
|
||||
);
|
||||
};
|
||||
|
||||
const shouldShowEmailNewsletterAction = (site) => {
|
||||
return (
|
||||
!hasMultipleNewsletters({site}) &&
|
||||
hasNewsletterSendingEnabled({site}) &&
|
||||
!hasCommentsEnabled({site})
|
||||
);
|
||||
};
|
||||
|
||||
const AccountActions = () => {
|
||||
const {member, onAction, site, t} = useContext(AppContext);
|
||||
const {name, email} = member;
|
||||
|
@ -17,9 +33,10 @@ const AccountActions = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const showEmailPreferences = hasMultipleNewsletters({site}) || hasCommentsEnabled({site}) || isEmailSuppressed({member});
|
||||
// Extract helper functions for complex conditions
|
||||
|
||||
const showEmailUnsubscribe = hasNewsletterSendingEnabled({site});
|
||||
const showEmailPreferences = shouldShowEmailPreferences(site, member);
|
||||
const showEmailNewsletterAction = shouldShowEmailNewsletterAction(site);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -39,20 +56,10 @@ const AccountActions = () => {
|
|||
</section>
|
||||
|
||||
<PaidAccountActions />
|
||||
{
|
||||
showEmailPreferences
|
||||
? <EmailPreferencesAction />
|
||||
: <></>
|
||||
}
|
||||
|
||||
{
|
||||
showEmailUnsubscribe && !showEmailPreferences
|
||||
? <EmailNewsletterAction />
|
||||
: <></>
|
||||
}
|
||||
|
||||
{showEmailPreferences && <EmailPreferencesAction />}
|
||||
{showEmailNewsletterAction && <EmailNewsletterAction />}
|
||||
</div>
|
||||
{/* <ProductList openUpdatePlan={openUpdatePlan}></ProductList> */}
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,35 +1,51 @@
|
|||
import AppContext from '../../../../AppContext';
|
||||
import {useContext} from 'react';
|
||||
import {isEmailSuppressed} from '../../../../utils/helpers';
|
||||
import {isEmailSuppressed, hasNewsletterSendingEnabled, hasCommentsEnabled} from '../../../../utils/helpers';
|
||||
import {ReactComponent as EmailDeliveryFailedIcon} from '../../../../images/icons/email-delivery-failed.svg';
|
||||
|
||||
function DisabledEmailNotice({t}) {
|
||||
return (
|
||||
<p className="gh-portal-email-notice">
|
||||
<EmailDeliveryFailedIcon className="gh-portal-email-notice-icon" />
|
||||
<span className="gh-mobile-only">{t('You\'re not receiving emails')}</span>
|
||||
<span className="gh-desktop-only">{t('You\'re currently not receiving emails')}</span>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
function EmailPreferencesAction() {
|
||||
const {onAction, member, t} = useContext(AppContext);
|
||||
const {onAction, member, t, site} = useContext(AppContext);
|
||||
|
||||
const emailSuppressed = isEmailSuppressed({member});
|
||||
const hasNewslettersEnabled = hasNewsletterSendingEnabled({site});
|
||||
const commentsEnabled = hasCommentsEnabled({site});
|
||||
const page = emailSuppressed ? 'emailSuppressed' : 'accountEmail';
|
||||
|
||||
const hasNewslettersAndCommentsDisabled = !hasNewslettersEnabled && !commentsEnabled;
|
||||
|
||||
const renderEmailNotice = () => {
|
||||
if (emailSuppressed || hasNewslettersAndCommentsDisabled) {
|
||||
return <DisabledEmailNotice t={t} />;
|
||||
}
|
||||
return <p>{t('Update your preferences')}</p>;
|
||||
};
|
||||
|
||||
return (
|
||||
<section>
|
||||
<div className='gh-portal-list-detail'>
|
||||
<div className="gh-portal-list-detail">
|
||||
<h3>{t('Emails')}</h3>
|
||||
{
|
||||
emailSuppressed
|
||||
? (
|
||||
<p className="gh-portal-email-notice">
|
||||
<EmailDeliveryFailedIcon className="gh-portal-email-notice-icon" />
|
||||
<span className="gh-mobile-only">{t('You\'re not receiving emails')}</span>
|
||||
<span className="gh-desktop-only">{t('You\'re currently not receiving emails')}</span>
|
||||
</p>
|
||||
)
|
||||
: <p>{t('Update your preferences')}</p>
|
||||
}
|
||||
{renderEmailNotice()}
|
||||
</div>
|
||||
<button className='gh-portal-btn gh-portal-btn-list' onClick={() => {
|
||||
onAction('switchPage', {
|
||||
page,
|
||||
lastPage: 'accountHome'
|
||||
});
|
||||
}} data-test-button='manage-newsletters'>
|
||||
<button
|
||||
className="gh-portal-btn gh-portal-btn-list"
|
||||
onClick={() => {
|
||||
onAction('switchPage', {
|
||||
page,
|
||||
lastPage: 'accountHome'
|
||||
});
|
||||
}}
|
||||
data-test-button="manage-newsletters"
|
||||
>
|
||||
{t('Manage')}
|
||||
</button>
|
||||
</section>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import AppContext from '../../AppContext';
|
||||
import ActionButton from '../common/ActionButton';
|
||||
import {useContext, useEffect, useState} from 'react';
|
||||
import {getSiteNewsletters} from '../../utils/helpers';
|
||||
import {getSiteNewsletters,hasNewsletterSendingEnabled} from '../../utils/helpers';
|
||||
import NewsletterManagement from '../common/NewsletterManagement';
|
||||
import CloseButton from '../common/CloseButton';
|
||||
import {ReactComponent as WarningIcon} from '../../images/icons/warning-fill.svg';
|
||||
|
@ -57,6 +57,8 @@ export default function UnsubscribePage() {
|
|||
const {comments_enabled: commentsEnabled} = site;
|
||||
const {enable_comment_notifications: enableCommentNotifications = false} = member || {};
|
||||
|
||||
const hasNewslettersEnabled = hasNewsletterSendingEnabled({site});
|
||||
|
||||
const updateNewsletters = async (newsletters) => {
|
||||
if (loggedInMember) {
|
||||
onAction('updateNewsletterPreference', {newsletters});
|
||||
|
@ -256,6 +258,7 @@ export default function UnsubscribePage() {
|
|||
|
||||
return (
|
||||
<NewsletterManagement
|
||||
hasNewslettersEnabled={hasNewslettersEnabled}
|
||||
notification={HeaderNotification}
|
||||
subscribedNewsletters={subscribedNewsletters}
|
||||
updateSubscribedNewsletters={async (newsletters) => {
|
||||
|
|
Loading…
Reference in a new issue