From 48587a7a628ac1b3c05fe6d430164a7de9160eef Mon Sep 17 00:00:00 2001
From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com>
Date: Wed, 1 Mar 2023 11:32:55 +0200
Subject: [PATCH] Merge pull request #12007 from
overleaf/ii-react-subscription-dash-thank-you
[web] Successful subscription react migration
GitOrigin-RevId: 1d7d849415f4b7a7f60ddf8a4e18570ff5142196
---
.../app/src/infrastructure/ExpressLocals.js | 1 +
.../successful-subscription-react.pug | 4 +
.../web/frontend/extracted-translations.json | 6 +
.../successful-subscription/root.tsx | 8 +-
.../successful-subscription.tsx | 108 ++++++++++++++++++
.../web/frontend/stories/decorators/scope.tsx | 1 +
.../successful-subscription.test.tsx | 84 ++++++++++++++
services/web/types/exposed-settings.ts | 1 +
8 files changed, 212 insertions(+), 1 deletion(-)
create mode 100644 services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx
create mode 100644 services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx
diff --git a/services/web/app/src/infrastructure/ExpressLocals.js b/services/web/app/src/infrastructure/ExpressLocals.js
index f73ccd6f07..7d1ed633b6 100644
--- a/services/web/app/src/infrastructure/ExpressLocals.js
+++ b/services/web/app/src/infrastructure/ExpressLocals.js
@@ -367,6 +367,7 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
res.locals.ExposedSettings = {
isOverleaf: Settings.overleaf != null,
appName: Settings.appName,
+ adminEmail: Settings.adminEmail,
dropboxAppName:
Settings.apis.thirdPartyDataStore?.dropboxAppName || 'Overleaf',
hasSamlBeta: req.session.samlBeta,
diff --git a/services/web/app/views/subscriptions/successful-subscription-react.pug b/services/web/app/views/subscriptions/successful-subscription-react.pug
index 8403c167e9..fbe2767141 100644
--- a/services/web/app/views/subscriptions/successful-subscription-react.pug
+++ b/services/web/app/views/subscriptions/successful-subscription-react.pug
@@ -3,5 +3,9 @@ extends ../layout-marketing
block entrypointVar
- entrypoint = 'pages/user/subscription/successful-subscription'
+block append meta
+ meta(name="ol-subscription" data-type="json" content=personalSubscription)
+ meta(name="ol-postCheckoutRedirect" content=postCheckoutRedirect)
+
block content
main.content.content-alt#subscription-success-root
diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json
index 610c4d5c51..55fe1b2d47 100644
--- a/services/web/frontend/extracted-translations.json
+++ b/services/web/frontend/extracted-translations.json
@@ -28,6 +28,7 @@
"add_or_remove_project_from_tag": "",
"add_role_and_department": "",
"add_to_folder": "",
+ "add_your_first_group_member_now": "",
"adding": "",
"additional_licenses": "",
"address_line_1": "",
@@ -338,6 +339,7 @@
"have_more_days_to_try": "",
"headers": "",
"help": "",
+ "help_improve_overleaf_fill_out_this_survey": "",
"hide_document_preamble": "",
"hide_outline": "",
"history": "",
@@ -489,6 +491,7 @@
"name": "",
"navigate_log_source": "",
"navigation": "",
+ "need_anything_contact_us_at": "",
"need_more_than_x_licenses": "",
"need_to_add_new_primary_before_remove": "",
"need_to_leave": "",
@@ -648,6 +651,7 @@
"refresh_page_after_linking_dropbox": "",
"refresh_page_after_starting_free_trial": "",
"refreshing": "",
+ "regards": "",
"relink_your_account": "",
"remote_service_error": "",
"remove": "",
@@ -792,6 +796,8 @@
"terminated": "",
"tex_live_version": "",
"thank_you_exclamation": "",
+ "thanks_for_subscribing": "",
+ "thanks_for_subscribing_you_help_sl": "",
"thanks_settings_updated": "",
"the_following_files_already_exist_in_this_project": "",
"then_x_price_per_month": "",
diff --git a/services/web/frontend/js/features/subscription/components/successful-subscription/root.tsx b/services/web/frontend/js/features/subscription/components/successful-subscription/root.tsx
index d9f7c16d99..3fa8fbb0f3 100644
--- a/services/web/frontend/js/features/subscription/components/successful-subscription/root.tsx
+++ b/services/web/frontend/js/features/subscription/components/successful-subscription/root.tsx
@@ -1,4 +1,6 @@
import useWaitForI18n from '../../../../shared/hooks/use-wait-for-i18n'
+import { SubscriptionDashboardProvider } from '../../context/subscription-dashboard-context'
+import SuccessfulSubscription from './successful-subscription'
function Root() {
const { isReady } = useWaitForI18n()
@@ -7,7 +9,11 @@ function Root() {
return null
}
- return
React Subscription Success
+ return (
+
+
+
+ )
}
export default Root
diff --git a/services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx b/services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx
new file mode 100644
index 0000000000..5b4b07934b
--- /dev/null
+++ b/services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx
@@ -0,0 +1,108 @@
+import { useTranslation, Trans } from 'react-i18next'
+import { Col, Row } from 'react-bootstrap'
+import { PriceExceptions } from '../shared/price-exceptions'
+import PremiumFeaturesLink from '../dashboard/premium-features-link'
+import getMeta from '../../../../utils/meta'
+import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context'
+import { ExposedSettings } from '../../../../../../types/exposed-settings'
+
+function SuccessfulSubscription() {
+ const { t } = useTranslation()
+ const { personalSubscription: subscription } =
+ useSubscriptionDashboardContext()
+ const postCheckoutRedirect = getMeta('ol-postCheckoutRedirect') as
+ | string
+ | undefined
+ const { appName, adminEmail }: ExposedSettings = getMeta('ol-ExposedSettings')
+
+ if (!subscription || !('recurly' in subscription)) return null
+
+ return (
+
+ )
+}
+
+export default SuccessfulSubscription
diff --git a/services/web/frontend/stories/decorators/scope.tsx b/services/web/frontend/stories/decorators/scope.tsx
index e277a54f99..f4ae1dbc89 100644
--- a/services/web/frontend/stories/decorators/scope.tsx
+++ b/services/web/frontend/stories/decorators/scope.tsx
@@ -124,6 +124,7 @@ const initialize = () => {
window.user = user
window.ExposedSettings = {
+ adminEmail: 'placeholder@example.com',
appName: 'Overleaf',
cookieDomain: '.overleaf.stories',
dropboxAppName: 'Overleaf-Stories',
diff --git a/services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx b/services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx
new file mode 100644
index 0000000000..3cad154062
--- /dev/null
+++ b/services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx
@@ -0,0 +1,84 @@
+import { expect } from 'chai'
+import { screen, within } from '@testing-library/react'
+import SuccessfulSubscription from '../../../../../../frontend/js/features/subscription/components/successful-subscription/successful-subscription'
+import { renderWithSubscriptionDashContext } from '../../helpers/render-with-subscription-dash-context'
+import { annualActiveSubscription } from '../../fixtures/subscriptions'
+
+describe('successful subscription page', function () {
+ afterEach(function () {
+ window.metaAttributesCache = new Map()
+ })
+
+ it('renders the invoices link', function () {
+ const adminEmail = 'foo@example.com'
+ const options = {
+ metaTags: [
+ {
+ name: 'ol-ExposedSettings',
+ value: {
+ adminEmail,
+ },
+ },
+ { name: 'ol-subscription', value: annualActiveSubscription },
+ ],
+ }
+ renderWithSubscriptionDashContext(, options)
+
+ screen.getByRole('heading', { name: /thanks for subscribing/i })
+ const alert = screen.getByRole('alert')
+ within(alert).getByText(/to modify your subscription go to/i)
+ const manageSubscriptionLink = within(alert).getByRole('link', {
+ name: /manage subscription/i,
+ })
+ expect(manageSubscriptionLink.getAttribute('href')).to.equal(
+ '/user/subscription'
+ )
+ screen.getByText(
+ `Thank you for subscribing to the ${annualActiveSubscription.plan.name} plan.`,
+ { exact: false }
+ )
+ screen.getByText(
+ /it’s support from people like yourself that allows .* to continue to grow and improve/i
+ )
+ expect(screen.getByText(/get the most out of your/i).textContent).to.match(
+ /get the most out of your .* subscription by checking out the list of .*’s premium features/i
+ )
+ expect(
+ screen
+ .getByText(/if there is anything you ever/i)
+ .textContent?.replace(/\xA0/g, ' ')
+ ).to.equal(
+ `If there is anything you ever need please feel free to contact us directly at ${adminEmail}.`
+ )
+
+ const contactLink = screen.getByRole('link', {
+ name: adminEmail,
+ })
+ expect(contactLink.getAttribute('href')).to.equal(`mailto:${adminEmail}`)
+
+ expect(
+ screen.getByText(/if you would like to help us improve/i).textContent
+ ).to.match(
+ /if you would like to help us improve .*, please take a moment to fill out this survey/i
+ )
+
+ const surveyLink = screen.getByRole('link', {
+ name: /this survey/i,
+ })
+ expect(surveyLink.getAttribute('href')).to.equal(
+ 'https://forms.gle/CdLNX9m6NLxkv1yr5'
+ )
+
+ const helpLink = screen.getByRole('link', {
+ name: /.*’s premium features/i,
+ })
+ expect(helpLink.getAttribute('href')).to.equal(
+ '/learn/how-to/Overleaf_premium_features'
+ )
+
+ const backToYourProjectsLink = screen.getByRole('link', {
+ name: /back to your projects/i,
+ })
+ expect(backToYourProjectsLink.getAttribute('href')).to.equal('/project')
+ })
+})
diff --git a/services/web/types/exposed-settings.ts b/services/web/types/exposed-settings.ts
index 7cf39cffcf..5c75a9ca63 100644
--- a/services/web/types/exposed-settings.ts
+++ b/services/web/types/exposed-settings.ts
@@ -5,6 +5,7 @@ type TemplateLink = {
}
export type ExposedSettings = {
+ adminEmail: string
appName: string
cookieDomain: string
dropboxAppName: string