diff --git a/services/web/app/src/Features/User/UserPagesController.mjs b/services/web/app/src/Features/User/UserPagesController.mjs
index b4c72fd82f..e25c1ca8f8 100644
--- a/services/web/app/src/Features/User/UserPagesController.mjs
+++ b/services/web/app/src/Features/User/UserPagesController.mjs
@@ -11,6 +11,7 @@ import _ from 'lodash'
import { expressify } from '@overleaf/promise-utils'
import Features from '../../infrastructure/Features.mjs'
import Modules from '../../infrastructure/Modules.mjs'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.mjs'
async function settingsPage(req, res) {
const userId = SessionManager.getLoggedInUserId(req.session)
@@ -116,6 +117,8 @@ async function settingsPage(req, res) {
)
}
+ await SplitTestHandler.promises.getAssignment(req, res, 'email-notifications')
+
res.render('user/settings', {
title: 'account_settings',
user: {
diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json
index ff8f673ba6..cbd1becc43 100644
--- a/services/web/frontend/extracted-translations.json
+++ b/services/web/frontend/extracted-translations.json
@@ -550,6 +550,7 @@
"email_must_be_linked_to_institution": "",
"email_notifications_are_currently_in_beta": "",
"email_or_password_wrong_try_again": "",
+ "email_preferences": "",
"email_remove_by_date": "",
"emails_and_affiliations_explanation": "",
"emails_and_affiliations_title": "",
@@ -1047,6 +1048,7 @@
"make_primary": "",
"make_private": "",
"manage_beta_program_membership": "",
+ "manage_email_preferences": "",
"manage_files_from_your_dropbox_folder": "",
"manage_group_members_subtext": "",
"manage_group_settings": "",
@@ -1142,6 +1144,7 @@
"new_tag": "",
"new_tag_name": "",
"newsletter": "",
+ "newsletter_info_note": "",
"newsletter_onboarding_accept": "",
"next": "",
"next_page": "",
diff --git a/services/web/frontend/js/features/settings/components/notifications-section.tsx b/services/web/frontend/js/features/settings/components/notifications-section.tsx
new file mode 100644
index 0000000000..067e99ee70
--- /dev/null
+++ b/services/web/frontend/js/features/settings/components/notifications-section.tsx
@@ -0,0 +1,16 @@
+import { useTranslation } from 'react-i18next'
+
+function NotificationsSection() {
+ const { t } = useTranslation()
+
+ return (
+ <>
+
{t('email_preferences')}
+
+ {t('manage_email_preferences')}
+
+ >
+ )
+}
+
+export default NotificationsSection
diff --git a/services/web/frontend/js/features/settings/components/root.tsx b/services/web/frontend/js/features/settings/components/root.tsx
index 31e1b16541..c2a71b229f 100644
--- a/services/web/frontend/js/features/settings/components/root.tsx
+++ b/services/web/frontend/js/features/settings/components/root.tsx
@@ -15,13 +15,14 @@ import LeaveSection from './leave-section'
import * as eventTracking from '../../../infrastructure/event-tracking'
import { UserProvider } from '../../../shared/context/user-context'
import { SSOProvider } from '../context/sso-context'
-import { SplitTestProvider } from '@/shared/context/split-test-context'
import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
import useScrollToIdOnLoad from '../../../shared/hooks/use-scroll-to-id-on-load'
import { SSOAlert } from './emails/sso-alert'
import OLRow from '@/shared/components/ol/ol-row'
import OLCol from '@/shared/components/ol/ol-col'
import OLPageContentCard from '@/shared/components/ol/ol-page-content-card'
+import { isSplitTestEnabled } from '@/utils/splitTestUtils'
+import NotificationsSection from './notifications-section'
function SettingsPageRoot() {
const { isReady } = useWaitForI18n()
@@ -45,7 +46,7 @@ function SettingsPageRoot() {
function SettingsPageContent() {
const { t } = useTranslation()
const { isOverleaf, labsEnabled } = getMeta('ol-ExposedSettings')
-
+ const inNotificationsSplitTest = isSplitTestEnabled('email-notifications')
return (
@@ -66,11 +67,9 @@ function SettingsPageContent() {
-
-
-
-
-
+
+
+
{isOverleaf ? (
<>
@@ -86,7 +85,11 @@ function SettingsPageContent() {
{isOverleaf ? (
<>
-
+ {inNotificationsSplitTest ? (
+
+ ) : (
+
+ )}
>
diff --git a/services/web/frontend/js/utils/meta.ts b/services/web/frontend/js/utils/meta.ts
index 404d614bdc..75dc79e40e 100644
--- a/services/web/frontend/js/utils/meta.ts
+++ b/services/web/frontend/js/utils/meta.ts
@@ -66,6 +66,7 @@ import { Subscription as AdminSubscription } from '../../../types/admin/subscrip
import { AdminCapability } from '../../../types/admin-capabilities'
import { AlgoliaConfig } from '../../../modules/algolia-search/frontend/js/types'
import { WritefullPublicEnv } from '@wf/domain/writefull-public-env'
+import { UserNotificationPreferences } from '../../../types/notifications'
export interface Meta {
'ol-ExposedSettings': ExposedSettings
@@ -317,6 +318,7 @@ export interface Meta {
'ol-userCanExtendTrial': boolean
'ol-userCanNotStartRequestedTrial': boolean
'ol-userEmails': UserEmailData[]
+ 'ol-userNotificationPreferences': UserNotificationPreferences
'ol-userSettings': UserSettings
'ol-user_id': string | undefined
'ol-users': ManagedUser[]
diff --git a/services/web/frontend/stylesheets/pages/all.scss b/services/web/frontend/stylesheets/pages/all.scss
index de358919ea..e9e0e1778a 100644
--- a/services/web/frontend/stylesheets/pages/all.scss
+++ b/services/web/frontend/stylesheets/pages/all.scss
@@ -60,3 +60,4 @@
@import 'portals';
@import 'wiki';
@import 'templates';
+@import 'notification-settings';
diff --git a/services/web/frontend/stylesheets/pages/notification-settings.scss b/services/web/frontend/stylesheets/pages/notification-settings.scss
new file mode 100644
index 0000000000..0058c4af99
--- /dev/null
+++ b/services/web/frontend/stylesheets/pages/notification-settings.scss
@@ -0,0 +1,20 @@
+.notification-settings-container {
+ input {
+ margin-top: var(--spacing-01);
+ margin-bottom: auto;
+ accent-color: var(--green-50);
+ }
+
+ .setting-container {
+ display: flex;
+ gap: 10px;
+ }
+
+ h2 {
+ margin-bottom: 0;
+ }
+
+ h4 {
+ margin-bottom: 0;
+ }
+}
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index 4be04f15aa..fb4a0bbc22 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -698,6 +698,7 @@
"email_notifications_are_currently_in_beta": "Email notifications are currently in beta.",
"email_or_password_wrong_try_again": "Your email or password is incorrect. Please try again.",
"email_or_password_wrong_try_again_or_reset": "Your email or password is incorrect. Please try again, or <0>set or reset your password0>.",
+ "email_preferences": "Email preferences",
"email_remove_by_date": "If this is not done by __date__, it will be removed from the account.",
"email_required": "Email required",
"email_sent": "Email Sent",
@@ -1363,6 +1364,7 @@
"make_primary": "Make primary",
"make_private": "Make private",
"manage_beta_program_membership": "Manage beta program membership",
+ "manage_email_preferences": "Manage email preferences",
"manage_files_from_your_dropbox_folder": "Manage files from your Dropbox folder",
"manage_group_members_subtext": "Add or remove members from your group subscription",
"manage_group_settings": "Manage group settings",
diff --git a/services/web/types/notifications.ts b/services/web/types/notifications.ts
new file mode 100644
index 0000000000..0360d01490
--- /dev/null
+++ b/services/web/types/notifications.ts
@@ -0,0 +1,7 @@
+type GlobalNotificationPreferences = {
+ muteAllNotifications: boolean
+}
+
+export type UserNotificationPreferences = {
+ newsletter: boolean
+} & GlobalNotificationPreferences