فهرست منبع

Merge pull request #23472 from overleaf/rh-timeout-paywall-plans

Expose plan prices to compile timeout paywall

GitOrigin-RevId: 33ee11bc0b770a2786931894ba9ae57312a7efa9
roo hutton 1 سال پیش
والد
کامیت
be8adaf142

+ 39 - 3
services/web/app/src/Features/Project/ProjectController.js

@@ -49,6 +49,8 @@ const UserGetter = require('../User/UserGetter')
 const {
   isStandaloneAiAddOnPlanCode,
 } = require('../Subscription/RecurlyEntities')
+const SubscriptionController = require('../Subscription/SubscriptionController.js')
+const { formatCurrency } = require('../../util/currency')
 
 /**
  * @import { GetProjectsRequest, GetProjectsResponse, Project } from "./types"
@@ -741,6 +743,14 @@ const _ProjectController = {
         chatEnabled = Features.hasFeature('chat')
       }
 
+      const isPaywallChangeCompileTimeoutEnabled =
+        splitTestAssignments['paywall-change-compile-timeout']?.variant ===
+        'enabled'
+
+      const paywallPlans =
+        isPaywallChangeCompileTimeoutEnabled &&
+        (await ProjectController._getPaywallPlansPrices(req, res))
+
       res.render(template, {
         title: project.name,
         priority_title: true,
@@ -841,9 +851,8 @@ const _ProjectController = {
         isReviewerRoleEnabled:
           reviewerRoleAssignment?.variant === 'enabled' ||
           Object.keys(project.reviewer_refs || {}).length > 0,
-        isPaywallChangeCompileTimeoutEnabled:
-          splitTestAssignments['paywall-change-compile-timeout']?.variant ===
-          'enabled',
+        isPaywallChangeCompileTimeoutEnabled,
+        paywallPlans,
       })
       timer.done()
     } catch (err) {
@@ -852,6 +861,32 @@ const _ProjectController = {
     }
   },
 
+  async _getPaywallPlansPrices(
+    req,
+    res,
+    paywallPlans = ['collaborator', 'student']
+  ) {
+    const plansData = {}
+
+    const locale = req.i18n.language
+    const { currency } = await SubscriptionController.getRecommendedCurrency(
+      req,
+      res
+    )
+
+    paywallPlans.forEach(plan => {
+      const planPrice = Settings.localizedPlanPricing[currency][plan].monthly
+      const formattedPlanPrice = formatCurrency(
+        planPrice,
+        currency,
+        locale,
+        true
+      )
+      plansData[plan] = formattedPlanPrice
+    })
+    return plansData
+  },
+
   async _refreshFeatures(req, user) {
     // If the feature refresh has failed in this session, don't retry
     // it - require the user to log in again.
@@ -1154,6 +1189,7 @@ const ProjectController = {
   _injectProjectUsers: _ProjectController._injectProjectUsers,
   _isInPercentageRollout: _ProjectController._isInPercentageRollout,
   _refreshFeatures: _ProjectController._refreshFeatures,
+  _getPaywallPlansPrices: _ProjectController._getPaywallPlansPrices,
 }
 
 module.exports = ProjectController

+ 3 - 0
services/web/app/views/project/editor/_meta.pug

@@ -42,6 +42,9 @@ meta(name="ol-shouldLoadHotjar" data-type="boolean" content=shouldLoadHotjar)
 meta(name="ol-isReviewerRoleEnabled" data-type="boolean" content=isReviewerRoleEnabled)
 meta(name="ol-odcRole" data-type="string" content=odcRole)
 meta(name="ol-isPaywallChangeCompileTimeoutEnabled" data-type="boolean" content=isPaywallChangeCompileTimeoutEnabled)
+if(isPaywallChangeCompileTimeoutEnabled)
+	//- expose plans info to show prices in paywall-change-compile-timeout test 
+	meta(name="ol-paywallPlans", data-type="json" content=paywallPlans)
 
 // translations for the loading page, before i18n has loaded in the client
 meta(name="ol-loadingText", data-type="string" content=translate("loading"))

+ 3 - 0
services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-paywall-prompt.tsx

@@ -12,11 +12,14 @@ const studentRoles = [
 // We can display TimeoutMessageAfterPaywallDismissal after the user has dismissed the paywall. That logic can be implemented in this file or somewhere else?
 function TimeoutUpgradePaywallPrompt() {
   const odcRole = getMeta('ol-odcRole')
+  const planPrices = getMeta('ol-paywallPlans')
   const isStudent = useMemo(() => studentRoles.includes(odcRole), [odcRole])
 
   return (
     <div>
       <p>Current user is {!isStudent && 'not'} a student.</p>
+      <p>Student plan: {planPrices.student} per month</p>
+      <p>Standard plan: {planPrices.collaborator} per month</p>
       <TimeoutMessageAfterPaywallDismissal />
     </div>
   )

+ 1 - 0
services/web/frontend/js/utils/meta.ts

@@ -160,6 +160,7 @@ export interface Meta {
   'ol-odcRole': string
   'ol-overallThemes': OverallThemeMeta[]
   'ol-passwordStrengthOptions': PasswordStrengthOptions
+  'ol-paywallPlans': { [key: string]: string }
   'ol-personalAccessTokens': AccessToken[] | undefined
   'ol-plan': Plan
   'ol-planCode': string

+ 6 - 0
services/web/test/unit/src/Project/ProjectControllerTests.js

@@ -62,6 +62,11 @@ describe('ProjectController', function () {
         getUsersSubscription: sinon.stub().resolves(),
       },
     }
+    this.SubscriptionController = {
+      promises: {
+        getRecommendedCurrency: sinon.stub().resolves({ currency: 'USD' }),
+      },
+    }
     this.LimitationsManager = {
       hasPaidSubscription: sinon.stub(),
       promises: {
@@ -231,6 +236,7 @@ describe('ProjectController', function () {
         '../User/UserController': this.UserController,
         './ProjectHelper': this.ProjectHelper,
         '../Subscription/SubscriptionLocator': this.SubscriptionLocator,
+        '../Subscription/SubscriptionController': this.SubscriptionController,
         '../Subscription/LimitationsManager': this.LimitationsManager,
         '../Tags/TagsHandler': this.TagsHandler,
         '../../models/User': { User: this.UserModel },