Merge pull request #12593 from overleaf/jk-remove-plans-split-test

[web] Remove 'plans-page-layout-v3' split test

GitOrigin-RevId: 91e0d3d8bc40632df630131b2e872fa824015da5
This commit is contained in:
June Kelly 2023-04-25 13:33:04 +01:00 committed by Copybot
parent 70072481f4
commit f5740e6b17
16 changed files with 95 additions and 1266 deletions

View file

@ -56,37 +56,7 @@ async function plansPage(req, res) {
return defaultValue
}
let plansPageLayoutV3Assignment = { variant: 'default' }
try {
plansPageLayoutV3Assignment = await SplitTestHandler.promises.getAssignment(
req,
res,
'plans-page-layout-v3'
)
if (plansPageLayoutV3Assignment.variant === 'old-plans-page-annual') {
plansPageLayoutV3Assignment.variant = 'old-plans-page-annual-fixed'
res.locals.splitTestVariants['plans-page-layout-v3'] =
'old-plans-page-annual-fixed'
}
} catch (error) {
logger.error(
{ err: error },
'failed to get "plans-page-layout-v3" split test assignment'
)
}
let currentView = 'monthly'
if (
plansPageLayoutV3Assignment.variant === 'old-plans-page-annual-fixed' ||
plansPageLayoutV3Assignment.variant === 'new-plans-page'
) {
currentView = 'annual'
}
const showNewPlansPage =
plansPageLayoutV3Assignment.variant === 'new-plans-page'
const currentView = 'annual'
let defaultGroupPlanModalCurrency = 'USD'
if (validGroupPlanModalOptions.currency.includes(recommendedCurrency)) {
@ -94,20 +64,14 @@ async function plansPage(req, res) {
}
const groupPlanModalDefaults = {
plan_code: getDefault('plan', 'plan_code', 'collaborator'),
size: getDefault('number', 'size', showNewPlansPage ? '2' : '10'),
size: getDefault('number', 'size', '2'),
currency: getDefault('currency', 'currency', defaultGroupPlanModalCurrency),
usage: getDefault('usage', 'usage', 'enterprise'),
}
AnalyticsManager.recordEventForSession(req.session, 'plans-page-view', {
'plans-page-layout-v3': plansPageLayoutV3Assignment.variant,
})
AnalyticsManager.recordEventForSession(req.session, 'plans-page-view')
const template = showNewPlansPage
? 'subscriptions/plans-marketing-v2'
: 'subscriptions/plans-marketing'
res.render(template, {
res.render('subscriptions/plans-marketing-v2', {
title: 'plans_and_pricing',
currentView,
plans,
@ -120,7 +84,6 @@ async function plansPage(req, res) {
groupPlans: GroupPlansData,
groupPlanModalOptions,
groupPlanModalDefaults,
plansPageLayoutV3Variant: plansPageLayoutV3Assignment.variant,
initialLocalizedGroupPrice:
SubscriptionHelper.generateInitialLocalizedGroupPrice(
recommendedCurrency

View file

@ -17,9 +17,7 @@ const config = {
},
},
eventTrackingKey: 'plans-page-click',
additionalEventSegmentation: {
'plans-page-layout-v3': 'new-plans-page',
},
additionalEventSegmentation: {},
},
group: {
tableHead: {
@ -35,9 +33,7 @@ const config = {
},
},
eventTrackingKey: 'plans-page-click',
additionalEventSegmentation: {
'plans-page-layout-v3': 'new-plans-page',
},
additionalEventSegmentation: {},
},
student: {
baseColspan: 2,
@ -60,9 +56,7 @@ const config = {
},
},
eventTrackingKey: 'plans-page-click',
additionalEventSegmentation: {
'plans-page-layout-v3': 'new-plans-page',
},
additionalEventSegmentation: {},
},
}

View file

@ -1,7 +1,5 @@
extends ../layout
include ./plans-marketing/_mixins
include ./plans-marketing/_tables
include ./plans-marketing/v2/_mixins
block vars

View file

@ -1,8 +1,5 @@
extends ../layout-marketing
include ./plans-marketing/_mixins
include ./plans-marketing/_tables
block vars
- entrypoint = 'pages/user/subscription/plans-v2/plans-v2-main'

View file

@ -1,99 +0,0 @@
extends ../layout-marketing
include ./plans-marketing/_mixins
include ./plans-marketing/_tables
block vars
- entrypoint = 'pages/user/subscription/plans'
block append meta
meta(name="ol-recommendedCurrency" content=recommendedCurrency)
meta(name="ol-groupPlans" data-type="json" content=groupPlans)
meta(name="ol-currencySymbols" data-type="json" content=groupPlanModalOptions.currencySymbols)
meta(name="ol-itm_content" content=itm_content)
meta(name="ol-currentView" content=currentView)
block content
main.content.content-alt#main-content
.content-page
.plans
.container(ng-cloak)
.row
.col-md-12
.page-header.centered.plans-header.text-centered
h1.text-capitalize(ng-non-bindable) #{translate('get_instant_access_to')} #{settings.appName}
.row
.col-md-8.col-md-offset-2
p.text-centered #{translate("sl_benefits_plans")}
+allCardsAndControls()
.row.row-spaced-large.text-centered
.col-xs-12
p.text-centered !{translate('also_provides_free_plan', {}, [{ name: 'a', attrs: { href: '/register' }}])}
i.fa.fa-cc-mastercard.fa-2x(aria-hidden="true")  
span.sr-only Mastercard accepted
i.fa.fa-cc-visa.fa-2x(aria-hidden="true")  
span.sr-only Visa accepted
i.fa.fa-cc-amex.fa-2x(aria-hidden="true")  
span.sr-only Amex accepted
i.fa.fa-cc-paypal.fa-2x(aria-hidden="true")  
span.sr-only Paypal accepted
div.text-centered #{translate('change_plans_any_time')}<br/> #{translate('billed_after_x_days', {len:'7'})}
br
div.text-centered #{translate('subject_to_additional_vat')}<br/> #{translate('select_country_vat')}
.row.row-spaced-large
.col-md-8.col-md-offset-2
.card.text-centered
.card-header
h2 #{translate('looking_multiple_licenses')}
span #{translate('reduce_costs_group_licenses')}
br
br
a.btn.btn-default(
href="#groups"
data-ol-open-group-plan-modal
data-ol-location='callout'
) #{translate('find_out_more')}
.row.row-spaced-large
.col-sm-12
.page-header.plans-header.plans-subheader.text-centered
h2 #{translate('compare_plan_features')}
.row
.col-md-6.col-md-offset-3
if (plansPageLayoutV3Variant === 'old-plans-page-annual-fixed')
+plan_switch_annual_default('table')
else
+plan_switch('table')
.col-md-3.text-right
+currency_dropdown
.row(event-tracking="features-table-viewed" event-tracking-ga="subscription-funnel" event-tracking-trigger="scroll" event-tracking-send-once="true" event-tracking-label="exp-")
.col-sm-12(hidden=(currentView !== 'monthly') data-ol-view='monthly')
+table_premium
.col-sm-12(hidden=(currentView !== 'annual') data-ol-view='annual')
+table_premium
.col-sm-12(hidden=(currentView !== 'student') data-ol-view='student')
+table_student
include ./plans-marketing/_quotes
include ./plans-marketing/_faq
#bottom-cards.row.row-spaced(style="display: none;")
.col-sm-12
+allCardsAndControls(true, 'bottom')
.row.row-spaced-large
.col-md-12
.plans-header.plans-subheader.text-centered
h2.header-with-btn #{translate('still_have_questions')}
button.btn.btn-default.btn-header.text-capitalize(
data-ol-open-contact-form-modal="general"
) #{translate('get_in_touch')}
.row.row-spaced
include ./plans-marketing/_group_plan_modal
!= moduleIncludes("contactModalGeneral-marketing", locals)

View file

@ -1,34 +0,0 @@
.faq
.row.row-spaced-large
.col-md-12
.page-header.plans-header.plans-subheader.text-centered
h2 FAQ
.row
.col-md-6
h3 #{translate("faq_how_free_trial_works_question")}
p #{translate('faq_how_does_free_trial_works_answer', { len:'7' })}
.col-md-6
h3 #{translate('faq_change_plans_question')}
p #{translate('faq_change_plans_answer')}
.row
.col-md-6
h3 #{translate('faq_do_collab_need_premium_question')}
p #{translate('faq_do_collab_need_premium_answer')}
.col-md-6
h3 #{translate('faq_need_more_collab_question')}
p !{translate('faq_need_more_collab_answer', { referFriendsLink: translate('referring_your_friends') })}
.row
.col-md-6
h3 #{translate('faq_purchase_more_licenses_question')}
p !{translate('faq_purchase_more_licenses_answer', { groupLink: translate('discounted_group_accounts') })}&nbsp;
a(href='#groups' data-ol-open-group-plan-modal) #{translate("get_in_touch_for_details")}
.col-md-6
h3 #{translate('faq_monthly_or_annual_question')}
p #{translate('faq_monthly_or_annual_answer')}
.row
.col-md-6
h3 #{translate('faq_how_to_pay_question')}
p #{translate('faq_how_to_pay_answer')}
.col-md-6
h3 #{translate('faq_pay_by_invoice_question')}
p !{translate('faq_pay_by_invoice_answer', {}, [{ name: 'a', attrs: { href: "#pay-by-invoice", 'data-ol-open-contact-form-modal': 'general' }}])}

View file

@ -61,7 +61,6 @@ div.modal.fade(tabindex="-1" role="dialog" data-ol-group-plan-modal)
event-tracking-mb="true"
event-tracking-trigger="click"
event-tracking-element="select"
event-segmentation='{"plans-page-layout-v3": "' + (plansPageLayoutV3Variant) + '"}'
)
for size in groupPlanModalOptions.sizes
option(
@ -89,7 +88,6 @@ div.modal.fade(tabindex="-1" role="dialog" data-ol-group-plan-modal)
event-tracking-mb="true"
event-tracking-trigger="click"
event-tracking-element="checkbox"
event-segmentation='{"plans-page-layout-v3": "' + (plansPageLayoutV3Variant) + '"}'
)
span This license is for educational purposes (applies to students or faculty using Overleaf for teaching)

View file

@ -1,303 +0,0 @@
//- Buy Buttons
mixin btn_buy_collaborator(location)
a.btn.btn-primary(
data-ol-start-new-subscription='collaborator'
data-ol-location=location
)
span(hidden=(currentView !== 'monthly') data-ol-view='monthly') #{translate("start_free_trial")}
span(hidden=(currentView !== 'annual') data-ol-view='annual') #{translate("buy_now")}
mixin btn_buy_personal(location)
a.btn.btn-primary(
data-ol-start-new-subscription='paid-personal'
data-ol-tracking-plan='personal'
data-ol-location=location
)
span(hidden=(currentView !== 'monthly') data-ol-view='monthly') #{translate("start_free_trial")}
span(hidden=(currentView !== 'annual') data-ol-view='annual') #{translate("buy_now")}
mixin btn_buy_free(location)
a.btn.btn-primary(
data-ol-has-custom-href
href="/register"
style=(getLoggedInUserId() === null ? "" : "visibility: hidden")
data-ol-start-new-subscription='free'
data-ol-location=location
)
span.text-capitalize #{translate('get_started_now')}
mixin btn_buy_professional(location)
a.btn.btn-primary(
data-ol-start-new-subscription='professional'
data-ol-location=location
)
span(hidden=(currentView !== 'monthly') data-ol-view='monthly') #{translate("start_free_trial")}
span(hidden=(currentView !== 'annual') data-ol-view='annual') #{translate("buy_now")}
mixin btn_buy_student(location, plan)
if plan == 'annual'
a.btn.btn-primary(
data-ol-start-new-subscription='student'
data-ol-item-view='annual'
data-ol-tracking-label='student-annual'
data-ol-location=location
) #{translate("buy_now")}
else
a.btn.btn-primary(
data-ol-start-new-subscription='student'
data-ol-item-view='monthly'
data-ol-tracking-label='student-monthly'
data-ol-location=location
) #{translate("start_free_trial")}
//- Cards
mixin card_student_annual(location)
.best-value
strong #{translate('best_value')}
.card-header
h2 #{translate("student")} (#{translate("annual")})
h5.tagline #{translate('tagline_student_annual')}
.circle
span
+price_student_annual
+features_student(location, 'annual')
mixin card_student_monthly(location)
.card-header
h2 #{translate("student")}
h5.tagline #{translate('tagline_student_monthly')}
.circle
span
+price_student_monthly
+features_student(location, 'monthly')
//- Features Lists, used within cards
mixin features_collaborator(location)
ul.list-unstyled
li
strong #{translate("collabs_per_proj", {collabcount:10})}
+features_premium
li
br
+btn_buy_collaborator(location)
mixin features_free(location)
ul.list-unstyled
li #{translate("one_collaborator")}
li(class="hidden-xs hidden-sm") &nbsp;
li(class="hidden-xs hidden-sm") &nbsp;
li(class="hidden-xs hidden-sm") &nbsp;
li(class="hidden-xs hidden-sm") &nbsp;
li(class="hidden-xs hidden-sm") &nbsp;
li(class="hidden-xs hidden-sm") &nbsp;
li
br
+btn_buy_free(location)
mixin features_personal(location)
ul.list-unstyled
li #{translate("one_collaborator")}
li &nbsp;
li
strong #{translate('premium_features')}
li #{translate('sync_dropbox_github')}
li #{translate('full_doc_history')}
li + #{translate('more').toLowerCase()}
li(class="hidden-xs hidden-sm") &nbsp;
li
br
+btn_buy_personal(location)
mixin features_premium
li &nbsp;
li
strong #{translate('all_premium_features')}
li #{translate('sync_dropbox_github')}
li #{translate('full_doc_history')}
li #{translate('track_changes')}
li + #{translate('more').toLowerCase()}
mixin features_professional(location)
ul.list-unstyled
li
strong #{translate("unlimited_collabs")}
+features_premium
li
br
+btn_buy_professional(location)
mixin features_student(location, plan)
ul.list-unstyled
li
strong #{translate("collabs_per_proj", {collabcount:6})}
+features_premium
li
br
+btn_buy_student(location, plan)
mixin gen_localized_price_for_plan_view(plan, view)
for currencyCode in Object.keys(settings.localizedPlanPricing)
span(
hidden=(currencyCode !== recommendedCurrency)
data-ol-currencyCode=currencyCode
) #{settings.localizedPlanPricing[currencyCode][plan][view]}
mixin gen_localized_undiscounted_price_for_plan_view(plan)
for currencyCode in Object.keys(settings.localizedPlanPricing)
span(
hidden=(currencyCode !== recommendedCurrency)
data-ol-currencyCode=currencyCode
) #{settings.localizedPlanPricing[currencyCode][plan]['monthlyTimesTwelve']}
mixin gen_localized_price_for_plan(plan)
div(hidden=(currentView !== 'monthly') data-ol-view='monthly')
+gen_localized_price_for_plan_view(plan, 'monthly')
span.small /mo
div(hidden=(currentView !== 'annual') data-ol-view='annual')
+gen_localized_price_for_plan_view(plan, 'annual')
span.small /yr
mixin gen_localized_undiscounted_price_for_plan(plan)
div(hidden=(currentView !== 'annual') data-ol-view='annual')
strike.undiscounted-price.small
span.sr-only Price reduced from
+gen_localized_undiscounted_price_for_plan_view(plan)
| /yr
//- Prices
mixin price_personal
+gen_localized_price_for_plan('personal')
mixin price_personal_undiscounted
+gen_localized_undiscounted_price_for_plan('personal')
mixin price_collaborator
+gen_localized_price_for_plan('collaborator')
mixin price_collaborator_undiscounted
+gen_localized_undiscounted_price_for_plan('collaborator')
mixin price_professional
+gen_localized_price_for_plan('professional')
mixin price_professional_undiscounted
+gen_localized_undiscounted_price_for_plan('professional')
mixin price_student_annual
+gen_localized_price_for_plan_view('student', 'annual')
span.small /yr
mixin price_student_monthly
+gen_localized_price_for_plan_view('student', 'monthly')
span.small /mo
//- UI Control
mixin currency_dropdown
.dropdown.currency-dropdown(dropdown)
a.btn.btn-default.dropdown-toggle(
href="#",
data-toggle="dropdown",
dropdown-toggle
)
for currencyCode in Object.keys(settings.localizedPlanPricing)
span(
hidden=(currencyCode !== recommendedCurrency)
data-ol-currencyCode=currencyCode
) #{currencyCode} (#{settings.localizedPlanPricing[currencyCode]['symbol']})
span.caret
ul.dropdown-menu.dropdown-menu-right.text-right(role="menu")
for currencyCode in Object.keys(settings.localizedPlanPricing)
li
a(
href='#'
data-ol-currencyCode-switch=currencyCode
) #{currencyCode} #{settings.localizedPlanPricing[currencyCode]['symbol']}
mixin plan_switch(location)
ul.nav.nav-pills(class=(location === 'card' ? "above-cards" : ""))
li.active(data-ol-view-tab='monthly')
button.btn-default-outline #{translate("monthly")}
li(data-ol-view-tab='annual' class=(location === 'card' ? "annual-saving-tooltip-container" : ""))
button.btn-default-outline #{translate("annual")}
if (location === 'card')
.tooltip.in.bottom.annual-saving-tooltip(
role="tooltip"
data-ol-annual-saving-tooltip
)
.tooltip-arrow
.tooltip-inner
span(hidden=(currentView !== 'monthly') data-ol-view='monthly') #{translate("save_20_percent_by_paying_annually")}
span(hidden=(currentView !== 'annual') data-ol-view='annual') #{translate("saving_20_percent")}
span(hidden=(currentView !== 'student') data-ol-view='student') #{translate("save_20_percent_by_paying_annually")}
li(data-ol-view-tab='student')
button.btn-default-outline #{translate("special_price_student")}
mixin plan_switch_annual_default(location)
ul.nav.nav-pills(class=(location === 'card' ? "above-cards" : ""))
li.active(data-ol-view-tab='annual' class=(location === 'card' ? "annual-saving-tooltip-container" : ""))
button.btn-default-outline #{translate("annual")}
if (location === 'card')
.tooltip.in.bottom.annual-saving-tooltip.annual-selected.green-background(
role="tooltip"
data-ol-annual-saving-tooltip
)
.tooltip-arrow
.tooltip-inner
span(hidden=(currentView !== 'annual') data-ol-view='annual') #{translate("saving_20_percent")}
span(hidden=(currentView !== 'monthly') data-ol-view='monthly') #{translate("save_20_percent_by_paying_annually")}
span(hidden=(currentView !== 'student') data-ol-view='student') #{translate("save_20_percent_by_paying_annually")}
li(data-ol-view-tab='monthly')
button.btn-default-outline #{translate("monthly")}
li(data-ol-view-tab='student')
button.btn-default-outline #{translate("special_price_student")}
mixin allCardsAndControls(controlsRowSpaced, listLocation)
- var location = listLocation ? 'card_' + listLocation : 'card'
.row.top-switch(class=(controlsRowSpaced ? "row-spaced" : ""))
.col-md-6.col-md-offset-3
if (plansPageLayoutV3Variant === 'old-plans-page-annual-fixed')
+plan_switch_annual_default(location)
else
+plan_switch(location)
.col-md-2.text-right
+currency_dropdown
.row
.col-md-10.col-md-offset-1
.row
for view in ['monthly', 'annual']
.card-group.text-centered(data-ol-view=view hidden=(view==='annual'))
.col-md-4
.card.card-first
.card-header
h2 #{translate("personal")}
.card-byline
h5.tagline #{translate("tagline_personal")}
.circle
+price_personal
+price_personal_undiscounted
+features_personal(location)
.col-md-4
.card.card-highlighted
.best-value
strong #{translate('best_value')}
.card-header
h2 #{translate("standard")}
.card-byline
h5.tagline #{translate("tagline_collaborator")}
.circle
+price_collaborator
+price_collaborator_undiscounted
+features_collaborator(location)
.col-md-4
.card.card-last
.card-header
h2 #{translate("professional")}
.card-byline
h5.tagline #{translate("tagline_professional")}
.circle
+price_professional
+price_professional_undiscounted
+features_professional(location)
.card-group.text-centered(hidden=(currentView !== 'student') data-ol-view='student')
.col-md-4
.card.card-first
.card-header
h2 #{translate("free")}
h5.tagline #{translate("tagline_free")}
.circle #{translate("free")}
+features_free(location)
.col-md-4
.card.card-highlighted
+card_student_annual(location)
.col-md-4
.card.card-last
+card_student_monthly(location)

View file

@ -1,116 +0,0 @@
//- Features Tables
mixin table_premium
table.card.plans-table.plans-table-main
tr
th
th #{translate("free")}
th #{translate("personal")}
th #{translate("standard")}
.outer.outer-top
.outer-content
.best-value
strong #{translate('best_value')}
th #{translate("professional")}
tr
td #{translate("price")}
td #{translate("free")}
td
+price_personal
td
+price_collaborator
td
+price_professional
for feature in planFeatures
tr
td(event-tracking="features-table" event-tracking-trigger="hover" event-tracking-ga="subscription-funnel" event-tracking-label=`${feature.feature}`)
if feature.info
span(data-toggle="tooltip" title=translate(feature.info)) #{translate(feature.feature)}
else
| #{translate(feature.feature)}
for plan in feature.plans
td(ng-non-bindable)
if feature.value == 'str'
| #{plan}
else if plan
i.fa.fa-check(aria-hidden="true")
span.sr-only #{translate("feature_included")}
else
i.fa.fa-times(aria-hidden="true")
span.sr-only #{translate("feature_not_included")}
tr
td
td
+btn_buy_free('table')
td
+btn_buy_personal('table')
td
+btn_buy_collaborator('table')
.outer.outer-btm
.outer-content &nbsp;
td
+btn_buy_professional('table')
mixin table_cell_student(feature)
if feature.value == 'str'
| #{feature.student}
else if feature.student
i.fa.fa-check(aria-hidden="true")
span.sr-only #{translate("feature_included")}
else
i.fa.fa-times(aria-hidden="true")
span.sr-only #{translate("feature_not_included")}
mixin table_student
table.card.plans-table.plans-table-student
tr
th
th #{translate("free")}
th #{translate("student")} (#{translate("annual")})
.outer.outer-top
.outer-content
.best-value
strong Best Value
th #{translate("student")}
tr
td #{translate("price")}
td #{translate("free")}
td
+price_student_annual
td
+price_student_monthly
for feature in planFeatures
tr
td(event-tracking="plans-page-table" event-tracking-trigger="hover" event-tracking-ga="subscription-funnel" event-tracking-label=`${feature.feature}`)
if feature.info
span(data-toggle="tooltip" title=translate(feature.info)) #{translate(feature.feature)}
else
| #{translate(feature.feature)}
td(ng-non-bindable)
if feature.value == 'str'
| #{feature.plans.free}
else if feature.plans.free
i.fa.fa-check(aria-hidden="true")
span.sr-only #{translate("feature_included")}
else
i.fa.fa-times(aria-hidden="true")
span.sr-only #{translate("feature_not_included")}
td(ng-non-bindable)
+table_cell_student(feature)
td(ng-non-bindable)
+table_cell_student(feature)
tr
td
td
+btn_buy_free('table')
td
+btn_buy_student('table', 'annual')
.outer.outer-btm
.outer-content &nbsp;
td
+btn_buy_student('table', 'monthly')

View file

@ -8,7 +8,7 @@ include ./_mixins
event-tracking="plans-page-toggle-plan"
event-tracking-mb="true"
event-tracking-trigger="click"
event-segmentation='{"button": "individual", "plans-page-layout-v3": "new-plans-page"}'
event-segmentation='{"button": "individual"}'
)
button.btn.btn-default-outline #{translate("indvidual_plans")}
li.plans-v2-top-switch-group(
@ -16,7 +16,7 @@ include ./_mixins
event-tracking="plans-page-toggle-plan"
event-tracking-mb="true"
event-tracking-trigger="click"
event-segmentation='{"button": "group", "plans-page-layout-v3": "new-plans-page"}'
event-segmentation='{"button": "group"}'
)
button.btn.btn-default-outline(
href="#"
@ -28,13 +28,13 @@ include ./_mixins
event-tracking="plans-page-toggle-plan"
event-tracking-mb="true"
event-tracking-trigger="click"
event-segmentation='{"button": "student", "plans-page-layout-v3": "new-plans-page"}'
event-segmentation='{"button": "student"}'
)
button.btn.btn-default-outline(
href="#"
) #{translate("student_plans")}
+monthly_annual_switch("annual", "plans-page-toggle-period", '{"plans-page-layout-v3": "new-plans-page"}')
+monthly_annual_switch("annual", "plans-page-toggle-period")
.row(hidden data-ol-plans-v2-license-picker-container)
.col-sm-12
@ -62,4 +62,4 @@ include ./_mixins
+table_student('annual')
//- sticky header on mobile will be "hidden" (by removing its sticky position) if it reaches this div
.invisible(aria-hidden="true" data-ol-plans-v2-table-sticky-header-stop)
.invisible(aria-hidden="true" data-ol-plans-v2-table-sticky-header-stop)

View file

@ -1,3 +1,15 @@
mixin features_premium
li &nbsp;
li
strong #{translate('all_premium_features')}
li #{translate('sync_dropbox_github')}
li #{translate('full_doc_history')}
li #{translate('track_changes')}
li + #{translate('more').toLowerCase()}
mixin gen_localized_price_for_plan_view(plan, view)
span #{settings.localizedPlanPricing[recommendedCurrency][plan][view]}
mixin plans_v2_table(period, config)
- var baseColspan = config.baseColspan || 1
- var maxColumn = config.maxColumn || 4
@ -344,7 +356,6 @@ mixin group_plans_license_picker()
event-tracking-mb="true"
event-tracking-trigger="click"
event-tracking-element="select"
event-segmentation='{"plans-page-layout-v3": "new-plans-page"}'
)
option(value="2") 2
option(value="3") 3
@ -364,7 +375,6 @@ mixin group_plans_license_picker()
event-tracking-mb="true"
event-tracking-trigger="click"
event-tracking-element="checkbox"
event-segmentation='{"plans-page-layout-v3": "new-plans-page"}'
)
span #{translate("apply_educational_discount")}
//- will only appear on screen width >= 768px (using CSS)

