subscription-dashboard.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import _ from 'lodash'
  2. /* global recurly */
  3. /* eslint-disable
  4. camelcase,
  5. max-len,
  6. no-return-assign,
  7. no-unused-vars,
  8. */
  9. // TODO: This file was created by bulk-decaffeinate.
  10. // Fix any style issues and re-enable lint.
  11. /*
  12. * decaffeinate suggestions:
  13. * DS102: Remove unnecessary code created because of implicit returns
  14. * DS104: Avoid inline assignments
  15. * DS204: Change includes calls to have a more natural evaluation order
  16. * DS207: Consider shorter variations of null checks
  17. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  18. */
  19. import App from '../base'
  20. const SUBSCRIPTION_URL = '/user/subscription/update'
  21. const ensureRecurlyIsSetup = _.once(() => {
  22. if (typeof recurly === 'undefined' || !recurly) {
  23. return false
  24. }
  25. recurly.configure(window.recurlyApiKey)
  26. return true
  27. })
  28. App.controller('MetricsEmailController', function($scope, $http) {
  29. $scope.institutionEmailSubscription = function(institutionId) {
  30. var inst = _.find(window.managedInstitutions, function(institution) {
  31. return institution.v1Id === parseInt(institutionId)
  32. })
  33. if (inst.metricsEmail.optedOutUserIds.includes(window.user_id)) {
  34. return 'Subscribe'
  35. } else {
  36. return 'Unsubscribe'
  37. }
  38. }
  39. $scope.changeInstitutionalEmailSubscription = function(institutionId) {
  40. $scope.subscriptionChanging = true
  41. return $http({
  42. method: 'POST',
  43. url: `/institutions/${institutionId}/emailSubscription`,
  44. headers: {
  45. 'X-CSRF-Token': window.csrfToken
  46. }
  47. }).then(function successCallback(response) {
  48. window.managedInstitutions = _.map(window.managedInstitutions, function(
  49. institution
  50. ) {
  51. if (institution.v1Id === parseInt(institutionId)) {
  52. institution.metricsEmail.optedOutUserIds = response.data
  53. }
  54. return institution
  55. })
  56. $scope.subscriptionChanging = false
  57. })
  58. }
  59. })
  60. App.factory('RecurlyPricing', function($q, MultiCurrencyPricing) {
  61. return {
  62. loadDisplayPriceWithTax: function(planCode, currency, taxRate) {
  63. if (!ensureRecurlyIsSetup()) return
  64. const currencySymbol = MultiCurrencyPricing.plans[currency].symbol
  65. const pricing = recurly.Pricing()
  66. return $q(function(resolve, reject) {
  67. pricing
  68. .plan(planCode, { quantity: 1 })
  69. .currency(currency)
  70. .done(function(price) {
  71. const totalPriceExTax = parseFloat(price.next.total)
  72. let taxAmmount = totalPriceExTax * taxRate
  73. if (isNaN(taxAmmount)) {
  74. taxAmmount = 0
  75. }
  76. let total = totalPriceExTax + taxAmmount
  77. if (total % 1 !== 0) {
  78. total = total.toFixed(2)
  79. }
  80. resolve(`${currencySymbol}${total}`)
  81. })
  82. })
  83. }
  84. }
  85. })
  86. App.controller('ChangePlanFormController', function(
  87. $scope,
  88. $modal,
  89. RecurlyPricing
  90. ) {
  91. if (!ensureRecurlyIsSetup()) return
  92. $scope.changePlan = () =>
  93. $modal.open({
  94. templateUrl: 'confirmChangePlanModalTemplate',
  95. controller: 'ConfirmChangePlanController',
  96. scope: $scope
  97. })
  98. $scope.$watch('plan', function(plan) {
  99. if (!plan) return
  100. const planCode = plan.planCode
  101. const { currency, taxRate } = window.subscription.recurly
  102. $scope.price = '...' // Placeholder while we talk to recurly
  103. RecurlyPricing.loadDisplayPriceWithTax(planCode, currency, taxRate).then(
  104. price => {
  105. $scope.price = price
  106. }
  107. )
  108. })
  109. })
  110. App.controller('ConfirmChangePlanController', function(
  111. $scope,
  112. $modalInstance,
  113. $http
  114. ) {
  115. $scope.confirmChangePlan = function() {
  116. const body = {
  117. plan_code: $scope.plan.planCode,
  118. _csrf: window.csrfToken
  119. }
  120. $scope.inflight = true
  121. return $http
  122. .post(`${SUBSCRIPTION_URL}?origin=confirmChangePlan`, body)
  123. .then(() => location.reload())
  124. .catch(() => console.log('something went wrong changing plan'))
  125. }
  126. return ($scope.cancel = () => $modalInstance.dismiss('cancel'))
  127. })
  128. App.controller('LeaveGroupModalController', function(
  129. $scope,
  130. $modalInstance,
  131. $http
  132. ) {
  133. $scope.confirmLeaveGroup = function() {
  134. $scope.inflight = true
  135. return $http({
  136. url: '/subscription/group/user',
  137. method: 'DELETE',
  138. params: { admin_user_id: $scope.admin_id, _csrf: window.csrfToken }
  139. })
  140. .then(() => location.reload())
  141. .catch(() => console.log('something went wrong changing plan'))
  142. }
  143. return ($scope.cancel = () => $modalInstance.dismiss('cancel'))
  144. })
  145. App.controller('GroupMembershipController', function($scope, $modal) {
  146. $scope.removeSelfFromGroup = function(admin_id) {
  147. $scope.admin_id = admin_id
  148. return $modal.open({
  149. templateUrl: 'LeaveGroupModalTemplate',
  150. controller: 'LeaveGroupModalController',
  151. scope: $scope
  152. })
  153. }
  154. })
  155. App.controller('RecurlySubscriptionController', function($scope) {
  156. const recurlyIsSetup = ensureRecurlyIsSetup()
  157. $scope.showChangePlanButton = recurlyIsSetup && !window.subscription.groupPlan
  158. $scope.recurlyLoadError = !recurlyIsSetup
  159. $scope.switchToDefaultView = () => {
  160. $scope.showCancellation = false
  161. $scope.showChangePlan = false
  162. }
  163. $scope.switchToDefaultView()
  164. $scope.switchToCancellationView = () => {
  165. $scope.showCancellation = true
  166. $scope.showChangePlan = false
  167. }
  168. $scope.switchToChangePlanView = () => {
  169. $scope.showCancellation = false
  170. $scope.showChangePlan = true
  171. }
  172. })
  173. App.controller('RecurlyCancellationController', function(
  174. $scope,
  175. RecurlyPricing,
  176. $http
  177. ) {
  178. if (!ensureRecurlyIsSetup()) return
  179. const subscription = window.subscription
  180. const sevenDaysTime = new Date()
  181. sevenDaysTime.setDate(sevenDaysTime.getDate() + 7)
  182. const freeTrialEndDate = new Date(subscription.recurly.trial_ends_at)
  183. const freeTrialInFuture = freeTrialEndDate > new Date()
  184. const freeTrialExpiresUnderSevenDays = freeTrialEndDate < sevenDaysTime
  185. const isMonthlyCollab =
  186. subscription.plan.planCode.indexOf('collaborator') !== -1 &&
  187. subscription.plan.planCode.indexOf('ann') === -1 &&
  188. !subscription.groupPlan
  189. const stillInFreeTrial = freeTrialInFuture && freeTrialExpiresUnderSevenDays
  190. if (isMonthlyCollab && stillInFreeTrial) {
  191. $scope.showExtendFreeTrial = true
  192. } else if (isMonthlyCollab && !stillInFreeTrial) {
  193. $scope.showDowngradeToStudent = true
  194. } else {
  195. $scope.showBasicCancel = true
  196. }
  197. const { currency, taxRate } = window.subscription.recurly
  198. $scope.studentPrice = '...' // Placeholder while we talk to recurly
  199. RecurlyPricing.loadDisplayPriceWithTax('student', currency, taxRate).then(
  200. price => {
  201. $scope.studentPrice = price
  202. }
  203. )
  204. $scope.downgradeToStudent = function() {
  205. const body = {
  206. plan_code: 'student',
  207. _csrf: window.csrfToken
  208. }
  209. $scope.inflight = true
  210. return $http
  211. .post(`${SUBSCRIPTION_URL}?origin=downgradeToStudent`, body)
  212. .then(() => location.reload())
  213. .catch(() => console.log('something went wrong changing plan'))
  214. }
  215. $scope.cancelSubscription = function() {
  216. const body = { _csrf: window.csrfToken }
  217. $scope.inflight = true
  218. return $http
  219. .post('/user/subscription/cancel', body)
  220. .then(() => (location.href = '/user/subscription/canceled'))
  221. .catch(() => console.log('something went wrong changing plan'))
  222. }
  223. $scope.extendTrial = function() {
  224. const body = { _csrf: window.csrfToken }
  225. $scope.inflight = true
  226. return $http
  227. .put('/user/subscription/extend', body)
  228. .then(() => location.reload())
  229. .catch(() => console.log('something went wrong changing plan'))
  230. }
  231. })