diff --git a/services/web/app/src/Features/Subscription/SubscriptionController.js b/services/web/app/src/Features/Subscription/SubscriptionController.js
index 882dccc255..4b267a2639 100644
--- a/services/web/app/src/Features/Subscription/SubscriptionController.js
+++ b/services/web/app/src/Features/Subscription/SubscriptionController.js
@@ -263,6 +263,8 @@ async function interstitialPaymentPage(req, res) {
const hasSubscription =
await LimitationsManager.promises.userHasV1OrV2Subscription(user)
+ const showSkipLink = req.query?.skipLink === 'true'
+
if (hasSubscription) {
res.redirect('/user/subscription?hasSubscription=true')
} else {
@@ -272,6 +274,7 @@ async function interstitialPaymentPage(req, res) {
itm_campaign: req.query?.itm_campaign,
recommendedCurrency,
interstitialPaymentConfig,
+ showSkipLink,
})
}
}
@@ -339,6 +342,8 @@ async function successfulSubscription(req, res) {
const premiumFeaturesDiscoverability =
premiumFeaturesDiscoverabilityAssignment?.variant === 'active'
+ const postCheckoutRedirect = req.session?.postCheckoutRedirect
+
if (!personalSubscription) {
res.redirect('/user/subscription/plans')
} else {
@@ -346,6 +351,7 @@ async function successfulSubscription(req, res) {
title: 'thank_you',
personalSubscription,
premiumFeaturesDiscoverability,
+ postCheckoutRedirect,
})
}
}
diff --git a/services/web/app/src/models/User.js b/services/web/app/src/models/User.js
index dabaf91c7e..200c19a2aa 100644
--- a/services/web/app/src/models/User.js
+++ b/services/web/app/src/models/User.js
@@ -181,6 +181,7 @@ const UserSchema = new Schema({
auditLog: [AuditLogEntrySchema],
splitTests: Schema.Types.Mixed,
analyticsId: { type: String },
+ surveyResponses: Schema.Types.Mixed,
})
function formatSplitTestsSchema(next) {
diff --git a/services/web/app/views/layout/navbar-marketing.pug b/services/web/app/views/layout/navbar-marketing.pug
index 4f3100127c..d679b847ab 100644
--- a/services/web/app/views/layout/navbar-marketing.pug
+++ b/services/web/app/views/layout/navbar-marketing.pug
@@ -1,13 +1,14 @@
nav.navbar.navbar-default.navbar-main
.container-fluid
.navbar-header
- button.navbar-toggle.collapsed(
- type="button",
- data-toggle="collapse",
- data-target="[data-ol-navbar-main-collapse]"
- aria-label="Toggle " + translate('navigation')
- )
- i.fa.fa-bars(aria-hidden="true")
+ if (typeof(suppressNavbarRight) == "undefined")
+ button.navbar-toggle.collapsed(
+ type="button",
+ data-toggle="collapse",
+ data-target="[data-ol-navbar-main-collapse]"
+ aria-label="Toggle " + translate('navigation')
+ )
+ i.fa.fa-bars(aria-hidden="true")
if settings.nav.custom_logo
a(href='/', aria-label=settings.appName, style='background-image:url("'+settings.nav.custom_logo+'")').navbar-brand
else if (nav.title)
@@ -20,72 +21,85 @@ nav.navbar.navbar-default.navbar-main
- var canDisplaySplitTestMenu = hasFeature('saas') && (canDisplayAdminMenu || (getSessionUser() && getSessionUser().staffAccess && (getSessionUser().staffAccess.splitTestMetrics || getSessionUser().staffAccess.splitTestManagement)))
- var canDisplaySurveyMenu = hasFeature('saas') && canDisplayAdminMenu
- .navbar-collapse.collapse(data-ol-navbar-main-collapse)
- ul.nav.navbar-nav.navbar-right
- if (canDisplayAdminMenu || canDisplayAdminRedirect || canDisplaySplitTestMenu)
- li.dropdown.subdued
- a.dropdown-toggle(
- href="#",
- role="button",
- aria-haspopup="true",
- aria-expanded="false",
- data-toggle="dropdown"
- )
- | Admin
- span.caret
- ul.dropdown-menu
- if canDisplayAdminMenu
- li
- a(href="/admin") Manage Site
- li
- a(href="/admin/user") Manage Users
- li
- a(href="/admin/project") Project URL Lookup
- if canDisplayAdminRedirect
- li
- a(href=settings.adminUrl) Switch to Admin
- if canDisplaySplitTestMenu
- li
- a(href="/admin/split-test") Manage Split Tests
- if canDisplaySurveyMenu
- li
- a(href="/admin/survey") Manage Surveys
+ if (typeof(suppressNavbarRight) == "undefined")
+ .navbar-collapse.collapse(data-ol-navbar-main-collapse)
+ ul.nav.navbar-nav.navbar-right
+ if (canDisplayAdminMenu || canDisplayAdminRedirect || canDisplaySplitTestMenu)
+ li.dropdown.subdued
+ a.dropdown-toggle(
+ href="#",
+ role="button",
+ aria-haspopup="true",
+ aria-expanded="false",
+ data-toggle="dropdown"
+ )
+ | Admin
+ span.caret
+ ul.dropdown-menu
+ if canDisplayAdminMenu
+ li
+ a(href="/admin") Manage Site
+ li
+ a(href="/admin/user") Manage Users
+ li
+ a(href="/admin/project") Project URL Lookup
+ if canDisplayAdminRedirect
+ li
+ a(href=settings.adminUrl) Switch to Admin
+ if canDisplaySplitTestMenu
+ li
+ a(href="/admin/split-test") Manage Split Tests
+ if canDisplaySurveyMenu
+ li
+ a(href="/admin/survey") Manage Surveys
- // loop over header_extras
- each item in ((splitTestVariants && (splitTestVariants['unified-navigation'] === 'show-unified-navigation')) ? nav.header_extras_unified : nav.header_extras)
- -
- if ((item.only_when_logged_in && getSessionUser())
- || (item.only_when_logged_out && (!getSessionUser()))
- || (!item.only_when_logged_out && !item.only_when_logged_in && !item.only_content_pages)
- || (item.only_content_pages && (typeof(suppressNavContentLinks) == "undefined" || !suppressNavContentLinks))
- ){
- var showNavItem = true
- } else {
- var showNavItem = false
- }
+ // loop over header_extras
+ each item in ((splitTestVariants && (splitTestVariants['unified-navigation'] === 'show-unified-navigation')) ? nav.header_extras_unified : nav.header_extras)
+ -
+ if ((item.only_when_logged_in && getSessionUser())
+ || (item.only_when_logged_out && (!getSessionUser()))
+ || (!item.only_when_logged_out && !item.only_when_logged_in && !item.only_content_pages)
+ || (item.only_content_pages && (typeof(suppressNavContentLinks) == "undefined" || !suppressNavContentLinks))
+ ){
+ var showNavItem = true
+ } else {
+ var showNavItem = false
+ }
- if showNavItem
- if item.dropdown
- li.dropdown(class=item.class)
- a.dropdown-toggle(
- href="#",
- role="button",
- aria-haspopup="true",
- aria-expanded="false",
- data-toggle="dropdown"
- )
- | !{translate(item.text)}
- span.caret
- ul.dropdown-menu
- each child in item.dropdown
- if child.divider
- li.divider
- if child.splitTest
- if (splitTestVariants && (splitTestVariants[child.splitTest.name] === child.splitTest.variant))
+ if showNavItem
+ if item.dropdown
+ li.dropdown(class=item.class)
+ a.dropdown-toggle(
+ href="#",
+ role="button",
+ aria-haspopup="true",
+ aria-expanded="false",
+ data-toggle="dropdown"
+ )
+ | !{translate(item.text)}
+ span.caret
+ ul.dropdown-menu
+ each child in item.dropdown
+ if child.divider
+ li.divider
+ if child.splitTest
+ if (splitTestVariants && (splitTestVariants[child.splitTest.name] === child.splitTest.variant))
+ li
+ if child.url
+ a(
+ href=child.url,
+ class=child.class,
+ event-tracking=child.event
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ ) !{translate(child.text)}
+ else
+ | !{translate(child.text)}
+ else
li
if child.url
a(
- href=child.url,
+ href=child.url,
class=child.class,
event-tracking=child.event
event-tracking-mb="true"
@@ -93,81 +107,69 @@ nav.navbar.navbar-default.navbar-main
) !{translate(child.text)}
else
| !{translate(child.text)}
- else
- li
- if child.url
- a(
- href=child.url,
- class=child.class,
- event-tracking=child.event
- event-tracking-mb="true"
- event-tracking-trigger="click"
- ) !{translate(child.text)}
- else
- | !{translate(child.text)}
- else
- li(class=item.class)
- if item.url
- a(
- href=item.url,
- class=item.class,
- event-tracking=item.event
- event-tracking-mb="true"
- event-tracking-trigger="click"
- ) !{translate(item.text)}
- else
- | !{translate(item.text)}
+ else
+ li(class=item.class)
+ if item.url
+ a(
+ href=item.url,
+ class=item.class,
+ event-tracking=item.event
+ event-tracking-mb="true"
+ event-tracking-trigger="click"
+ ) !{translate(item.text)}
+ else
+ | !{translate(item.text)}
- // logged out
- if !getSessionUser()
- // register link
- if hasFeature('registration-page')
+ // logged out
+ if !getSessionUser()
+ // register link
+ if hasFeature('registration-page')
+ li
+ a(
+ href="/register"
+ event-tracking="menu-clicked-register"
+ event-tracking-action="clicked"
+ event-tracking-trigger="click"
+ event-tracking-mb="true"
+ event-segmentation={ page: currentUrl }
+ ) #{translate('register')}
+
+ // login link
li
a(
- href="/register"
- event-tracking="menu-clicked-register"
+ href="/login"
+ event-tracking="menu-clicked-login"
event-tracking-action="clicked"
event-tracking-trigger="click"
event-tracking-mb="true"
event-segmentation={ page: currentUrl }
- ) #{translate('register')}
+ ) #{translate('log_in')}
- // login link
- li
- a(
- href="/login"
- event-tracking="menu-clicked-login"
- event-tracking-action="clicked"
- event-tracking-trigger="click"
- event-tracking-mb="true"
- event-segmentation={ page: currentUrl }
- ) #{translate('log_in')}
-
- // projects link and account menu
- if getSessionUser()
- li
- a(href="/project") #{translate('Projects')}
- li.dropdown
- a.dropdown-toggle(
- href="#",
- role="button",
- aria-haspopup="true",
- aria-expanded="false",
- data-toggle="dropdown"
- )
- | #{translate('Account')}
- span.caret
- ul.dropdown-menu
- li
- div.subdued #{getSessionUser().email}
- li.divider.hidden-xs.hidden-sm
- li
- a(href="/user/settings") #{translate('Account Settings')}
- if nav.showSubscriptionLink
+ // projects link and account menu
+ if getSessionUser()
+ li
+ a(href="/project") #{translate('Projects')}
+ li.dropdown
+ a.dropdown-toggle(
+ href="#",
+ role="button",
+ aria-haspopup="true",
+ aria-expanded="false",
+ data-toggle="dropdown"
+ )
+ | #{translate('Account')}
+ span.caret
+ ul.dropdown-menu
li
- a(href="/user/subscription") #{translate('subscription')}
- li.divider.hidden-xs.hidden-sm
- li
- form(method="POST" action="/logout")
- input(name='_csrf', type='hidden', value=csrfToken)
- button.btn-link.text-left.dropdown-menu-button #{translate('log_out')}
+ div.subdued #{getSessionUser().email}
+ li.divider.hidden-xs.hidden-sm
+ li
+ a(href="/user/settings") #{translate('Account Settings')}
+ if nav.showSubscriptionLink
+ li
+ a(href="/user/subscription") #{translate('subscription')}
+ li.divider.hidden-xs.hidden-sm
+ li
+ form(method="POST" action="/logout")
+ input(name='_csrf', type='hidden', value=csrfToken)
+ button.btn-link.text-left.dropdown-menu-button #{translate('log_out')}
diff --git a/services/web/app/views/subscriptions/interstitial-payment.pug b/services/web/app/views/subscriptions/interstitial-payment.pug
index c9143b42f3..046c7c2856 100644
--- a/services/web/app/views/subscriptions/interstitial-payment.pug
+++ b/services/web/app/views/subscriptions/interstitial-payment.pug
@@ -41,5 +41,15 @@ block content
//- 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='{"paywall-type": "interstitial-page"}'
+ )
+ | #{translate("continue_with_free_plan")}
+
!= moduleIncludes("contactModalGeneral-marketing", locals)
diff --git a/services/web/app/views/subscriptions/successful_subscription.pug b/services/web/app/views/subscriptions/successful_subscription.pug
index d55cf2af86..5107d3851d 100644
--- a/services/web/app/views/subscriptions/successful_subscription.pug
+++ b/services/web/app/views/subscriptions/successful_subscription.pug
@@ -30,4 +30,7 @@ block content
br(ng-non-bindable)
| The #{settings.appName} Team
p
- a.btn.btn-primary(href="/project") < #{translate("back_to_your_projects")}
+ if (postCheckoutRedirect)
+ a.btn.btn-primary(href=postCheckoutRedirect) < #{translate("back_to_your_projects")}
+ else
+ a.btn.btn-primary(href="/project") < #{translate("back_to_your_projects")}
diff --git a/services/web/frontend/stylesheets/components/lists.less b/services/web/frontend/stylesheets/components/lists.less
index f7986b38db..b0e1978d22 100644
--- a/services/web/frontend/stylesheets/components/lists.less
+++ b/services/web/frontend/stylesheets/components/lists.less
@@ -21,3 +21,7 @@
}
}
}
+
+.list-style-check-green {
+ list-style-image: url('../../../public/img/fa-check-green.svg');
+}
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index 2342cc6720..6044994fef 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -667,6 +667,8 @@
"dropbox_sync_error": "Sorry, there was a problem checking our Dropbox service. Please try again in a few moments.",
"send": "Send",
"sending": "Sending",
+ "continue": "Continue",
+ "skip": "Skip",
"invalid_password": "Invalid Password",
"invalid_password_not_set": "Password is required",
"invalid_password_too_short": "Password too short, minimum __minLength__",
@@ -1836,6 +1838,17 @@
"server_pro_license_entitlement_line_1": "<0>__appName__0> Server Pro license",
"server_pro_license_entitlement_line_2": "You currently have <0>__count__ active users0>. If you need to increase your license entitlement, please <1>contact Overleaf1>.",
"server_pro_license_entitlement_line_3": "An active user is one who has opened a project in this Server Pro instance in the last 12 months.",
+ "get_the_most_out_headline": "Get the most out of __appName__ with features such as:",
+ "more_project_collaborators": "<0>More0> project <0>collaborators0>",
+ "advanced_reference_search": "Advanced <0>reference search0>",
+ "longer_compile_timeout": "Longer <0>compile timeout0>",
+ "symbol_palette_highlighted": "<0>Symbol0> palette",
+ "real_time_track_changes": "Real-time <0>track-changes0>",
+ "full_document_history": "Full document <0>history0>",
+ "github_git_and_dropbox_integrations": "<0>Github0>, <0>Git0> and <0>Dropbox0> integrations",
+ "zotero_and_mendeley_integrations": "<0>Zotero0> and <0>Mendeley0> integrations",
+ "skip": "Skip",
+ "continue_with_free_plan": "Continue with free plan",
"history_entry_origin_upload": "upload",
"history_entry_origin_git": "via Git",
"history_entry_origin_github": "via GitHub",
diff --git a/services/web/public/img/fa-check-green.svg b/services/web/public/img/fa-check-green.svg
new file mode 100644
index 0000000000..9c6efcca7e
--- /dev/null
+++ b/services/web/public/img/fa-check-green.svg
@@ -0,0 +1,3 @@
+
diff --git a/services/web/public/img/third-party-icons/dropbox.svg b/services/web/public/img/third-party-icons/dropbox.svg
new file mode 100644
index 0000000000..0dc2e21556
--- /dev/null
+++ b/services/web/public/img/third-party-icons/dropbox.svg
@@ -0,0 +1,15 @@
+
diff --git a/services/web/public/img/third-party-icons/git.svg b/services/web/public/img/third-party-icons/git.svg
new file mode 100644
index 0000000000..d0c64d71f5
--- /dev/null
+++ b/services/web/public/img/third-party-icons/git.svg
@@ -0,0 +1,3 @@
+
diff --git a/services/web/public/img/third-party-icons/github.svg b/services/web/public/img/third-party-icons/github.svg
new file mode 100644
index 0000000000..19191709cb
--- /dev/null
+++ b/services/web/public/img/third-party-icons/github.svg
@@ -0,0 +1,3 @@
+
diff --git a/services/web/public/img/third-party-icons/mendely.png b/services/web/public/img/third-party-icons/mendely.png
new file mode 100644
index 0000000000..5f98fa81b4
Binary files /dev/null and b/services/web/public/img/third-party-icons/mendely.png differ
diff --git a/services/web/public/img/third-party-icons/zotero.png b/services/web/public/img/third-party-icons/zotero.png
new file mode 100644
index 0000000000..c6c4221605
Binary files /dev/null and b/services/web/public/img/third-party-icons/zotero.png differ
diff --git a/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js b/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js
index ffc771ee5a..8d46b2335e 100644
--- a/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js
+++ b/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js
@@ -404,6 +404,7 @@ describe('SubscriptionController', function () {
title: 'thank_you',
personalSubscription: 'foo',
premiumFeaturesDiscoverability: false,
+ postCheckoutRedirect: undefined,
})
done()
}