Skip to content

Commit b3bd8d1

Browse files
authored
Removed welcome email editor feature flag (#26916)
closes https://linear.app/ghost/issue/NY-1105 This change should have no user impact. All it does is remove the flag, enabling the feature for everyone. In addition to automated tests, I manually verified that the new welcome email editor shows up.
1 parent 3e33f9b commit b3bd8d1

File tree

5 files changed

+8
-116
lines changed

5 files changed

+8
-116
lines changed

apps/admin-x-settings/src/components/settings/membership/member-emails/welcome-email-modal.tsx

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import React from 'react';
33
import {useCallback, useEffect, useRef, useState} from 'react';
44

55
import MemberEmailEditor from './member-email-editor';
6-
import useFeatureFlag from '../../../../hooks/use-feature-flag';
76
import {Hint, Button as LegacyButton, Modal, TextField} from '@tryghost/admin-x-design-system';
87
import {confirmIfDirty} from '@tryghost/admin-x-design-system';
98
import {useForm, useHandleError} from '@tryghost/admin-x-framework/hooks';
@@ -125,7 +124,6 @@ const WelcomeEmailModal = NiceModal.create<WelcomeEmailModalProps>(({emailType =
125124
const {settings} = useGlobalData();
126125
const [siteTitle] = getSettingValues<string>(settings, ['title']);
127126
const {resolvedSenderName, resolvedSenderEmail, resolvedReplyToEmail, hasDistinctReplyTo} = useWelcomeEmailSenderDetails(automatedEmail);
128-
const welcomeEmailEditorEnabled = useFeatureFlag('welcomeEmailEditor');
129127
const emailTypeLabel = emailType === 'paid' ? 'Paid' : 'Free';
130128
const modalTitle = `${emailTypeLabel} members welcome email`;
131129

@@ -220,99 +218,6 @@ const WelcomeEmailModal = NiceModal.create<WelcomeEmailModalProps>(({emailType =
220218
}
221219
}, [setFormState, updateForm]);
222220

223-
if (!welcomeEmailEditorEnabled) {
224-
return (
225-
<Modal
226-
afterClose={() => {
227-
updateRoute('memberemails');
228-
}}
229-
dirty={isDirty}
230-
footer={false}
231-
header={false}
232-
testId='welcome-email-modal'
233-
width={672}
234-
>
235-
<div className='-mx-8 flex h-[calc(100vh-16vmin)] flex-col overflow-y-auto dark:bg-grey-975!'>
236-
<div className='sticky top-0 z-10 flex flex-col gap-2 border-b border-grey-100 bg-white p-5 dark:border-grey-900 dark:bg-grey-975'>
237-
<div className='mb-2 flex items-center justify-between'>
238-
<h3 className='text-lg font-semibold'>{modalTitle}</h3>
239-
<div className='flex items-center gap-2'>
240-
<div ref={dropdownRef} className='relative'>
241-
<LegacyButton
242-
className='border border-grey-200 font-semibold hover:border-grey-300 hover:bg-white! dark:border-grey-900 dark:hover:border-grey-800 dark:hover:bg-grey-950!'
243-
color="clear"
244-
icon='send'
245-
label="Test"
246-
onClick={() => setShowTestDropdown(!showTestDropdown)}
247-
/>
248-
{showTestDropdown && (
249-
<TestEmailDropdown automatedEmailId={automatedEmail.id} lexical={formState.lexical} subject={formState.subject} validateForm={validate} onClose={() => setShowTestDropdown(false)} />
250-
)}
251-
</div>
252-
<LegacyButton
253-
color={okProps.color}
254-
disabled={okProps.disabled}
255-
label={saveButtonLabel}
256-
onClick={async () => await handleSave({fakeWhenUnchanged: true})}
257-
/>
258-
</div>
259-
</div>
260-
<div className='flex items-center'>
261-
<div className='w-20 shrink-0 font-semibold'>From:</div>
262-
<div className='min-w-0 grow'>
263-
<span className='flex gap-1 truncate whitespace-nowrap'>
264-
<span>{resolvedSenderName}</span>
265-
<span className='text-grey-700 dark:text-grey-400'>{`<${resolvedSenderEmail}>`}</span>
266-
</span>
267-
</div>
268-
</div>
269-
{hasDistinctReplyTo && (
270-
<div className='flex items-center py-0.5'>
271-
<div className='w-20 shrink-0 font-semibold'>Reply-to:</div>
272-
<div className='grow text-grey-700 dark:text-grey-400'>
273-
{resolvedReplyToEmail}
274-
</div>
275-
</div>
276-
)}
277-
<div className='flex items-center'>
278-
<div className='w-20 shrink-0 font-semibold'>Subject:</div>
279-
<div className='grow'>
280-
<TextField
281-
className='w-full'
282-
error={Boolean(errors.subject)}
283-
hint={errors.subject || ''}
284-
maxLength={300}
285-
placeholder={`Welcome to ${siteTitle}`}
286-
value={formState.subject}
287-
onChange={e => updateForm(state => ({...state, subject: e.target.value}))}
288-
/>
289-
</div>
290-
</div>
291-
</div>
292-
<div className='flex grow flex-col bg-grey-50 p-8 dark:bg-grey-975'>
293-
<div
294-
className={`mx-auto flex w-full max-w-[600px] grow flex-col rounded border bg-white p-8 shadow-sm dark:bg-grey-950/25 dark:shadow-none ${errors.lexical ? 'border-red' : 'border-grey-200 dark:border-grey-925'}`}
295-
data-testid='welcome-email-editor'
296-
onFocus={() => {
297-
hasEditorBeenFocused.current = true;
298-
}}
299-
>
300-
<MemberEmailEditor
301-
key={automatedEmail?.id || 'new'}
302-
className='welcome-email-editor'
303-
placeholder='Write your welcome email content...'
304-
305-
value={automatedEmail?.lexical || ''}
306-
onChange={handleEditorChange}
307-
/>
308-
</div>
309-
{errors.lexical && <Hint className='mt-2 mr-auto ml-8 max-w-[600px]' color='red'>{errors.lexical}</Hint>}
310-
</div>
311-
</div>
312-
</Modal>
313-
);
314-
}
315-
316221
return (
317222
<Modal
318223
afterClose={() => {

apps/admin-x-settings/test/acceptance/membership/member-welcome-emails.test.ts

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,10 @@ const newslettersRequest = {
3434
browseNewslettersLimit: {method: 'GET', path: '/newsletters/?filter=status%3Aactive&limit=1', response: responseFixtures.newsletters}
3535
};
3636

37-
const configWithWelcomeEmailEditorEnabled = {
37+
const configWithTenorEnabled = {
3838
...responseFixtures.config,
3939
config: {
4040
...responseFixtures.config.config,
41-
labs: {
42-
...responseFixtures.config.config.labs,
43-
welcomeEmailEditor: true
44-
}
45-
}
46-
};
47-
48-
const configWithWelcomeEmailEditorAndTenorEnabled = {
49-
...configWithWelcomeEmailEditorEnabled,
50-
config: {
51-
...configWithWelcomeEmailEditorEnabled.config,
5241
tenor: {
5342
googleApiKey: 'test-tenor-key',
5443
contentFilter: 'off'
@@ -249,7 +238,7 @@ test.describe('Member emails settings', async () => {
249238
const {lastApiRequests} = await mockApi({page, requests: {
250239
...globalDataRequests,
251240
...newslettersRequest,
252-
browseConfig: {method: 'GET', path: '/config/', response: configWithWelcomeEmailEditorEnabled},
241+
browseConfig: {method: 'GET', path: '/config/', response: responseFixtures.config},
253242
browseAutomatedEmails: {method: 'GET', path: '/automated_emails/', response: automatedEmailsFixture},
254243
fetchOembed: {
255244
method: 'GET',
@@ -288,7 +277,7 @@ test.describe('Member emails settings', async () => {
288277
const {lastApiRequests} = await mockApi({page, requests: {
289278
...globalDataRequests,
290279
...newslettersRequest,
291-
browseConfig: {method: 'GET', path: '/config/', response: configWithWelcomeEmailEditorEnabled},
280+
browseConfig: {method: 'GET', path: '/config/', response: responseFixtures.config},
292281
browseAutomatedEmails: {method: 'GET', path: '/automated_emails/', response: automatedEmailsFixture},
293282
fetchOembed: {
294283
method: 'GET',
@@ -337,7 +326,7 @@ test.describe('Member emails settings', async () => {
337326
await mockApi({page, requests: {
338327
...globalDataRequests,
339328
...newslettersRequest,
340-
browseConfig: {method: 'GET', path: '/config/', response: configWithWelcomeEmailEditorEnabled},
329+
browseConfig: {method: 'GET', path: '/config/', response: responseFixtures.config},
341330
browseAutomatedEmails: {method: 'GET', path: '/automated_emails/', response: automatedEmailsFixture}
342331
}});
343332

@@ -365,7 +354,7 @@ test.describe('Member emails settings', async () => {
365354
await mockApi({page, requests: {
366355
...globalDataRequests,
367356
...newslettersRequest,
368-
browseConfig: {method: 'GET', path: '/config/', response: configWithWelcomeEmailEditorEnabled},
357+
browseConfig: {method: 'GET', path: '/config/', response: responseFixtures.config},
369358
browseAutomatedEmails: {method: 'GET', path: '/automated_emails/', response: automatedEmailsFixture}
370359
}});
371360

@@ -406,7 +395,7 @@ test.describe('Member emails settings', async () => {
406395
await mockApi({page, requests: {
407396
...globalDataRequests,
408397
...newslettersRequest,
409-
browseConfig: {method: 'GET', path: '/config/', response: configWithWelcomeEmailEditorEnabled},
398+
browseConfig: {method: 'GET', path: '/config/', response: responseFixtures.config},
410399
browseAutomatedEmails: {method: 'GET', path: '/automated_emails/', response: automatedEmailsFixture}
411400
}});
412401

@@ -449,7 +438,7 @@ test.describe('Member emails settings', async () => {
449438
await mockApi({page, requests: {
450439
...globalDataRequests,
451440
...newslettersRequest,
452-
browseConfig: {method: 'GET', path: '/config/', response: configWithWelcomeEmailEditorAndTenorEnabled},
441+
browseConfig: {method: 'GET', path: '/config/', response: configWithTenorEnabled},
453442
browseAutomatedEmails: {method: 'GET', path: '/automated_emails/', response: automatedEmailsFixture}
454443
}});
455444

ghost/core/core/shared/labs.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ const GA_FEATURES = [
2525
'explore',
2626
'commentModeration',
2727
'featurebaseFeedback',
28-
'welcomeEmailEditor',
2928
'transistor'
3029
];
3130

ghost/core/test/e2e-api/admin/__snapshots__/config.test.js.snap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ Object {
3131
"transistor": true,
3232
"urlCache": true,
3333
"verificationFlow": true,
34-
"welcomeEmailEditor": true,
3534
"welcomeEmailsDesignCustomization": true,
3635
},
3736
"mail": "",

ghost/core/test/e2e-api/admin/__snapshots__/settings.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1675,7 +1675,7 @@ exports[`Settings API Edit can edit Stripe settings when Stripe Connect limit is
16751675
Object {
16761676
"access-control-allow-origin": "http://127.0.0.1:2369",
16771677
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
1678-
"content-length": "5171",
1678+
"content-length": "5143",
16791679
"content-type": "application/json; charset=utf-8",
16801680
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
16811681
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,

0 commit comments

Comments
 (0)