ducky/web
21:bc1478742a50 Browse Files
Implement subscriptions. Create a Subscription model and a Subscriptions collection, and attach them to the app context. Add a helper to our Profile model to retrieve the Subscription of that model. Still not sure this should be on the Profile--wouldn't it be better on the Me model? Isn't that generally where we would need it?
src/main.js src/models/profile.js src/models/subscription.js src/models/subscriptions.js
1.1 --- a/src/main.js Tue Jul 07 21:25:49 2015 -0400 1.2 +++ b/src/main.js Tue Jul 07 21:29:19 2015 -0400 1.3 @@ -1,6 +1,7 @@ 1.4 import app from 'ampersand-app' 1.5 import Router from './router' 1.6 import Profiles from './models/profiles' 1.7 +import Subscriptions from './models/subscriptions' 1.8 import Me from './models/me' 1.9 import normalize from 'normalize.css/normalize.css' 1.10 import styles from './styles/main.scss' 1.11 @@ -8,10 +9,11 @@ 1.12 window.app = app.extend({ 1.13 init () { 1.14 this.profiles = new Profiles() 1.15 + this.subscriptions = new Subscriptions() 1.16 this.me = new Me().load() 1.17 this.me.on('change', this.me.debouncedWriteToCache) 1.18 this.router = new Router() 1.19 - this.router.history.start({ pushState: true }) 1.20 + this.router.history.start() 1.21 } 1.22 }) 1.23
2.1 --- a/src/models/profile.js Tue Jul 07 21:25:49 2015 -0400 2.2 +++ b/src/models/profile.js Tue Jul 07 21:29:19 2015 -0400 2.3 @@ -23,4 +23,16 @@ 2.4 } 2.5 } 2.6 }, 2.7 + 2.8 + subscription() { 2.9 + return new Promise((resolve, reject) => { 2.10 + app.subscriptions.getOrFetch(this.id, (err, model) => { 2.11 + if (err) { 2.12 + reject(err) 2.13 + } else { 2.14 + resolve(model) 2.15 + } 2.16 + }) 2.17 + }) 2.18 + }, 2.19 })
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/models/subscription.js Tue Jul 07 21:29:19 2015 -0400 3.3 @@ -0,0 +1,47 @@ 3.4 +import Model from 'ampersand-model' 3.5 +import refresh from '../helpers/oauth-refresh' 3.6 + 3.7 +export default Model.extend({ 3.8 + props: { 3.9 + 'userID': 'string', 3.10 + 'stripe_subscription': 'string', 3.11 + 'plan': 'string', 3.12 + 'status': 'string', 3.13 + 'canceling': 'boolean', 3.14 + 'created': 'date', 3.15 + 'trialStart': 'date', 3.16 + 'trialEnd': 'date', 3.17 + 'periodStart': 'date', 3.18 + 'periodEnd': 'date', 3.19 + 'canceledAt': 'date', 3.20 + 'failedChargeAttempts': 'integer', 3.21 + 'lastFailedCharge': 'date', 3.22 + 'lastNotified': 'date', 3.23 + }, 3.24 + idAttribute: 'userID', 3.25 + sync: refresh.Sync, 3.26 + parse (attrs) { 3.27 + if (attrs.subscriptions && attrs.subscriptions.length == 1) { 3.28 + attrs = attrs.subscriptions[0] 3.29 + } 3.30 + attrs.userID = attrs.user_id 3.31 + attrs.stripeSubscription = attrs.stripeSubscription 3.32 + attrs.trialStart = attrs.trial_start 3.33 + attrs.trialEnd = attrs.trial_end 3.34 + attrs.periodStart = attrs.period_start 3.35 + attrs.periodEnd = attrs.period_end 3.36 + attrs.canceledAt = attrs.canceled_at 3.37 + attrs.failedChargeAttempts = attrs.failed_charge_attempts 3.38 + attrs.lastFailedCharge = attrs.last_failed_charge 3.39 + attrs.lastNotified = attrs.last_notified 3.40 + return attrs 3.41 + }, 3.42 + ajaxConfig () { 3.43 + return { 3.44 + headers: { 3.45 + 'Authorization': 'Bearer '+app.me.access_token, 3.46 + 'Accept': 'application/json', 3.47 + } 3.48 + } 3.49 + }, 3.50 +})
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/models/subscriptions.js Tue Jul 07 21:29:19 2015 -0400 4.3 @@ -0,0 +1,46 @@ 4.4 +import Collection from 'ampersand-rest-collection' 4.5 +import Subscription from './subscription' 4.6 +import config from '../config' 4.7 +import refresh from '../helpers/oauth-refresh' 4.8 +import app from 'ampersand-app' 4.9 +import isObject from 'lodash.isobject' 4.10 + 4.11 +export default Collection.extend({ 4.12 + model: Subscription, 4.13 + url: config.urlBase + '/subscriptions/subscriptions', 4.14 + ajaxConfig () { 4.15 + return { 4.16 + headers: { 4.17 + 'Authorization': 'Bearer '+app.me.access_token, 4.18 + 'Accept': 'application/json', 4.19 + } 4.20 + } 4.21 + }, 4.22 + 4.23 + sync: refresh.Sync, 4.24 + 4.25 + create (params) { 4.26 + let options = { 4.27 + data: JSON.stringify({ 4.28 + 'user_id': params.user_id, 4.29 + 'email': params.email, 4.30 + 'stripe_token': params.stripe_token, 4.31 + 'plan': params.plan, 4.32 + }), 4.33 + } 4.34 + let moc = this 4.35 + options.success = function(resp) { 4.36 + let serverAttrs = moc.parse(resp, options) 4.37 + if (options.wait) serverAttrs = assign({}, serverAttrs) 4.38 + if (isObject(serverAttrs) && !moc.set(serverAttrs, options)) { 4.39 + // TODO: throw error? 4.40 + return 4.41 + } 4.42 + moc.trigger('sync', moc, resp, options) 4.43 + } 4.44 + options.error = function(resp) { 4.45 + moc.trigger('error', moc, resp, options) 4.46 + } 4.47 + refresh.Sync('create', moc, options) 4.48 + } 4.49 +})