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

Expose plan prices to compile timeout paywall

GitOrigin-RevId: 33ee11bc0b770a2786931894ba9ae57312a7efa9
This commit is contained in:
roo hutton
2025-02-14 09:03:45 +00:00
committed by Copybot
parent 8183c0785c
commit be8adaf142
5 changed files with 52 additions and 3 deletions
@@ -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
@@ -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"))
@@ -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
View File
@@ -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
@@ -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 },