diff --git a/services/web/app/src/Features/Project/ProjectListController.mjs b/services/web/app/src/Features/Project/ProjectListController.mjs index 6ae7080961..88541ee826 100644 --- a/services/web/app/src/Features/Project/ProjectListController.mjs +++ b/services/web/app/src/Features/Project/ProjectListController.mjs @@ -115,7 +115,7 @@ async function projectListPage(req, res, next) { }) const user = await User.findById( userId, - `email emails features alphaProgram betaProgram lastPrimaryEmailCheck signUpDate${ + `email emails features alphaProgram betaProgram lastPrimaryEmailCheck signUpDate refProviders${ isSaas ? ' enrollment writefull completedTutorials' : '' }` ) @@ -126,6 +126,8 @@ async function projectListPage(req, res, next) { return } + user.refProviders = _.mapValues(user.refProviders, Boolean) + if (isSaas) { await SplitTestSessionHandler.promises.sessionMaintenance(req, user) @@ -418,6 +420,15 @@ async function projectListPage(req, res, next) { 'sidebar-navigation-ui-update' ) + // Get the user's assignment for the papers notification banner split test, + // which populates splitTestVariants with a value for the split test name and + // allows Pug to send it to the browser + await SplitTestHandler.promises.getAssignment( + req, + res, + 'papers-notification-banner' + ) + res.render('project/list-react', { title: 'your_projects', usersBestSubscription, diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index b65269eeee..c5595af725 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -122,6 +122,7 @@ "all_projects_will_be_transferred_immediately": "", "all_these_experiments_are_available_exclusively": "", "allows_to_search_by_author_title_etc_possible_to_pull_results_directly_from_your_reference_manager_if_connected": "", + "already_have_a_papers_account": "", "already_subscribed_try_refreshing_the_page": "", "an_email_has_already_been_sent_to": "", "an_error_occured_while_restoring_project": "", @@ -1862,6 +1863,7 @@ "try_for_free": "", "try_it_for_free": "", "try_now": "", + "try_papers_for_free": "", "try_premium_for_free": "", "try_recompile_project_or_troubleshoot": "", "try_relinking_provider": "", @@ -2072,6 +2074,7 @@ "you_can_manage_your_reference_manager_integrations_from_your_account_settings_page": "", "you_can_now_enable_sso": "", "you_can_now_log_in_sso": "", + "you_can_now_sync_your_papers_library_directly_with_your_overleaf_projects": "", "you_can_request_a_maximum_of_limit_fixes_per_day": "", "you_can_select_or_invite_collaborator": "", "you_can_select_or_invite_collaborator_plural": "", diff --git a/services/web/frontend/js/features/project-list/components/notifications/hooks/use-papers-notification.ts b/services/web/frontend/js/features/project-list/components/notifications/hooks/use-papers-notification.ts new file mode 100644 index 0000000000..2d5426bc39 --- /dev/null +++ b/services/web/frontend/js/features/project-list/components/notifications/hooks/use-papers-notification.ts @@ -0,0 +1,16 @@ +import { useFeatureFlag } from '@/shared/context/split-test-context' +import getMeta from '@/utils/meta' + +export const usePapersNotification = () => { + const user = getMeta('ol-user') + const inRollout = useFeatureFlag('papers-notification-banner') + const shouldShow = + inRollout && + user && + user.features?.references && + !user.refProviders?.mendeley && + !user.refProviders?.zotero && + !user.refProviders?.papers + + return { shouldShow } +} diff --git a/services/web/frontend/js/features/project-list/components/notifications/papers-notification-banner.tsx b/services/web/frontend/js/features/project-list/components/notifications/papers-notification-banner.tsx new file mode 100644 index 0000000000..5cb0c0e024 --- /dev/null +++ b/services/web/frontend/js/features/project-list/components/notifications/papers-notification-banner.tsx @@ -0,0 +1,86 @@ +import { memo, useCallback, useEffect } from 'react' +import Notification from './notification' +import { Trans, useTranslation } from 'react-i18next' +import OLButton from '@/features/ui/components/ol/ol-button' +import usePersistedState from '@/shared/hooks/use-persisted-state' +import { sendMB } from '@/infrastructure/event-tracking' + +function PapersNotificationBanner() { + const { t } = useTranslation() + const [dismissed, setDismissed] = usePersistedState( + 'papers-notification-banner-dismissed', + false + ) + + useEffect(() => { + if (!dismissed) { + sendMB('promo-prompt', { + location: 'dashboard-banner', + name: 'papers-integration', + }) + } + }, [dismissed]) + + const handleClose = useCallback(() => { + sendMB('promo-dismiss', { + location: 'dashboard-banner', + name: 'papers-integration', + }) + setDismissed(true) + }, [setDismissed]) + + const handlePapersButtonClick = useCallback(() => { + sendMB('promo-click', { + location: 'dashboard-banner', + name: 'papers-integration', + type: 'click-try-for-free', + }) + }, []) + + const handleSettingsLinkClick = useCallback(() => { + sendMB('promo-click', { + location: 'dashboard-banner', + name: 'papers-integration', + type: 'click-link-account', + }) + }, []) + + if (dismissed) return null + + return ( + + , + ]} + /> +

+ } + action={ + + {t('try_papers_for_free')} + + } + /> + ) +} + +export default memo(PapersNotificationBanner) 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 ef1fd85088..8edb6a53cc 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 @@ -13,6 +13,8 @@ import { DeprecatedBrowser, isDeprecatedBrowser, } from '@/shared/components/deprecated-browser' +import PapersNotificationBanner from './papers-notification-banner' +import { usePapersNotification } from './hooks/use-papers-notification' const [enrollmentNotificationModule] = importOverleafModules( 'managedGroupSubscriptionEnrollmentNotification' @@ -32,6 +34,8 @@ function UserNotifications() { const groupSubscriptionsPendingEnrollment = getMeta('ol-groupSubscriptionsPendingEnrollment') || [] + const { shouldShow: showPapersNotificationBanner } = usePapersNotification() + return (
    @@ -52,6 +56,7 @@ function UserNotifications() { {USGovBanner && } + {showPapersNotificationBanner && } {isDeprecatedBrowser() && } diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 4201c15d75..f0339343ee 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -148,6 +148,7 @@ "all_the_pros_of_our_standard_plan_plus_unlimited_collab": "All the pros of our standard plan, plus unlimited collaborators per project.", "all_these_experiments_are_available_exclusively": "All these experiments are available exclusively to members of the Labs program. If you sign up, you can choose which experiments you want to try.", "allows_to_search_by_author_title_etc_possible_to_pull_results_directly_from_your_reference_manager_if_connected": "Allows to search by author, title, etc. Possible to pull results directly from your reference manager (if connected).", + "already_have_a_papers_account": "Managing your citations and bibliographies in Overleaf just got way easier! Already have a Papers account? <0>Link your account here.", "already_have_an_account": "Already have an account?", "already_have_sl_account": "Already have an __appName__ account?", "already_subscribed_try_refreshing_the_page": "Already subscribed? Try refreshing the page.", @@ -2392,6 +2393,7 @@ "try_for_free": "Try for free", "try_it_for_free": "Try it for free", "try_now": "Try Now", + "try_papers_for_free": "Try Papers for free", "try_premium_for_free": "Try Premium for free", "try_recompile_project_or_troubleshoot": "Please try recompiling the project from scratch, and if that doesn’t help, follow our <0>troubleshooting guide.", "try_relinking_provider": "It looks like you need to re-link your __provider__ account.", @@ -2628,6 +2630,7 @@ "you_can_manage_your_reference_manager_integrations_from_your_account_settings_page": "You can manage your reference manager integrations from your <0>account settings page.", "you_can_now_enable_sso": "You can now enable SSO on your Group settings page.", "you_can_now_log_in_sso": "You can now log in through your institution and if eligible you will receive <0>__appName__ Professional features.", + "you_can_now_sync_your_papers_library_directly_with_your_overleaf_projects": "You can now sync your Papers library directly with your Overleaf projects", "you_can_opt_in_and_out_of_the_program_at_any_time_on_this_page": "You can <0>opt in and out of the program at any time on this page", "you_can_request_a_maximum_of_limit_fixes_per_day": "You can request a maximum of __limit__ fixes per day. Please try again tomorrow.", "you_can_select_or_invite_collaborator": "You can select or invite __count__ collaborator on your current plan. Upgrade to add more editors or reviewers.",