View file

@ -13,7 +13,69 @@ import {
updateMainGroupPlanPricing,
} from './plans-v2-group-plan'
import { setUpGroupSubscriptionButtonAction } from './plans-v2-subscription-button'
import { updateLinkTargets } from '../plans'
import getMeta from '../../../../utils/meta'
const currentCurrencyCode = getMeta('ol-recommendedCurrency')
function setUpSubscriptionTracking(linkEl) {
linkEl.addEventListener('click', function () {
const plan =
linkEl.getAttribute('data-ol-tracking-plan') ||
linkEl.getAttribute('data-ol-start-new-subscription')
const location = linkEl.getAttribute('data-ol-location')
const period = linkEl.getAttribute('data-ol-item-view')
const DEFAULT_EVENT_TRACKING_KEY = 'plans-page-click'
const eventTrackingKey =
linkEl.getAttribute('data-ol-event-tracking-key') ||
DEFAULT_EVENT_TRACKING_KEY
const eventTrackingSegmentation = {
button: plan,
location,
'billing-period': period,
}
eventTracking.sendMB('plans-page-start-trial') // deprecated by plans-page-click
eventTracking.sendMB(eventTrackingKey, eventTrackingSegmentation)
})
}
const searchParams = new URLSearchParams(window.location.search)
export function updateLinkTargets() {
document.querySelectorAll('[data-ol-start-new-subscription]').forEach(el => {
if (el.hasAttribute('data-ol-has-custom-href')) return
const plan = el.getAttribute('data-ol-start-new-subscription')
const view = el.getAttribute('data-ol-item-view')
const suffix = view === 'annual' ? `-annual` : `_free_trial_7_days`
const planCode = `${plan}${suffix}`
const location = el.getAttribute('data-ol-location')
const itmCampaign = searchParams.get('itm_campaign') || 'plans'
const itmContent =
itmCampaign === 'plans' ? location : searchParams.get('itm_content')
const queryString = new URLSearchParams({
planCode,
currency: currentCurrencyCode,
itm_campaign: itmCampaign,
})
if (itmContent) {
queryString.set('itm_content', itmContent)
}
if (searchParams.get('itm_referrer')) {
queryString.set('itm_referrer', searchParams.get('itm_referrer'))
}
el.href = `/user/subscription/new?${queryString.toString()}`
})
}
// We need this mutable variable because the group tab only have annual.
// There's some difference between the monthly and annual UI
@ -133,6 +195,10 @@ document
switchMonthlyAnnual(currentMonthlyAnnualSwitchValue)
})
document
.querySelectorAll('[data-ol-start-new-subscription]')
.forEach(setUpSubscriptionTracking)
setUpTabSwitching()
setUpGroupPlanPricingChange()
setUpMonthlyAnnualSwitching()

