0
Fork 0
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:
Ronald Langeveld 2024-12-16 13:14:21 +07:00 committed by GitHub
parent 011f6a71ed
commit 3233bae37c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 115 additions and 39 deletions

View file

@ -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) => {

View file

@ -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) => {

View file

@ -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');
});
});

View file

@ -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
});
});

View file

@ -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>
);
};

View file

@ -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>

View file

@ -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) => {