0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-04 02:01:58 -05:00

🐛 Prevented newsletter subscriptions from getting out of sync in Portal

refs https://linear.app/tryghost/issue/ENG-677
- UnsubscribePage is intended to be able to be used without logging in to Portal. The app context (member state) was not synchronized when logged in, causing conflicts in the client data vs. database.
- Now when a logged in member is found, the member object is manually updated to reflect the API response(s).
This commit is contained in:
Steve Larson 2024-02-27 19:02:06 -06:00
parent 6a4d36878e
commit e79fe1cbe3

View file

@ -41,9 +41,12 @@ async function updateMemberNewsletters({api, memberUuid, newsletters, enableComm
} }
} }
// NOTE: This modal is available even if not logged in, but because it's possible to also be logged in while making modifications,
// we need to update the member data in the context if logged in.
export default function UnsubscribePage() { export default function UnsubscribePage() {
const {site, pageData, onAction, t} = useContext(AppContext); const {site, pageData, member: loggedInMember, onAction, t} = useContext(AppContext);
const api = setupGhostApi({siteUrl: site.url}); const api = setupGhostApi({siteUrl: site.url});
// member is the member data fetched from the API based on the uuid and its state is limited to just this modal, not all of Portal
const [member, setMember] = useState(); const [member, setMember] = useState();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const siteNewsletters = getSiteNewsletters({site}); const siteNewsletters = getSiteNewsletters({site});
@ -56,6 +59,7 @@ export default function UnsubscribePage() {
const {comments_enabled: commentsEnabled} = site; const {comments_enabled: commentsEnabled} = site;
const {enable_comment_notifications: enableCommentNotifications = false} = member || {}; const {enable_comment_notifications: enableCommentNotifications = false} = member || {};
// This handles the url query param actions that ultimately launch this component/modal
useEffect(() => { useEffect(() => {
const ghostApi = setupGhostApi({siteUrl: site.url}); const ghostApi = setupGhostApi({siteUrl: site.url});
(async () => { (async () => {
@ -86,6 +90,10 @@ export default function UnsubscribePage() {
newsletters: [] newsletters: []
}); });
setSubscribedNewsletters(updatedData.newsletters); setSubscribedNewsletters(updatedData.newsletters);
// Update the member data in the context if logged in
if (loggedInMember) {
loggedInMember.newsletters = updatedData.newsletters;
}
} else if (pageData.newsletterUuid) { } else if (pageData.newsletterUuid) {
// Unsubscribe link for a specific newsletter // Unsubscribe link for a specific newsletter
const updatedData = await updateMemberNewsletters({ const updatedData = await updateMemberNewsletters({
@ -96,6 +104,10 @@ export default function UnsubscribePage() {
}) })
}); });
setSubscribedNewsletters(updatedData.newsletters); setSubscribedNewsletters(updatedData.newsletters);
// Update the member data in the context if logged in
if (loggedInMember) {
loggedInMember.newsletters = updatedData.newsletters;
}
} else if (pageData.comments && commentsEnabled) { } else if (pageData.comments && commentsEnabled) {
// Unsubscribe link for comments // Unsubscribe link for comments
const updatedData = await updateMemberNewsletters({ const updatedData = await updateMemberNewsletters({
@ -105,6 +117,9 @@ export default function UnsubscribePage() {
}); });
setMember(updatedData); setMember(updatedData);
if (loggedInMember) {
loggedInMember.enable_comment_notifications = false;
}
} }
})(); })();
}, [commentsEnabled, pageData.uuid, pageData.newsletterUuid, pageData.comments, site.url, siteNewsletters?.length]); }, [commentsEnabled, pageData.uuid, pageData.newsletterUuid, pageData.comments, site.url, siteNewsletters?.length]);
@ -229,10 +244,16 @@ export default function UnsubscribePage() {
setSubscribedNewsletters(newsletters); setSubscribedNewsletters(newsletters);
setHasInteracted(true); setHasInteracted(true);
await api.member.updateNewsletters({uuid: pageData.uuid, newsletters}); await api.member.updateNewsletters({uuid: pageData.uuid, newsletters});
if (loggedInMember) {
loggedInMember.newsletters = newsletters;
}
}} }}
updateCommentNotifications={async (enabled) => { updateCommentNotifications={async (enabled) => {
const updatedMember = await api.member.updateNewsletters({uuid: pageData.uuid, enableCommentNotifications: enabled}); const updatedMember = await api.member.updateNewsletters({uuid: pageData.uuid, enableCommentNotifications: enabled});
setMember(updatedMember); setMember(updatedMember);
if (loggedInMember) {
loggedInMember.enable_comment_notifications = enabled;
}
}} }}
unsubscribeAll={async () => { unsubscribeAll={async () => {
setHasInteracted(true); setHasInteracted(true);
@ -243,6 +264,10 @@ export default function UnsubscribePage() {
}); });
const updatedMember = await api.member.updateNewsletters({uuid: pageData.uuid, newsletters: [], enableCommentNotifications: false}); const updatedMember = await api.member.updateNewsletters({uuid: pageData.uuid, newsletters: [], enableCommentNotifications: false});
setMember(updatedMember); setMember(updatedMember);
if (loggedInMember) {
loggedInMember.newsletters = [];
loggedInMember.enable_comment_notifications = false;
}
}} }}
isPaidMember={member?.status !== 'free'} isPaidMember={member?.status !== 'free'}
isCommentsEnabled={commentsEnabled !== 'off'} isCommentsEnabled={commentsEnabled !== 'off'}