View file

@ -1,202 +0,0 @@
import '../../../marketing'
import '../../../features/plans/group-plan-modal'
import * as eventTracking from '../../../infrastructure/event-tracking'
import getMeta from '../../../utils/meta'
let currentView = getMeta('ol-currentView')
let currentCurrencyCode = getMeta('ol-recommendedCurrency')
const plansPageLayoutV3Variant =
getMeta('ol-splitTestVariants')?.['plans-page-layout-v3'] ?? 'default'
if (window.location.href.includes('validate-pre-rendering=true')) {
validatePreRendering()
}
function selectView(view) {
document.querySelectorAll('[data-ol-view-tab]').forEach(el => {
if (el.getAttribute('data-ol-view-tab') === view) {
el.classList.add('active')
} else {
el.classList.remove('active')
}
})
document.querySelectorAll('[data-ol-view]').forEach(el => {
el.hidden = el.getAttribute('data-ol-view') !== view
})
updateAnnualSavingBanner(view)
currentView = view
updateLinkTargets()
}
function setUpViewSwitching(liEl) {
liEl.querySelector('button').addEventListener('click', function (e) {
e.preventDefault()
const view = liEl.getAttribute('data-ol-view-tab')
eventTracking.send('subscription-funnel', 'plans-page', `${view}-prices`)
eventTracking.sendMB('plans-page-toggle', {
button: view,
'plans-page-layout-v3': plansPageLayoutV3Variant,
})
selectView(view)
})
}
function setUpCurrencySwitching(linkEl) {
linkEl.addEventListener('click', function (e) {
e.preventDefault()
const currencyCode = linkEl.getAttribute('data-ol-currencyCode-switch')
document.querySelectorAll('[data-ol-currencyCode]').forEach(el => {
el.hidden = el.getAttribute('data-ol-currencyCode') !== currencyCode
})
currentCurrencyCode = currencyCode
eventTracking.sendMB('plans-page-currency', { currency: currencyCode })
updateLinkTargets()
})
}
function setUpSubscriptionTracking(linkEl) {
linkEl.addEventListener('click', function () {
const plansPageLayoutV3Variant =
getMeta('ol-splitTestVariants')?.['plans-page-layout-v3'] ?? 'default'
const plan =
linkEl.getAttribute('data-ol-tracking-plan') ||
linkEl.getAttribute('data-ol-start-new-subscription')
const location = linkEl.getAttribute('data-ol-location')
const period = linkEl.getAttribute('data-ol-item-view') || currentView
const DEFAULT_EVENT_TRACKING_KEY = 'plans-page-click'
const eventTrackingKey =
linkEl.getAttribute('data-ol-event-tracking-key') ||
DEFAULT_EVENT_TRACKING_KEY
const eventTrackingSegmentation = {
button: plan,
location,
'billing-period': period,
}
if (eventTrackingKey === DEFAULT_EVENT_TRACKING_KEY) {
eventTrackingSegmentation['plans-page-layout-v3'] =
plansPageLayoutV3Variant
}
const customLabel = linkEl.getAttribute('data-ol-tracking-label')
const computedLabel = currentView === 'annual' ? `${plan}_annual` : plan
const label = customLabel || computedLabel
eventTracking.sendMB('plans-page-start-trial') // deprecated by plans-page-click
eventTracking.send('subscription-funnel', 'sign_up_now_button', label) // deprecated by plans-page-click
eventTracking.sendMB(eventTrackingKey, eventTrackingSegmentation)
})
}
const searchParams = new URLSearchParams(window.location.search)
export function updateLinkTargets() {
document.querySelectorAll('[data-ol-start-new-subscription]').forEach(el => {
if (el.hasAttribute('data-ol-has-custom-href')) return
const plan = el.getAttribute('data-ol-start-new-subscription')
const view = el.getAttribute('data-ol-item-view') || currentView
const suffix = view === 'annual' ? `-annual` : `_free_trial_7_days`
const planCode = `${plan}${suffix}`
const location = el.getAttribute('data-ol-location')
const itmCampaign = searchParams.get('itm_campaign') || 'plans'
const itmContent =
itmCampaign === 'plans' ? location : searchParams.get('itm_content')
const queryString = new URLSearchParams({
planCode,
currency: currentCurrencyCode,
itm_campaign: itmCampaign,
})
if (itmContent) {
queryString.set('itm_content', itmContent)
}
if (searchParams.get('itm_referrer')) {
queryString.set('itm_referrer', searchParams.get('itm_referrer'))
}
el.href = `/user/subscription/new?${queryString.toString()}`
})
}
function updateAnnualSavingBanner(view) {
const tooltipEl = document.querySelector('[data-ol-annual-saving-tooltip]')
if (view === 'annual') {
tooltipEl.classList.add('annual-selected')
} else {
tooltipEl.classList.remove('annual-selected')
}
}
function selectViewFromHash() {
try {
const params = new URLSearchParams(window.location.hash.substring(1))
const view = params.get('view')
if (view) {
// make sure the selected view is valid
if (document.querySelector(`[data-ol-view-tab="${view}"]`)) {
selectView(view)
// clear the hash so it doesn't persist when switching plans
window.location.hash = ''
}
}
} catch {
// do nothing
}
}
function validatePreRendering() {
document.querySelectorAll('[data-ol-view-tab]').forEach(el => {
console.assert(
(el.getAttribute('data-ol-view-tab') === currentView) ===
el.classList.contains('active'),
el
)
})
document.querySelectorAll('[data-ol-view]').forEach(el => {
console.assert(
(el.hidden === el.getAttribute('data-ol-view')) !== currentView,
el
)
})
const plansPageLayoutV3Variant = getMeta('ol-splitTestVariants')?.[
'plans-page-layout-v3'
]
if (plansPageLayoutV3Variant !== 'new-plans-page') {
const tooltipEl = document.querySelector('[data-ol-annual-saving-tooltip]')
console.assert(
(currentView === 'annual') ===
tooltipEl.classList.contains('annual-selected'),
tooltipEl
)
}
console.log('validated pre-rendering')
}
document.querySelectorAll('[data-ol-view-tab]').forEach(setUpViewSwitching)
document
.querySelectorAll('[data-ol-currencyCode-switch]')
.forEach(setUpCurrencySwitching)
document
.querySelectorAll('[data-ol-start-new-subscription]')
.forEach(setUpSubscriptionTracking)
updateLinkTargets()
selectViewFromHash()
window.addEventListener('hashchange', selectViewFromHash)

