ducky/web
ducky/web/src/models/me.js
Update to use plans instead of PWYW. If we're going to lean on Stripe for most of our subscription processing, we need to use plans, instead of pay what you want. This updates the page to replace our amount input with a plan select box. It also removes the nonsense about finding your first charge date, because Stripe forced us into a simpler, but harder to predict, billing model. We also updated our CSS to work with select boxes, as well as text inputs.
| paddy@0 | 1 import Model from 'ampersand-model' |
| paddy@0 | 2 import Sync from 'ampersand-sync' |
| paddy@0 | 3 import qs from 'qs' |
| paddy@0 | 4 import config from '../config' |
| paddy@0 | 5 import isObject from 'lodash.isobject' |
| paddy@2 | 6 import jwtDecode from 'jwt-decode' |
| paddy@0 | 7 |
| paddy@0 | 8 export default Model.extend({ |
| paddy@0 | 9 url: config.urlBase + '/token', |
| paddy@0 | 10 ajaxConfig: { |
| paddy@0 | 11 headers: { |
| paddy@0 | 12 'Content-Type': 'application/x-www-form-urlencoded', |
| paddy@0 | 13 'Authorization': 'Basic ' + btoa(config.clientID + ':' + config.clientSecret), |
| paddy@0 | 14 } |
| paddy@0 | 15 }, |
| paddy@0 | 16 |
| paddy@0 | 17 props: { |
| paddy@0 | 18 access_token: 'string', |
| paddy@0 | 19 refresh_token: 'string', |
| paddy@0 | 20 expires_in: 'int', |
| paddy@0 | 21 token_created: 'date', |
| paddy@0 | 22 name: 'string', |
| paddy@2 | 23 profileID: 'string', |
| paddy@0 | 24 }, |
| paddy@0 | 25 |
| paddy@0 | 26 derived: { |
| paddy@0 | 27 loggedIn () { |
| paddy@0 | 28 return !!this.access_token |
| paddy@0 | 29 }, |
| paddy@0 | 30 needsRefresh () { |
| paddy@0 | 31 let d = this.token_created |
| paddy@0 | 32 return !!this.refresh_token && (new Date() >= d.setSeconds(d.getSeconds() + this.expires_in - 900)) |
| paddy@0 | 33 }, |
| paddy@2 | 34 profile: { |
| paddy@2 | 35 deps: ['profileID'], |
| paddy@2 | 36 fn () { |
| paddy@2 | 37 return app.profiles.get(this.profileID) |
| paddy@2 | 38 }, |
| paddy@2 | 39 }, |
| paddy@0 | 40 }, |
| paddy@0 | 41 |
| paddy@0 | 42 login (email, password) { |
| paddy@0 | 43 let options = { |
| paddy@0 | 44 data: qs.stringify({ |
| paddy@0 | 45 'username': email, |
| paddy@0 | 46 'password': password, |
| paddy@0 | 47 'grant_type': 'password', |
| paddy@0 | 48 }), |
| paddy@0 | 49 } |
| paddy@0 | 50 let moc = this |
| paddy@0 | 51 options.success = function(resp) { |
| paddy@0 | 52 if (!resp.access_token) { |
| paddy@0 | 53 return false |
| paddy@0 | 54 } |
| paddy@0 | 55 let serverAttrs = moc.parse(resp, options) |
| paddy@0 | 56 serverAttrs.token_created = new Date() |
| paddy@0 | 57 console.log(serverAttrs) |
| paddy@0 | 58 if (options.wait) serverAttrs = assign({}, serverAttrs) |
| paddy@0 | 59 if (isObject(serverAttrs) && !moc.set(serverAttrs, options)) { |
| paddy@0 | 60 return false |
| paddy@0 | 61 } |
| paddy@2 | 62 const token = jwtDecode(moc.access_token) |
| paddy@2 | 63 moc.profileID = token.sub |
| paddy@0 | 64 moc.trigger('sync', moc, resp, options) |
| paddy@0 | 65 } |
| paddy@0 | 66 options.error = function(resp) { |
| paddy@0 | 67 moc.trigger('error', moc, resp, options) |
| paddy@0 | 68 } |
| paddy@0 | 69 let sync = Sync('create', moc, options) |
| paddy@0 | 70 }, |
| paddy@0 | 71 |
| paddy@0 | 72 writeToCache () { |
| paddy@0 | 73 // TODO: write this to chrome.storage.local |
| paddy@0 | 74 }, |
| paddy@0 | 75 |
| paddy@0 | 76 logout () { |
| paddy@0 | 77 // TODO: clear all cached data |
| paddy@0 | 78 }, |
| paddy@0 | 79 |
| paddy@0 | 80 }) |