diff --git a/services/web/app/src/Features/Project/ProjectListController.js b/services/web/app/src/Features/Project/ProjectListController.js
index a8be77ab74..8a72b2aa07 100644
--- a/services/web/app/src/Features/Project/ProjectListController.js
+++ b/services/web/app/src/Features/Project/ProjectListController.js
@@ -433,6 +433,12 @@ async function projectListPage(req, res, next) {
'bootstrap-5-project-dashboard'
)
+ await SplitTestHandler.promises.getAssignment(
+ req,
+ res,
+ 'ai-fake-door-offering-test'
+ )
+
res.render('project/list-react', {
title: 'your_projects',
usersBestSubscription,
diff --git a/services/web/config/settings.defaults.js b/services/web/config/settings.defaults.js
index c2e8df5f76..cad13ab815 100644
--- a/services/web/config/settings.defaults.js
+++ b/services/web/config/settings.defaults.js
@@ -892,6 +892,7 @@ module.exports = {
editorLeftMenuManageTemplate: [],
oauth2Server: [],
managedGroupSubscriptionEnrollmentNotification: [],
+ userNotifications: [],
managedGroupEnrollmentInvite: [],
ssoCertificateInfo: [],
},
diff --git a/services/web/frontend/js/features/project-list/components/notifications/labs-ai-promo-banner.tsx b/services/web/frontend/js/features/project-list/components/notifications/labs-ai-promo-banner.tsx
deleted file mode 100644
index f8d382be58..0000000000
--- a/services/web/frontend/js/features/project-list/components/notifications/labs-ai-promo-banner.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import { memo, useCallback, useState } from 'react'
-import Notification from './notification'
-import customLocalStorage from '@/infrastructure/local-storage'
-import OLButton from '@/features/ui/components/ol/ol-button'
-import getMeta from '@/utils/meta'
-import * as eventTracking from '../../../../infrastructure/event-tracking'
-import { useTranslation } from 'react-i18next'
-
-function LabsAiPromoBanner() {
- const user = getMeta('ol-user')
- const cannotUseAi = getMeta('ol-cannot-use-ai')
- const { t } = useTranslation()
-
- const [show, setShow] = useState(() => {
- const dismissed = customLocalStorage.getItem(
- 'has_dismissed_labs_ai_promo_banner'
- )
- if (dismissed || cannotUseAi) {
- return false
- }
-
- const show = user?.labsProgram === true && !user?.features?.aiErrorAssistant
- return show
- })
-
- const handleClose = useCallback(() => {
- eventTracking.sendMB('promo-dismiss', {
- name: 'labs-ai-experiment-promo',
- })
- customLocalStorage.setItem('has_dismissed_labs_ai_promo_banner', true)
- setShow(false)
- }, [setShow])
-
- const handleClick = useCallback(() => {
- eventTracking.sendMB('promo-click', {
- name: 'labs-ai-experiment-promo',
- content: 'try-now',
- })
- customLocalStorage.setItem('has_dismissed_labs_ai_promo_banner', true)
- }, [])
-
- if (!show) {
- return null
- }
-
- return (
-
-
{t('get_early_access_to_ai')}}
- action={
-
- {t('try_now')}
-
- }
- />
-
- )
-}
-
-export default memo(LabsAiPromoBanner)
diff --git a/services/web/frontend/js/features/project-list/components/notifications/user-notifications.tsx b/services/web/frontend/js/features/project-list/components/notifications/user-notifications.tsx
index 9aab99d0b5..9282755da6 100644
--- a/services/web/frontend/js/features/project-list/components/notifications/user-notifications.tsx
+++ b/services/web/frontend/js/features/project-list/components/notifications/user-notifications.tsx
@@ -1,4 +1,4 @@
-import { JSXElementConstructor, useState } from 'react'
+import { JSXElementConstructor, useState, ElementType } from 'react'
import Common from './groups/common'
import Institution from './groups/institution'
import ConfirmEmail from './groups/confirm-email'
@@ -12,11 +12,16 @@ import customLocalStorage from '../../../../infrastructure/local-storage'
import { sendMB } from '../../../../infrastructure/event-tracking'
import GeoBanners from './geo-banners'
import AccessibilitySurveyBanner from './accessibility-survey-banner'
-import LabsAiPromoBanner from './labs-ai-promo-banner'
const [enrollmentNotificationModule] = importOverleafModules(
'managedGroupSubscriptionEnrollmentNotification'
)
+
+const moduleNotifications = importOverleafModules('userNotifications') as {
+ import: { default: ElementType }
+ path: string
+}[]
+
const EnrollmentNotification: JSXElementConstructor<{
groupId: string
groupName: string
@@ -80,7 +85,11 @@ function UserNotifications() {
setDismissedWritefull(true)
}}
/>
-
+ {moduleNotifications.map(({ import: { default: Component }, path }) => (
+
+
+
+ ))}
)
diff --git a/services/web/frontend/stylesheets/modules/labs.less b/services/web/frontend/stylesheets/modules/labs.less
index 01c1ad112f..e9ffb78987 100644
--- a/services/web/frontend/stylesheets/modules/labs.less
+++ b/services/web/frontend/stylesheets/modules/labs.less
@@ -76,3 +76,8 @@
}
}
}
+
+.fake-door-container {
+ margin-top: 8em;
+ margin-bottom: 12em;
+}
diff --git a/services/web/test/frontend/features/project-list/components/notifications.test.tsx b/services/web/test/frontend/features/project-list/components/notifications.test.tsx
index 4e89c1e5c7..c9cbe8e6ab 100644
--- a/services/web/test/frontend/features/project-list/components/notifications.test.tsx
+++ b/services/web/test/frontend/features/project-list/components/notifications.test.tsx
@@ -28,6 +28,7 @@ import ConfirmEmail from '../../../../../frontend/js/features/project-list/compo
import ReconfirmationInfo from '../../../../../frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirmation-info'
import UserNotifications from '../../../../../frontend/js/features/project-list/components/notifications/user-notifications'
import { ProjectListProvider } from '../../../../../frontend/js/features/project-list/context/project-list-context'
+import { SplitTestProvider } from '@/shared/context/split-test-context'
import {
Notification,
Institution as InstitutionType,
@@ -50,7 +51,9 @@ const renderWithinProjectListProvider = (Component: React.ComponentType) => {
render(, {
wrapper: ({ children }) => (
-
+
+
+
),
})
diff --git a/services/web/types/assets.d.ts b/services/web/types/assets.d.ts
index 63199ce7ee..84a7393dd9 100644
--- a/services/web/types/assets.d.ts
+++ b/services/web/types/assets.d.ts
@@ -1 +1,2 @@
declare module '*.svg'
+declare module '*.png'