diff --git a/services/web/app/src/Features/Subscription/SubscriptionController.js b/services/web/app/src/Features/Subscription/SubscriptionController.js
index 0a4cc2ee5f..4315462be7 100644
--- a/services/web/app/src/Features/Subscription/SubscriptionController.js
+++ b/services/web/app/src/Features/Subscription/SubscriptionController.js
@@ -9,7 +9,10 @@ const logger = require('@overleaf/logger')
const GeoIpLookup = require('../../infrastructure/GeoIpLookup')
const FeaturesUpdater = require('./FeaturesUpdater')
const planFeatures = require('./planFeatures')
-const plansV2Config = require('./plansV2Config')
+const noPersonalPlansConfig = require('./st-personal-off-variant/plansConfig')
+const hasPersonalPlansConfig = require('./st-personal-off-default/plansConfig')
+const noPersonalInterstitialPaymentConfig = require('./st-personal-off-variant/interstitialPaymentConfig')
+const hasPersonalInterstitialPaymentConfig = require('./st-personal-off-default/interstitialPaymentConfig')
const GroupPlansData = require('./GroupPlansData')
const V1SubscriptionManager = require('./V1SubscriptionManager')
const Errors = require('../Errors/Errors')
@@ -21,7 +24,6 @@ const { expressify } = require('../../util/promises')
const OError = require('@overleaf/o-error')
const SplitTestHandler = require('../SplitTests/SplitTestHandler')
const SubscriptionHelper = require('./SubscriptionHelper')
-const interstitialPaymentConfig = require('./interstitialPaymentConfig')
const groupPlanModalOptions = Settings.groupPlanModalOptions
const validGroupPlanModalOptions = {
@@ -31,6 +33,22 @@ const validGroupPlanModalOptions = {
usage: groupPlanModalOptions.usages.map(item => item.code),
}
+function getPlansSplitOptions(assignment) {
+ if (assignment?.variant === 'personal-off') {
+ return {
+ directory: 'st-personal-off-variant',
+ plansConfig: noPersonalPlansConfig,
+ interstitialPaymentConfig: noPersonalInterstitialPaymentConfig,
+ }
+ }
+
+ return {
+ directory: 'st-personal-off-default',
+ plansConfig: hasPersonalPlansConfig,
+ interstitialPaymentConfig: hasPersonalInterstitialPaymentConfig,
+ }
+}
+
async function plansPage(req, res) {
const plans = SubscriptionViewModelBuilder.buildPlansList()
@@ -66,14 +84,34 @@ async function plansPage(req, res) {
usage: getDefault('usage', 'usage', 'enterprise'),
}
+ let removePersonalPlanAssingment = { variant: 'default' }
+ try {
+ removePersonalPlanAssingment =
+ await SplitTestHandler.promises.getAssignment(
+ req,
+ res,
+ 'remove-personal-plan'
+ )
+ } catch (error) {
+ logger.error(
+ { err: error },
+ 'Failed to get assignment for remove-personal-plan test'
+ )
+ }
+
+ const { plansConfig, directory } = getPlansSplitOptions(
+ removePersonalPlanAssingment
+ )
+
AnalyticsManager.recordEventForSession(req.session, 'plans-page-view', {
- currency,
+ currency: recommendedCurrency,
+ 'remove-personal-plan-page': removePersonalPlanAssingment?.variant,
countryCode,
'geo-pricing-inr-group': geoPricingTestVariant,
'geo-pricing-inr-page': currency === 'INR' ? 'inr' : 'default',
})
- res.render('subscriptions/plans-marketing-v2', {
+ res.render(`subscriptions/plans-marketing/${directory}/plans-marketing-v2`, {
title: 'plans_and_pricing',
currentView,
plans,
@@ -82,7 +120,7 @@ async function plansPage(req, res) {
itm_campaign: 'plans',
recommendedCurrency: currency,
planFeatures,
- plansV2Config,
+ plansConfig,
groupPlans: GroupPlansData,
groupPlanModalOptions,
groupPlanModalDefaults,
@@ -380,6 +418,25 @@ async function interstitialPaymentPage(req, res) {
const showSkipLink = req.query?.skipLink === 'true'
+ let removePersonalPlanAssingment = { variant: 'default' }
+ try {
+ removePersonalPlanAssingment =
+ await SplitTestHandler.promises.getAssignment(
+ req,
+ res,
+ 'remove-personal-plan'
+ )
+ } catch (error) {
+ logger.error(
+ { err: error },
+ 'Failed to get assignment for remove-personal-plan test'
+ )
+ }
+
+ const { interstitialPaymentConfig, directory } = getPlansSplitOptions(
+ removePersonalPlanAssingment
+ )
+
if (hasSubscription) {
res.redirect('/user/subscription?hasSubscription=true')
} else {
@@ -392,18 +449,22 @@ async function interstitialPaymentPage(req, res) {
'geo-pricing-inr-group': geoPricingTestVariant,
'geo-pricing-inr-page':
recommendedCurrency === 'INR' ? 'inr' : 'default',
+ 'remove-personal-plan-page': removePersonalPlanAssingment?.variant,
}
)
- res.render('subscriptions/interstitial-payment', {
- title: 'subscribe',
- itm_content: req.query?.itm_content,
- itm_campaign: req.query?.itm_campaign,
- itm_referrer: req.query?.itm_referrer,
- recommendedCurrency,
- interstitialPaymentConfig,
- showSkipLink,
- })
+ res.render(
+ `subscriptions/plans-marketing/${directory}/interstitial-payment`,
+ {
+ title: 'subscribe',
+ itm_content: req.query?.itm_content,
+ itm_campaign: req.query?.itm_campaign,
+ itm_referrer: req.query?.itm_referrer,
+ recommendedCurrency,
+ interstitialPaymentConfig,
+ showSkipLink,
+ }
+ )
}
}
diff --git a/services/web/app/src/Features/Subscription/interstitialPaymentConfig.js b/services/web/app/src/Features/Subscription/st-personal-off-default/interstitialPaymentConfig.js
similarity index 100%
rename from services/web/app/src/Features/Subscription/interstitialPaymentConfig.js
rename to services/web/app/src/Features/Subscription/st-personal-off-default/interstitialPaymentConfig.js
diff --git a/services/web/app/src/Features/Subscription/plansV2Config.js b/services/web/app/src/Features/Subscription/st-personal-off-default/plansConfig.js
similarity index 96%
rename from services/web/app/src/Features/Subscription/plansV2Config.js
rename to services/web/app/src/Features/Subscription/st-personal-off-default/plansConfig.js
index 3aade2fd24..b6747e4d2c 100644
--- a/services/web/app/src/Features/Subscription/plansV2Config.js
+++ b/services/web/app/src/Features/Subscription/st-personal-off-default/plansConfig.js
@@ -1,4 +1,4 @@
-const plansV2Features = require('./plansV2Features')
+const plansV2Features = require('./plansFeatures')
const config = {
individual: {
diff --git a/services/web/app/src/Features/Subscription/plansV2Features.js b/services/web/app/src/Features/Subscription/st-personal-off-default/plansFeatures.js
similarity index 100%
rename from services/web/app/src/Features/Subscription/plansV2Features.js
rename to services/web/app/src/Features/Subscription/st-personal-off-default/plansFeatures.js
diff --git a/services/web/app/src/Features/Subscription/st-personal-off-variant/interstitialPaymentConfig.js b/services/web/app/src/Features/Subscription/st-personal-off-variant/interstitialPaymentConfig.js
new file mode 100644
index 0000000000..b7ef58ee07
--- /dev/null
+++ b/services/web/app/src/Features/Subscription/st-personal-off-variant/interstitialPaymentConfig.js
@@ -0,0 +1,218 @@
+const config = {
+ tableHead: {
+ individual_free: {},
+ individual_collaborator: {},
+ individual_professional: {},
+ student_student: {
+ showExtraContent: true,
+ },
+ },
+ highlightedColumn: {
+ index: 1,
+ text: {
+ monthly: 'MOST POPULAR',
+ annual: 'MOST POPULAR',
+ },
+ },
+ eventTrackingKey: 'paywall-plans-page-click',
+ showStudentsOnlyLabel: true,
+ features: [
+ {
+ divider: false,
+ items: [
+ {
+ feature: 'number_of_users',
+ info: 'number_of_users_info',
+ value: 'str',
+ plans: {
+ free: '1 user',
+ collaborator: '1 user',
+ professional: '1 user',
+ student: '1 user',
+ },
+ },
+ {
+ feature: 'max_collab_per_project',
+ info: 'max_collab_per_project_info',
+ value: 'richText',
+ plans: {
+ free: 'You + 1',
+ collaborator: 'You + 10',
+ professional: 'Unlimited',
+ student: 'You + 6',
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'you_and_collaborators_get_access_to',
+ dividerInfo: 'you_and_collaborators_get_access_to_info',
+ items: [
+ {
+ feature: 'compile_timeout_short',
+ info: 'compile_timeout_short_info',
+ value: 'str',
+ plans: {
+ free: '1 minute',
+ collaborator: '4 minutes',
+ professional: '4 minutes',
+ student: '4 minutes',
+ },
+ },
+ {
+ feature: 'realtime_track_changes',
+ info: 'realtime_track_changes_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'full_doc_history',
+ info: 'full_doc_history_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'reference_search',
+ info: 'reference_search_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'git_integration_lowercase',
+ info: 'git_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'you_get_access_to',
+ dividerInfo: 'you_get_access_to_info',
+ items: [
+ {
+ feature: 'powerful_latex_editor_and_realtime_collaboration',
+ info: 'powerful_latex_editor_and_realtime_collaboration_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'unlimited_projects',
+ info: 'unlimited_projects_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'thousands_templates',
+ info: 'hundreds_templates_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'symbol_palette',
+ info: 'symbol_palette_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'github_only_integration_lowercase',
+ info: 'github_only_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'dropbox_integration_lowercase',
+ info: 'dropbox_integration_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'mendeley_integration_lowercase',
+ info: 'mendeley_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'zotero_integration_lowercase',
+ info: 'zotero_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'priority_support',
+ info: 'priority_support_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ student: true,
+ },
+ },
+ ],
+ },
+ ],
+}
+
+module.exports = config
diff --git a/services/web/app/src/Features/Subscription/st-personal-off-variant/plansConfig.js b/services/web/app/src/Features/Subscription/st-personal-off-variant/plansConfig.js
new file mode 100644
index 0000000000..7a39a1df20
--- /dev/null
+++ b/services/web/app/src/Features/Subscription/st-personal-off-variant/plansConfig.js
@@ -0,0 +1,62 @@
+const plansV2Features = require('./plansFeatures')
+
+const config = {
+ individual: {
+ tableHead: {
+ individual_free: {},
+ individual_collaborator: {},
+ individual_professional: {},
+ },
+ features: plansV2Features.individual,
+ highlightedColumn: {
+ index: 1,
+ text: {
+ monthly: 'MOST POPULAR',
+ annual: 'MOST POPULAR',
+ },
+ },
+ eventTrackingKey: 'plans-page-click',
+ additionalEventSegmentation: {},
+ },
+ group: {
+ tableHead: {
+ group_collaborator: {},
+ group_professional: {},
+ group_organization: {},
+ },
+ features: plansV2Features.group,
+ highlightedColumn: {
+ index: 0,
+ text: {
+ annual: 'MOST POPULAR',
+ },
+ },
+ eventTrackingKey: 'plans-page-click',
+ additionalEventSegmentation: {},
+ },
+ student: {
+ baseColspan: 2,
+ maxColumn: 3,
+ tableHead: {
+ student_free: {
+ colspan: 3,
+ },
+ student_student: {
+ showExtraContent: false,
+ colspan: 3,
+ },
+ },
+ features: plansV2Features.student,
+ highlightedColumn: {
+ index: 1,
+ text: {
+ monthly: 'SAVE 20% ON ANNUAL PLAN',
+ annual: 'SAVING 20%',
+ },
+ },
+ eventTrackingKey: 'plans-page-click',
+ additionalEventSegmentation: {},
+ },
+}
+
+module.exports = config
diff --git a/services/web/app/src/Features/Subscription/st-personal-off-variant/plansFeatures.js b/services/web/app/src/Features/Subscription/st-personal-off-variant/plansFeatures.js
new file mode 100644
index 0000000000..4c11ea3929
--- /dev/null
+++ b/services/web/app/src/Features/Subscription/st-personal-off-variant/plansFeatures.js
@@ -0,0 +1,612 @@
+const individualPlans = [
+ {
+ divider: false,
+ items: [
+ {
+ feature: 'number_of_users',
+ info: 'number_of_users_info',
+ value: 'str',
+ plans: {
+ free: '1 user',
+ collaborator: '1 user',
+ professional: '1 user',
+ },
+ },
+ {
+ feature: 'max_collab_per_project',
+ info: 'max_collab_per_project_info',
+ value: 'richText',
+ plans: {
+ free: 'You + 1',
+ collaborator: 'You + 10',
+ professional: 'Unlimited',
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'you_and_collaborators_get_access_to',
+ dividerInfo: 'you_and_collaborators_get_access_to_info',
+ items: [
+ {
+ feature: 'compile_timeout_short',
+ info: 'compile_timeout_short_info',
+ value: 'str',
+ plans: {
+ free: '1 minute',
+ collaborator: '4 minutes',
+ professional: '4 minutes',
+ },
+ },
+ {
+ feature: 'realtime_track_changes',
+ info: 'realtime_track_changes_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'full_doc_history',
+ info: 'full_doc_history_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'reference_search',
+ info: 'reference_search_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'git_integration_lowercase',
+ info: 'git_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'you_get_access_to',
+ dividerInfo: 'you_get_access_to_info',
+ items: [
+ {
+ feature: 'powerful_latex_editor_and_realtime_collaboration',
+ info: 'powerful_latex_editor_and_realtime_collaboration_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'unlimited_projects',
+ info: 'unlimited_projects_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'thousands_templates',
+ info: 'hundreds_templates_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'symbol_palette',
+ info: 'symbol_palette_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'github_only_integration_lowercase',
+ info: 'github_only_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'dropbox_integration_lowercase',
+ info: 'dropbox_integration_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'mendeley_integration_lowercase',
+ info: 'mendeley_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'zotero_integration_lowercase',
+ info: 'zotero_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ {
+ feature: 'priority_support',
+ info: 'priority_support_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ collaborator: true,
+ professional: true,
+ },
+ },
+ ],
+ },
+]
+
+const groupPlans = [
+ {
+ divider: false,
+ items: [
+ {
+ feature: 'number_of_users',
+ info: 'number_of_users_info',
+ value: 'str',
+ plans: {
+ group_standard: '2 users',
+ group_professional: '2 users',
+ organization: 'Contact sales',
+ },
+ },
+ {
+ feature: 'max_collab_per_project',
+ info: 'max_collab_per_project_info',
+ value: 'richText',
+ plans: {
+ group_standard: 'Project author + 10',
+ group_professional: 'Unlimited',
+ organization: 'Unlimited',
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'group_admins_get_access_to',
+ dividerInfo: 'group_admins_get_access_to_info',
+ items: [
+ {
+ feature: 'user_management',
+ info: 'user_management_info',
+ value: 'str',
+ plans: {
+ group_standard: 'admin panel',
+ group_professional: 'admin panel',
+ organization: 'automatic user registration',
+ },
+ },
+ {
+ feature: 'usage_metrics',
+ info: 'usage_metrics_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'sso_integration',
+ info: 'sso_integration_info',
+ value: 'bool',
+ plans: {
+ group_standard: false,
+ group_professional: false,
+ organization: true,
+ },
+ },
+ {
+ feature: 'sitewide_option_available',
+ info: 'sitewide_option_available_info',
+ value: 'bool',
+ plans: {
+ group_standard: false,
+ group_professional: false,
+ organization: true,
+ },
+ },
+ {
+ feature: 'custom_resource_portal',
+ info: 'custom_resource_portal_info',
+ value: 'bool',
+ plans: {
+ group_standard: false,
+ group_professional: false,
+ organization: true,
+ },
+ },
+ {
+ feature: 'personalized_onboarding',
+ info: 'personalized_onboarding_info',
+ value: 'bool',
+ plans: {
+ group_standard: false,
+ group_professional: false,
+ organization: true,
+ },
+ },
+ {
+ feature: 'dedicated_account_manager',
+ info: 'dedicated_account_manager_info',
+ value: 'bool',
+ plans: {
+ group_standard: false,
+ group_professional: false,
+ organization: true,
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'group_members_and_collaborators_get_access_to',
+ dividerInfo: 'group_members_and_collaborators_get_access_to_info',
+ items: [
+ {
+ feature: 'compile_timeout_short',
+ info: 'compile_timeout_short_info',
+ value: 'str',
+ plans: {
+ group_standard: '4 minutes',
+ group_professional: '4 minutes',
+ organization: '4 minutes',
+ },
+ },
+ {
+ feature: 'realtime_track_changes',
+ info: 'realtime_track_changes_info_v2',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'full_doc_history',
+ info: 'full_doc_history_info_v2',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'reference_search',
+ info: 'reference_search_info_v2',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'git_integration_lowercase',
+ info: 'git_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'group_members_get_access_to',
+ dividerInfo: 'group_members_get_access_to_info',
+ items: [
+ {
+ feature: 'powerful_latex_editor_and_realtime_collaboration',
+ info: 'powerful_latex_editor_and_realtime_collaboration_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'unlimited_projects',
+ info: 'unlimited_projects_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'thousands_templates',
+ info: 'hundreds_templates_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'symbol_palette',
+ info: 'symbol_palette_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'github_only_integration_lowercase',
+ info: 'github_only_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'dropbox_integration_lowercase',
+ info: 'dropbox_integration_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'mendeley_integration_lowercase',
+ info: 'mendeley_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'zotero_integration_lowercase',
+ info: 'zotero_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ {
+ feature: 'priority_support',
+ info: 'priority_support_info',
+ value: 'bool',
+ plans: {
+ group_standard: true,
+ group_professional: true,
+ organization: true,
+ },
+ },
+ ],
+ },
+]
+
+const studentPlans = [
+ {
+ divider: false,
+ items: [
+ {
+ feature: 'number_of_users',
+ info: 'number_of_users_info',
+ value: 'str',
+ plans: {
+ free: '1 user',
+ student: '1 user',
+ },
+ },
+ {
+ feature: 'max_collab_per_project',
+ info: 'max_collab_per_project_info',
+ value: 'str',
+ plans: {
+ free: 'You + 1',
+ student: 'You + 6',
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'you_and_collaborators_get_access_to',
+ dividerInfo: 'you_and_collaborators_get_access_to_info',
+ items: [
+ {
+ feature: 'compile_timeout_short',
+ info: 'compile_timeout_short_info',
+ value: 'str',
+ plans: {
+ free: '1 minute',
+ student: '4 minutes',
+ },
+ },
+ {
+ feature: 'realtime_track_changes',
+ info: 'realtime_track_changes_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'full_doc_history',
+ info: 'full_doc_history_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'reference_search',
+ info: 'reference_search_info_v2',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'git_integration_lowercase',
+ info: 'git_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ dividerLabel: 'you_get_access_to',
+ dividerInfo: 'you_get_access_to_info',
+ items: [
+ {
+ feature: 'powerful_latex_editor_and_realtime_collaboration',
+ info: 'powerful_latex_editor_and_realtime_collaboration_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'unlimited_projects',
+ info: 'unlimited_projects_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'thousands_templates',
+ info: 'thousands_templates_info',
+ value: 'bool',
+ plans: {
+ free: true,
+ student: true,
+ },
+ },
+ {
+ feature: 'symbol_palette',
+ info: 'symbol_palette_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'github_only_integration_lowercase',
+ info: 'github_only_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'dropbox_integration_lowercase',
+ info: 'dropbox_integration_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'mendeley_integration_lowercase',
+ info: 'mendeley_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'zotero_integration_lowercase',
+ info: 'zotero_integration_lowercase_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ {
+ feature: 'priority_support',
+ info: 'priority_support_info',
+ value: 'bool',
+ plans: {
+ free: false,
+ student: true,
+ },
+ },
+ ],
+ },
+]
+
+module.exports = {
+ individual: individualPlans,
+ group: groupPlans,
+ student: studentPlans,
+}
diff --git a/services/web/app/views/subscriptions/interstitial-payment.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/interstitial-payment.pug
similarity index 96%
rename from services/web/app/views/subscriptions/interstitial-payment.pug
rename to services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/interstitial-payment.pug
index 0391b9286b..4f34c0340c 100644
--- a/services/web/app/views/subscriptions/interstitial-payment.pug
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/interstitial-payment.pug
@@ -1,6 +1,6 @@
-extends ../layout
+extends ../../../layout
-include ./plans-marketing/v2/_mixins
+include ./v2/_mixins
block vars
- entrypoint = 'pages/user/subscription/plans-v2/plans-v2-main'
diff --git a/services/web/app/views/subscriptions/plans-marketing-v2.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/plans-marketing-v2.pug
similarity index 86%
rename from services/web/app/views/subscriptions/plans-marketing-v2.pug
rename to services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/plans-marketing-v2.pug
index f765d84aa8..4cc687de3a 100644
--- a/services/web/app/views/subscriptions/plans-marketing-v2.pug
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/plans-marketing-v2.pug
@@ -1,4 +1,4 @@
-extends ../layout-marketing
+extends ../../../layout-marketing
block vars
- entrypoint = 'pages/user/subscription/plans-v2/plans-v2-main'
@@ -20,7 +20,7 @@ block content
.page-header.centered.plans-header.text-centered.top-page-header
h1.text-capitalize(ng-non-bindable) #{translate('choose_your_plan')}
- include ./plans-marketing/v2/_cards_controls_tables
+ include ./v2/_cards_controls_tables
.row.row-spaced-large.text-centered
.col-xs-12
p.text-centered
@@ -36,11 +36,11 @@ block content
i.fa.fa-cc-paypal.fa-2x(aria-hidden="true")
span.sr-only Paypal accepted
- include ./plans-marketing/v2/_university_info
+ include ./v2/_university_info
- include ./plans-marketing/_quotes
+ include ../_quotes
- include ./plans-marketing/v2/_faq
+ include ./v2/_faq
.row.row-spaced-large
.col-md-12
@@ -53,5 +53,5 @@ block content
.row.row-spaced
- include ./plans-marketing/_group_plan_modal
+ include ../_group_plan_modal
!= moduleIncludes("contactModalGeneral-marketing", locals)
diff --git a/services/web/app/views/subscriptions/plans-marketing/v2/_cards_controls_tables.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_cards_controls_tables.pug
similarity index 98%
rename from services/web/app/views/subscriptions/plans-marketing/v2/_cards_controls_tables.pug
rename to services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_cards_controls_tables.pug
index 69ccafa655..b1f108103d 100644
--- a/services/web/app/views/subscriptions/plans-marketing/v2/_cards_controls_tables.pug
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_cards_controls_tables.pug
@@ -40,7 +40,7 @@ include ./_mixins
.col-sm-12
+group_plans_license_picker()
-+table_sticky_header_all(plansV2Config)
++table_sticky_header_all(plansConfig)
.row.plans-v2-table-container(hidden data-ol-plans-v2-period='monthly')
.col-sm-12(data-ol-plans-v2-view='individual')
diff --git a/services/web/app/views/subscriptions/plans-marketing/v2/_faq.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_faq.pug
similarity index 100%
rename from services/web/app/views/subscriptions/plans-marketing/v2/_faq.pug
rename to services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_faq.pug
diff --git a/services/web/app/views/subscriptions/plans-marketing/v2/_mixins.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_mixins.pug
similarity index 98%
rename from services/web/app/views/subscriptions/plans-marketing/v2/_mixins.pug
rename to services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_mixins.pug
index c26cc98b36..2e33a25a2f 100644
--- a/services/web/app/views/subscriptions/plans-marketing/v2/_mixins.pug
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_mixins.pug
@@ -141,15 +141,15 @@ mixin plans_v2_table(period, config)
mixin table_individual(period)
table.card.plans-v2-table.plans-v2-table-individual
- +plans_v2_table(period, plansV2Config.individual)
+ +plans_v2_table(period, plansConfig.individual)
mixin table_group
table.card.plans-v2-table.plans-v2-table-group
- +plans_v2_table('annual', plansV2Config.group)
+ +plans_v2_table('annual', plansConfig.group)
mixin table_student(period)
table.card.plans-v2-table.plans-v2-table-student
- +plans_v2_table(period, plansV2Config.student)
+ +plans_v2_table(period, plansConfig.student)
mixin table_head_individual_free(highlighted, period)
.plans-v2-table-th-content
@@ -193,7 +193,7 @@ mixin table_head_individual_professional(highlighted, eventTrackingKey, addition
.plans-v2-table-btn-buy-container-mobile
+btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period)
ul.plans-v2-table-th-content-benefit
- li #{translate("unlimited_collabs")}
+ li !{translate("unlimited_collabs_rt",{},["b"])}
li #{translate("all_premium_features")}
.plans-v2-table-btn-buy-container-desktop
+btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period)
@@ -566,21 +566,21 @@ mixin plans_v2_table_sticky_header(withSwitch, config)
default
span #{translate(translateKey)}
-mixin table_sticky_header_all(plansV2Config)
+mixin table_sticky_header_all(plansConfig)
.row.plans-v2-table-sticky-header-container(
data-ol-plans-v2-view='individual'
)
- +plans_v2_table_sticky_header(true, plansV2Config.individual)
+ +plans_v2_table_sticky_header(true, plansConfig.individual)
.row.plans-v2-table-sticky-header-container(
hidden
data-ol-plans-v2-view='group'
)
- +plans_v2_table_sticky_header(false, plansV2Config.group)
+ +plans_v2_table_sticky_header(false, plansConfig.group)
.row.plans-v2-table-sticky-header-container(
hidden
data-ol-plans-v2-view='student'
)
- +plans_v2_table_sticky_header(true, plansV2Config.student)
+ +plans_v2_table_sticky_header(true, plansConfig.student)
mixin monthly_annual_switch(initialState, eventTracking, eventSegmentation)
- var monthlyAnnualToggleChecked = initialState === 'monthly'
diff --git a/services/web/app/views/subscriptions/plans-marketing/v2/_university_info.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_university_info.pug
similarity index 100%
rename from services/web/app/views/subscriptions/plans-marketing/v2/_university_info.pug
rename to services/web/app/views/subscriptions/plans-marketing/st-personal-off-default/v2/_university_info.pug
diff --git a/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/interstitial-payment.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/interstitial-payment.pug
new file mode 100644
index 0000000000..4f34c0340c
--- /dev/null
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/interstitial-payment.pug
@@ -0,0 +1,53 @@
+extends ../../../layout
+
+include ./v2/_mixins
+
+block vars
+ - entrypoint = 'pages/user/subscription/plans-v2/plans-v2-main'
+ - var suppressFooter = true
+ - var suppressNavbarRight = true
+
+block append meta
+ meta(name="ol-recommendedCurrency" content=recommendedCurrency)
+ meta(name="ol-itm_content" content=itm_content)
+
+block content
+ main.content.content-alt#main-content
+ .content-page
+ .plans
+ .container
+ .row
+ .col-md-12
+ .page-header.centered.plans-header.text-centered.top-page-header
+ h1.text-capitalize #{translate('choose_your_plan')}
+
+ +monthly_annual_switch("monthly", "paywall-plans-page-toggle", '{}')
+
+ +plans_v2_table_sticky_header(true, interstitialPaymentConfig)
+
+ .row.plans-v2-table-container(data-ol-plans-v2-period='monthly')
+ .col-sm-12
+ .row
+ table.card.plans-v2-table.plans-v2-table-individual
+ +plans_v2_table('monthly', interstitialPaymentConfig)
+
+ .row.plans-v2-table-container(hidden data-ol-plans-v2-period='annual')
+ .col-sm-12
+ .row
+ table.card.plans-v2-table.plans-v2-table-individual
+ +plans_v2_table('annual', interstitialPaymentConfig)
+
+ //- 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)
+
+ if (showSkipLink)
+ .row.row-spaced-small.text-center
+ a(href='/project'
+ event-tracking="skip-button-click"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation='{"location": "interstitial-page"}'
+ )
+ | #{translate("continue_with_free_plan")}
+
+ != moduleIncludes("contactModalGeneral-marketing", locals)
diff --git a/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/plans-marketing-v2.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/plans-marketing-v2.pug
new file mode 100644
index 0000000000..4cc687de3a
--- /dev/null
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/plans-marketing-v2.pug
@@ -0,0 +1,57 @@
+extends ../../../layout-marketing
+
+block vars
+ - entrypoint = 'pages/user/subscription/plans-v2/plans-v2-main'
+
+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.top-page-header
+ h1.text-capitalize(ng-non-bindable) #{translate('choose_your_plan')}
+
+ include ./v2/_cards_controls_tables
+ .row.row-spaced-large.text-centered
+ .col-xs-12
+ p.text-centered
+ strong #{translate("all_prices_displayed_are_in_currency", {recommendedCurrency})}
+ |
+ span #{translate("subject_to_additional_vat")}
+ 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
+
+ include ./v2/_university_info
+
+ include ../_quotes
+
+ include ./v2/_faq
+
+ .row.row-spaced-large
+ .col-md-12
+ .plans-header.plans-subheader.text-centered
+ hr
+ h2.header-with-btn #{translate('still_have_questions')}
+ button.btn.plans-v2-btn-header.text-capitalize(
+ data-ol-open-contact-form-modal="general"
+ ) #{translate('contact_us')}
+
+ .row.row-spaced
+
+ include ../_group_plan_modal
+ != moduleIncludes("contactModalGeneral-marketing", locals)
diff --git a/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_cards_controls_tables.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_cards_controls_tables.pug
new file mode 100644
index 0000000000..b1f108103d
--- /dev/null
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_cards_controls_tables.pug
@@ -0,0 +1,65 @@
+include ./_mixins
+
+.row.plans-v2-top-switch
+ .col-xs-12
+ ul.nav.plans-v2-nav
+ li.active.plans-v2-top-switch-individual(
+ data-ol-plans-v2-view-tab='individual'
+ event-tracking="plans-page-toggle-plan"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation='{"button": "individual"}'
+ )
+ button.btn.btn-default-outline #{translate("indvidual_plans")}
+ li.plans-v2-top-switch-group(
+ data-ol-plans-v2-view-tab='group'
+ event-tracking="plans-page-toggle-plan"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation='{"button": "group"}'
+ )
+ button.btn.btn-default-outline(
+ href="#"
+ )
+ span #{translate("group_plans")}
+ span (save 30% or more)
+ li.plans-v2-top-switch-student(
+ data-ol-plans-v2-view-tab='student'
+ event-tracking="plans-page-toggle-plan"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation='{"button": "student"}'
+ )
+ button.btn.btn-default-outline(
+ href="#"
+ ) #{translate("student_plans")}
+
++monthly_annual_switch("annual", "plans-page-toggle-period")
+
+.row(hidden data-ol-plans-v2-license-picker-container)
+ .col-sm-12
+ +group_plans_license_picker()
+
++table_sticky_header_all(plansConfig)
+
+.row.plans-v2-table-container(hidden data-ol-plans-v2-period='monthly')
+ .col-sm-12(data-ol-plans-v2-view='individual')
+ .row
+ +table_individual('monthly')
+ .col-sm-12(hidden data-ol-plans-v2-view='student')
+ .row
+ +table_student('monthly')
+
+.row.plans-v2-table-container(data-ol-plans-v2-period='annual')
+ .col-sm-12(data-ol-plans-v2-view='individual')
+ .row
+ +table_individual('annual')
+ .col-sm-12(hidden data-ol-plans-v2-view='group')
+ .row
+ +table_group('annual')
+ .col-sm-12(hidden data-ol-plans-v2-view='student')
+ .row
+ +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)
diff --git a/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_faq.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_faq.pug
new file mode 100644
index 0000000000..4e8ae14c6d
--- /dev/null
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_faq.pug
@@ -0,0 +1,43 @@
+.faq.plans-v2-faq
+ .row.row-spaced-large
+ .col-md-12
+ .page-header.plans-header.plans-subheader.text-centered
+ h2 FAQ
+ .row
+ .col-md-12
+ h3 #{translate('faq_what_is_the_difference_between_users_and_collaborators_question')}
+ p !{translate('faq_what_is_the_difference_between_users_and_collaborators_answer_first_paragraph', {}, [{name: 'strong'}])}
+ br
+ p #{translate('faq_what_is_the_difference_between_users_and_collaborators_answer_second_paragraph')}
+ .row
+ .col-md-12
+ h3 #{translate('faq_do_collab_need_on_paid_plan_question')}
+ p !{translate('faq_do_collab_need_on_paid_plan_answer', {}, [{ name: 'a', attrs: { href: "/learn/how-to/Overleaf_Accounts_and_Subscriptions", target: '_blank'}}, { name: 'a', attrs: { href: "/learn/how-to/Overleaf_premium_features", target: '_blank'}}])}
+ .row
+ .col-md-12
+ h3 #{translate('faq_i_have_free_account_want_subscription_how_question')}
+ p !{translate('faq_i_have_free_account_want_subscription_how_answer_first_paragraph', {}, [{ name: 'a', attrs: { href: "/for/universities", target: '_blank'}}])}
+ br
+ p !{translate('faq_i_have_free_account_want_subscription_how_answer_second_paragraph', {}, [{ name: 'a', attrs: { href: "/learn/how-to/Overleaf_Accounts_and_Subscriptions", target: '_blank'}}])}
+ .row
+ .col-md-12
+ h3 #{translate('faq_the_individual_standard_plan_10_collab_question')}
+ p #{translate('faq_the_individual_standard_plan_10_collab_first_paragraph')}
+ br
+ p !{translate('faq_the_individual_standard_plan_10_collab_second_paragraph', {}, [{ name: 'a', attrs: { href: "/learn/how-to/Overleaf_premium_features#Account_and_project_level_features", target: '_blank'}}])}
+ .row
+ .col-md-12
+ h3 #{translate('faq_how_does_a_group_plan_work_question')}
+ p !{translate('faq_how_does_a_group_plan_work_answer', {}, [{ name: 'a', attrs: { href: "/learn/how-to/Joining_an_Overleaf_Group_Subscription", target: '_blank'}}, { name: 'a', attrs: { href: "/learn/how-to/Managing_a_group_subscription", target: '_blank'}}, { name: 'a', attrs: { href: "/contact", target: '_blank'}}])}
+ .row
+ .col-md-12
+ h3 #{translate('faq_how_free_trial_works_question')}
+ p #{translate('faq_how_free_trial_works_answer_v2', { len:'7' })}
+ .row
+ .col-md-12
+ h3 #{translate('faq_change_plans_or_cancel_question')}
+ p #{translate('faq_change_plans_or_cancel_answer')}
+ .row
+ .col-md-12
+ h3 #{translate('faq_pay_by_invoice_question')}
+ p #{translate('faq_pay_by_invoice_answer_v2')}
diff --git a/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_mixins.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_mixins.pug
new file mode 100644
index 0000000000..9ae1f31ffe
--- /dev/null
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_mixins.pug
@@ -0,0 +1,598 @@
+mixin features_premium
+ li
+ 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
+ - var discountedColumn = config.discountedColumn || {}
+ tr
+ th(colspan=baseColspan)
+ - for (var i = 0; i < maxColumn; i++)
+ - var tableHeadKey = Object.keys(config.tableHead)[i]
+ - var tableHeadOptions = Object.values(config.tableHead)[i] || {}
+ - var colspan = tableHeadOptions.colspan || baseColspan
+ - var highlighted = i === config.highlightedColumn.index
+ - var discountHighlighted = i === discountedColumn.index
+ - var eventTrackingKey = config.eventTrackingKey
+ - var additionalEventSegmentation = config.additionalEventSegmentation || {}
+ -
+ if (discountHighlighted) {
+ var thClass = 'plans-v2-table-discount-highlighted'
+ } else if (highlighted) {
+ var thClass = 'plans-v2-table-green-highlighted'
+ } else if (i === config.highlightedColumn.index - 1) {
+ var thClass = 'plans-v2-table-cell-before-green-highlighted-column'
+ } else {
+ var thClass = ''
+ }
+ th(
+ class=thClass
+ colspan=colspan
+ )
+ if (discountHighlighted)
+ p.plans-v2-table-discount-highlighted-text !{config.discountedColumn.text[period]}
+ if (highlighted)
+ p.plans-v2-table-green-highlighted-text !{config.highlightedColumn.text[period]}
+ case tableHeadKey
+ when 'individual_free'
+ +table_head_individual_free(highlighted, period)
+ when 'individual_collaborator'
+ +table_head_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ when 'individual_professional'
+ +table_head_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ when 'group_collaborator'
+ +table_head_group_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation)
+ when 'group_professional'
+ +table_head_group_professional(highlighted, eventTrackingKey, additionalEventSegmentation)
+ when 'group_organization'
+ +table_head_group_organization(highlighted, eventTrackingKey, additionalEventSegmentation)
+ when 'student_free'
+ +table_head_student_free(highlighted, period)
+ when 'student_student'
+ +table_head_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period, tableHeadOptions.showExtraContent)
+ when 'student_university'
+ +table_head_student_university(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+
+ for featuresPerSection in config.features
+ - var dividerColspan = Object.values(config.tableHead).reduce((prev, curr) => (prev) + (curr.colspan || 1), baseColspan)
+ if featuresPerSection.divider
+ tr.plans-v2-table-divider
+ td(
+ colspan=dividerColspan
+ class=((config.highlightedColumn.index === Object.keys(config.tableHead).length - 1) ? 'plans-v2-table-divider-highlighted' : '')
+ )
+ div
+ b.plans-v2-table-divider-label #{translate(featuresPerSection.dividerLabel)}
+ //- will only appear on screen width >= 768px (using CSS)
+ i.fa.fa-question-circle.plans-v2-table-divider-question-icon(
+ data-toggle="tooltip"
+ title=translate(featuresPerSection.dividerInfo),
+ data-placement="top"
+ )
+ //- will only appear on screen width < 768px (using CSS)
+ span.plans-v2-table-divider-learn-more-container
+ span (
+ span.plans-v2-table-divider-learn-more-text(
+ data-toggle="tooltip"
+ title=translate(featuresPerSection.dividerInfo),
+ data-placement="top"
+ ) #{translate("learn_more_lowercase")}
+ span )
+ for feature, featureIndex in featuresPerSection.items
+ tr(
+ class=(featureIndex === (featuresPerSection.items.length - 1) ? 'plans-v2-table-row-last-row-per-section' : '')
+ )
+ td(
+ event-tracking="plans-page-table"
+ event-tracking-trigger="hover"
+ event-tracking-ga="subscription-funnel"
+ event-tracking-label=`${feature.feature}`
+ colspan=baseColspan
+ )
+ .plans-v2-table-feature-name
+ if feature.info
+ span #{translate(feature.feature)}
+ //- will only appear on screen width >= 768px (using CSS)
+ i.fa.fa-question-circle.plans-v2-table-feature-name-question-icon(
+ data-toggle="tooltip"
+ title=translate(feature.info),
+ data-placement="right"
+ )
+ //- will only appear on screen width < 768px (using CSS)
+ span.plans-v2-table-feature-name-learn-more-container
+ span (
+ span.plans-v2-table-feature-name-learn-more-text(
+ data-toggle="tooltip"
+ title=translate(feature.info),
+ data-placement="top"
+ ) #{translate("learn_more_lowercase")}
+ span )
+ else
+ | #{translate(feature.feature)}
+ for plan, planIndex in Object.keys(feature.plans)
+ - var tableHeadOptions = Object.values(config.tableHead)[planIndex] || {}
+ - var colspan = tableHeadOptions.colspan || baseColspan
+ -
+ if (planIndex === discountedColumn.index) {
+ var tdClass = 'plans-v2-table-discount-highlighted'
+ } else if (planIndex === config.highlightedColumn.index) {
+ var tdClass = 'plans-v2-table-green-highlighted'
+ } else if (planIndex === config.highlightedColumn.index - 1) {
+ var tdClass = 'plans-v2-table-cell-before-green-highlighted-column'
+ } else {
+ var tdClass = ''
+ }
+ td(
+ class=tdClass
+ colspan=colspan
+ )
+ +table_cell(feature, plan)
+
+mixin table_individual(period)
+ table.card.plans-v2-table.plans-v2-table-individual
+ +plans_v2_table(period, plansConfig.individual)
+
+mixin table_group
+ table.card.plans-v2-table.plans-v2-table-group
+ +plans_v2_table('annual', plansConfig.group)
+
+mixin table_student(period)
+ table.card.plans-v2-table.plans-v2-table-student
+ +plans_v2_table(period, plansConfig.student)
+
+mixin table_head_individual_free(highlighted, period)
+ .plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("free")}
+ +table_head_price('free', period)
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_individual_free(highlighted)
+ ul.plans-v2-table-th-content-benefit
+ li #{translate("one_collaborator")}
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_individual_free(highlighted)
+
+mixin table_head_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ .plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("standard")}
+ +table_head_price('collaborator', period)
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ ul.plans-v2-table-th-content-benefit
+ li !{translate("x_collaborators_per_project", {collaboratorsCount: '10'})}
+ li #{translate("all_premium_features")}
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+
+mixin table_head_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ .plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("professional")}
+ +table_head_price('professional', period)
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ ul.plans-v2-table-th-content-benefit
+ li !{translate("unlimited_collabs_rt",{},["b"])}
+ li #{translate("all_premium_features")}
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+
+mixin table_head_group_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation)
+ .plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("group_standard")}
+ .plans-v2-table-price-container
+ strike.plans-v2-table-price-before-discount
+ +gen_localized_price_for_plan_view('collaborator', 'annual')
+ p.plans-v2-table-price
+ span(data-ol-plans-v2-group-price-per-user='collaborator') #{initialLocalizedGroupPrice.pricePerUser.collaborator}
+ p.plans-v2-table-price-period-label
+ | per user / year
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_group_collaborator(highlighted, eventTrackingKey)
+ +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_collaborator')
+ ul.plans-v2-table-th-content-benefit
+ li #{translate("up_to")} !{translate("x_collaborators_per_project", {collaboratorsCount: '10'})}
+ li
+ +table_head_group_total_per_year('collaborator')
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_group_collaborator(highlighted, eventTrackingKey)
+ +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_collaborator')
+
+mixin table_head_group_professional(highlighted, eventTrackingKey, additionalEventSegmentation)
+ .plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("group_professional")}
+ .plans-v2-table-price-container
+ strike.plans-v2-table-price-before-discount
+ +gen_localized_price_for_plan_view('professional', 'annual')
+ p.plans-v2-table-price
+ span(data-ol-plans-v2-group-price-per-user='professional') #{initialLocalizedGroupPrice.pricePerUser.professional}
+ p.plans-v2-table-price-period-label
+ | per user / year
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_group_professional(highlighted, eventTrackingKey)
+ +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_professional')
+ ul.plans-v2-table-th-content-benefit
+ li #{translate("unlimited_collaborators_in_each_project")}
+ li
+ +table_head_group_total_per_year('professional')
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_group_professional(highlighted, eventTrackingKey)
+ +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_professional')
+
+mixin table_head_group_total_per_year(groupPlan)
+ - var initialLicenseSize = '2'
+ span.plans-v2-group-total-price(data-ol-plans-v2-group-total-price=groupPlan) #{initialLocalizedGroupPrice.price[groupPlan]}
+ |
+ for licenseSize in groupPlanModalOptions.sizes
+ span(
+ hidden=(licenseSize !== initialLicenseSize)
+ data-ol-plans-v2-table-th-group-license-size=licenseSize
+ ) !{translate("total_per_year_for_x_users", {licenseSize})}
+
+mixin table_head_group_organization(highlighted, eventTrackingKey, additionalEventSegmentation)
+ - var segmentation = JSON.stringify(Object.assign({}, {button: 'group_organization-link', location: 'table-header-list', period: 'annual'}, additionalEventSegmentation))
+ .plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("organization")}
+ .plans-v2-table-comments-icon
+ i.fa.fa-comments-o
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_group_organization(highlighted, eventTrackingKey)
+ small.plans-v2-table-th-content-additional-link.invisible(aria-hidden="true")
+ ul.plans-v2-table-th-content-benefit
+ li #{translate("best_choices_companies_universities_non_profits")}
+ li #{translate("for_groups_or_site_wide")}
+ li
+ a(
+ target="_blank"
+ href="/for/contact-sales"
+ event-tracking="plans-page-click"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation=segmentation
+ ) #{translate("also_available_as_on_premises")}
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_group_organization(highlighted, eventTrackingKey)
+ small.plans-v2-table-th-content-additional-link.invisible(aria-hidden="true")
+
+mixin table_head_student_free(highlighted, period)
+ div.plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("free")}
+ +table_head_price('free', period)
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_student_free(highlighted)
+ ul.plans-v2-table-th-content-benefit
+ li #{translate("one_collaborator")}
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_student_free(highlighted)
+
+mixin table_head_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period, showExtraContent)
+ div.plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("student")}
+ +table_head_price('student', period)
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ ul.plans-v2-table-th-content-benefit
+ li !{translate("x_collaborators_per_project", {collaboratorsCount: '6'})}
+ li #{translate("all_premium_features")}
+ if showExtraContent
+ li
+ b !{translate("for_students_only")}
+
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+
+mixin table_head_student_university(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ div.plans-v2-table-th-content
+ p.plans-v2-table-th-content-title #{translate("university")}
+ div.plans-v2-table-comments-icon
+ i.fa.fa-comments-o
+ .plans-v2-table-btn-buy-container-mobile
+ +btn_buy_student_university(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ p.plans-v2-table-th-content-benefit !{translate("all_our_group_plans_offer_educational_discount", {}, [{name: 'b'}, {name: 'b'}])}
+ .plans-v2-table-btn-buy-container-desktop
+ +btn_buy_student_university(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+
+mixin table_head_price(plan, period)
+ div.plans-v2-table-price-container
+ if plan !== 'free' && period === 'annual'
+ strike.plans-v2-table-price-before-discount
+ +gen_localized_price_for_plan_view(plan, 'monthlyTimesTwelve')
+ p.plans-v2-table-price
+ +gen_localized_price_for_plan_view(plan, period)
+ p.plans-v2-table-price-period-label
+ if period == 'annual'
+ | per year
+ else
+ | per month
+
+mixin table_cell(feature, plan)
+ - var planValue = feature.plans[plan]
+ - var featureName = feature.feature
+
+ .plans-v2-table-cell(
+ data-ol-plans-v2-table-cell-plan=plan
+ data-ol-plans-v2-table-cell-feature=featureName
+ )
+ if (feature.value === 'richText')
+ | !{planValue}
+ else if (feature.value === 'str')
+ | #{planValue}
+ else if (feature.value === 'bool')
+ if (planValue)
+ i.fa.fa-check(aria-hidden="true")
+ span.sr-only #{translate("feature_included")}
+ else
+ span(aria-hidden="true") -
+ span.sr-only #{translate("feature_not_included")}
+
+mixin group_plans_license_picker()
+ form.plans-v2-license-picker-form(data-ol-plans-v2-license-picker-form)
+ .plans-v2-license-picker-select-container
+ span #{translate("number_of_users_with_colon")}
+ select.plans-v2-license-picker-select(
+ name="plans-v2-license-picker-select"
+ id="plans-v2-license-picker-select"
+ autocomplete="off"
+ data-ol-plans-v2-license-picker-select
+ event-tracking="plans-page-group-size"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-tracking-element="select"
+ )
+ option(value="2") 2
+ option(value="3") 3
+ option(value="4") 4
+ option(value="5") 5
+ option(value="10") 10
+ option(value="20") 20
+ option(value="50") 50
+ .plans-v2-license-picker-educational-discount
+ label.plans-v2-license-picker-educational-discount-label(data-ol-plans-v2-license-picker-educational-discount-label)
+ input.plans-v2-license-picker-educational-discount-checkbox(
+ type="checkbox"
+ id="license-picker-educational-discount"
+ autocomplete="off"
+ data-ol-plans-v2-license-picker-educational-discount-input
+ event-tracking="plans-page-edu-discount"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-tracking-element="checkbox"
+ )
+ span #{translate("apply_educational_discount")}
+ //- will only appear on screen width >= 768px (using CSS)
+ i.fa.fa-question-circle.plans-v2-license-picker-educational-discount-question-icon(
+ data-toggle="tooltip"
+ title=translate("apply_educational_discount_info"),
+ data-placement="bottom"
+ )
+ //- will only appear on screen width < 768px (using CSS)
+ span.plans-v2-license-picker-educational-discount-learn-more-container
+ span (
+ span.plans-v2-license-picker-educational-discount-learn-more-text(
+ data-toggle="tooltip"
+ title=translate("apply_educational_discount_info"),
+ data-placement="bottom"
+ ) #{translate("learn_more_lowercase")}
+ span )
+
+mixin btn_buy_individual(highlighted, discountHighlighted, eventTrackingKey, subscriptionPlan, period)
+ a.btn.plans-v2-table-btn-buy(
+ data-ol-start-new-subscription=subscriptionPlan
+ data-ol-event-tracking-key=eventTrackingKey
+ data-ol-item-view=period
+ class=(discountHighlighted ? 'btn-dark-blue' : (highlighted ? 'btn-primary' : 'btn-default'))
+ )
+ if (period === 'monthly')
+ span #{translate("try_for_free")}
+ else
+ span #{translate("buy_now_no_exclamation_mark")}
+
+mixin btn_buy_individual_free()
+ if (!getSessionUser())
+ a.btn.plans-v2-table-btn-buy(
+ href="/register"
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+ span #{translate("try_for_free")}
+ else
+ a.btn.plans-v2-table-btn-buy.invisible(
+ aria-hidden="true"
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+
+mixin btn_buy_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ +btn_buy_individual(highlighted, false, eventTrackingKey, 'collaborator', period)
+ if (period === 'monthly')
+ +additional_link_buy(eventTrackingKey, additionalEventSegmentation, 'collaborator', period)
+
+mixin btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ +btn_buy_individual(highlighted, false, eventTrackingKey, 'professional', period)
+ if (period === 'monthly')
+ +additional_link_buy(eventTrackingKey, additionalEventSegmentation, 'professional', period)
+
+mixin btn_buy_group_collaborator(highlighted, eventTrackingKey)
+ a.btn.plans-v2-table-btn-buy(
+ data-ol-start-new-subscription='group_collaborator'
+ data-ol-event-tracking-key=eventTrackingKey
+ data-ol-item-view='annual'
+ data-ol-has-custom-href
+ data-ol-location='table-header'
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+ span.hidden-desktop #{translate("customize")}
+ span.hidden-mobile #{translate("customize_your_plan")}
+
+mixin btn_buy_group_professional(highlighted, eventTrackingKey)
+ a.btn.plans-v2-table-btn-buy(
+ data-ol-start-new-subscription='group_professional'
+ data-ol-event-tracking-key=eventTrackingKey
+ data-ol-item-view='annual'
+ data-ol-has-custom-href
+ data-ol-location='table-header'
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+ span.hidden-desktop #{translate("customize")}
+ span.hidden-mobile #{translate("customize_your_plan")}
+
+mixin btn_buy_group_organization(highlighted, eventTrackingKey)
+ a.btn.plans-v2-table-btn-buy(
+ data-ol-start-new-subscription='group_organization'
+ data-ol-event-tracking-key=eventTrackingKey
+ data-ol-item-view='annual'
+ data-ol-has-custom-href
+ data-ol-location='table-header'
+ href='/for/contact-sales'
+ target='_blank'
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+ span #{translate("contact_us_lowercase")}
+
+mixin btn_buy_student_free(highlighted)
+ if (!getSessionUser())
+ a.btn.plans-v2-table-btn-buy(
+ href="/register"
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+ span #{translate("try_for_free")}
+
+mixin btn_buy_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ a.btn.plans-v2-table-btn-buy(
+ data-ol-start-new-subscription='student'
+ data-ol-event-tracking-key=eventTrackingKey
+ data-ol-item-view=period
+ data-ol-location='card'
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+ if (period === 'monthly')
+ span #{translate("try_for_free")}
+ else
+ span #{translate("buy_now_no_exclamation_mark")}
+ if (period === 'monthly')
+ +additional_link_buy(eventTrackingKey, additionalEventSegmentation, 'student', period)
+
+mixin btn_buy_student_university(highlighted, eventTrackingKey, additionalEventSegmentation, period)
+ - var segmentation = JSON.stringify(Object.assign({}, {button: 'student-university', location: 'table-header-list', period}, additionalEventSegmentation))
+ a.btn.plans-v2-table-btn-buy(
+ href="/for/contact-sales"
+ target="_blank"
+ event-tracking=eventTrackingKey
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation=segmentation
+ class=(highlighted ? 'btn-primary' : 'btn-default')
+ )
+ span #{translate("contact_us_lowercase")}
+
+mixin additional_link_group(eventTrackingKey, additionalEventSegmentation, plan)
+ - var buttonSegmentation = plan + '-link'
+ - var segmentation = JSON.stringify(Object.assign({}, {button: buttonSegmentation, location: 'table-header'}, additionalEventSegmentation))
+ small.plans-v2-table-th-content-additional-link
+ | #{translate("or")}
+ a(
+ href="/for/contact-sales"
+ target="_blank"
+ event-tracking=eventTrackingKey
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation=segmentation
+ ) #{translate("contact_us_lowercase")}
+
+mixin additional_link_buy(eventTrackingKey, additionalEventSegmentation, plan, period)
+ - var buttonSegmentation = plan + '-link'
+ - var segmentation = JSON.stringify(Object.assign({}, {button: buttonSegmentation, location: 'table-header', period}, additionalEventSegmentation))
+ - var itmCampaign = itm_campaign ? { itm_campaign } : {itm_campaign: 'plans'}
+ - var itmReferrer = itm_referrer ? { itm_referrer } : {}
+ - var qs = new URLSearchParams({planCode: plan, currency: recommendedCurrency, itm_content: 'card', ...itmCampaign, ...itmReferrer})
+ small.plans-v2-table-th-content-additional-link
+ | #{translate("or")}
+ a(
+ href=`/user/subscription/new?${qs.toString()}`
+ event-tracking=eventTrackingKey
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation=segmentation
+ ) #{translate("buy_now_no_exclamation_mark")}
+
+mixin plans_v2_table_sticky_header(withSwitch, config)
+ - var tableHeadKeys = Object.keys(config.tableHead)
+ .row.plans-v2-table-sticky-header.sticky(
+ data-ol-plans-v2-table-sticky-header
+ class=(withSwitch ? 'plans-v2-table-sticky-header-with-switch' : 'plans-v2-table-sticky-header-without-switch')
+ )
+ - for (var i = 0; i < tableHeadKeys.length; i++)
+ - var tableHeadKey = tableHeadKeys[i]
+ - var translateKey = tableHeadKey.split('_')[1]
+ -
+ if (config.discountedColumn?.index === i) {
+ var elClass = 'plans-v2-table-sticky-header-item-discount-highlighted'
+ } else if (config.highlightedColumn.index === i) {
+ var elClass = 'plans-v2-table-sticky-header-item-green-highlighted'
+ } else {
+ var elClass = ''
+ }
+ .plans-v2-table-sticky-header-item(
+ class=elClass
+ )
+ case tableHeadKey
+ when 'individual_collaborator'
+ span #{translate('standard')}
+ when 'group_professional'
+ span #{translate(tableHeadKey)}
+ when 'group_collaborator'
+ span #{translate('group_standard')}
+ default
+ span #{translate(translateKey)}
+
+mixin table_sticky_header_all(plansConfig)
+ .row.plans-v2-table-sticky-header-container(
+ data-ol-plans-v2-view='individual'
+ )
+ +plans_v2_table_sticky_header(true, plansConfig.individual)
+ .row.plans-v2-table-sticky-header-container(
+ hidden
+ data-ol-plans-v2-view='group'
+ )
+ +plans_v2_table_sticky_header(false, plansConfig.group)
+ .row.plans-v2-table-sticky-header-container(
+ hidden
+ data-ol-plans-v2-view='student'
+ )
+ +plans_v2_table_sticky_header(true, plansConfig.student)
+
+mixin monthly_annual_switch(initialState, eventTracking, eventSegmentation)
+ - var monthlyAnnualToggleChecked = initialState === 'monthly'
+ .row
+ .col-md-4.col-md-offset-4.text-centered.plans-v2-m-a-switch-container(data-ol-plans-v2-m-a-switch-container)
+ .plans-v2-m-a-switch-annual-text-container
+ span.underline(data-ol-plans-v2-m-a-switch-text='annual') #{translate("annual")}
+ .tooltip.in.left.plans-v2-m-a-tooltip(
+ role="tooltip"
+ data-ol-plans-v2-m-a-tooltip
+ class=monthlyAnnualToggleChecked ? 'plans-v2-m-a-tooltip-monthly-selected' : ''
+ )
+ .tooltip-arrow
+ .tooltip-inner
+ span(hidden=!monthlyAnnualToggleChecked data-ol-tooltip-period='monthly') #{translate("save_20_percent_by_paying_annually")}
+ span(hidden=monthlyAnnualToggleChecked data-ol-tooltip-period='annual') #{translate("saving_20_percent")}
+
+ label.plans-v2-m-a-switch(data-ol-plans-v2-m-a-switch)
+ input(
+ type="checkbox"
+ checked=monthlyAnnualToggleChecked
+ role="switch"
+ autocomplete="off"
+ event-tracking=eventTracking
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-tracking-element="checkbox"
+ event-segmentation=eventSegmentation
+ )
+ span
+ span(data-ol-plans-v2-m-a-switch-text='monthly') #{translate("monthly")}
diff --git a/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_university_info.pug b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_university_info.pug
new file mode 100644
index 0000000000..916303993d
--- /dev/null
+++ b/services/web/app/views/subscriptions/plans-marketing/st-personal-off-variant/v2/_university_info.pug
@@ -0,0 +1,15 @@
+.row.row-spaced-large.text-centered(
+ data-ol-plans-university-info-container
+ hidden
+)
+ .col-sm-8.col-sm-offset-2.col-xs-12.card.plans-v2-university-info
+ h3.plans-v2-university-info-header #{translate('would_you_like_to_see_a_university_subscription')}
+ p.plans-v2-university-info-text #{translate('student_and_faculty_support_make_difference')}
+ a.btn.plans-v2-btn-header.text-capitalize.plans-v2-btn-university-info(
+ target="_blank"
+ href="/for/support-an-overleaf-university-subscription"
+ event-tracking="plans-page-click"
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ event-segmentation='{"button": "university-support"}'
+ ) #{translate('show_your_support')}
\ No newline at end of file
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index accc079996..4a6a89b9a9 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -1674,6 +1674,7 @@
"unlimited": "Unlimited",
"unlimited_collaborators_in_each_project": "Unlimited collaborators in each project",
"unlimited_collabs": "Unlimited collaborators",
+ "unlimited_collabs_rt": "<0>Unlimited0> collaborators",
"unlimited_private": "Unlimited private projects",
"unlimited_private_info": "All your projects are private by default. Invite collaborators to read or edit by email address or by sending them a secret link.",
"unlimited_projects": "Unlimited projects",
diff --git a/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js b/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js
index 75f2c54459..33936edd0a 100644
--- a/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js
+++ b/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js
@@ -177,7 +177,9 @@ 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-v2')
+ page.should.equal(
+ 'subscriptions/plans-marketing/st-personal-off-default/plans-marketing-v2'
+ )
opts.groupPlanModalDefaults.currency.should.equal('GBP')
done()
}
@@ -189,7 +191,9 @@ describe('SubscriptionController', function () {
it('should fallback to USD when valid', function (done) {
this.res.render = (page, opts) => {
- page.should.equal('subscriptions/plans-marketing-v2')
+ page.should.equal(
+ 'subscriptions/plans-marketing/st-personal-off-default/plans-marketing-v2'
+ )
opts.groupPlanModalDefaults.currency.should.equal('USD')
done()
}
@@ -201,7 +205,9 @@ 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-v2')
+ page.should.equal(
+ 'subscriptions/plans-marketing/st-personal-off-default/plans-marketing-v2'
+ )
opts.groupPlanModalDefaults.size.should.equal('42')
opts.groupPlanModalDefaults.plan_code.should.equal('collaborator')
opts.groupPlanModalDefaults.currency.should.equal('GBP')
@@ -231,7 +237,9 @@ describe('SubscriptionController', function () {
describe('with a user without subscription', function () {
it('should render the interstitial payment page', function (done) {
this.res.render = (page, opts) => {
- page.should.equal('subscriptions/interstitial-payment')
+ page.should.equal(
+ 'subscriptions/plans-marketing/st-personal-off-default/interstitial-payment'
+ )
done()
}
this.SubscriptionController.interstitialPaymentPage(this.req, this.res)