From 47fb2a0878348fedc8c636207cf55467f31d1b0f Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 18 Dec 2014 17:48:23 +0000 Subject: [PATCH 01/34] basic angular form which has data bound to it --- services/web/app/views/subscriptions/new.jade | 50 ++++++++++++++----- .../coffee/main/new-subscription.coffee | 34 ++++++++++++- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 78ad380d59..cf08f9a4ce 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -1,14 +1,19 @@ extends ../layout block scripts + + script(type='text/javascript'). window.recomendedCurrency = '#{currency}' window.plan_code = '#{plan_code}' + window.recurlyCreds = { apiKey : "", apiUrl:""} + block content - locals.supressDefaultJs = true script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js', baseurl=jsPath) - script(src=jsPath+'libs/recurly.min.js') + script(src="https://js.recurly.com/v3/recurly.js") + .content.content-alt .container(ng-controller="NewSubscriptionController" ng-cloak) @@ -29,9 +34,38 @@ block content ng-click="changeCurrency(currency)", ) {{currency}} ({{value['symbol']}}) h1 #{translate("new_subscription")} - - #subscribeForm(style="min-height: 700px;") #{translate("loading_billing_form")}... - + span {{ error }} + form + .form-group + label #{translate("credit_card_number")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='number', ng-model='data.number') + .form-group + label #{translate("month")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='month', ng-model='data.month') + .form-group + label #{translate("year")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='year', ng-model='data.year') + .form-group + label #{translate("cvv")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='cvv', ng-model='data.cvv') + .form-group + label #{translate("first_name")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name") + .form-group + label #{translate("last_name")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") + + .form-group + button.btn.btn-success(ng-click="submit()") #{translate("submit")} + + + + + + + + + .col-md-3.col-md-pull-6 if showStudentPlan == 'true' @@ -77,14 +111,6 @@ block content script(type="text/javascript"). - Recurly.config(!{recurlyConfig}) - var recurlySubscriptionFormConfig = !{subscriptionFormOptions} - recurlySubscriptionFormConfig.successHandler = function(){ - ga('send', 'event', 'subscription-funnel', 'subscribed') - } - - Recurly.buildSubscriptionForm(recurlySubscriptionFormConfig); - window.ab = [ {step:1, bucket:"red", testName:"button_color"}, {step:1, bucket:"blue", testName:"button_color"} diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index f607cd3435..b383de1e00 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -11,4 +11,36 @@ define [ window.location = "/user/subscription/new?planCode=#{window.plan_code}¤cy=#{newCurrency}" $scope.switchToStudent = ()-> - window.location = "/user/subscription/new?planCode=student¤cy=#{$scope.currencyCode}" \ No newline at end of file + window.location = "/user/subscription/new?planCode=student¤cy=#{$scope.currencyCode}" + + + + + + __api_key = recurlyCreds.apiKey + __api_url = recurlyCreds.apiUrl + configured = false + $scope.error = false + $scope.token = false + $scope.data = + number: "" + month: "" + year: "" + cvv: "" + first_name: "" + last_last: "" + postal_code: "" + + $scope.submit = -> + throw new Error("Recurly API Library Missing.") if typeof recurly is "undefined" + console.log $scope.data + $scope.error = "" + if !configured + recurly.configure __api_key + configured = true + recurly.token $scope.data, (err, token) -> + if err + $scope.error = err.message + else + $scope.token = token + From cc545db17bf8ca83ef389789f3270ff3b853cab7 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 18 Dec 2014 18:59:29 +0000 Subject: [PATCH 02/34] can add account just about into recurly --- .../Subscription/RecurlyWrapper.coffee | 24 +++++++++++++- .../SubscriptionController.coffee | 6 ++-- .../Subscription/SubscriptionHandler.coffee | 5 +-- services/web/app/views/subscriptions/new.jade | 18 ++++++++-- .../coffee/main/new-subscription.coffee | 33 ++++++++++--------- 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index d6c7fe272d..b2b0955bbe 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -8,6 +8,28 @@ logger = require("logger-sharelatex") module.exports = RecurlyWrapper = apiUrl : "https://api.recurly.com/v2" + createSubscription: (subscription, recurly_token_id, callback)-> + requestBody = """ + + student + USD + + TEST_SUBSCRIPTION + + #{recurly_token_id} + + + + """ + @apiRequest({ + url : "subscriptions" + method : "POST" + body : requestBody + }, (error, response, responseBody) => + return callback(error) if error? + @_parseSubscriptionXml responseBody, callback + ) + apiRequest : (options, callback) -> options.url = @apiUrl + "/" + options.url options.headers = @@ -16,7 +38,7 @@ module.exports = RecurlyWrapper = "Content-Type" : "application/xml; charset=utf-8" request options, (error, response, body) -> unless error? or response.statusCode == 200 or response.statusCode == 201 or response.statusCode == 204 - logger.err err:error, options:options, "error returned from recurly" + logger.err err:error, body:body, options:options, statusCode:response?.statusCode, "error returned from recurly" error = "Recurly API returned with status code: #{response.statusCode}" callback(error, response, body) diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee index 7cebfdf535..c36374eaa0 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee @@ -132,9 +132,9 @@ module.exports = SubscriptionController = createSubscription: (req, res, next)-> SecurityManager.getCurrentUser req, (error, user) -> return callback(error) if error? - subscriptionId = req.body.recurly_token - logger.log subscription_id: subscriptionId, user_id:user._id, "creating subscription" - SubscriptionHandler.createSubscription user, subscriptionId, (err)-> + recurly_token_id = req.body.recurly_token_id + logger.log recurly_token_id: recurly_token_id, user_id:user._id, "creating subscription" + SubscriptionHandler.createSubscription user, recurly_token_id, (err)-> if err? logger.err err:err, user_id:user._id, "something went wrong creating subscription" res.redirect "/user/subscription/thank-you" diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee index c3423482ae..4acfc23b27 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee @@ -10,9 +10,10 @@ DropboxHandler = require("../Dropbox/DropboxHandler") module.exports = - createSubscription: (user, recurlySubscriptionId, callback)-> + createSubscription: (user, recurly_token_id, callback)-> self = @ - RecurlyWrapper.getSubscription recurlySubscriptionId, {recurlyJsResult: true}, (error, recurlySubscription) -> + clientTokenId = "" + RecurlyWrapper.createSubscription user, recurly_token_id, (error, recurlySubscription)-> return callback(error) if error? SubscriptionUpdater.syncSubscription recurlySubscription, user._id, (error) -> return callback(error) if error? diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index cf08f9a4ce..7da03faaa5 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -6,7 +6,7 @@ block scripts window.recomendedCurrency = '#{currency}' window.plan_code = '#{plan_code}' - window.recurlyCreds = { apiKey : "", apiUrl:""} + window.recurlyCreds = { apiKey : "sc-GVdZOe7akgWbZRIFPllOx9", apiUrl:""} block content @@ -34,7 +34,7 @@ block content ng-click="changeCurrency(currency)", ) {{currency}} ({{value['symbol']}}) h1 #{translate("new_subscription")} - span {{ error }} + form .form-group label #{translate("credit_card_number")} @@ -54,7 +54,19 @@ block content .form-group label #{translate("last_name")} input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") - + .form-group + label #{translate("address")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="address1", ng-model="data.address1") + .form-group + label #{translate("city")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city") + .form-group + label #{translate("country")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="country", ng-model="data.country") + .form-group + label #{translate("country")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code") + .form-group button.btn.btn-success(ng-click="submit()") #{translate("submit")} diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index b383de1e00..82fe9d6211 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -2,7 +2,7 @@ define [ "base" ], (App)-> - App.controller "NewSubscriptionController", ($scope, MultiCurrencyPricing, abTestManager)-> + App.controller "NewSubscriptionController", ($scope, MultiCurrencyPricing, abTestManager, $http)-> $scope.currencyCode = MultiCurrencyPricing.currencyCode $scope.plans = MultiCurrencyPricing.plans @@ -13,23 +13,23 @@ define [ $scope.switchToStudent = ()-> window.location = "/user/subscription/new?planCode=student¤cy=#{$scope.currencyCode}" - - - - __api_key = recurlyCreds.apiKey - __api_url = recurlyCreds.apiUrl configured = false $scope.error = false $scope.token = false $scope.data = - number: "" - month: "" - year: "" - cvv: "" - first_name: "" - last_last: "" - postal_code: "" + number: "4111111111111111" + month: "02" + year: "2015" + cvv: "111" + first_name: "h" + last_name: "o" + postal_code: "se153tt" + address1 : "7 somewhere" + city:"london" + country:"uk" + + $scope.submit = -> throw new Error("Recurly API Library Missing.") if typeof recurly is "undefined" @@ -38,9 +38,12 @@ define [ if !configured recurly.configure __api_key configured = true - recurly.token $scope.data, (err, token) -> + recurly.token $scope.data, (err, recurly_token_id) -> if err $scope.error = err.message else - $scope.token = token + $http.post("/user/subscription/create", {_csrf: window.csrfToken, recurly_token_id:recurly_token_id.id}) + .success -> + console.log "success" + From 5305cbfd3efb419b0e709d0bc9ebb88358de6213 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Fri, 19 Dec 2014 11:17:35 +0000 Subject: [PATCH 03/34] got more correct details making it to recurly and improved form. --- .../Subscription/RecurlyWrapper.coffee | 11 +- .../SubscriptionController.coffee | 5 +- .../Subscription/SubscriptionHandler.coffee | 4 +- services/web/app/views/subscriptions/new.jade | 295 +++++++++++++++++- .../coffee/main/new-subscription.coffee | 10 +- 5 files changed, 306 insertions(+), 19 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index b2b0955bbe..176f66dcf5 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -8,13 +8,16 @@ logger = require("logger-sharelatex") module.exports = RecurlyWrapper = apiUrl : "https://api.recurly.com/v2" - createSubscription: (subscription, recurly_token_id, callback)-> + createSubscription: (user, subscriptionDetails, recurly_token_id, callback)-> requestBody = """ - student - USD + #{subscriptionDetails.plan_code} + #{subscriptionDetails.currencyCode} - TEST_SUBSCRIPTION + #{user._id} + #{user.email} + #{user.first_name} + #{user.last_name} #{recurly_token_id} diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee index c36374eaa0..238db41d2e 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee @@ -133,8 +133,9 @@ module.exports = SubscriptionController = SecurityManager.getCurrentUser req, (error, user) -> return callback(error) if error? recurly_token_id = req.body.recurly_token_id - logger.log recurly_token_id: recurly_token_id, user_id:user._id, "creating subscription" - SubscriptionHandler.createSubscription user, recurly_token_id, (err)-> + subscriptionDetails = req.body.subscriptionDetails + logger.log recurly_token_id: recurly_token_id, user_id:user._id, subscriptionDetails:subscriptionDetails, "creating subscription" + SubscriptionHandler.createSubscription user, subscriptionDetails, recurly_token_id, (err)-> if err? logger.err err:err, user_id:user._id, "something went wrong creating subscription" res.redirect "/user/subscription/thank-you" diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee index 4acfc23b27..7a210b2ead 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee @@ -10,10 +10,10 @@ DropboxHandler = require("../Dropbox/DropboxHandler") module.exports = - createSubscription: (user, recurly_token_id, callback)-> + createSubscription: (user, subscriptionDetails, recurly_token_id, callback)-> self = @ clientTokenId = "" - RecurlyWrapper.createSubscription user, recurly_token_id, (error, recurlySubscription)-> + RecurlyWrapper.createSubscription user, subscriptionDetails, recurly_token_id, (error, recurlySubscription)-> return callback(error) if error? SubscriptionUpdater.syncSubscription recurlySubscription, user._id, (error) -> return callback(error) if error? diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 7da03faaa5..878d802984 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -34,20 +34,41 @@ block content ng-click="changeCurrency(currency)", ) {{currency}} ({{value['symbol']}}) h1 #{translate("new_subscription")} - + hr form .form-group - label #{translate("credit_card_number")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='number', ng-model='data.number') + input.form-control.input-lg-1(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='number', ng-model='data.number', placeholder='Credit Card Number') + input.form-control.input-lg-1(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='cvv', ng-model='data.cvv') .form-group label #{translate("month")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='month', ng-model='data.month') + select.form-control(data-recurly='month', ng-model='data.month') + option(value="01") 01 January + option(value="02") 02 February + option(value="03") 03 March + option(value="04") 04 April + option(value="05") 05 May + option(value="06") 06 June + option(value="07") 07 July + option(value="08") 08 August + option(value="09") 09 September + option(value="10") 10 October + option(value="11") 11 November + option(value="12") 12 December .form-group label #{translate("year")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='year', ng-model='data.year') - .form-group - label #{translate("cvv")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='cvv', ng-model='data.cvv') + select.form-control(data-recurly='year', ng-model='data.year') + option(value="2015") 2015 + option(value="2016") 2016 + option(value="2017") 2017 + option(value="2018") 2018 + option(value="2019") 2019 + option(value="2020") 2020 + option(value="2021") 2021 + option(value="2022") 2022 + option(value="2023") 2023 + option(value="2024") 2024 + option(value="2025") 2025 + option(value="2026") 2026 .form-group label #{translate("first_name")} input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name") @@ -62,7 +83,8 @@ block content input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city") .form-group label #{translate("country")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="country", ng-model="data.country") + select.form-control(data-recurly="country", ng-model="data.country") + mixin countries_options() .form-group label #{translate("country")} input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code") @@ -128,3 +150,258 @@ block content {step:1, bucket:"blue", testName:"button_color"} ] + +mixin countries_options() + option(value='-') Select Country + option(value='-') -------------- + option(value='AF') Afghanistan + option(value='AL') Albania + option(value='DZ') Algeria + option(value='AS') American Samoa + option(value='AD') Andorra + option(value='AO') Angola + option(value='AI') Anguilla + option(value='AQ') Antarctica + option(value='AG') Antigua and Barbuda + option(value='AR') Argentina + option(value='AM') Armenia + option(value='AW') Aruba + option(value='AC') Ascension Island + option(value='AU') Australia + option(value='AT') Austria + option(value='AZ') Azerbaijan + option(value='BS') Bahamas + option(value='BH') Bahrain + option(value='BD') Bangladesh + option(value='BB') Barbados + option(value='BE') Belgium + option(value='BZ') Belize + option(value='BJ') Benin + option(value='BM') Bermuda + option(value='BT') Bhutan + option(value='BO') Bolivia + option(value='BA') Bosnia and Herzegovina + option(value='BW') Botswana + option(value='BV') Bouvet Island + option(value='BR') Brazil + option(value='BQ') British Antarctic Territory + option(value='IO') British Indian Ocean Territory + option(value='VG') British Virgin Islands + option(value='BN') Brunei + option(value='BG') Bulgaria + option(value='BF') Burkina Faso + option(value='BI') Burundi + option(value='KH') Cambodia + option(value='CM') Cameroon + option(value='CA') Canada + option(value='IC') Canary Islands + option(value='CT') Canton and Enderbury Islands + option(value='CV') Cape Verde + option(value='KY') Cayman Islands + option(value='CF') Central African Republic + option(value='EA') Ceuta and Melilla + option(value='TD') Chad + option(value='CL') Chile + option(value='CN') China + option(value='CX') Christmas Island + option(value='CP') Clipperton Island + option(value='CC') Cocos [Keeling] Islands + option(value='CO') Colombia + option(value='KM') Comoros + option(value='CD') Congo [DRC] + option(value='CK') Cook Islands + option(value='CR') Costa Rica + option(value='HR') Croatia + option(value='CU') Cuba + option(value='CY') Cyprus + option(value='CZ') Czech Republic + option(value='DK') Denmark + option(value='DG') Diego Garcia + option(value='DJ') Djibouti + option(value='DM') Dominica + option(value='DO') Dominican Republic + option(value='NQ') Dronning Maud Land + option(value='TL') East Timor + option(value='EC') Ecuador + option(value='EG') Egypt + option(value='SV') El Salvador + option(value='EE') Estonia + option(value='ET') Ethiopia + option(value='FK') Falkland Islands [Islas Malvinas] + option(value='FO') Faroe Islands + option(value='FJ') Fiji + option(value='FI') Finland + option(value='FR') France + option(value='GF') French Guiana + option(value='PF') French Polynesia + option(value='TF') French Southern Territories + option(value='FQ') French Southern and Antarctic Territories + option(value='GA') Gabon + option(value='GM') Gambia + option(value='GE') Georgia + option(value='DE') Germany + option(value='GH') Ghana + option(value='GI') Gibraltar + option(value='GR') Greece + option(value='GL') Greenland + option(value='GD') Grenada + option(value='GP') Guadeloupe + option(value='GU') Guam + option(value='GT') Guatemala + option(value='GG') Guernsey + option(value='GW') Guinea-Bissau + option(value='GY') Guyana + option(value='HT') Haiti + option(value='HM') Heard Island and McDonald Islands + option(value='HN') Honduras + option(value='HK') Hong Kong + option(value='HU') Hungary + option(value='IS') Iceland + option(value='IN') India + option(value='ID') Indonesia + option(value='IE') Ireland + option(value='IM') Isle of Man + option(value='IL') Israel + option(value='IT') Italy + option(value='JM') Jamaica + option(value='JP') Japan + option(value='JE') Jersey + option(value='JT') Johnston Island + option(value='JO') Jordan + option(value='KZ') Kazakhstan + option(value='KE') Kenya + option(value='KI') Kiribati + option(value='KW') Kuwait + option(value='KG') Kyrgyzstan + option(value='LA') Laos + option(value='LV') Latvia + option(value='LS') Lesotho + option(value='LY') Libya + option(value='LI') Liechtenstein + option(value='LT') Lithuania + option(value='LU') Luxembourg + option(value='MO') Macau + option(value='MK') Macedonia [FYROM] + option(value='MG') Madagascar + option(value='MW') Malawi + option(value='MY') Malaysia + option(value='MV') Maldives + option(value='ML') Mali + option(value='MT') Malta + option(value='MH') Marshall Islands + option(value='MQ') Martinique + option(value='MR') Mauritania + option(value='MU') Mauritius + option(value='YT') Mayotte + option(value='FX') Metropolitan France + option(value='MX') Mexico + option(value='FM') Micronesia + option(value='MI') Midway Islands + option(value='MD') Moldova + option(value='MC') Monaco + option(value='MN') Mongolia + option(value='ME') Montenegro + option(value='MS') Montserrat + option(value='MA') Morocco + option(value='MZ') Mozambique + option(value='NA') Namibia + option(value='NR') Nauru + option(value='NP') Nepal + option(value='NL') Netherlands + option(value='AN') Netherlands Antilles + option(value='NT') Neutral Zone + option(value='NC') New Caledonia + option(value='NZ') New Zealand + option(value='NI') Nicaragua + option(value='NE') Niger + option(value='NG') Nigeria + option(value='NU') Niue + option(value='NF') Norfolk Island + option(value='VD') North Vietnam + option(value='MP') Northern Mariana Islands + option(value='NO') Norway + option(value='OM') Oman + option(value='QO') Outlying Oceania + option(value='PC') Pacific Islands Trust Territory + option(value='PK') Pakistan + option(value='PW') Palau + option(value='PS') Palestinian Territories + option(value='PA') Panama + option(value='PZ') Panama Canal Zone + option(value='PY') Paraguay + option(value='YD') People's Democratic Republic of Yemen + option(value='PE') Peru + option(value='PH') Philippines + option(value='PN') Pitcairn Islands + option(value='PL') Poland + option(value='PT') Portugal + option(value='PR') Puerto Rico + option(value='QA') Qatar + option(value='RO') Romania + option(value='RU') Russia + option(value='RW') Rwanda + option(value='RE') Réunion + option(value='BL') Saint Barthélemy + option(value='SH') Saint Helena + option(value='KN') Saint Kitts and Nevis + option(value='LC') Saint Lucia + option(value='MF') Saint Martin + option(value='PM') Saint Pierre and Miquelon + option(value='VC') Saint Vincent and the Grenadines + option(value='WS') Samoa + option(value='SM') San Marino + option(value='SA') Saudi Arabia + option(value='SN') Senegal + option(value='RS') Serbia + option(value='CS') Serbia and Montenegro + option(value='SC') Seychelles + option(value='SL') Sierra Leone + option(value='SG') Singapore + option(value='SK') Slovakia + option(value='SI') Slovenia + option(value='SB') Solomon Islands + option(value='ZA') South Africa + option(value='GS') South Georgia and the South Sandwich Islands + option(value='KR') South Korea + option(value='ES') Spain + option(value='LK') Sri Lanka + option(value='SR') Suriname + option(value='SJ') Svalbard and Jan Mayen + option(value='SZ') Swaziland + option(value='SE') Sweden + option(value='CH') Switzerland + option(value='ST') São Tomé and Príncipe + option(value='TW') Taiwan + option(value='TJ') Tajikistan + option(value='TZ') Tanzania + option(value='TH') Thailand + option(value='TG') Togo + option(value='TK') Tokelau + option(value='TO') Tonga + option(value='TT') Trinidad and Tobago + option(value='TA') Tristan da Cunha + option(value='TN') Tunisia + option(value='TR') Turkey + option(value='TM') Turkmenistan + option(value='TC') Turks and Caicos Islands + option(value='TV') Tuvalu + option(value='UM') U.S. Minor Outlying Islands + option(value='PU') U.S. Miscellaneous Pacific Islands + option(value='VI') U.S. Virgin Islands + option(value='UG') Uganda + option(value='UA') Ukraine + option(value='AE') United Arab Emirates + option(value='GB') United Kingdom + option(value='US') United States + option(value='UY') Uruguay + option(value='UZ') Uzbekistan + option(value='VU') Vanuatu + option(value='VA') Vatican City + option(value='VE') Venezuela + option(value='VN') Vietnam + option(value='WK') Wake Island + option(value='WF') Wallis and Futuna + option(value='EH') Western Sahara + option(value='YE') Yemen + option(value='ZM') Zambia + option(value='AX') Åland Islands diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 82fe9d6211..61741825d0 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -27,7 +27,7 @@ define [ postal_code: "se153tt" address1 : "7 somewhere" city:"london" - country:"uk" + country:"GB" @@ -42,7 +42,13 @@ define [ if err $scope.error = err.message else - $http.post("/user/subscription/create", {_csrf: window.csrfToken, recurly_token_id:recurly_token_id.id}) + postData = + _csrf: window.csrfToken + recurly_token_id:recurly_token_id.id + subscriptionDetails: + currencyCode:"USD" + plan_code:"student" + $http.post("/user/subscription/create", postData) .success -> console.log "success" From a47b25d4b298fa7834bca4bd942b26a3b24f47d4 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 22 Dec 2014 12:55:29 +0000 Subject: [PATCH 04/34] works with multi plan and currency, auto updates view on change --- services/web/app/views/subscriptions/new.jade | 27 ++++++++++++++----- .../coffee/main/new-subscription.coffee | 26 +++++++++++++----- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 878d802984..3926847169 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -35,10 +35,25 @@ block content ) {{currency}} ({{value['symbol']}}) h1 #{translate("new_subscription")} hr + form + + .row + .col-md-9 + h2 {{planName}} + span First {{trialLength}} days free + .col-md-3 + h2.pull-right {{price}} + span.pull-right every {{billingCycleType}} + + input(type='text', data-recurly='coupon') + + + + .form-group input.form-control.input-lg-1(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='number', ng-model='data.number', placeholder='Credit Card Number') - input.form-control.input-lg-1(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='cvv', ng-model='data.cvv') + input.form-control.input-lg-1(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='cvv', ng-model='data.cvv') .form-group label #{translate("month")} select.form-control(data-recurly='month', ng-model='data.month') @@ -71,23 +86,23 @@ block content option(value="2026") 2026 .form-group label #{translate("first_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name") .form-group label #{translate("last_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") .form-group label #{translate("address")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="address1", ng-model="data.address1") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="address1", ng-model="data.address1") .form-group label #{translate("city")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city") .form-group label #{translate("country")} select.form-control(data-recurly="country", ng-model="data.country") mixin countries_options() .form-group label #{translate("country")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code") .form-group button.btn.btn-success(ng-click="submit()") #{translate("submit")} diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 61741825d0..a1d106f723 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -3,12 +3,14 @@ define [ ], (App)-> App.controller "NewSubscriptionController", ($scope, MultiCurrencyPricing, abTestManager, $http)-> + throw new Error("Recurly API Library Missing.") if typeof recurly is "undefined" $scope.currencyCode = MultiCurrencyPricing.currencyCode $scope.plans = MultiCurrencyPricing.plans $scope.changeCurrency = (newCurrency)-> - window.location = "/user/subscription/new?planCode=#{window.plan_code}¤cy=#{newCurrency}" + $scope.currencyCode = newCurrency + updatePlan() $scope.switchToStudent = ()-> window.location = "/user/subscription/new?planCode=student¤cy=#{$scope.currencyCode}" @@ -28,16 +30,28 @@ define [ address1 : "7 somewhere" city:"london" country:"GB" + recurly.configure __api_key + pricing = recurly.Pricing() + #pricing.attach(document.querySelector('#pricing')) + window.pricing = pricing + + $scope.planName = "no yet set" + + updatePlan = -> + pricing.plan(window.plan_code, { quantity: 1 }).currency($scope.currencyCode).done() + + updatePlan() + pricing.on "change", => + $scope.planName = pricing.items.plan.name + $scope.price = pricing.price.currency.symbol+pricing.price.next.total + $scope.trialLength = pricing.items.plan.trial.length + $scope.billingCycleType = if pricing.items.plan.period.interval == "months" then "month" else "year" + $scope.$apply() $scope.submit = -> - throw new Error("Recurly API Library Missing.") if typeof recurly is "undefined" - console.log $scope.data $scope.error = "" - if !configured - recurly.configure __api_key - configured = true recurly.token $scope.data, (err, recurly_token_id) -> if err $scope.error = err.message From fa1ec44e22fbb21a65283eff5ab297e06d8e0f37 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 22 Dec 2014 14:06:39 +0000 Subject: [PATCH 05/34] coupons work --- services/web/app/views/subscriptions/new.jade | 2 +- .../web/public/coffee/main/new-subscription.coffee | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 3926847169..1e05ef1d66 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -46,7 +46,7 @@ block content h2.pull-right {{price}} span.pull-right every {{billingCycleType}} - input(type='text', data-recurly='coupon') + input(type='text', ng-blur="applyCoupon()", ng-model="data.coupon") diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index a1d106f723..7369c5ff72 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -8,13 +8,12 @@ define [ $scope.currencyCode = MultiCurrencyPricing.currencyCode $scope.plans = MultiCurrencyPricing.plans - $scope.changeCurrency = (newCurrency)-> - $scope.currencyCode = newCurrency - updatePlan() + $scope.switchToStudent = ()-> window.location = "/user/subscription/new?planCode=student¤cy=#{$scope.currencyCode}" + __api_key = recurlyCreds.apiKey configured = false $scope.error = false @@ -37,11 +36,14 @@ define [ $scope.planName = "no yet set" - updatePlan = -> - pricing.plan(window.plan_code, { quantity: 1 }).currency($scope.currencyCode).done() + pricing.plan(window.plan_code, { quantity: 1 }).currency($scope.currencyCode).done() - updatePlan() + $scope.applyCoupon = -> + pricing.coupon($scope.data.coupon).done() + $scope.changeCurrency = (newCurrency)-> + $scope.currencyCode = newCurrency + pricing.currency(newCurrency).done() pricing.on "change", => $scope.planName = pricing.items.plan.name From 6cedfb19d9175978a8d03a1d5b7e6cd6e412e52e Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 22 Dec 2014 15:07:55 +0000 Subject: [PATCH 06/34] cleaned up form and added basic validation --- services/web/app/views/subscriptions/new.jade | 116 +++++++++++------- .../coffee/main/new-subscription.coffee | 26 ++-- 2 files changed, 86 insertions(+), 56 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 1e05ef1d66..6aa9d6075f 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -45,65 +45,87 @@ block content .col-md-3 h2.pull-right {{price}} span.pull-right every {{billingCycleType}} - - input(type='text', ng-blur="applyCoupon()", ng-model="data.coupon") + hr - .form-group - input.form-control.input-lg-1(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='number', ng-model='data.number', placeholder='Credit Card Number') - input.form-control.input-lg-1(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly='cvv', ng-model='data.cvv') - .form-group - label #{translate("month")} - select.form-control(data-recurly='month', ng-model='data.month') - option(value="01") 01 January - option(value="02") 02 February - option(value="03") 03 March - option(value="04") 04 April - option(value="05") 05 May - option(value="06") 06 June - option(value="07") 07 July - option(value="08") 08 August - option(value="09") 09 September - option(value="10") 10 October - option(value="11") 11 November - option(value="12") 12 December - .form-group - label #{translate("year")} - select.form-control(data-recurly='year', ng-model='data.year') - option(value="2015") 2015 - option(value="2016") 2016 - option(value="2017") 2017 - option(value="2018") 2018 - option(value="2019") 2019 - option(value="2020") 2020 - option(value="2021") 2021 - option(value="2022") 2022 - option(value="2023") 2023 - option(value="2024") 2024 - option(value="2025") 2025 - option(value="2026") 2026 - .form-group - label #{translate("first_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name") - .form-group - label #{translate("last_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") + + .row + .col-md-12 + .form-group + div(ng-hide="validation.correctCvv") invalid cvv + div(ng-hide="validation.correctCardNumber") invalid card number + .col-md-9 + .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") + input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder='Credit Card Number') + .col-md-3 + .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") + input.form-control(ng-model='data.cvv', ng-blur="validateCvv()") + .row + div(ng-hide="validation.correctExpiry") invalid expiry + .col-md-5 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + label #{translate("month")} + select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') + option(value="01") 01 January + option(value="02") 02 February + option(value="03") 03 March + option(value="04") 04 April + option(value="05") 05 May + option(value="06") 06 June + option(value="07") 07 July + option(value="08") 08 August + option(value="09") 09 September + option(value="10") 10 October + option(value="11") 11 November + option(value="12") 12 December + .col-md-5 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + label #{translate("year")} + select.form-control(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') + option(value="2015") 2015 + option(value="2016") 2016 + option(value="2017") 2017 + option(value="2018") 2018 + option(value="2019") 2019 + option(value="2020") 2020 + option(value="2021") 2021 + option(value="2022") 2022 + option(value="2023") 2023 + option(value="2024") 2024 + option(value="2025") 2025 + option(value="2026") 2026 + .row + .col-md-6 + .form-group + label #{translate("first_name")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name") + .col-md-6 + .form-group + label #{translate("last_name")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") .form-group label #{translate("address")} input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="address1", ng-model="data.address1") - .form-group - label #{translate("city")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city") + .row + .col-md-8 + .form-group + label #{translate("city")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city") + .col-md-4 + label #{translate("zip_post_code")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code") + .form-group label #{translate("country")} select.form-control(data-recurly="country", ng-model="data.country") mixin countries_options() + .form-group - label #{translate("country")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code") - + label #{translate("Coupon")} + input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon") + .form-group button.btn.btn-success(ng-click="submit()") #{translate("submit")} diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 7369c5ff72..dcce0d15d1 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -8,16 +8,11 @@ define [ $scope.currencyCode = MultiCurrencyPricing.currencyCode $scope.plans = MultiCurrencyPricing.plans - - $scope.switchToStudent = ()-> window.location = "/user/subscription/new?planCode=student¤cy=#{$scope.currencyCode}" - __api_key = recurlyCreds.apiKey - configured = false - $scope.error = false - $scope.token = false + $scope.data = number: "4111111111111111" month: "02" @@ -29,13 +24,17 @@ define [ address1 : "7 somewhere" city:"london" country:"GB" + + $scope.validation = + correctCardNumber : true + correctExpiry: true + correctCvv:true + recurly.configure __api_key + pricing = recurly.Pricing() - #pricing.attach(document.querySelector('#pricing')) window.pricing = pricing - $scope.planName = "no yet set" - pricing.plan(window.plan_code, { quantity: 1 }).currency($scope.currencyCode).done() $scope.applyCoupon = -> @@ -45,6 +44,15 @@ define [ $scope.currencyCode = newCurrency pricing.currency(newCurrency).done() + $scope.validateCardNumber = -> + $scope.validation.correctCardNumber = recurly.validate.cardNumber($scope.data.number) + + $scope.validateExpiry = -> + $scope.validation.correctExpiry = recurly.validate.expiry($scope.data.month, $scope.data.year) + + $scope.validateCvv = -> + $scope.validation.correctCvv = recurly.validate.cvv($scope.data.cvv) + pricing.on "change", => $scope.planName = pricing.items.plan.name $scope.price = pricing.price.currency.symbol+pricing.price.next.total From fb0a083b36aa7a5525f634ba546b254c3fc42a25 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 22 Dec 2014 15:19:40 +0000 Subject: [PATCH 07/34] added address 2 --- services/web/app/views/subscriptions/new.jade | 4 +++- services/web/public/coffee/main/new-subscription.coffee | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 6aa9d6075f..bc512bbc6c 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -107,7 +107,9 @@ block content input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") .form-group label #{translate("address")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="address1", ng-model="data.address1") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") .row .col-md-8 .form-group diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index dcce0d15d1..9c44388f6c 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -22,6 +22,7 @@ define [ last_name: "o" postal_code: "se153tt" address1 : "7 somewhere" + address2 : "7 somewhere" city:"london" country:"GB" From d0c9783718e71687ff1f140fa54ce7a263bd9835 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 22 Dec 2014 15:51:50 +0000 Subject: [PATCH 08/34] added paypal option in, not tested as we don't have paypal in stag --- services/web/app/views/subscriptions/new.jade | 97 ++++++++++--------- .../coffee/main/new-subscription.coffee | 33 +++++-- 2 files changed, 75 insertions(+), 55 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index bc512bbc6c..8de136536b 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -47,55 +47,60 @@ block content span.pull-right every {{billingCycleType}} hr - - - - .row .col-md-12 .form-group - div(ng-hide="validation.correctCvv") invalid cvv - div(ng-hide="validation.correctCardNumber") invalid card number - .col-md-9 - .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") - input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder='Credit Card Number') - .col-md-3 - .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") - input.form-control(ng-model='data.cvv', ng-blur="validateCvv()") - .row - div(ng-hide="validation.correctExpiry") invalid expiry - .col-md-5 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - label #{translate("month")} - select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') - option(value="01") 01 January - option(value="02") 02 February - option(value="03") 03 March - option(value="04") 04 April - option(value="05") 05 May - option(value="06") 06 June - option(value="07") 07 July - option(value="08") 08 August - option(value="09") 09 September - option(value="10") 10 October - option(value="11") 11 November - option(value="12") 12 December - .col-md-5 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - label #{translate("year")} - select.form-control(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') - option(value="2015") 2015 - option(value="2016") 2016 - option(value="2017") 2017 - option(value="2018") 2018 - option(value="2019") 2019 - option(value="2020") 2020 - option(value="2021") 2021 - option(value="2022") 2022 - option(value="2023") 2023 - option(value="2024") 2024 - option(value="2025") 2025 - option(value="2026") 2026 + label.radio-inline Credit Card + input(type="radio",value="credit_card", ng-model="paymentMethod") + label.radio-inline Paypal + input(type="radio", value="paypal", ng-model="paymentMethod") + + .div(ng-hide="paymentMethod == 'paypal'") + .row + .col-md-12 + .form-group + div(ng-hide="validation.correctCvv") invalid cvv + div(ng-hide="validation.correctCardNumber") invalid card number + .col-md-9 + .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") + input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder='Credit Card Number') + .col-md-3 + .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") + input.form-control(ng-model='data.cvv', ng-blur="validateCvv()") + .row + div(ng-hide="validation.correctExpiry") invalid expiry + .col-md-5 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + label #{translate("month")} + select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') + option(value="01") 01 January + option(value="02") 02 February + option(value="03") 03 March + option(value="04") 04 April + option(value="05") 05 May + option(value="06") 06 June + option(value="07") 07 July + option(value="08") 08 August + option(value="09") 09 September + option(value="10") 10 October + option(value="11") 11 November + option(value="12") 12 December + .col-md-5 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + label #{translate("year")} + select.form-control(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') + option(value="2015") 2015 + option(value="2016") 2016 + option(value="2017") 2017 + option(value="2018") 2018 + option(value="2019") 2019 + option(value="2020") 2020 + option(value="2021") 2021 + option(value="2022") 2022 + option(value="2023") 2023 + option(value="2024") 2024 + option(value="2025") 2025 + option(value="2026") 2026 .row .col-md-6 .form-group diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 9c44388f6c..f13ca732d5 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -13,6 +13,8 @@ define [ __api_key = recurlyCreds.apiKey + $scope.paymentMethod = "credit_card" + $scope.data = number: "4111111111111111" month: "02" @@ -38,6 +40,14 @@ define [ pricing.plan(window.plan_code, { quantity: 1 }).currency($scope.currencyCode).done() + + pricing.on "change", => + $scope.planName = pricing.items.plan.name + $scope.price = pricing.price.currency.symbol+pricing.price.next.total + $scope.trialLength = pricing.items.plan.trial.length + $scope.billingCycleType = if pricing.items.plan.period.interval == "months" then "month" else "year" + $scope.$apply() + $scope.applyCoupon = -> pricing.coupon($scope.data.coupon).done() @@ -54,16 +64,13 @@ define [ $scope.validateCvv = -> $scope.validation.correctCvv = recurly.validate.cvv($scope.data.cvv) - pricing.on "change", => - $scope.planName = pricing.items.plan.name - $scope.price = pricing.price.currency.symbol+pricing.price.next.total - $scope.trialLength = pricing.items.plan.trial.length - $scope.billingCycleType = if pricing.items.plan.period.interval == "months" then "month" else "year" - $scope.$apply() + $scope.changePaymentMethod = (paymentMethod)-> + if paymentMethod == "paypal" + $scope.usePaypal = true + else + $scope.usePaypal = false - $scope.submit = -> - $scope.error = "" - recurly.token $scope.data, (err, recurly_token_id) -> + completeSubscription = (err, recurly_token_id) -> if err $scope.error = err.message else @@ -77,4 +84,12 @@ define [ .success -> console.log "success" + $scope.submit = -> + if $scope.paymentMethod == 'paypal' + opts = { description: $scope.planName } + recurly.paypal opts, completeSubscription + else + recurly.token $scope.data, completeSubscription + + From a7eb836c79131bd3d16ddd7bbec721af79147a18 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 22 Dec 2014 16:37:09 +0000 Subject: [PATCH 09/34] redirect to /thank-you on success and fix broken unit test from a few commits ago --- .../Subscription/SubscriptionController.coffee | 3 ++- .../Subscription/SubscriptionHandler.coffee | 1 + .../public/coffee/main/new-subscription.coffee | 4 +++- .../SubscriptionControllerTests.coffee | 18 +++++++++++------- .../SubscriptionHandlerTests.coffee | 11 ++++++++--- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee index 238db41d2e..4fea7d7382 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee @@ -138,7 +138,8 @@ module.exports = SubscriptionController = SubscriptionHandler.createSubscription user, subscriptionDetails, recurly_token_id, (err)-> if err? logger.err err:err, user_id:user._id, "something went wrong creating subscription" - res.redirect "/user/subscription/thank-you" + return res.send 500 + res.send 201 successful_subscription: (req, res)-> SecurityManager.getCurrentUser req, (error, user) => diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee index 7a210b2ead..4aa3310b89 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee @@ -14,6 +14,7 @@ module.exports = self = @ clientTokenId = "" RecurlyWrapper.createSubscription user, subscriptionDetails, recurly_token_id, (error, recurlySubscription)-> + console.log recurlySubscription return callback(error) if error? SubscriptionUpdater.syncSubscription recurlySubscription, user._id, (error) -> return callback(error) if error? diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index f13ca732d5..4d80e8c5a2 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -82,7 +82,9 @@ define [ plan_code:"student" $http.post("/user/subscription/create", postData) .success -> - console.log "success" + window.location.href = "/user/subscription/thank-you" + .error ()-> + console.log "something went wong" $scope.submit = -> if $scope.paymentMethod == 'paypal' diff --git a/services/web/test/UnitTests/coffee/Subscription/SubscriptionControllerTests.coffee b/services/web/test/UnitTests/coffee/Subscription/SubscriptionControllerTests.coffee index cb6c5a663b..624f55ef0d 100644 --- a/services/web/test/UnitTests/coffee/Subscription/SubscriptionControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/SubscriptionControllerTests.coffee @@ -20,13 +20,13 @@ mockSubscriptions = describe "SubscriptionController sanboxed", -> beforeEach -> - @user = {} + @user = {email:"tom@yahoo.com"} @activeRecurlySubscription = mockSubscriptions["subscription-123-active"] @SecurityManager = getCurrentUser: sinon.stub().callsArgWith(1, null, @user) @SubscriptionHandler = - createSubscription: sinon.stub().callsArgWith(2) + createSubscription: sinon.stub().callsArgWith(3) updateSubscription: sinon.stub().callsArgWith(3) reactivateSubscription: sinon.stub().callsArgWith(1) cancelSubscription: sinon.stub().callsArgWith(1) @@ -258,18 +258,22 @@ describe "SubscriptionController sanboxed", -> describe "createSubscription", -> beforeEach (done)-> @res = - redirect:-> + send:-> done() - sinon.spy @res, "redirect" - @req.body.recurly_token = "1234" + sinon.spy @res, "send" + @subscriptionDetails = + card:"1234" + cvv:"123" + @req.body.recurly_token_id = "1234" + @req.body.subscriptionDetails = @subscriptionDetails @SubscriptionController.createSubscription @req, @res it "should send the user and subscriptionId to the handler", (done)-> - @SubscriptionHandler.createSubscription.calledWith(@user, @req.body.recurly_token).should.equal true + @SubscriptionHandler.createSubscription.calledWith(@user, @subscriptionDetails, @req.body.recurly_token_id).should.equal true done() it "should redurect to the subscription page", (done)-> - @res.redirect.calledWith("/user/subscription/thank-you").should.equal true + @res.send.calledWith(201).should.equal true done() diff --git a/services/web/test/UnitTests/coffee/Subscription/SubscriptionHandlerTests.coffee b/services/web/test/UnitTests/coffee/Subscription/SubscriptionHandlerTests.coffee index 606216fedf..f66a1813d6 100644 --- a/services/web/test/UnitTests/coffee/Subscription/SubscriptionHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/SubscriptionHandlerTests.coffee @@ -42,6 +42,7 @@ describe "Subscription Handler sanboxed", -> cancelSubscription: sinon.stub().callsArgWith(1) reactivateSubscription: sinon.stub().callsArgWith(1) redeemCoupon:sinon.stub().callsArgWith(2) + createSubscription: sinon.stub().callsArgWith(3, null, @activeRecurlySubscription) @DropboxHandler = unlinkAccount:sinon.stub().callsArgWith(1) @@ -71,10 +72,14 @@ describe "Subscription Handler sanboxed", -> describe "createSubscription", -> beforeEach (done) -> - @SubscriptionHandler.createSubscription(@user, @activeRecurlySubscription.uuid, done) + @subscriptionDetails = + cvv:"123" + number:"12345" + @recurly_token_id = "45555666" + @SubscriptionHandler.createSubscription(@user, @subscriptionDetails, @recurly_token_id, done) - it "should get the subscription", (done)-> - @RecurlyWrapper.getSubscription.calledWith(@activeRecurlySubscription.uuid, {recurlyJsResult: true}).should.equal true + it "should create the subscription with the wrapper", (done)-> + @RecurlyWrapper.createSubscription.calledWith(@user, @subscriptionDetails, @recurly_token_id).should.equal true done() it "should sync the subscription to the user", (done)-> From e2819c3bc6aae48aec7cc30aea4d3046ba8a37f9 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 23 Dec 2014 11:04:54 +0000 Subject: [PATCH 10/34] added generic error handling to recurly processing and required fields --- services/web/app/views/subscriptions/new.jade | 10 ++++--- .../coffee/main/new-subscription.coffee | 28 +++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 8de136536b..6720556595 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -37,7 +37,6 @@ block content hr form - .row .col-md-9 h2 {{planName}} @@ -55,6 +54,9 @@ block content label.radio-inline Paypal input(type="radio", value="paypal", ng-model="paymentMethod") + .alert.alert-warning.small(ng-show="genericError") + strong {{genericError}} + .div(ng-hide="paymentMethod == 'paypal'") .row .col-md-12 @@ -105,11 +107,11 @@ block content .col-md-6 .form-group label #{translate("first_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required) .col-md-6 .form-group label #{translate("last_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required) .form-group label #{translate("address")} input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") @@ -126,7 +128,7 @@ block content .form-group label #{translate("country")} - select.form-control(data-recurly="country", ng-model="data.country") + select.form-control(data-recurly="country", ng-model="data.country", required) mixin countries_options() .form-group diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 4d80e8c5a2..4df41a7270 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -71,20 +71,20 @@ define [ $scope.usePaypal = false completeSubscription = (err, recurly_token_id) -> - if err - $scope.error = err.message - else - postData = - _csrf: window.csrfToken - recurly_token_id:recurly_token_id.id - subscriptionDetails: - currencyCode:"USD" - plan_code:"student" - $http.post("/user/subscription/create", postData) - .success -> - window.location.href = "/user/subscription/thank-you" - .error ()-> - console.log "something went wong" + if err? + $scope.genericError = err.message + else + postData = + _csrf: window.csrfToken + recurly_token_id:recurly_token_id.id + subscriptionDetails: + currencyCode:"USD" + plan_code:"student" + $http.post("/user/subscription/create", postData) + .success (data, status, headers)-> + window.location.href = "/user/subscription/thank-you" + .error (data, status, headers)-> + $scope.genericError = "Something went wrong processing the request" $scope.submit = -> if $scope.paymentMethod == 'paypal' From 03311311ddcb4d98be517fd68c15f2b6045dc534 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 23 Dec 2014 11:42:56 +0000 Subject: [PATCH 11/34] added translations in --- services/web/app/views/subscriptions/new.jade | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 6720556595..a2e6a26a91 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -1,18 +1,17 @@ extends ../layout block scripts + script(src="https://js.recurly.com/v3/recurly.js") script(type='text/javascript'). window.recomendedCurrency = '#{currency}' window.plan_code = '#{plan_code}' - window.recurlyCreds = { apiKey : "sc-GVdZOe7akgWbZRIFPllOx9", apiUrl:""} block content - locals.supressDefaultJs = true script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js', baseurl=jsPath) - script(src="https://js.recurly.com/v3/recurly.js") .content.content-alt @@ -40,16 +39,18 @@ block content .row .col-md-9 h2 {{planName}} - span First {{trialLength}} days free + span !{translate("first_few_days_free", {trialLen:'{{trialLen}}'})} + + .col-md-3 h2.pull-right {{price}} - span.pull-right every {{billingCycleType}} + span.pull-right #{translate("every")} {{billingCycleType}} hr .row .col-md-12 .form-group - label.radio-inline Credit Card + label.radio-inline #{translate("credit_card")} input(type="radio",value="credit_card", ng-model="paymentMethod") label.radio-inline Paypal input(type="radio", value="paypal", ng-model="paymentMethod") @@ -61,32 +62,32 @@ block content .row .col-md-12 .form-group - div(ng-hide="validation.correctCvv") invalid cvv - div(ng-hide="validation.correctCardNumber") invalid card number + div(ng-hide="validation.correctCvv") #{translate("invalid")} CVV + div(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} .col-md-9 .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") - input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder='Credit Card Number') + input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") .col-md-3 .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") - input.form-control(ng-model='data.cvv', ng-blur="validateCvv()") + input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") .row - div(ng-hide="validation.correctExpiry") invalid expiry + div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} .col-md-5 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") label #{translate("month")} select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') - option(value="01") 01 January - option(value="02") 02 February - option(value="03") 03 March - option(value="04") 04 April - option(value="05") 05 May - option(value="06") 06 June - option(value="07") 07 July - option(value="08") 08 August - option(value="09") 09 September - option(value="10") 10 October - option(value="11") 11 November - option(value="12") 12 December + option(value="01") 01 #{translate("january")} + option(value="02") 02 #{translate("february")} + option(value="03") 03 #{translate("march")} + option(value="04") 04 #{translate("april")} + option(value="05") 05 #{translate("may")} + option(value="06") 06 #{translate("june")} + option(value="07") 07 #{translate("july")} + option(value="08") 08 #{translate("august")} + option(value="09") 09 #{translate("september")} + option(value="10") 10 #{translate("october")} + option(value="11") 11 #{translate("november")} + option(value="12") 12 #{translate("december")} .col-md-5 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") label #{translate("year")} @@ -132,7 +133,7 @@ block content mixin countries_options() .form-group - label #{translate("Coupon")} + label #{translate("coupon")} input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon") .form-group @@ -198,7 +199,7 @@ block content mixin countries_options() - option(value='-') Select Country + option(value='-') #{translate("country")} option(value='-') -------------- option(value='AF') Afghanistan option(value='AL') Albania From 74347611e904ce42bd96a49feeea88316ce1acc7 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 23 Dec 2014 11:44:42 +0000 Subject: [PATCH 12/34] don't show the form until we have some data from recurly --- services/web/app/views/subscriptions/new.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index a2e6a26a91..c03ef33e8a 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -33,9 +33,9 @@ block content ng-click="changeCurrency(currency)", ) {{currency}} ({{value['symbol']}}) h1 #{translate("new_subscription")} - hr - form + form(ng-show="planName") + hr .row .col-md-9 h2 {{planName}} From 12a28d91f2d2c4d4d51675a1231dde0dd2f59ce7 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 23 Dec 2014 12:00:41 +0000 Subject: [PATCH 13/34] removed month names --- services/web/app/views/subscriptions/new.jade | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index c03ef33e8a..55e1ca1e1b 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -6,7 +6,7 @@ block scripts script(type='text/javascript'). window.recomendedCurrency = '#{currency}' window.plan_code = '#{plan_code}' - window.recurlyCreds = { apiKey : "sc-GVdZOe7akgWbZRIFPllOx9", apiUrl:""} + window.recurlyCreds = { apiKey : "sc-GVdZOe7akgWbZRIFPllOx9"} block content @@ -64,7 +64,7 @@ block content .form-group div(ng-hide="validation.correctCvv") #{translate("invalid")} CVV div(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} - .col-md-9 + .col-md-7 .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") .col-md-3 @@ -72,25 +72,23 @@ block content input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") .row div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} - .col-md-5 + .col-md-2 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - label #{translate("month")} select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') - option(value="01") 01 #{translate("january")} - option(value="02") 02 #{translate("february")} - option(value="03") 03 #{translate("march")} - option(value="04") 04 #{translate("april")} - option(value="05") 05 #{translate("may")} - option(value="06") 06 #{translate("june")} - option(value="07") 07 #{translate("july")} - option(value="08") 08 #{translate("august")} - option(value="09") 09 #{translate("september")} - option(value="10") 10 #{translate("october")} - option(value="11") 11 #{translate("november")} - option(value="12") 12 #{translate("december")} - .col-md-5 + option(value="01") 01 + option(value="02") 02 + option(value="03") 03 + option(value="04") 04 + option(value="05") 05 + option(value="06") 06 + option(value="07") 07 + option(value="08") 08 + option(value="09") 09 + option(value="10") 10 + option(value="11") 11 + option(value="12") 12 + .col-md-3 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - label #{translate("year")} select.form-control(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') option(value="2015") 2015 option(value="2016") 2016 From ecb71d5bbfbfd4e5ab2f66e588615a2e57df7f8c Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 23 Dec 2014 12:08:01 +0000 Subject: [PATCH 14/34] pull recurely pub api key from settings file --- services/web/app/views/subscriptions/new.jade | 2 +- services/web/public/coffee/main/new-subscription.coffee | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 55e1ca1e1b..e55be2edf1 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -6,7 +6,7 @@ block scripts script(type='text/javascript'). window.recomendedCurrency = '#{currency}' window.plan_code = '#{plan_code}' - window.recurlyCreds = { apiKey : "sc-GVdZOe7akgWbZRIFPllOx9"} + window.recurlyApiKey = "!{settings.apis.recurly.publicKey}" block content diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 4df41a7270..c5b910ed50 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -11,7 +11,6 @@ define [ $scope.switchToStudent = ()-> window.location = "/user/subscription/new?planCode=student¤cy=#{$scope.currencyCode}" - __api_key = recurlyCreds.apiKey $scope.paymentMethod = "credit_card" @@ -33,7 +32,7 @@ define [ correctExpiry: true correctCvv:true - recurly.configure __api_key + recurly.configure window.recurlyApiKey pricing = recurly.Pricing() window.pricing = pricing From 7f979e77db4d5282a248f6e919f13a5a91313d3c Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 17:16:21 +0000 Subject: [PATCH 15/34] - fixed new payment page so it uses correct plan and currency - submit button is disabled while processing - removed test data --- services/web/app/views/subscriptions/new.jade | 2 +- .../coffee/main/new-subscription.coffee | 30 +++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index e55be2edf1..adf49b4bf0 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -135,7 +135,7 @@ block content input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon") .form-group - button.btn.btn-success(ng-click="submit()") #{translate("submit")} + button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("submit")} diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index c5b910ed50..a1d73c3912 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -15,23 +15,25 @@ define [ $scope.paymentMethod = "credit_card" $scope.data = - number: "4111111111111111" - month: "02" - year: "2015" - cvv: "111" - first_name: "h" - last_name: "o" - postal_code: "se153tt" - address1 : "7 somewhere" - address2 : "7 somewhere" - city:"london" - country:"GB" + number: "" + month: "" + year: "" + cvv: "" + first_name: "" + last_name: "" + postal_code: "" + address1 : "" + address2 : "" + city:"" + country:"" $scope.validation = correctCardNumber : true correctExpiry: true correctCvv:true + $scope.processing = false + recurly.configure window.recurlyApiKey pricing = recurly.Pricing() @@ -77,15 +79,17 @@ define [ _csrf: window.csrfToken recurly_token_id:recurly_token_id.id subscriptionDetails: - currencyCode:"USD" - plan_code:"student" + currencyCode:pricing.items.currency + plan_code:pricing.items.plan.code $http.post("/user/subscription/create", postData) .success (data, status, headers)-> window.location.href = "/user/subscription/thank-you" .error (data, status, headers)-> + $scope.processing = false $scope.genericError = "Something went wrong processing the request" $scope.submit = -> + $scope.processing = true if $scope.paymentMethod == 'paypal' opts = { description: $scope.planName } recurly.paypal opts, completeSubscription From baa0a42825812a202c6e5a2c6abef1116292b630 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 17:51:36 +0000 Subject: [PATCH 16/34] coupon field is shown if query string scf is shown --- .../Features/Subscription/SubscriptionController.coffee | 1 + services/web/app/views/subscriptions/new.jade | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee index 4fea7d7382..5821a09d9c 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee @@ -61,6 +61,7 @@ module.exports = SubscriptionController = recurlyConfig: JSON.stringify currency: currency subdomain: Settings.apis.recurly.subdomain + showCouponField:req.query.scf subscriptionFormOptions: JSON.stringify acceptedCards: ['discover', 'mastercard', 'visa'] target : "#subscribeForm" diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index adf49b4bf0..575bd40684 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -130,9 +130,9 @@ block content select.form-control(data-recurly="country", ng-model="data.country", required) mixin countries_options() - .form-group - label #{translate("coupon")} - input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon") + if showCouponField == 'true' + .form-group + input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") .form-group button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("submit")} From 137b9c1077dbf2c3a3391026bf2c1369f78de179 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 17:59:29 +0000 Subject: [PATCH 17/34] removed some labels and added paypal/credit card logos --- services/web/app/views/subscriptions/new.jade | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 575bd40684..ffe2a9e8d0 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -39,7 +39,7 @@ block content .row .col-md-9 h2 {{planName}} - span !{translate("first_few_days_free", {trialLen:'{{trialLen}}'})} + span !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})} .col-md-3 @@ -50,10 +50,16 @@ block content .row .col-md-12 .form-group - label.radio-inline #{translate("credit_card")} - input(type="radio",value="credit_card", ng-model="paymentMethod") - label.radio-inline Paypal - input(type="radio", value="paypal", ng-model="paymentMethod") + .row + .col-md-3 + label.radio-inline + img(src="/recurly/images/credit_cards/mastercard.png") + img(src="/recurly/images/credit_cards/visa.png") + input(type="radio",value="credit_card", ng-model="paymentMethod") + .col-md-4 + label.radio-inline + img(src="/recurly/images/paypal_logo.png") + input(type="radio", value="paypal", ng-model="paymentMethod") .alert.alert-warning.small(ng-show="genericError") strong {{genericError}} @@ -74,7 +80,8 @@ block content div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} .col-md-2 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') + select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') + option(value="", disabled, selected) Month option(value="01") 01 option(value="02") 02 option(value="03") 03 @@ -89,7 +96,8 @@ block content option(value="12") 12 .col-md-3 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select.form-control(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') + select(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') + option(value="", disabled, selected) Year option(value="2015") 2015 option(value="2016") 2016 option(value="2017") 2017 @@ -105,37 +113,32 @@ block content .row .col-md-6 .form-group - label #{translate("first_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required) + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}") .col-md-6 .form-group - label #{translate("last_name")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required) + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}") + hr .form-group - label #{translate("address")} + label #{translate("billing_address")} input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") .form-group input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") .row .col-md-8 .form-group - label #{translate("city")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}") .col-md-4 - label #{translate("zip_post_code")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}") .form-group - label #{translate("country")} select.form-control(data-recurly="country", ng-model="data.country", required) mixin countries_options() - if showCouponField == 'true' .form-group input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") .form-group - button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("submit")} + button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} @@ -197,7 +200,7 @@ block content mixin countries_options() - option(value='-') #{translate("country")} + option(value='-', disabled, selected) #{translate("country")} option(value='-') -------------- option(value='AF') Afghanistan option(value='AL') Albania From 236d4d7ab36901b68943bfb5c337a6cb8c98f993 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 18:16:55 +0000 Subject: [PATCH 18/34] made the fields smaller and pushed plan name to header --- services/web/app/views/subscriptions/new.jade | 82 ++++++++++--------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index ffe2a9e8d0..35a67d2683 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -20,31 +20,28 @@ block content .col-md-6.col-md-push-3 .card.card-highlighted .page-header - span.dropdown.changePlanButton.pull-right(ng-cloak) - a.btn.btn-default.dropdown-toggle( - href="#", - data-toggle="dropdown" - ) - | {{currencyCode}} ({{plans[currencyCode]['symbol']}}) - span.caret - ul.dropdown-menu(role="menu") - li(ng-repeat="(currency, value) in plans", dropdown-toggle) - a( - ng-click="changeCurrency(currency)", - ) {{currency}} ({{value['symbol']}}) - h1 #{translate("new_subscription")} - + .row + .col-md-9 + h2 {{planName}} + div !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})} + div #{translate("every")} {{billingCycleType}} + .col-md-3 + div.dropdown.changePlanButton.pull-right(ng-cloak) + a.btn.btn-default.dropdown-toggle( + href="#", + data-toggle="dropdown" + ) + | {{currencyCode}} ({{plans[currencyCode]['symbol']}}) + span.caret + ul.dropdown-menu(role="menu") + li(ng-repeat="(currency, value) in plans", dropdown-toggle) + a( + ng-click="changeCurrency(currency)", + ) {{currency}} ({{value['symbol']}}) + div .  + h2.pull-right {{price}} form(ng-show="planName") - hr - .row - .col-md-9 - h2 {{planName}} - span !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})} - - - .col-md-3 - h2.pull-right {{price}} - span.pull-right #{translate("every")} {{billingCycleType}} + hr .row @@ -70,7 +67,7 @@ block content .form-group div(ng-hide="validation.correctCvv") #{translate("invalid")} CVV div(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} - .col-md-7 + .col-md-5 .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") .col-md-3 @@ -111,31 +108,36 @@ block content option(value="2025") 2025 option(value="2026") 2026 .row - .col-md-6 + .col-md-4 .form-group input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}") - .col-md-6 + .col-md-4 .form-group input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}") hr - .form-group - label #{translate("billing_address")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") .row .col-md-8 + .form-group + label #{translate("billing_address")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") + .row + .col-md-4 .form-group input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}") .col-md-4 input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}") - - .form-group - select.form-control(data-recurly="country", ng-model="data.country", required) - mixin countries_options() - if showCouponField == 'true' - .form-group - input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") + .row + .col-md-8 + .form-group + select.form-control(data-recurly="country", ng-model="data.country", required) + mixin countries_options() + .row + .col-md-8 + if showCouponField == 'true' + .form-group + input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") .form-group button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} @@ -200,7 +202,7 @@ block content mixin countries_options() - option(value='-', disabled, selected) #{translate("country")} + option(value='', disabled, selected) #{translate("country")} option(value='-') -------------- option(value='AF') Afghanistan option(value='AL') Albania From 9d572888097ca08b53926c612e60a65ded318288 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 18:23:08 +0000 Subject: [PATCH 19/34] centered the billing forms --- services/web/app/views/subscriptions/new.jade | 195 +++++++++--------- 1 file changed, 99 insertions(+), 96 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 35a67d2683..44b50c5280 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -40,107 +40,110 @@ block content ) {{currency}} ({{value['symbol']}}) div .  h2.pull-right {{price}} - form(ng-show="planName") - - hr + hr + .row + .col-md-offset-1.col-md-10 + form(ng-show="planName") + - .row - .col-md-12 - .form-group + .row + .col-md-12 + .form-group + .row + .col-md-3 + label.radio-inline + img(src="/recurly/images/credit_cards/mastercard.png") + img(src="/recurly/images/credit_cards/visa.png") + input(type="radio",value="credit_card", ng-model="paymentMethod") + .col-md-4 + label.radio-inline + img(src="/recurly/images/paypal_logo.png") + input(type="radio", value="paypal", ng-model="paymentMethod") + + .alert.alert-warning.small(ng-show="genericError") + strong {{genericError}} + + .div(ng-hide="paymentMethod == 'paypal'") .row + .col-md-12 + .form-group + div(ng-hide="validation.correctCvv") #{translate("invalid")} CVV + div(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} + .row + .col-md-6 + .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") + input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") .col-md-3 - label.radio-inline - img(src="/recurly/images/credit_cards/mastercard.png") - img(src="/recurly/images/credit_cards/visa.png") - input(type="radio",value="credit_card", ng-model="paymentMethod") - .col-md-4 - label.radio-inline - img(src="/recurly/images/paypal_logo.png") - input(type="radio", value="paypal", ng-model="paymentMethod") + .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") + input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") + .row + div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} + .col-md-2 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') + option(value="", disabled, selected) Month + option(value="01") 01 + option(value="02") 02 + option(value="03") 03 + option(value="04") 04 + option(value="05") 05 + option(value="06") 06 + option(value="07") 07 + option(value="08") 08 + option(value="09") 09 + option(value="10") 10 + option(value="11") 11 + option(value="12") 12 + .col-md-3 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + select(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') + option(value="", disabled, selected) Year + option(value="2015") 2015 + option(value="2016") 2016 + option(value="2017") 2017 + option(value="2018") 2018 + option(value="2019") 2019 + option(value="2020") 2020 + option(value="2021") 2021 + option(value="2022") 2022 + option(value="2023") 2023 + option(value="2024") 2024 + option(value="2025") 2025 + option(value="2026") 2026 + .row + .col-md-6 + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}") + .col-md-6 + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}") + hr + .row + .col-md-12 + .form-group + label #{translate("billing_address")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") + .row + .col-md-8 + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}") + .col-md-4 + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}") + .row + .col-md-8 + .form-group + select.form-control(data-recurly="country", ng-model="data.country", required) + mixin countries_options() + .row + .col-md-8 + if showCouponField == 'true' + .form-group + input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") - .alert.alert-warning.small(ng-show="genericError") - strong {{genericError}} - - .div(ng-hide="paymentMethod == 'paypal'") - .row - .col-md-12 - .form-group - div(ng-hide="validation.correctCvv") #{translate("invalid")} CVV - div(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} - .col-md-5 - .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") - input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") - .col-md-3 - .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") - input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") - .row - div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} - .col-md-2 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') - option(value="", disabled, selected) Month - option(value="01") 01 - option(value="02") 02 - option(value="03") 03 - option(value="04") 04 - option(value="05") 05 - option(value="06") 06 - option(value="07") 07 - option(value="08") 08 - option(value="09") 09 - option(value="10") 10 - option(value="11") 11 - option(value="12") 12 - .col-md-3 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') - option(value="", disabled, selected) Year - option(value="2015") 2015 - option(value="2016") 2016 - option(value="2017") 2017 - option(value="2018") 2018 - option(value="2019") 2019 - option(value="2020") 2020 - option(value="2021") 2021 - option(value="2022") 2022 - option(value="2023") 2023 - option(value="2024") 2024 - option(value="2025") 2025 - option(value="2026") 2026 - .row - .col-md-4 .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}") - .col-md-4 - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}") - hr - .row - .col-md-8 - .form-group - label #{translate("billing_address")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") - .row - .col-md-4 - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}") - .col-md-4 - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}") - .row - .col-md-8 - .form-group - select.form-control(data-recurly="country", ng-model="data.country", required) - mixin countries_options() - .row - .col-md-8 - if showCouponField == 'true' - .form-group - input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") - - .form-group - button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} + button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} From 673140b620e520f167ed3cd68d4e78c41a06ed0d Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 18:35:44 +0000 Subject: [PATCH 20/34] got new credit card logos from https://www.mastercardbrandcenter.com/us/getourbrand/index.shtml?pageId=dl_0340&expertVisible=false --- services/web/app/views/subscriptions/new.jade | 5 ++--- .../images/credit_cards/visa_mastercard.png | Bin 0 -> 7509 bytes 2 files changed, 2 insertions(+), 3 deletions(-) create mode 100644 services/web/public/recurly/images/credit_cards/visa_mastercard.png diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 44b50c5280..d7e238bd70 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -50,10 +50,9 @@ block content .col-md-12 .form-group .row - .col-md-3 + .col-md-6 label.radio-inline - img(src="/recurly/images/credit_cards/mastercard.png") - img(src="/recurly/images/credit_cards/visa.png") + img(src="/recurly/images/credit_cards/visa_mastercard.png") input(type="radio",value="credit_card", ng-model="paymentMethod") .col-md-4 label.radio-inline diff --git a/services/web/public/recurly/images/credit_cards/visa_mastercard.png b/services/web/public/recurly/images/credit_cards/visa_mastercard.png new file mode 100644 index 0000000000000000000000000000000000000000..feed5358813d73ace962761a712d21b5ace7a747 GIT binary patch literal 7509 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 f36mQL=>Ho4r%*9%-H6`{00000NkvXXu0mjfl$ Date: Sun, 28 Dec 2014 18:43:53 +0000 Subject: [PATCH 21/34] added new official paypal logo from https://www.paypal.com/uk/webapps/mpp/logo-center --- services/web/app/views/subscriptions/new.jade | 6 +++--- .../web/public/recurly/images/paypal_large.png | Bin 0 -> 5525 bytes 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 services/web/public/recurly/images/paypal_large.png diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index d7e238bd70..29a7c11370 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -52,12 +52,12 @@ block content .row .col-md-6 label.radio-inline - img(src="/recurly/images/credit_cards/visa_mastercard.png") input(type="radio",value="credit_card", ng-model="paymentMethod") - .col-md-4 + img(src="/recurly/images/credit_cards/visa_mastercard.png") + .col-md-6 label.radio-inline - img(src="/recurly/images/paypal_logo.png") input(type="radio", value="paypal", ng-model="paymentMethod") + img(src="/recurly/images/paypal_large.png") .alert.alert-warning.small(ng-show="genericError") strong {{genericError}} diff --git a/services/web/public/recurly/images/paypal_large.png b/services/web/public/recurly/images/paypal_large.png new file mode 100644 index 0000000000000000000000000000000000000000..e8c641ece47283dd2b3dbed75d013916d8bdc06c GIT binary patch literal 5525 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 Date: Sun, 28 Dec 2014 18:55:29 +0000 Subject: [PATCH 22/34] added little ssl secure message --- services/web/app/views/subscriptions/new.jade | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 29a7c11370..292ef418f8 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -76,7 +76,8 @@ block content .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") .row - div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} + .col-md-12 + div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} .col-md-2 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') @@ -142,7 +143,8 @@ block content input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") .form-group - button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} + button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} + .alert.alert-info.small This is a secure 128-bit SSL encrypted payment. Your safe. From 2d03e0532f262d1585cb72d2a795d0e04f0c4c09 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 19:04:47 +0000 Subject: [PATCH 23/34] adjusted style of payment options --- services/web/app/views/subscriptions/new.jade | 10 +++++----- services/web/public/stylesheets/app/plans.less | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 292ef418f8..d5a83bbf50 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -52,17 +52,17 @@ block content .row .col-md-6 label.radio-inline - input(type="radio",value="credit_card", ng-model="paymentMethod") - img(src="/recurly/images/credit_cards/visa_mastercard.png") + input.paymentTypeOption(type="radio",value="credit_card", ng-model="paymentMethod") + img(src="/recurly/images/credit_cards/visa_mastercard.png") .col-md-6 label.radio-inline - input(type="radio", value="paypal", ng-model="paymentMethod") - img(src="/recurly/images/paypal_large.png") + input.paymentTypeOption(type="radio", value="paypal", ng-model="paymentMethod") + img(src="/recurly/images/paypal_large.png") .alert.alert-warning.small(ng-show="genericError") strong {{genericError}} - .div(ng-hide="paymentMethod == 'paypal'") + span(ng-hide="paymentMethod == 'paypal'") .row .col-md-12 .form-group diff --git a/services/web/public/stylesheets/app/plans.less b/services/web/public/stylesheets/app/plans.less index 777a4400c3..611aa30f0e 100644 --- a/services/web/public/stylesheets/app/plans.less +++ b/services/web/public/stylesheets/app/plans.less @@ -96,7 +96,9 @@ margin-top: 20px; } - +input.paymentTypeOption.ng-valid { + margin-top: 10px; +} From 0efb1bba5b532071718caeca1623a87baa351398 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 19:06:01 +0000 Subject: [PATCH 24/34] adjusted post code and country field sizes --- services/web/app/views/subscriptions/new.jade | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index d5a83bbf50..407c213a6e 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -126,13 +126,13 @@ block content .form-group input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") .row - .col-md-8 + .col-md-7 .form-group input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}") - .col-md-4 + .col-md-5 input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}") .row - .col-md-8 + .col-md-7 .form-group select.form-control(data-recurly="country", ng-model="data.country", required) mixin countries_options() From 1a4825a47b18ce23e1d7e76f2794bb9bb1ec882d Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 19:08:36 +0000 Subject: [PATCH 25/34] pulled total price down a little --- services/web/app/views/subscriptions/new.jade | 3 +-- services/web/public/stylesheets/app/plans.less | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 407c213a6e..3e85f1bb3f 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -38,8 +38,7 @@ block content a( ng-click="changeCurrency(currency)", ) {{currency}} ({{value['symbol']}}) - div .  - h2.pull-right {{price}} + h2.pull-right.totalPrice {{price}} hr .row .col-md-offset-1.col-md-10 diff --git a/services/web/public/stylesheets/app/plans.less b/services/web/public/stylesheets/app/plans.less index 611aa30f0e..e74755a266 100644 --- a/services/web/public/stylesheets/app/plans.less +++ b/services/web/public/stylesheets/app/plans.less @@ -100,6 +100,9 @@ input.paymentTypeOption.ng-valid { margin-top: 10px; } +.totalPrice { + padding-top: 15px; +} From 474fa5fe19180ba702365bd3779939811083a851 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 21:53:12 +0000 Subject: [PATCH 26/34] only validate expiry when both are set --- services/web/public/coffee/main/new-subscription.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index a1d73c3912..4202308ce3 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -16,8 +16,8 @@ define [ $scope.data = number: "" - month: "" - year: "" + month: undefined + year: undefined cvv: "" first_name: "" last_name: "" @@ -60,7 +60,8 @@ define [ $scope.validation.correctCardNumber = recurly.validate.cardNumber($scope.data.number) $scope.validateExpiry = -> - $scope.validation.correctExpiry = recurly.validate.expiry($scope.data.month, $scope.data.year) + if $scope.data.month? and $scope.data.year? + $scope.validation.correctExpiry = recurly.validate.expiry($scope.data.month, $scope.data.year) $scope.validateCvv = -> $scope.validation.correctCvv = recurly.validate.cvv($scope.data.cvv) From afab06bcacc367c197f743200a0ad2d173a28ae7 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 21:56:17 +0000 Subject: [PATCH 27/34] removed safe message from payment form. --- services/web/app/views/subscriptions/new.jade | 1 - 1 file changed, 1 deletion(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 3e85f1bb3f..225f0a5c17 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -143,7 +143,6 @@ block content .form-group button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} - .alert.alert-info.small This is a secure 128-bit SSL encrypted payment. Your safe. From 1716b16fb061e5c176bacdda048a15f06c903225 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 22:03:12 +0000 Subject: [PATCH 28/34] added placeholder info to address --- services/web/app/views/subscriptions/new.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 225f0a5c17..74c094bf90 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -121,9 +121,9 @@ block content .col-md-12 .form-group label #{translate("billing_address")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1", placeholder="#{translate('address')}") .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2") + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2", placeholder="#{translate('address')}") .row .col-md-7 .form-group From 735dd0811c110740cedf55f8df1c21a75f9a697b Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 22:14:39 +0000 Subject: [PATCH 29/34] changed credit card/paypal logs from offical ones to font very good ones upgraded fontamerican to 4.2 --- services/web/app/views/layout.jade | 2 +- services/web/app/views/subscriptions/new.jade | 8 ++++++-- services/web/public/stylesheets/app/plans.less | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/services/web/app/views/layout.jade b/services/web/app/views/layout.jade index 8e82cefa25..3d17e9b1a1 100644 --- a/services/web/app/views/layout.jade +++ b/services/web/app/views/layout.jade @@ -14,7 +14,7 @@ html(itemscope, itemtype='http://schema.org/Product') link(rel="icon", href="/favicon.ico") link(rel='stylesheet', href='/stylesheets/style.css?fingerprint='+fingerprint('/stylesheets/style.css')) - link(href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css",rel="stylesheet") + link(href="//netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css",rel="stylesheet") if settings.i18n.subdomainLang each subdomainDetails in settings.i18n.subdomainLang diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 74c094bf90..65265e15a1 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -52,11 +52,15 @@ block content .col-md-6 label.radio-inline input.paymentTypeOption(type="radio",value="credit_card", ng-model="paymentMethod") - img(src="/recurly/images/credit_cards/visa_mastercard.png") + i.fa.fa-cc-mastercard.fa-3x + span   + i.fa.fa-cc-visa.fa-3x .col-md-6 label.radio-inline input.paymentTypeOption(type="radio", value="paypal", ng-model="paymentMethod") - img(src="/recurly/images/paypal_large.png") + i.fa.fa-cc-paypal.fa-3x + + .alert.alert-warning.small(ng-show="genericError") strong {{genericError}} diff --git a/services/web/public/stylesheets/app/plans.less b/services/web/public/stylesheets/app/plans.less index e74755a266..3f7d6c2fae 100644 --- a/services/web/public/stylesheets/app/plans.less +++ b/services/web/public/stylesheets/app/plans.less @@ -97,7 +97,7 @@ } input.paymentTypeOption.ng-valid { - margin-top: 10px; + margin-top: 15px; } .totalPrice { From d678af4417f3fd2a134b59f4bcd9497489acfa33 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Dec 2014 22:19:15 +0000 Subject: [PATCH 30/34] only validate credit card an cvv if there is data in them --- services/web/app/views/subscriptions/new.jade | 6 +++--- .../web/public/coffee/main/new-subscription.coffee | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 65265e15a1..36cbefc310 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -69,8 +69,8 @@ block content .row .col-md-12 .form-group - div(ng-hide="validation.correctCvv") #{translate("invalid")} CVV - div(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} + div.alert.alert-warning.small(ng-hide="validation.correctCvv") #{translate("invalid")} CVV + div.alert.alert-warning.small(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} .row .col-md-6 .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") @@ -80,7 +80,7 @@ block content input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") .row .col-md-12 - div(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} + div.alert.alert-warning.small(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} .col-md-2 .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 4202308ce3..7b3cf0e55e 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -15,10 +15,10 @@ define [ $scope.paymentMethod = "credit_card" $scope.data = - number: "" + number: undefined month: undefined year: undefined - cvv: "" + cvv: undefined first_name: "" last_name: "" postal_code: "" @@ -57,14 +57,16 @@ define [ pricing.currency(newCurrency).done() $scope.validateCardNumber = -> - $scope.validation.correctCardNumber = recurly.validate.cardNumber($scope.data.number) + if $scope.data.number? + $scope.validation.correctCardNumber = recurly.validate.cardNumber($scope.data.number) $scope.validateExpiry = -> if $scope.data.month? and $scope.data.year? $scope.validation.correctExpiry = recurly.validate.expiry($scope.data.month, $scope.data.year) $scope.validateCvv = -> - $scope.validation.correctCvv = recurly.validate.cvv($scope.data.cvv) + if $scope.data.cvv? + $scope.validation.correctCvv = recurly.validate.cvv($scope.data.cvv) $scope.changePaymentMethod = (paymentMethod)-> if paymentMethod == "paypal" From f9843b3709a106a1bdde820f2c71210519a7ec68 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 7 Jan 2015 13:16:19 +0000 Subject: [PATCH 31/34] tax auto updates on change of address now. Is also preset based on users ip address --- .../SubscriptionController.coffee | 3 +- .../coffee/infrastructure/GeoIpLookup.coffee | 2 +- services/web/app/views/subscriptions/new.jade | 206 +++++++++--------- .../coffee/main/new-subscription.coffee | 10 +- 4 files changed, 115 insertions(+), 106 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee index 5821a09d9c..b7d948a47c 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee @@ -41,7 +41,7 @@ module.exports = SubscriptionController = res.redirect "/user/subscription" else currency = req.query.currency?.toUpperCase() - GeoIpLookup.getCurrencyCode req.query?.ip || req.ip, (err, recomendedCurrency)-> + GeoIpLookup.getCurrencyCode req.query?.ip || req.ip, (err, recomendedCurrency, countryCode)-> return next(err) if err? if recomendedCurrency? and !currency? currency = recomendedCurrency @@ -56,6 +56,7 @@ module.exports = SubscriptionController = title : "subscribe" plan_code: req.query.planCode currency: currency + countryCode:countryCode plan:plan showStudentPlan: req.query.ssp recurlyConfig: JSON.stringify diff --git a/services/web/app/coffee/infrastructure/GeoIpLookup.coffee b/services/web/app/coffee/infrastructure/GeoIpLookup.coffee index a49627d0cb..5b64b8e6f4 100644 --- a/services/web/app/coffee/infrastructure/GeoIpLookup.coffee +++ b/services/web/app/coffee/infrastructure/GeoIpLookup.coffee @@ -48,4 +48,4 @@ module.exports = GeoIpLookup = countryCode = ipDetails?.country_code?.toUpperCase() currencyCode = currencyMappings[countryCode] || "USD" logger.log ip:ip, currencyCode:currencyCode, ipDetails:ipDetails, "got currencyCode for ip" - callback(err, currencyCode) \ No newline at end of file + callback(err, currencyCode, countryCode) \ No newline at end of file diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index 36cbefc310..e82c56635c 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -5,6 +5,7 @@ block scripts script(type='text/javascript'). window.recomendedCurrency = '#{currency}' + window.countryCode = '#{countryCode}' window.plan_code = '#{plan_code}' window.recurlyApiKey = "!{settings.apis.recurly.publicKey}" @@ -38,117 +39,122 @@ block content a( ng-click="changeCurrency(currency)", ) {{currency}} ({{value['symbol']}}) - h2.pull-right.totalPrice {{price}} - hr - .row - .col-md-offset-1.col-md-10 - form(ng-show="planName") - + h2.pull-right.totalPrice {{price.currency.symbol}}{{price.next.total}} + .row + .col-md-12 + form(ng-show="planName") + + .row + .col-md-12 + .form-group + .row + .col-md-6 + label.radio-inline + input.paymentTypeOption(type="radio",value="credit_card", ng-model="paymentMethod") + i.fa.fa-cc-mastercard.fa-3x + span   + i.fa.fa-cc-visa.fa-3x + .col-md-6 + label.radio-inline + input.paymentTypeOption(type="radio", value="paypal", ng-model="paymentMethod") + i.fa.fa-cc-paypal.fa-3x + + + + .alert.alert-warning.small(ng-show="genericError") + strong {{genericError}} + + span(ng-hide="paymentMethod == 'paypal'") .row .col-md-12 .form-group - .row - .col-md-6 - label.radio-inline - input.paymentTypeOption(type="radio",value="credit_card", ng-model="paymentMethod") - i.fa.fa-cc-mastercard.fa-3x - span   - i.fa.fa-cc-visa.fa-3x - .col-md-6 - label.radio-inline - input.paymentTypeOption(type="radio", value="paypal", ng-model="paymentMethod") - i.fa.fa-cc-paypal.fa-3x - - - - .alert.alert-warning.small(ng-show="genericError") - strong {{genericError}} - - span(ng-hide="paymentMethod == 'paypal'") - .row - .col-md-12 - .form-group - div.alert.alert-warning.small(ng-hide="validation.correctCvv") #{translate("invalid")} CVV - div.alert.alert-warning.small(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} - .row - .col-md-6 - .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") - input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") - .col-md-3 - .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") - input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") - .row - .col-md-12 - div.alert.alert-warning.small(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} - .col-md-2 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') - option(value="", disabled, selected) Month - option(value="01") 01 - option(value="02") 02 - option(value="03") 03 - option(value="04") 04 - option(value="05") 05 - option(value="06") 06 - option(value="07") 07 - option(value="08") 08 - option(value="09") 09 - option(value="10") 10 - option(value="11") 11 - option(value="12") 12 - .col-md-3 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') - option(value="", disabled, selected) Year - option(value="2015") 2015 - option(value="2016") 2016 - option(value="2017") 2017 - option(value="2018") 2018 - option(value="2019") 2019 - option(value="2020") 2020 - option(value="2021") 2021 - option(value="2022") 2022 - option(value="2023") 2023 - option(value="2024") 2024 - option(value="2025") 2025 - option(value="2026") 2026 + div.alert.alert-warning.small(ng-hide="validation.correctCvv") #{translate("invalid")} CVV + div.alert.alert-warning.small(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} .row .col-md-6 - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}") - .col-md-6 - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}") - hr + .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") + input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") + .col-md-3 + .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") + input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") .row .col-md-12 + div.alert.alert-warning.small(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} + .col-md-2 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') + option(value="", disabled, selected) Month + option(value="01") 01 + option(value="02") 02 + option(value="03") 03 + option(value="04") 04 + option(value="05") 05 + option(value="06") 06 + option(value="07") 07 + option(value="08") 08 + option(value="09") 09 + option(value="10") 10 + option(value="11") 11 + option(value="12") 12 + .col-md-3 + .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") + select(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') + option(value="", disabled, selected) Year + option(value="2015") 2015 + option(value="2016") 2016 + option(value="2017") 2017 + option(value="2018") 2018 + option(value="2019") 2019 + option(value="2020") 2020 + option(value="2021") 2021 + option(value="2022") 2022 + option(value="2023") 2023 + option(value="2024") 2024 + option(value="2025") 2025 + option(value="2026") 2026 + .row + .col-md-6 + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}") + .col-md-6 + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}") + hr + .row + .col-md-12 + .form-group + label #{translate("billing_address")} + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1", placeholder="#{translate('address')}") + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2", placeholder="#{translate('address')}") + .row + .col-md-7 + .form-group + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}") + .col-md-5 + input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}") + .row + .col-md-7 + .form-group + select.form-control(data-recurly="country", ng-model="data.country", ng-change="updateCountry()",required) + mixin countries_options() + .row + .col-md-8 + if showCouponField == 'true' .form-group - label #{translate("billing_address")} - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address1", placeholder="#{translate('address')}") - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', ng-model="data.address2", placeholder="#{translate('address')}") - .row - .col-md-7 - .form-group - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}") - .col-md-5 - input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}") - .row - .col-md-7 - .form-group - select.form-control(data-recurly="country", ng-model="data.country", required) - mixin countries_options() - .row - .col-md-8 - if showCouponField == 'true' - .form-group - input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") - - .form-group - button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} + input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") + .form-group + button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} + .row + .col-md-12 + span.pull-right + div Subtotal - {{price.currency.symbol}}{{price.next.subtotal}} + div Tax - {{price.currency.symbol}}{{price.next.tax}} + div + strong Total - {{price.currency.symbol}}{{price.next.total}} diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 7b3cf0e55e..cac4ccfae5 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -25,7 +25,7 @@ define [ address1 : "" address2 : "" city:"" - country:"" + country:window.countryCode $scope.validation = correctCardNumber : true @@ -39,12 +39,11 @@ define [ pricing = recurly.Pricing() window.pricing = pricing - pricing.plan(window.plan_code, { quantity: 1 }).currency($scope.currencyCode).done() - + pricing.plan(window.plan_code, { quantity: 1 }).address({country: $scope.data.country}).tax({tax_code: 'digital', vat_number: ''}).currency($scope.currencyCode).done() pricing.on "change", => $scope.planName = pricing.items.plan.name - $scope.price = pricing.price.currency.symbol+pricing.price.next.total + $scope.price = pricing.price $scope.trialLength = pricing.items.plan.trial.length $scope.billingCycleType = if pricing.items.plan.period.interval == "months" then "month" else "year" $scope.$apply() @@ -68,6 +67,9 @@ define [ if $scope.data.cvv? $scope.validation.correctCvv = recurly.validate.cvv($scope.data.cvv) + $scope.updateCountry = -> + pricing.address({country:$scope.data.country}).done() + $scope.changePaymentMethod = (paymentMethod)-> if paymentMethod == "paypal" $scope.usePaypal = true From 5d6a96ba4f49ffd788cfc4d4b28fb01f15a19e37 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 7 Jan 2015 14:51:54 +0000 Subject: [PATCH 32/34] made form thinner --- services/web/app/views/subscriptions/new.jade | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index e82c56635c..bf730024e3 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -18,7 +18,7 @@ block content .content.content-alt .container(ng-controller="NewSubscriptionController" ng-cloak) .row.card-group - .col-md-6.col-md-push-3 + .col-md-5.col-md-push-4 .card.card-highlighted .page-header .row @@ -158,12 +158,7 @@ block content - - - - - - .col-md-3.col-md-pull-6 + .col-md-3.col-md-pull-4 if showStudentPlan == 'true' a.btn-primary.btn.plansPageStudentLink( href, From f6e9c544e68da69e463a9a855490db1ed86e93d1 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 7 Jan 2015 14:59:56 +0000 Subject: [PATCH 33/34] slightly improved the breakdown form. Still not very pretty. --- services/web/app/views/subscriptions/new.jade | 21 ++++++++++++------- .../web/public/stylesheets/app/plans.less | 4 +++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index bf730024e3..b4f5f8e279 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -145,17 +145,22 @@ block content .form-group input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}") - .form-group - button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} .row - .col-md-12 - span.pull-right - div Subtotal - {{price.currency.symbol}}{{price.next.subtotal}} - div Tax - {{price.currency.symbol}}{{price.next.tax}} + .col-md-6 + .form-group + button.btn.btn-success(ng-click="submit()", ng-disabled="processing") #{translate("upgrade_now")} + + .col-md-3.pricingBreakdown + div Subtotal + div Tax div - strong Total - {{price.currency.symbol}}{{price.next.total}} - + strong Total + .col-md-3 + div {{price.currency.symbol}}{{price.next.subtotal}} + div {{price.currency.symbol}}{{price.next.tax}} + div + strong {{price.currency.symbol}}{{price.next.total}} .col-md-3.col-md-pull-4 diff --git a/services/web/public/stylesheets/app/plans.less b/services/web/public/stylesheets/app/plans.less index 3f7d6c2fae..c375052394 100644 --- a/services/web/public/stylesheets/app/plans.less +++ b/services/web/public/stylesheets/app/plans.less @@ -104,6 +104,8 @@ input.paymentTypeOption.ng-valid { padding-top: 15px; } - +.pricingBreakdown { + text-align: right; +} From 7508ba6c47fbe36bd6f78551d02dceb9919cf1f9 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 7 Jan 2015 16:43:20 +0000 Subject: [PATCH 34/34] improved validation so that fields recurly said are wrong get highlighted --- services/web/app/views/subscriptions/new.jade | 21 +++++++++-------- .../coffee/main/new-subscription.coffee | 23 +++++++++++-------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/services/web/app/views/subscriptions/new.jade b/services/web/app/views/subscriptions/new.jade index b4f5f8e279..53ade84a71 100644 --- a/services/web/app/views/subscriptions/new.jade +++ b/services/web/app/views/subscriptions/new.jade @@ -73,17 +73,18 @@ block content div.alert.alert-warning.small(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")} .row .col-md-6 - .form-group(ng-class="validation.correctCardNumber ? '' : 'has-error' ") + .form-group(ng-class="validation.number == false || validation.errorFields.number ? 'has-error' : ''") input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}") .col-md-3 - .form-group(ng-class="validation.correctCvv ? '' : 'has-error' ") + .form-group(ng-class="validation.correctCvv == false || validation.errorFields.cvv ? 'has-error' : ''") input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV") .row .col-md-12 div.alert.alert-warning.small(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")} - .col-md-2 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') + .row + .col-md-3 + .form-group(ng-class="validation.correctExpiry == false || validation.errorFields.month ? 'has-error' : ''") + select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month') option(value="", disabled, selected) Month option(value="01") 01 option(value="02") 02 @@ -98,8 +99,8 @@ block content option(value="11") 11 option(value="12") 12 .col-md-3 - .form-group(ng-class="validation.correctExpiry ? '' : 'has-error' ") - select(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') + .form-group(ng-class="validation.correctExpiry == false || validation.errorFields.year ? 'has-error' : ''") + select.form-control(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year') option(value="", disabled, selected) Year option(value="2015") 2015 option(value="2016") 2016 @@ -115,10 +116,10 @@ block content option(value="2026") 2026 .row .col-md-6 - .form-group + .form-group(ng-class="validation.errorFields.first_name ? 'has-error' : ''") input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}") .col-md-6 - .form-group + .form-group(ng-class="validation.errorFields.last_name ? 'has-error' : ''") input.form-control(type='text', value='', maxlength='255', tabindex='1', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}") hr .row @@ -137,7 +138,7 @@ block content .row .col-md-7 .form-group - select.form-control(data-recurly="country", ng-model="data.country", ng-change="updateCountry()",required) + select.form-control(data-recurly="country", ng-model="data.country", ng-change="updateCountry()", required) mixin countries_options() .row .col-md-8 diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index cac4ccfae5..d7e792bebf 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -15,10 +15,10 @@ define [ $scope.paymentMethod = "credit_card" $scope.data = - number: undefined - month: undefined - year: undefined - cvv: undefined + number: "" + month: "" + year: "" + cvv: "" first_name: "" last_name: "" postal_code: "" @@ -27,6 +27,7 @@ define [ city:"" country:window.countryCode + $scope.validation = correctCardNumber : true correctExpiry: true @@ -55,16 +56,16 @@ define [ $scope.currencyCode = newCurrency pricing.currency(newCurrency).done() - $scope.validateCardNumber = -> - if $scope.data.number? + $scope.validateCardNumber = validateCardNumber = -> + if $scope.data.number?.length != 0 $scope.validation.correctCardNumber = recurly.validate.cardNumber($scope.data.number) - $scope.validateExpiry = -> - if $scope.data.month? and $scope.data.year? + $scope.validateExpiry = validateExpiry = -> + if $scope.data.month?.length != 0 and $scope.data.year?.length != 0 $scope.validation.correctExpiry = recurly.validate.expiry($scope.data.month, $scope.data.year) - $scope.validateCvv = -> - if $scope.data.cvv? + $scope.validateCvv = validateCvv = -> + if $scope.data.cvv?.length != 0 $scope.validation.correctCvv = recurly.validate.cvv($scope.data.cvv) $scope.updateCountry = -> @@ -77,8 +78,10 @@ define [ $scope.usePaypal = false completeSubscription = (err, recurly_token_id) -> + $scope.validation.errorFields = {} if err? $scope.genericError = err.message + _.each err.fields, (field)-> $scope.validation.errorFields[field] = true else postData = _csrf: window.csrfToken