diff --git a/apps/admin-x-framework/src/api/users.ts b/apps/admin-x-framework/src/api/users.ts index b5c8b855a4..4eda024595 100644 --- a/apps/admin-x-framework/src/api/users.ts +++ b/apps/admin-x-framework/src/api/users.ts @@ -33,6 +33,7 @@ export type User = { mention_notifications: boolean; recommendation_notifications: boolean; milestone_notifications: boolean; + donation_notifications: boolean; roles: UserRole[]; url: string; } diff --git a/apps/admin-x-framework/src/test/responses/users.json b/apps/admin-x-framework/src/test/responses/users.json index f1616a5985..4a87e35864 100644 --- a/apps/admin-x-framework/src/test/responses/users.json +++ b/apps/admin-x-framework/src/test/responses/users.json @@ -25,6 +25,7 @@ "mention_notifications": true, "recommendation_notifications": true, "milestone_notifications": true, + "donation_notifications": true, "created_at": "2023-06-26T00:21:57.000Z", "updated_at": "2023-06-26T00:21:58.000Z", "roles": [ @@ -63,6 +64,7 @@ "mention_notifications": true, "recommendation_notifications": true, "milestone_notifications": true, + "donation_notifications": true, "created_at": "2023-06-26T00:21:22.000Z", "updated_at": "2023-06-26T00:21:22.000Z", "roles": [ @@ -101,6 +103,7 @@ "mention_notifications": true, "recommendation_notifications": true, "milestone_notifications": true, + "donation_notifications": true, "created_at": "2023-06-26T00:20:56.000Z", "updated_at": "2023-06-26T00:20:57.000Z", "roles": [ @@ -139,6 +142,7 @@ "mention_notifications": true, "recommendation_notifications": true, "milestone_notifications": true, + "donation_notifications": true, "created_at": "2023-05-05T00:55:15.000Z", "updated_at": "2023-06-25T23:34:33.000Z", "roles": [ @@ -177,6 +181,7 @@ "mention_notifications": true, "recommendation_notifications": true, "milestone_notifications": true, + "donation_notifications": true, "created_at": "2023-06-22T05:39:57.000Z", "updated_at": "2023-06-22T05:39:58.000Z", "roles": [ diff --git a/apps/admin-x-settings/src/components/settings/general/users/EmailNotifications.tsx b/apps/admin-x-settings/src/components/settings/general/users/EmailNotifications.tsx index 00f7369d4e..d1c573e7d7 100644 --- a/apps/admin-x-settings/src/components/settings/general/users/EmailNotifications.tsx +++ b/apps/admin-x-settings/src/components/settings/general/users/EmailNotifications.tsx @@ -2,9 +2,14 @@ import CustomHeader from './CustomHeader'; import useFeatureFlag from '../../../../hooks/useFeatureFlag'; import {SettingGroup, SettingGroupContent, Toggle} from '@tryghost/admin-x-design-system'; import {User, hasAdminAccess} from '@tryghost/admin-x-framework/api/users'; +import {checkStripeEnabled} from '@tryghost/admin-x-framework/api/settings'; +import {useGlobalData} from '../../../providers/GlobalDataProvider'; const EmailNotificationsInputs: React.FC<{ user: User; setUserData: (user: User) => void; }> = ({user, setUserData}) => { + const {config, settings} = useGlobalData(); const hasWebmentions = useFeatureFlag('webmentions'); + const hasTipsAndDonations = useFeatureFlag('tipsAndDonations'); + const hasStripeEnabled = checkStripeEnabled(settings || [], config || {}); return ( @@ -72,6 +77,15 @@ const EmailNotificationsInputs: React.FC<{ user: User; setUserData: (user: User) setUserData?.({...user, milestone_notifications: e.target.checked}); }} /> + {hasTipsAndDonations && hasStripeEnabled && { + setUserData?.({...user, donation_notifications: e.target.checked}); + }} + />} } ); diff --git a/apps/admin-x-settings/test/acceptance/general/users/profile.test.ts b/apps/admin-x-settings/test/acceptance/general/users/profile.test.ts index 4c7f10ae28..18f6b4516c 100644 --- a/apps/admin-x-settings/test/acceptance/general/users/profile.test.ts +++ b/apps/admin-x-settings/test/acceptance/general/users/profile.test.ts @@ -1,7 +1,7 @@ import {StaffTokenResponseType} from '@tryghost/admin-x-framework/api/staffToken'; import {expect, test} from '@playwright/test'; import {globalDataRequests} from '../../../utils/acceptance'; -import {mockApi, responseFixtures, testUrlValidation} from '@tryghost/admin-x-framework/test/acceptance'; +import {mockApi, responseFixtures, settingsWithStripe, testUrlValidation, toggleLabsFlag} from '@tryghost/admin-x-framework/test/acceptance'; test.describe('User profile', async () => { test('Supports editing user profiles', async ({page}) => { @@ -291,6 +291,75 @@ test.describe('User profile', async () => { await expect(modal.getByLabel(/Milestones/)).toBeHidden(); }); + test('Shows donation notification option when Stripe enabled', async ({page}) => { + toggleLabsFlag('tipsAndDonations', true); + + const userToEdit = responseFixtures.users.users.find(user => user.email === 'administrator@test.com')!; + + const {lastApiRequests} = await mockApi({page, requests: { + ...globalDataRequests, + browseSettings: {...globalDataRequests.browseSettings, response: settingsWithStripe}, + browseUsers: {method: 'GET', path: '/users/?limit=100&include=roles', response: responseFixtures.users}, + editUser: {method: 'PUT', path: `/users/${userToEdit.id}/?include=roles`, response: { + users: [{ + ...userToEdit + }] + }} + }}); + + await page.goto('/'); + + const section = page.getByTestId('users'); + const activeTab = section.locator('[role=tabpanel]:not(.hidden)'); + + await section.getByRole('tab', {name: 'Administrators'}).click(); + + const listItem = activeTab.getByTestId('user-list-item').last(); + await listItem.hover(); + await listItem.getByRole('button', {name: 'Edit'}).click(); + + const modal = page.getByTestId('user-detail-modal'); + + await expect(modal.getByLabel(/Tips & donations/)).toBeVisible(); + await expect(modal.getByLabel(/Tips & donations/)).toHaveAttribute('aria-checked', 'true'); + + await modal.getByLabel(/Tips & donations/).uncheck(); + + await expect(modal.getByLabel(/Tips & donations/)).toHaveAttribute('aria-checked', 'false'); + + await modal.getByRole('button', {name: 'Save'}).click(); + + expect(lastApiRequests.editUser?.body).toMatchObject({ + users: [{ + donation_notifications: false + }] + }); + }); + + test('Hides donation notification option when Stripe disabled', async ({page}) => { + toggleLabsFlag('tipsAndDonations', true); + + await mockApi({page, requests: { + ...globalDataRequests, + browseUsers: {method: 'GET', path: '/users/?limit=100&include=roles', response: responseFixtures.users} + }}); + + await page.goto('/'); + + const section = page.getByTestId('users'); + const activeTab = section.locator('[role=tabpanel]:not(.hidden)'); + + await section.getByRole('tab', {name: 'Administrators'}).click(); + + const listItem = activeTab.getByTestId('user-list-item').last(); + await listItem.hover(); + await listItem.getByRole('button', {name: 'Edit'}).click(); + + const modal = page.getByTestId('user-detail-modal'); + + await expect(modal.getByLabel(/Tips & donations/)).not.toBeVisible(); + }); + test('Warns when leaving without saving', async ({page}) => { const userToEdit = responseFixtures.users.users.find(user => user.email === 'administrator@test.com')!;