Ver Fonte

Merge pull request #24923 from overleaf/dp-mj-papers-notification

Add notification banner for Papers integration marketing

GitOrigin-RevId: 625c3afcc6ca617fd01af58a05a6c85f7126398b
Mathias Jakobsen há 1 ano atrás
pai
commit
8fc206073b

+ 12 - 1
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,

+ 3 - 0
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": "",

+ 16 - 0
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 }
+}

+ 86 - 0
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 (
+    <Notification
+      type="info"
+      title={t(
+        'you_can_now_sync_your_papers_library_directly_with_your_overleaf_projects'
+      )}
+      onDismiss={handleClose}
+      content={
+        <p>
+          <Trans
+            i18nKey="already_have_a_papers_account"
+            components={[
+              // eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
+              <a
+                onClick={handleSettingsLinkClick}
+                href="/user/settings#references"
+              />,
+            ]}
+          />
+        </p>
+      }
+      action={
+        <OLButton
+          variant="secondary"
+          onClick={handlePapersButtonClick}
+          href="https://www.papersapp.com/30-day-trial/?utm_source=overleaf_inproduct&utm_medium=referral&utm_campaign=overleaf_integration"
+          target="_blank"
+          rel="noreferrer"
+        >
+          {t('try_papers_for_free')}
+        </OLButton>
+      }
+    />
+  )
+}
+
+export default memo(PapersNotificationBanner)

+ 5 - 0
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 (
     <div className="user-notifications notification-list">
       <ul className="list-unstyled">
@@ -52,6 +56,7 @@ function UserNotifications() {
         <GroupsAndEnterpriseBanner />
         {USGovBanner && <USGovBanner />}
 
+        {showPapersNotificationBanner && <PapersNotificationBanner />}
         <AccessibilitySurveyBanner />
 
         {isDeprecatedBrowser() && <DeprecatedBrowser />}

+ 3 - 0
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</0>.",
   "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</0>.",
   "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</0>.",
   "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</0>.",
+  "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</0> 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.",