View file

@ -3,35 +3,15 @@
color: @gray-dark;
margin-bottom: @line-height-computed;
}
.best-value {
color: @brand-secondary;
line-height: @line-height-computed;
text-transform: capitalize;
}
blockquote {
footer {
/* accessibility fix */
color: @gray-med;
}
}
.btn-header {
font-family: @font-family-sans-serif;
margin-left: 10px;
margin-top: -10px;
text-shadow: 0 0 0;
}
.card .btn {
white-space: normal;
}
.card.features {
margin-top: @line-height-computed;
i {
color: @red;
}
p {
margin: 0;
}
}
.btn-header {
font-family: @font-family-sans-serif;
margin-left: 10px;
@ -41,29 +21,6 @@
.card .btn {
white-space: normal;
}
.card-group {
.card-highlighted {
padding-top: @line-height-computed * 2;
padding-bottom: @line-height-computed * 2;
}
}
.card-first,
.card-last {
background: @plans-non-highlighted;
}
.card-highlighted {
border: @border-width-base solid @border-color-base;
padding-top: 10px !important;
.best-value {
margin-bottom: 15px;
}
.card-header {
padding-bottom: 22px; /* align hr with other plans */
}
}
.card-header {
margin-bottom: 15px;
}
.circle {
font-size: 1.5rem;
font-weight: 700;
@ -125,89 +82,6 @@
.tagline {
margin-bottom: 20px;
}
ul.nav-pills {
text-align: center;
margin-bottom: @line-height-computed;
display: flex;
justify-content: center;
li {
float: none;
display: inline-block;
position: relative;
.annual-saving-tooltip {
// hide tooltip below group modal, which has 1050 z-index value (from bootstrap .modal class)
// .tooltip (this element) has 1070 default z-index value
z-index: 1040;
white-space: nowrap;
left: 50%;
width: @tooltip-max-width;
margin-left: -(@tooltip-max-width / 2);
&.bottom {
margin-top: 0px;
}
&.annual-selected {
width: 110px;
margin-left: -55px;
.tooltip-inner {
background-color: @ol-green;
}
.tooltip-arrow {
border-bottom-color: @ol-green;
}
}
&.green-background {
.tooltip-inner {
background-color: @ol-green;
}
.tooltip-arrow {
border-bottom-color: @ol-green;
}
}
.tooltip-inner {
max-width: none;
}
}
}
> li + li {
margin-left: @line-height-computed / 2;
}
}
ul.nav-pills.above-cards {
margin-bottom: @line-height-computed * 2;
}
}
#changePlanSection {
padding-top: 30px;
.changePlanButton {
padding-top: 15px;
}
}
.paymentPageFeatures {
h1,
h2,
h3 {
color: @gray-dark;
}
h3 {
font-size: 18px;
&:first-child {
margin-top: 0;
}
}
p {
font-size: 14px;
color: @gray;
}
.small {
font-size: 12px;
}
}
.plansPageStudentLink {
margin-left: 20px;
margin-top: 20px;
}
/**
@ -220,41 +94,13 @@
/* Media Queries */
@media (max-width: @screen-sm-max) {
.plans {
.card-group {
/*override style in cards.less */
.card {
margin-left: 0;
margin-right: 0;
}
.card-highlighted {
margin-top: @line-height-computed!important;
}
}
.circle-img {
float: left;
margin: 0 15px;
}
ul.nav-pills {
margin-bottom: @margin-xs;
li {
margin-bottom: @margin-sm;
}
}
}
}
@media (max-width: @screen-xs-max) {
.plans ul.nav-pills {
li {
button {
font-size: @font-size-small;
padding: 8px 10px;
}
}
> li + li {
margin-left: @margin-sm;
}
}
}
@media (min-width: @screen-md-min) {
.plans {
blockquote {
@ -267,11 +113,6 @@
}
}
}
.top-switch {
.currency-dropdown {
margin-right: -15px;
}
}
}
}
@ -281,266 +122,6 @@
margin: 12.5px 0 0 0;
}
/**
Plans Table
*/
.plans-table {
border: 1px solid @gray-lighter;
background-color: @plans-non-highlighted;
margin: @best-val-height 0 15px 0;
table-layout: fixed;
width: 100%;
th,
td {
-moz-background-clip: padding;
-webkit-background-clip: padding;
background-clip: padding-box; /* needed for firefox when there is bg color */
border: 1px solid @gray-lighter;
padding: 6px;
text-align: center;
vertical-align: middle;
}
td {
font-weight: bold;
}
th {
border-top: 0;
font-family: @headings-font-family;
font-size: @font-size-h2;
font-weight: @headings-font-weight;
hyphens: auto;
line-height: @headings-line-height;
padding: 18px;
}
th:first-child,
td:first-child {
border-left: 0;
}
th:last-child,
td:last-child {
border-right: 0;
}
td:first-child {
font-weight: bold;
padding-left: 18px;
text-align: left;
}
tr:first-child {
th {
position: relative;
/* keep here position here, otherwise messes up border on safari */
}
}
tr:last-child {
td {
border-bottom: 0;
padding: 18px;
}
td:first-child {
border: 0;
}
}
.fa-check {
color: @green;
}
/* accessibility fixes */
.small {
color: @gray-med;
}
.outer {
left: -@border-width-base;
right: -@border-width-base;
position: absolute;
.outer-content {
background: white;
border: @border-width-base solid @border-color-base;
border-radius: @border-radius-base;
font-size: @font-size-base;
font-family: @font-family-sans-serif;
font-weight: bold;
height: @best-val-height;
padding-top: 10px;
}
}
.outer.outer-top {
top: -@best-val-height;
.outer-content {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-bottom: 0;
}
}
.outer.outer-btm {
bottom: -@best-val-height / 2;
.outer-content {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-top: 0;
height: @best-val-height / 2;
}
}
@media (min-width: @screen-sm-min) {
/* highlight rows on hover */
tr:hover {
td {
background-color: @table-hover-bg;
}
}
tr:first-child:hover {
background-color: transparent;
}
tr:last-child:hover {
background-color: transparent;
td {
background-color: transparent;
}
}
}
/* tooltip */
sup {
color: @brand-secondary;
cursor: pointer;
margin-left: 5px;
}
.tooltip.in {
min-width: 200px;
}
/* Media Queries */
@media (max-width: @screen-sm-max) {
font-size: @font-size-small;
hyphens: auto;
margin-top: @best-val-height*2;
th {
font-size: @font-size-base;
padding-left: @padding-xs;
padding-right: @padding-xs;
}
td:first-child {
padding-left: @padding-xs;
}
tr:last-child {
td {
padding: @padding-xs;
.btn {
word-break: normal;
}
}
}
.best-value {
line-height: 1;
}
.btn {
font-size: @font-size-small;
}
}
@media screen and (max-width: @screen-xs-max) {
tbody,
thead {
display: block;
}
tr {
display: flex;
flex-flow: row wrap;
justify-content: space-around;
}
th {
font-size: 12px;
}
/* hide the first column header */
tr:first-child {
th:first-child {
display: none;
}
}
/* make the first column into a row */
td:first-child {
text-align: center;
background: @gray-lightest;
width: 100%;
}
}
}
.plans-table-main {
td:nth-child(4),
th:nth-child(4) {
background-color: white;
border-left: @border-width-base solid @border-color-base;
border-right: @border-width-base solid @border-color-base;
}
tr:last-child {
/* highlighted column */
td:nth-child(4) {
position: relative;
/* keep here position here, otherwise messes up border on safari when there is a bg color */
&:before {
/* needed for safafi */
border-top: 1px solid @border-color-base;
content: '';
left: 0;
position: absolute;
top: -1px;
width: 100%;
}
}
}
@media screen and (max-width: @screen-xs-max) {
td,
th {
display: block;
width: 25%;
}
}
}
.plans-table-student {
td:nth-child(3),
th:nth-child(3) {
background-color: white;
border-left: @border-width-base solid @border-color-base;
border-right: @border-width-base solid @border-color-base;
}
tr:last-child {
/* highlighted column */
td:nth-child(3) {
position: relative;
/* keep here position here, otherwise messes up border on safari when there is a bg color */
&:before {
/* needed for safafi */
border-top: 1px solid @border-color-base;
content: '';
left: 0;
position: absolute;
top: -1px;
width: 100%;
}
}
}
@media screen and (max-width: @screen-xs-max) {
td,
th {
display: block;
width: 33.3%;
}
}
}
.group-subscription-modal {
.modal-header {
text-align: center;

View file

@ -80,7 +80,6 @@
"already_have_sl_account": "Already have an __appName__ account?",
"also": "Also",
"also_available_as_on_premises": "Also available as On-Premises",
"also_provides_free_plan": "__appName__ also provides a free plan -- simply <0>register here</0> to get started.",
"alternatively_create_new_institution_account": "Alternatively, you can create a <b>new account</b> with your institution email (<b>__email__</b>) by clicking <b>__clickText__</b>.",
"an_error_occurred_when_verifying_the_coupon_code": "An error occurred when verifying the coupon code",
"and": "and",
@ -134,7 +133,6 @@
"beta_program_opt_in_action": "Opt-In to Beta Program",
"beta_program_opt_out_action": "Opt-Out of Beta Program",
"bibliographies": "Bibliographies",
"billed_after_x_days": "You wont be billed until after your __len__ day trial expires.",
"binary_history_error": "Preview not available for this file type",
"blank_project": "Blank Project",
"blocked_filename": "This file name is blocked.",
@ -197,7 +195,6 @@
"change_owner": "Change owner",
"change_password": "Change Password",
"change_plan": "Change plan",
"change_plans_any_time": "You can change plans or change your account at any time. ",
"change_primary_email_address_instructions": "To change your primary email, please add your new primary email address first (by clicking <0>Add another email</0>) and confirm it. Then click the <0>Make Primary</0> button. <1>Learn more</1> about managing your __appName__ emails.",
"change_project_owner": "Change Project Owner",
"change_to_annual_billing_and_save": "Get <0>__percentage__</0> off with annual billing. If you switch now youll save <1>__yearlySaving__</1> per year.",
@ -240,7 +237,6 @@
"commons_plan_tooltip": "Youre on the __plan__ plan because of your affiliation with __institution__. Click to find out how to make the most of your Overleaf premium features.",
"compact": "Compact",
"company_name": "Company Name",
"compare_plan_features": "Compare Plan Features",
"compare_to_another_version": "Compare to another version",
"comparing_x_to_y": "Comparing <0>__startTime__</0> to <0>__endTime__</0>",
"compile_error_entry_description": "An error which prevented this project from compiling",
@ -344,7 +340,6 @@
"disable_stop_on_first_error": "Disable “Stop on first error”",
"disconnected": "Disconnected",
"discount_of": "Discount of __amount__",
"discounted_group_accounts": "discounted group accounts",
"dismiss": "Dismiss",
"dismiss_error_popup": "Dismiss first error alert",
"do_not_have_acct_or_do_not_want_to_link": "If you dont have an <b>__appName__</b> account, or if you dont want to link to your <b>__institutionName__</b> account, please click <b>__clickText__</b>.",
@ -445,33 +440,20 @@
"expiry": "Expiry Date",
"export_csv": "Export CSV",
"export_project_to_github": "Export Project to GitHub",
"faq_change_plans_answer": "Yes, you can change your plan at any time via your subscription settings. This includes options to switch to a different plan, or to switch between monthly and annual billing options, or to cancel to downgrade to the free plan.",
"faq_change_plans_or_cancel_answer": "Yes, you can do this at any time via your subscription settings. You can change plans, switch between monthly and annual billing options, or cancel to downgrade to the free plan. When cancelling, your subscription will continue until the end of the billing period. If your account temporarily does not have a subscription, the only change will be to the features available to you. Your projects will always be available on your account.",
"faq_change_plans_or_cancel_question": "Can I change plans or cancel later?",
"faq_change_plans_question": "Can I change plans later?",
"faq_do_collab_need_on_paid_plan_answer": "No, they can be on any plan, including the free plan. If you are on a premium plan, some premium features will be available to your collaborators in projects that you have created, even if those collaborators are on the free plan. For more information, read about <0>account and subscriptions</0> and <1>how premium features work</1>.",
"faq_do_collab_need_on_paid_plan_question": "Do my collaborators also need to be on a paid plan?",
"faq_do_collab_need_premium_answer": "Premium features, such as tracked changes, will be available to your collaborators on projects that you have created, even if those collaborators have free accounts.",
"faq_do_collab_need_premium_question": "Do my collaborators also need premium accounts?",
"faq_how_does_a_group_plan_work_answer": "Group subscriptions are a way to upgrade more than one Overleaf account. They are easy to manage, help to save on paperwork, and reduce the cost of purchasing multiple subscriptions separately. To learn more, read about <0>joining a group subscription</0> and <1>managing a group subscription</1>. You can purchase group subscriptions above or by <2>contacting us</2>.",
"faq_how_does_a_group_plan_work_question": "How does a group plan work? How can I add people to the plan?",
"faq_how_does_free_trial_works_answer": "You get full access to your chosen __appName__ plan during your __len__-day free trial. There is no obligation to continue beyond the trial. Your card will be charged at the end of your __len__ day trial unless you cancel before then. You can cancel via your subscription settings.",
"faq_how_free_trial_works_answer_v2": "You get full access to your chosen premium plan during your __len__ day free trial, and there is no obligation to continue beyond the trial. Your card will be charged at the end of your trial unless you cancel before then. To cancel, go to your subscription settings in your account (the trial will continue for the full __len__ days).",
"faq_how_free_trial_works_question": "How does the free trial work?",
"faq_how_to_pay_answer": "Yes, you can. All major credit and debit cards and Paypal are supported. Select the plan youd like above, and youll have the option to pay by card or to go through to PayPal when its time to set up payment.",
"faq_how_to_pay_question": "Can I pay online with a credit or debit card, or PayPal?",
"faq_i_have_free_account_want_subscription_how_answer_first_paragraph": "In Overleaf, every user creates and manages their own Overleaf account. Most users start on the free plan but can upgrade and enjoy the premium features by subscribing to a plan, joining a group subscription or joining a <0>Common subscription</0>. When you purchase, join or leave a subscription, you can still keep the same Overleaf account.",
"faq_i_have_free_account_want_subscription_how_answer_second_paragraph": "To find out more, read more about <0>how accounts and subscriptions work together in Overleaf</0>.",
"faq_i_have_free_account_want_subscription_how_question": "I have a free account and want to join a subscription, how do I do that?",
"faq_monthly_or_annual_answer": "Annual billing offers a way to cut down on your admin and paperwork. If youd prefer to manage a single payment every year, instead of twelve, annual billing is for you.",
"faq_monthly_or_annual_question": "Should I choose monthly or annual billing?",
"faq_need_more_collab_answer": "You can upgrade to one of our paid accounts, which support more collaborators. You can also earn additional collaborators on our free accounts by __referFriendsLink__.",
"faq_need_more_collab_question": "What if I need more collaborators?",
"faq_pay_by_invoice_answer": "Yes, if youd like to purchase a group account or site license and would prefer to pay by invoice,\r\nor need to raise a purchase order, please <0>let us know</0>.\r\nFor individual accounts or accounts with monthly billing, we can only accept payment online\r\nvia credit or debit card, or PayPal.",
"faq_pay_by_invoice_answer_v2": "Yes, if youd like to purchase a group subscription for five or more people, or a site license. For individual subscriptions we can only accept payment online via credit card, debit card or PayPal.",
"faq_pay_by_invoice_question": "Can I pay by invoice / purchase order?",
"faq_purchase_more_licenses_answer": "Yes, we provide __groupLink__, which are easy to manage, help to save on paperwork, and reduce the cost of purchasing multiple licenses.",
"faq_purchase_more_licenses_question": "Can I purchase additional licenses for my colleagues?",
"faq_the_individual_standard_plan_10_collab_first_paragraph": "No. Only the subscribers account will be upgraded. An individual Standard subscription allows you to invite 10 collaborators to each project owned by you.",
"faq_the_individual_standard_plan_10_collab_question": "The individual Standard plan has 10 project collaborators, does it mean that 10 people will be upgraded?",
"faq_the_individual_standard_plan_10_collab_second_paragraph": "While working on a project that you, as a subscriber, share with them, your collaborators will be able to access some premium features such as the full document history and extended compile time for that particular project. Inviting them to a particular project does not upgrade their accounts overall, however. Read more about <0>which features are per project, and which are per account</0>.",
@ -584,10 +566,7 @@
"generic_linked_file_compile_error": "This projects output files are not available because it failed to compile. Please open the project to see the compilation error details.",
"generic_something_went_wrong": "Sorry, something went wrong",
"get_collaborative_benefits": "Get the collaborative benefits from __appName__, even if you prefer to work offline",
"get_in_touch": "Get in touch",
"get_in_touch_for_details": "Get in touch for details!",
"get_in_touch_having_problems": "<a href=\"__link__\">Get in touch with support</a> if youre having problems",
"get_instant_access_to": "Get instant access to",
"get_involved": "Get involved",
"get_most_subscription_by_checking_features": "Get the most out of your __appName__ subscription by checking out <0>__appName__s features</0>.",
"get_most_subscription_by_checking_premium_features": "Get the most out of your __appName__ subscription by checking out the list of <0>__appName__s premium features</0>.",
@ -1220,7 +1199,6 @@
"reference_sync": "Reference manager sync",
"reference_sync_info": "Manage your reference library in Mendeley or Zotero and link it directly to a .bib file in Overleaf, so you can easily cite anything in your library.",
"references_search_hint": "Press CTRL-Space to Search",
"referring_your_friends": "referring your friends",
"refresh": "Refresh",
"refresh_page_after_linking_dropbox": "Please refresh this page after linking your account to Dropbox.",
"refresh_page_after_starting_free_trial": "Please refresh this page after starting your free trial.",
@ -1327,7 +1305,6 @@
"select_all": "Select all",
"select_all_projects": "Select all projects",
"select_an_output_file": "Select an Output File",
"select_country_vat": "Please select your country on the payment page to view the total price including any VAT.",
"select_from_output_files": "select from output files",
"select_from_source_files": "select from source files",
"select_github_repository": "Select a GitHub repository to import into __appName__.",
@ -1383,7 +1360,6 @@
"sitewide_option_available_info": "Users are automatically upgraded when they register or add their email address to Overleaf (domain-based enrollment or SSO).",
"skip": "Skip",
"skip_to_content": "Skip to content",
"sl_benefits_plans": "__appName__ is the worlds easiest to use LaTeX editor. Stay up to date with your collaborators, keep track of all changes to your work, and use our LaTeX environment from anywhere in the world.",
"sl_gives_you_free_stuff_see_progress_below": "When someone starts using __appName__ after your recommendation well give you some <strong>free stuff</strong> to say thanks! Check your progress below.",
"sl_included_history_of_changes_blurb": "__appName__ includes a history of all of your changes so you can see exactly who changed what, and when. This makes it extremely easy to keep up to date with any progress made by your collaborators and allows you to review recent work.",
"something_went_wrong_canceling_your_subscription": "Something went wrong canceling your subscription. Please contact support.",

View file

@ -177,7 +177,7 @@ describe('SubscriptionController', function () {
describe('groupPlanModal data', function () {
it('should pass local currency if valid', function (done) {
this.res.render = (page, opts) => {
page.should.equal('subscriptions/plans-marketing')
page.should.equal('subscriptions/plans-marketing-v2')
opts.groupPlanModalDefaults.currency.should.equal('GBP')
done()
}
@ -189,7 +189,7 @@ describe('SubscriptionController', function () {
it('should fallback to USD when valid', function (done) {
this.res.render = (page, opts) => {
page.should.equal('subscriptions/plans-marketing')
page.should.equal('subscriptions/plans-marketing-v2')
opts.groupPlanModalDefaults.currency.should.equal('USD')
done()
}
@ -201,7 +201,7 @@ describe('SubscriptionController', function () {
it('should pass valid options for group plan modal and discard invalid', function (done) {
this.res.render = (page, opts) => {
page.should.equal('subscriptions/plans-marketing')
page.should.equal('subscriptions/plans-marketing-v2')
opts.groupPlanModalDefaults.size.should.equal('42')
opts.groupPlanModalDefaults.plan_code.should.equal('collaborator')
opts.groupPlanModalDefaults.currency.should.equal('GBP')