mirror of
https://github.com/overleaf/overleaf.git
synced 2024-09-16 02:52:31 -04:00
Merge pull request #2015 from overleaf/ta-recurly-upgrade
Upgrade Recurly GitOrigin-RevId: 9a7c4804d2fafa31ea634498359dbfd95416b2ae
This commit is contained in:
parent
018b2cc474
commit
b9ab0edf69
12 changed files with 102 additions and 70 deletions
|
@ -415,7 +415,8 @@ module.exports = RecurlyWrapper = {
|
|||
'base64'
|
||||
)}`,
|
||||
Accept: 'application/xml',
|
||||
'Content-Type': 'application/xml; charset=utf-8'
|
||||
'Content-Type': 'application/xml; charset=utf-8',
|
||||
'X-Api-Version': Settings.apis.recurly.apiVersion
|
||||
}
|
||||
const { expect404 } = options
|
||||
delete options.expect404
|
||||
|
|
|
@ -117,29 +117,33 @@ html(
|
|||
include scribtex-modal
|
||||
|
||||
block requirejs
|
||||
script(type='text/javascript').
|
||||
// minimal requirejs configuration (can be extended/overridden)
|
||||
window.requirejs = {
|
||||
"paths" : {
|
||||
"moment": "libs/#{lib('moment')}",
|
||||
"fineuploader": "libs/#{lib('fineuploader')}",
|
||||
"main": "#{buildJsPath('main.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
|
||||
"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
|
||||
},
|
||||
"config":{
|
||||
"moment":{
|
||||
"noGlobal": true
|
||||
block requirejs-config
|
||||
script(type='text/javascript').
|
||||
// minimal requirejs configuration (can be extended/overridden)
|
||||
window.requirejs = {
|
||||
"paths" : {
|
||||
"moment": "libs/#{lib('moment')}",
|
||||
"fineuploader": "libs/#{lib('fineuploader')}",
|
||||
"main": "#{buildJsPath('main.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
|
||||
"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
|
||||
"recurly": "https://js.recurly.com/v4/recurly.js"
|
||||
},
|
||||
"config":{
|
||||
"moment":{
|
||||
"noGlobal": true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
script(
|
||||
data-main=buildJsPath('main.js', {hashedPath:false}),
|
||||
baseurl=fullJsPath,
|
||||
src=buildJsPath('libs/require.js', {hashedPath:true})
|
||||
)
|
||||
};
|
||||
|
||||
block requirejs-init
|
||||
script(
|
||||
data-main=buildJsPath('main.js', {hashedPath:false}),
|
||||
baseurl=fullJsPath,
|
||||
src=buildJsPath('libs/require.js', {hashedPath:true})
|
||||
)
|
||||
|
||||
!= moduleIncludes("contactModal", locals)
|
||||
include v1-tooltip
|
||||
include sentry
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,13 @@ extends ../layout
|
|||
|
||||
include ./dashboard/_team_name_mixin
|
||||
|
||||
block requirejs-init
|
||||
script(
|
||||
data-main=buildJsPath("main-recurly.js", {hashedPath:false}),
|
||||
baseurl=fullJsPath,
|
||||
src=buildJsPath('libs/require.js', {hashedPath:true})
|
||||
)
|
||||
|
||||
block content
|
||||
.content.content-alt(ng-cloak)
|
||||
.container
|
||||
|
@ -12,7 +19,7 @@ block content
|
|||
p You already have a subscription
|
||||
.card
|
||||
.page-header
|
||||
h1 #{translate("your_subscription")}
|
||||
h1 #{translate("your_subscription")}
|
||||
|
||||
-var hasDisplayedSubscription = false
|
||||
-if (personalSubscription)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
script(src="https://js.recurly.com/v3/recurly.js")
|
||||
script(type='text/javascript').
|
||||
window.recurlyApiKey = "!{settings.apis.recurly.publicKey}"
|
||||
window.subscription = !{StringHelper.stringifyJsonForScript(personalSubscription)}
|
||||
|
@ -8,7 +7,7 @@ div(ng-controller="RecurlySubscriptionController")
|
|||
div(ng-show="!showCancellation")
|
||||
case personalSubscription.recurly.state
|
||||
when "active"
|
||||
p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})}
|
||||
p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})}
|
||||
a(href, ng-click="switchToChangePlanView()", ng-if="showChangePlanButton") !{translate("change_plan")}.
|
||||
-if (personalSubscription.recurly.trialEndsAtFormatted && personalSubscription.recurly.trial_ends_at > Date.now())
|
||||
p You're on a free trial which ends on <strong ng-non-bindable>#{personalSubscription.recurly.trialEndsAtFormatted}</strong>
|
||||
|
@ -18,7 +17,7 @@ div(ng-controller="RecurlySubscriptionController")
|
|||
p
|
||||
a(href=personalSubscription.recurly.billingDetailsLink, target="_blank").btn.btn-info #{translate("update_your_billing_details")}
|
||||
|
|
||||
a(href, ng-click="switchToCancellationView()").btn.btn-primary !{translate("cancel_your_subscription")}
|
||||
a(href, ng-click="switchToCancellationView()", ng-hide="recurlyLoadError").btn.btn-primary !{translate("cancel_your_subscription")}
|
||||
when "canceled"
|
||||
p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})}
|
||||
p !{translate("subscription_canceled_and_terminate_on_x", {terminateDate:"<strong>" + personalSubscription.recurly.nextPaymentDueAt + "</strong>"})}
|
||||
|
@ -26,11 +25,14 @@ div(ng-controller="RecurlySubscriptionController")
|
|||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
input(type="submit",value="Reactivate your subscription").btn.btn-success
|
||||
when "expired"
|
||||
p !{translate("your_subscription_has_expired")}
|
||||
p !{translate("your_subscription_has_expired")}
|
||||
a(href="/user/subscription/plans") !{translate("create_new_subscription")}
|
||||
default
|
||||
p !{translate("problem_with_subscription_contact_us")}
|
||||
|
||||
.alert.alert-warning(ng-show="recurlyLoadError")
|
||||
strong #{translate('payment_provider_unreachable_error')}
|
||||
|
||||
include ./_change_plans_mixins
|
||||
div(ng-show="showChangePlan", ng-cloak)
|
||||
h2 !{translate("change_plan")}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
extends ../layout
|
||||
|
||||
block requirejs-init
|
||||
script(
|
||||
data-main=buildJsPath("main-recurly.js", {hashedPath:false}),
|
||||
baseurl=fullJsPath,
|
||||
src=buildJsPath('libs/require.js', {hashedPath:true})
|
||||
)
|
||||
|
||||
block scripts
|
||||
script(type='text/javascript').
|
||||
window.countryCode = '#{countryCode}'
|
||||
|
@ -15,7 +22,9 @@ block content
|
|||
.row.card-group
|
||||
.col-md-5.col-md-push-4
|
||||
.card.card-highlighted.card-border
|
||||
.page-header
|
||||
.alert.alert-danger(ng-show="recurlyLoadError")
|
||||
strong #{translate('payment_provider_unreachable_error')}
|
||||
.page-header(ng-hide="recurlyLoadError")
|
||||
.row
|
||||
.col-xs-9
|
||||
h2 {{planName}}
|
||||
|
@ -26,13 +35,13 @@ block content
|
|||
data-toggle="dropdown",
|
||||
dropdown-toggle
|
||||
)
|
||||
| {{currencyCode}} ({{allCurrencies[currencyCode]['symbol']}})
|
||||
| {{currencyCode}} ({{allCurrencies[currencyCode]['symbol']}})
|
||||
span.caret
|
||||
ul.dropdown-menu(role="menu")
|
||||
li(ng-repeat="(currency, value) in availableCurrencies")
|
||||
a(
|
||||
ng-click="changeCurrency(currency)",
|
||||
) {{currency}} ({{value['symbol']}})
|
||||
) {{currency}} ({{value['symbol']}})
|
||||
.row(ng-if="planCode == 'student-annual' || planCode == 'student-monthly' || planCode == 'student_free_trial_7_days'")
|
||||
.col-xs-12
|
||||
p.student-disclaimer #{translate('student_disclaimer')}
|
||||
|
@ -40,16 +49,16 @@ block content
|
|||
hr.thin
|
||||
.row
|
||||
.col-md-12.text-center
|
||||
div(ng-if="trialLength")
|
||||
div(ng-if="trialLength")
|
||||
span !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})}
|
||||
span(ng-if="discountMonths && discountRate") - {{discountMonths}} #{translate("month")}s {{discountRate}}% Off
|
||||
div(ng-if="price")
|
||||
strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
|
||||
strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
|
||||
span(ng-if="monthlyBilling") #{translate("every")} #{translate("month")}
|
||||
span(ng-if="!monthlyBilling") #{translate("every")} #{translate("year")}
|
||||
div(ng-if="normalPrice")
|
||||
span.small Normally {{availableCurrencies[currencyCode]['symbol']}}{{normalPrice}}
|
||||
.row
|
||||
.row(ng-hide="recurlyLoadError")
|
||||
div()
|
||||
.col-md-12()
|
||||
form(
|
||||
|
@ -57,7 +66,7 @@ block content
|
|||
novalidate
|
||||
)
|
||||
|
||||
|
||||
|
||||
div.payment-method-toggle
|
||||
a.payment-method-toggle-switch(
|
||||
href
|
||||
|
@ -77,7 +86,7 @@ block content
|
|||
)
|
||||
i.fa.fa-cc-paypal.fa-2x(aria-hidden="true")
|
||||
span.sr-only Pay with PayPal
|
||||
|
||||
|
||||
.alert.alert-warning.small(ng-show="genericError")
|
||||
strong {{genericError}}
|
||||
|
||||
|
@ -132,7 +141,7 @@ block content
|
|||
name="year"
|
||||
data-recurly="year"
|
||||
)
|
||||
|
||||
|
||||
.col-xs-6
|
||||
.form-group.has-feedback(ng-class="validation.errorFields.cvv ? 'has-external-error' : ''")
|
||||
label #{translate("security_code")}
|
||||
|
@ -184,14 +193,14 @@ block content
|
|||
ng-blur="applyCoupon()"
|
||||
ng-model="data.coupon"
|
||||
)
|
||||
|
||||
|
||||
p(ng-if="paymentMethod.value === 'paypal'") #{translate("paypal_upgrade")}
|
||||
|
||||
|
||||
div.price-breakdown(ng-if="price.next.tax !== '0.00'")
|
||||
hr.thin
|
||||
span Total:
|
||||
strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
|
||||
span ({{availableCurrencies[currencyCode]['symbol']}}{{price.next.subtotal}} + {{availableCurrencies[currencyCode]['symbol']}}{{price.next.tax}} tax)
|
||||
span Total:
|
||||
strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
|
||||
span ({{availableCurrencies[currencyCode]['symbol']}}{{price.next.subtotal}} + {{availableCurrencies[currencyCode]['symbol']}}{{price.next.tax}} tax)
|
||||
span(ng-if="monthlyBilling") #{translate("every")} #{translate("month")}
|
||||
span(ng-if="!monthlyBilling") #{translate("every")} #{translate("year")}
|
||||
hr.thin
|
||||
|
@ -199,9 +208,9 @@ block content
|
|||
div.payment-submit
|
||||
button.btn.btn-success.btn-block(
|
||||
ng-click="submit()"
|
||||
ng-disabled="processing || !isFormValid(simpleCCForm);"
|
||||
)
|
||||
span(ng-show="processing")
|
||||
ng-disabled="processing || !isFormValid(simpleCCForm);"
|
||||
)
|
||||
span(ng-show="processing")
|
||||
i.fa.fa-spinner.fa-spin(aria-hidden="true")
|
||||
span.sr-only #{translate('processing')}
|
||||
|
|
||||
|
@ -215,13 +224,13 @@ block content
|
|||
a.btn-primary.btn.plansPageStudentLink(
|
||||
href,
|
||||
ng-click="switchToStudent()"
|
||||
) #{translate("half_price_student")}
|
||||
) #{translate("half_price_student")}
|
||||
|
||||
.card.card-first
|
||||
.paymentPageFeatures
|
||||
h3 #{translate("unlimited_projects")}
|
||||
p #{translate("create_unlimited_projects")}
|
||||
|
||||
|
||||
h3
|
||||
if plan.features.collaborators == -1
|
||||
- var collaboratorCount = 'Unlimited'
|
||||
|
@ -229,21 +238,21 @@ block content
|
|||
- var collaboratorCount = plan.features.collaborators
|
||||
| #{translate("collabs_per_proj", {collabcount:collaboratorCount})}
|
||||
p #{translate("work_on_single_version")}. #{translate("view_collab_edits")} in real time.
|
||||
|
||||
|
||||
h3 #{translate("full_doc_history")}
|
||||
p #{translate("see_what_has_been")}
|
||||
span.added #{translate("added")}
|
||||
| #{translate("and")}
|
||||
span.removed #{translate("removed")}.
|
||||
p #{translate("see_what_has_been")}
|
||||
span.added #{translate("added")}
|
||||
| #{translate("and")}
|
||||
span.removed #{translate("removed")}.
|
||||
| #{translate("restore_to_any_older_version")}.
|
||||
|
||||
|
||||
h3 #{translate("sync_to_dropbox")}
|
||||
p
|
||||
| #{translate("acces_work_from_anywhere")}.
|
||||
| #{translate("acces_work_from_anywhere")}.
|
||||
| #{translate("work_offline_and_sync_with_dropbox")}.
|
||||
|
||||
|
||||
hr
|
||||
|
||||
|
||||
p.small.text-center(ng-non-bindable) We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
|
||||
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ module.exports = settings =
|
|||
url: "http://#{process.env['GITHUB_SYNC_HOST'] or 'localhost'}:3022"
|
||||
recurly:
|
||||
apiKey: process.env['RECURLY_API_KEY'] or ''
|
||||
apiVersion: process.env['RECURLY_API_VERSION']
|
||||
subdomain: process.env['RECURLY_SUBDOMAIN'] or ''
|
||||
publicKey: process.env['RECURLY_PUBLIC_KEY'] or ''
|
||||
geoIpLookup:
|
||||
|
|
File diff suppressed because one or more lines are too long
8
services/web/public/src/main-recurly.js
Normal file
8
services/web/public/src/main-recurly.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
// main bundle plus recurly (loaded externaly from CDN) and all files requiring
|
||||
// Recurly JS
|
||||
define([
|
||||
'main',
|
||||
'recurly',
|
||||
'main/subscription-dashboard',
|
||||
'main/new-subscription'
|
||||
], function() {})
|
|
@ -22,8 +22,6 @@ define([
|
|||
'main/bonus',
|
||||
'main/system-messages',
|
||||
'main/translations',
|
||||
'main/subscription-dashboard',
|
||||
'main/new-subscription',
|
||||
'main/annual-upgrade',
|
||||
'main/announcements',
|
||||
'main/register-users',
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
no-return-assign
|
||||
*/
|
||||
/* global recurly,_,define */
|
||||
define(['base', 'directives/creditCards', 'libs/recurly-4.8.5'], App =>
|
||||
define(['base', 'directives/creditCards'], App =>
|
||||
App.controller('NewSubscriptionController', function(
|
||||
$scope,
|
||||
MultiCurrencyPricing,
|
||||
|
@ -12,10 +12,12 @@ define(['base', 'directives/creditCards', 'libs/recurly-4.8.5'], App =>
|
|||
event_tracking,
|
||||
ccUtils
|
||||
) {
|
||||
if (typeof recurly === 'undefined') {
|
||||
throw new Error('Recurly API Library Missing.')
|
||||
if (typeof recurly === 'undefined' || !recurly) {
|
||||
$scope.recurlyLoadError = true
|
||||
return
|
||||
}
|
||||
|
||||
$scope.recurlyLoadError = false
|
||||
$scope.currencyCode = MultiCurrencyPricing.currencyCode
|
||||
$scope.allCurrencies = MultiCurrencyPricing.plans
|
||||
$scope.availableCurrencies = {}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
max-len
|
||||
*/
|
||||
/* global define,history */
|
||||
define(['base', 'libs/recurly-4.8.5'], function(App, recurly) {
|
||||
define(['base'], function(App) {
|
||||
App.factory('MultiCurrencyPricing', function() {
|
||||
const currencyCode = window.recomendedCurrency
|
||||
|
||||
|
|
|
@ -19,8 +19,11 @@ define(['base'], function(App) {
|
|||
const SUBSCRIPTION_URL = '/user/subscription/update'
|
||||
|
||||
const ensureRecurlyIsSetup = _.once(() => {
|
||||
if (!recurly) return
|
||||
if (typeof recurly === 'undefined' || !recurly) {
|
||||
return false
|
||||
}
|
||||
recurly.configure(window.recurlyApiKey)
|
||||
return true
|
||||
})
|
||||
|
||||
App.controller('MetricsEmailController', function($scope, $http) {
|
||||
|
@ -60,7 +63,7 @@ define(['base'], function(App) {
|
|||
App.factory('RecurlyPricing', function($q, MultiCurrencyPricing) {
|
||||
return {
|
||||
loadDisplayPriceWithTax: function(planCode, currency, taxRate) {
|
||||
ensureRecurlyIsSetup()
|
||||
if (!ensureRecurlyIsSetup()) return
|
||||
const currencySymbol = MultiCurrencyPricing.plans[currency].symbol
|
||||
const pricing = recurly.Pricing()
|
||||
return $q(function(resolve, reject) {
|
||||
|
@ -89,7 +92,7 @@ define(['base'], function(App) {
|
|||
$modal,
|
||||
RecurlyPricing
|
||||
) {
|
||||
ensureRecurlyIsSetup()
|
||||
if (!ensureRecurlyIsSetup()) return
|
||||
|
||||
$scope.changePlan = () =>
|
||||
$modal.open({
|
||||
|
@ -164,7 +167,9 @@ define(['base'], function(App) {
|
|||
})
|
||||
|
||||
App.controller('RecurlySubscriptionController', function($scope) {
|
||||
$scope.showChangePlanButton = !subscription.groupPlan
|
||||
const recurlyIsSetup = ensureRecurlyIsSetup()
|
||||
$scope.showChangePlanButton = recurlyIsSetup && !subscription.groupPlan
|
||||
$scope.recurlyLoadError = !recurlyIsSetup
|
||||
|
||||
$scope.switchToDefaultView = () => {
|
||||
$scope.showCancellation = false
|
||||
|
@ -188,6 +193,7 @@ define(['base'], function(App) {
|
|||
RecurlyPricing,
|
||||
$http
|
||||
) {
|
||||
if (!ensureRecurlyIsSetup()) return
|
||||
const subscription = window.subscription
|
||||
const sevenDaysTime = new Date()
|
||||
sevenDaysTime.setDate(sevenDaysTime.getDate() + 7)
|
||||
|
|
Loading…
Reference in a new issue