Convert js to ES6+
This commit is contained in:
Родитель
c1424a05c0
Коммит
aab26f1680
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
export function error(debugMessage) {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
import $ from 'jquery';
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
// TODO: expand these actions to encapsulate the Ajax
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
'use strict';
|
||||
import $ from 'jquery';
|
||||
|
||||
var $ = require('jquery');
|
||||
|
||||
var appActions = require('./app');
|
||||
var actionTypes = require('constants/action-types');
|
||||
import * as appActions from './app';
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
|
||||
export function signIn(accessToken) {
|
||||
export function signIn(accessToken, jquery=$) {
|
||||
return function(dispatch) {
|
||||
$.ajax({
|
||||
jquery.ajax({
|
||||
data: {
|
||||
access_token: accessToken,
|
||||
},
|
||||
|
@ -19,7 +17,7 @@ export function signIn(accessToken) {
|
|||
|
||||
console.log('setting CSRF token for subsequent requests:',
|
||||
data.csrf_token);
|
||||
$.ajaxSetup({
|
||||
jquery.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRFToken': data.csrf_token,
|
||||
},
|
||||
|
|
|
@ -1,35 +1,28 @@
|
|||
'use strict';
|
||||
import 'shims';
|
||||
|
||||
require('shims');
|
||||
import React, { Component } from 'react';
|
||||
import { Provider, Connector } from 'redux/react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
var React = require('react');
|
||||
var Provider = require('redux/react').Provider;
|
||||
var Connector = require('redux/react').Connector;
|
||||
var bindActionCreators = require('redux').bindActionCreators;
|
||||
import reduxConfig from 'redux-config';
|
||||
import * as managementActions from 'actions/management';
|
||||
|
||||
var reduxConfig = require('redux-config');
|
||||
var managementActions = require('actions/management');
|
||||
|
||||
var ModalError = require('views/modal-error');
|
||||
var Management = require('views/management');
|
||||
var ManageCards = require('views/manage-cards');
|
||||
import ModalError from 'views/modal-error';
|
||||
import Management from 'views/management';
|
||||
import ManageCards from 'views/manage-cards';
|
||||
|
||||
|
||||
export default class ManagementApp extends Component {
|
||||
|
||||
var App = React.createClass({
|
||||
|
||||
displayName: 'ManagementApp',
|
||||
|
||||
selectData: function(state) {
|
||||
selectData(state) {
|
||||
return {
|
||||
management: state.management,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
renderChild(connector) {
|
||||
var actions = bindActionCreators(managementActions, connector.dispatch);
|
||||
var children = [];
|
||||
|
||||
if (connector.management.error) {
|
||||
children.push(
|
||||
<ModalError {...actions} error={connector.management.error} />
|
||||
|
@ -42,9 +35,9 @@ var App = React.createClass({
|
|||
}
|
||||
children.push(<Management {...actions} />);
|
||||
return <div>{children}</div>;
|
||||
},
|
||||
}
|
||||
|
||||
render () {
|
||||
render() {
|
||||
return (
|
||||
<main>
|
||||
<Connector select={this.selectData}>
|
||||
|
@ -52,19 +45,16 @@ var App = React.createClass({
|
|||
</Connector>
|
||||
</main>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
component: App,
|
||||
init: function() {
|
||||
React.render((
|
||||
<Provider redux={reduxConfig.default}>
|
||||
{function() {
|
||||
return <App/>;
|
||||
}}
|
||||
</Provider>
|
||||
), document.body);
|
||||
},
|
||||
};
|
||||
export function init() {
|
||||
React.render((
|
||||
<Provider redux={reduxConfig}>
|
||||
{function() {
|
||||
return <ManagementApp/>;
|
||||
}}
|
||||
</Provider>
|
||||
), document.body);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
var $ = require('jquery');
|
||||
var App = require('./app');
|
||||
import $ from 'jquery';
|
||||
import { init as appInit } from './app';
|
||||
|
||||
// Common ajax settings.
|
||||
$.ajaxSetup({
|
||||
dataType: 'json',
|
||||
});
|
||||
|
||||
App.init();
|
||||
appInit();
|
||||
|
|
|
@ -1,42 +1,54 @@
|
|||
'use strict';
|
||||
import 'shims';
|
||||
|
||||
require('shims');
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var React = require('react');
|
||||
var Provider = require('redux/react').Provider;
|
||||
var Connector = require('redux/react').Connector;
|
||||
var bindActionCreators = require('redux').bindActionCreators;
|
||||
import { Connector, Provider } from 'redux/react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
var reduxConfig = require('redux-config');
|
||||
var ErrorMessage = require('components/error');
|
||||
var Login = require('views/login');
|
||||
var Purchase = require('views/purchase');
|
||||
var userActions = require('actions/user');
|
||||
var utils = require('utils');
|
||||
import reduxConfig from 'redux-config';
|
||||
import ErrorMessage from 'components/error';
|
||||
import Login from 'views/login';
|
||||
import Purchase from 'views/purchase';
|
||||
import * as userActions from 'actions/user';
|
||||
import { parseQuery } from 'utils';
|
||||
|
||||
|
||||
var App = React.createClass({
|
||||
export default class PaymentApp extends Component {
|
||||
|
||||
displayName: 'PaymentApp',
|
||||
static propTypes = {
|
||||
Login: PropTypes.object,
|
||||
Purchase: PropTypes.object,
|
||||
win: PropTypes.object,
|
||||
}
|
||||
|
||||
getInitialState: function() {
|
||||
var qs = utils.parseQuery(window.location.href);
|
||||
static defaultProps = {
|
||||
Login: Login,
|
||||
Purchase: Purchase,
|
||||
win: window,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
var qs = parseQuery(props.win.location.href);
|
||||
// TODO: we should validate/clean this input to raise early errors.
|
||||
return {
|
||||
this.state = {
|
||||
accessToken: qs.access_token,
|
||||
productId: qs.product,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
selectData: function(state) {
|
||||
selectData(state) {
|
||||
return {
|
||||
app: state.app,
|
||||
user: state.user,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
render () {
|
||||
render() {
|
||||
var state = this.state;
|
||||
var Login_ = this.props.Login;
|
||||
var Purchase_ = this.props.Purchase;
|
||||
|
||||
return (
|
||||
<main>
|
||||
<Connector select={this.selectData}>
|
||||
|
@ -47,7 +59,7 @@ var App = React.createClass({
|
|||
} else if (!result.user.signedIn) {
|
||||
console.log('rendering login');
|
||||
return (
|
||||
<Login
|
||||
<Login_
|
||||
accessToken={state.accessToken}
|
||||
{...bindActionCreators(userActions, result.dispatch) }
|
||||
/>
|
||||
|
@ -55,26 +67,23 @@ var App = React.createClass({
|
|||
} else {
|
||||
console.log('rendering purchase flow');
|
||||
return (
|
||||
<Purchase user={result.user} productId={state.productId} />
|
||||
<Purchase_ user={result.user} productId={state.productId} />
|
||||
);
|
||||
}
|
||||
}}
|
||||
</Connector>
|
||||
</main>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
component: App,
|
||||
init: function() {
|
||||
React.render((
|
||||
<Provider redux={reduxConfig.default}>
|
||||
{function() {
|
||||
return <App/>;
|
||||
}}
|
||||
</Provider>
|
||||
), document.body);
|
||||
},
|
||||
};
|
||||
export function init() {
|
||||
React.render((
|
||||
<Provider redux={reduxConfig}>
|
||||
{function() {
|
||||
return <PaymentApp/>;
|
||||
}}
|
||||
</Provider>
|
||||
), document.body);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
var $ = require('jquery');
|
||||
var tracking = require('tracking');
|
||||
var App = require('./app');
|
||||
import $ from 'jquery';
|
||||
import tracking from 'tracking';
|
||||
import { init as appInit } from './app';
|
||||
|
||||
// Common ajax settings.
|
||||
$.ajaxSetup({
|
||||
|
@ -10,4 +8,4 @@ $.ajaxSetup({
|
|||
});
|
||||
|
||||
tracking.init();
|
||||
App.init();
|
||||
appInit();
|
||||
|
|
|
@ -1,31 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
/*eslint react/no-multi-comp: 0 */
|
||||
|
||||
var React = require('react');
|
||||
var cx = require('classnames');
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
|
||||
var Accordion = React.createClass({
|
||||
class Accordion extends Component {
|
||||
|
||||
displayName: 'Accordion',
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
children: React.PropTypes.node.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
var sections = [];
|
||||
React.Children.forEach(this.props.children, function() {
|
||||
sections.push({isActive: false});
|
||||
});
|
||||
sections[0].isActive = true;
|
||||
return {
|
||||
this.state = {
|
||||
sections: sections,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
activate: function(sectionIdx, e) {
|
||||
activate(sectionIdx, e) {
|
||||
if (e.target.getAttribute('data-activate') !== null) {
|
||||
e.preventDefault();
|
||||
var sections = this.state.sections;
|
||||
|
@ -34,14 +30,13 @@ var Accordion = React.createClass({
|
|||
});
|
||||
this.setState({sections: sections});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
render: function() {
|
||||
var that = this;
|
||||
var children = React.Children.map(this.props.children, function(child, idx){
|
||||
render() {
|
||||
var children = React.Children.map(this.props.children, (child, idx) => {
|
||||
return React.cloneElement(child, {
|
||||
activate: that.activate.bind(that, idx),
|
||||
isActive: that.state.sections[idx].isActive,
|
||||
activate: this.activate.bind(this, idx),
|
||||
isActive: this.state.sections[idx].isActive,
|
||||
});
|
||||
});
|
||||
return (
|
||||
|
@ -49,21 +44,19 @@ var Accordion = React.createClass({
|
|||
{children}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var AccordionSection = React.createClass({
|
||||
|
||||
displayName: 'AccordionSection',
|
||||
class AccordionSection extends Component {
|
||||
|
||||
propTypes: {
|
||||
static propTypes = {
|
||||
activate: React.PropTypes.func.isRequired,
|
||||
children: React.PropTypes.node.isRequired,
|
||||
isActive: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
};
|
||||
|
||||
render() {
|
||||
var classes = cx(
|
||||
'ac-section', {'active': this.props.isActive});
|
||||
|
||||
|
@ -73,29 +66,28 @@ var AccordionSection = React.createClass({
|
|||
{this.props.children}
|
||||
</section>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var AccordionContent = React.createClass({
|
||||
class AccordionContent extends Component {
|
||||
|
||||
displayName: 'AccordionContent',
|
||||
|
||||
propTypes: {
|
||||
static propTypes = {
|
||||
children: React.PropTypes.node.isRequired,
|
||||
},
|
||||
};
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div className="ac-content">
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Accordion: Accordion,
|
||||
AccordionContent: AccordionContent,
|
||||
AccordionSection: AccordionSection,
|
||||
|
||||
export default {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionSection,
|
||||
};
|
||||
|
|
|
@ -1,40 +1,39 @@
|
|||
'use strict';
|
||||
import $ from 'jquery';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var $ = require('jquery');
|
||||
var React = require('react');
|
||||
import CardList from 'components/card-list';
|
||||
import SubmitButton from 'components/submit-button';
|
||||
|
||||
var CardList = require('components/card-list');
|
||||
var SubmitButton = require('components/submit-button');
|
||||
import { gettext } from 'utils';
|
||||
import * as purchaseActions from 'actions/purchase';
|
||||
|
||||
var gettext = require('utils').gettext;
|
||||
var purchaseActions = require('actions/purchase');
|
||||
var reduxConfig = require('redux-config');
|
||||
import reduxConfig from 'redux-config';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'CardChoice',
|
||||
export default class CardChoice extends Component {
|
||||
|
||||
propTypes: {
|
||||
cards: React.PropTypes.arrayOf(
|
||||
React.PropTypes.shape({
|
||||
id: React.PropTypes.number,
|
||||
resource_uri: React.PropTypes.string,
|
||||
truncated_id: React.PropTypes.string,
|
||||
type_name: React.PropTypes.string,
|
||||
static propTypes = {
|
||||
cards: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
resource_uri: PropTypes.string,
|
||||
truncated_id: PropTypes.string,
|
||||
type_name: PropTypes.string,
|
||||
}
|
||||
)).isRequired,
|
||||
productId: React.PropTypes.string.isRequired,
|
||||
},
|
||||
productId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isSubmitting: false,
|
||||
card: (this.props.cards.length === 1 ?
|
||||
this.props.cards[0].resource_uri : null),
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
handleSubmit: function(e) {
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
this.setState({isSubmitting: true});
|
||||
|
@ -51,20 +50,20 @@ module.exports = React.createClass({
|
|||
}).done(function() {
|
||||
console.log('Successfully subscribed with existing card');
|
||||
|
||||
reduxConfig.default.dispatch(
|
||||
reduxConfig.dispatch(
|
||||
purchaseActions.complete()
|
||||
);
|
||||
|
||||
}).fail(function() {
|
||||
// TODO: handler errors.
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
handleCardChange: function(e) {
|
||||
handleCardChange = (e) => {
|
||||
this.setState({card: e.target.value});
|
||||
},
|
||||
}
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
var cardData = this.props.cards;
|
||||
for (var i = 0; i < cardData.length; i += 1) {
|
||||
var card = cardData[i];
|
||||
|
@ -75,12 +74,14 @@ module.exports = React.createClass({
|
|||
|
||||
return (
|
||||
<form id="card-listing" onSubmit={this.handleSubmit}>
|
||||
<CardList cards={cardData} onCardChange={this.handleCardChange} />
|
||||
<CardList
|
||||
cards={cardData}
|
||||
onCardChange={this.handleCardChange} />
|
||||
<SubmitButton isDisabled={!formIsValid}
|
||||
showSpinner={this.state.isSubmitting}
|
||||
text={gettext('Subscribe')}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
'use strict';
|
||||
import $ from 'jquery';
|
||||
import CardValidator from 'card-validator';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import braintree from 'braintree-web';
|
||||
|
||||
var $ = require('jquery');
|
||||
var CardValidator = require('card-validator');
|
||||
var React = require('react');
|
||||
var braintree = require('braintree-web');
|
||||
import { gettext } from 'utils';
|
||||
|
||||
var utils = require('utils');
|
||||
var gettext = utils.gettext;
|
||||
|
||||
var CardInput = require('components/card-input');
|
||||
var SubmitButton = require('components/submit-button');
|
||||
var purchaseActions = require('actions/purchase');
|
||||
var reduxConfig = require('redux-config');
|
||||
import CardInput from 'components/card-input';
|
||||
import SubmitButton from 'components/submit-button';
|
||||
import * as purchaseActions from 'actions/purchase';
|
||||
import reduxConfig from 'redux-config';
|
||||
|
||||
|
||||
var defaultFieldAttrs = {
|
||||
const defaultFieldAttrs = {
|
||||
'autoComplete': 'off',
|
||||
// inputMode is not yet supported in React.
|
||||
// See https://github.com/facebook/react/pull/3798
|
||||
|
@ -22,22 +19,73 @@ var defaultFieldAttrs = {
|
|||
'type': 'tel',
|
||||
};
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
displayName: 'CardForm',
|
||||
|
||||
propTypes: {
|
||||
card: React.PropTypes.object,
|
||||
cvv: React.PropTypes.object,
|
||||
'data-token': React.PropTypes.string.isRequired,
|
||||
expiration: React.PropTypes.object,
|
||||
id: React.PropTypes.string.isRequired,
|
||||
productId: React.PropTypes.string.isRequired,
|
||||
const errorKeyToFieldMap = {
|
||||
'__all__': {
|
||||
field: 'card',
|
||||
error: 'declined',
|
||||
},
|
||||
'fraud': {
|
||||
field: 'card',
|
||||
error: 'declined',
|
||||
},
|
||||
'cvv': {
|
||||
field: 'cvv',
|
||||
error: 'invalid',
|
||||
},
|
||||
};
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
const fieldProps = {
|
||||
card: {
|
||||
'attrs': defaultFieldAttrs,
|
||||
'classNames': ['card'],
|
||||
'errors': {
|
||||
invalid: gettext('Incorrect card number'),
|
||||
declined: gettext('Card was declined'),
|
||||
},
|
||||
'id': 'card',
|
||||
'placeholder': gettext('Card number'),
|
||||
'validator': CardValidator.number,
|
||||
},
|
||||
expiration: {
|
||||
'attrs': defaultFieldAttrs,
|
||||
'classNames': ['expiration'],
|
||||
'errors': {
|
||||
invalid: gettext('Invalid expiry date'),
|
||||
},
|
||||
'id': 'expiration',
|
||||
// Expiration pattern doesn't change based on card type.
|
||||
'pattern': '11/11',
|
||||
'placeholder': 'MM/YY',
|
||||
'validator': CardValidator.expirationDate,
|
||||
},
|
||||
cvv: {
|
||||
'attrs': defaultFieldAttrs,
|
||||
'autocomplete': 'off',
|
||||
'classNames': ['cvv'],
|
||||
'errors': {
|
||||
invalid: gettext('Invalid CVV'),
|
||||
},
|
||||
'errorModifier': 'right',
|
||||
'id': 'cvv',
|
||||
'validator': CardValidator.cvv,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
export default class CardForm extends Component {
|
||||
|
||||
static propTypes = {
|
||||
card: PropTypes.object,
|
||||
cvv: PropTypes.object,
|
||||
'data-token': PropTypes.string.isRequired,
|
||||
expiration: PropTypes.object,
|
||||
id: PropTypes.string.isRequired,
|
||||
productId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isSubmitting: false,
|
||||
cardType: null,
|
||||
errors: {},
|
||||
|
@ -45,55 +93,18 @@ module.exports = React.createClass({
|
|||
expiration: '',
|
||||
cvv: '',
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
fieldProps: {
|
||||
card: {
|
||||
'attrs': defaultFieldAttrs,
|
||||
'classNames': ['card'],
|
||||
'errors': {
|
||||
invalid: gettext('Incorrect card number'),
|
||||
declined: gettext('Card was declined'),
|
||||
},
|
||||
'id': 'card',
|
||||
'placeholder': gettext('Card number'),
|
||||
'validator': CardValidator.number,
|
||||
},
|
||||
expiration: {
|
||||
'attrs': defaultFieldAttrs,
|
||||
'classNames': ['expiration'],
|
||||
'errors': {
|
||||
invalid: gettext('Invalid expiry date'),
|
||||
},
|
||||
'id': 'expiration',
|
||||
// Expiration pattern doesn't change based on card type.
|
||||
'pattern': '11/11',
|
||||
'placeholder': 'MM/YY',
|
||||
'validator': CardValidator.expirationDate,
|
||||
},
|
||||
cvv: {
|
||||
'attrs': defaultFieldAttrs,
|
||||
'autocomplete': 'off',
|
||||
'classNames': ['cvv'],
|
||||
'errors': {
|
||||
invalid: gettext('Invalid CVV'),
|
||||
},
|
||||
'errorModifier': 'right',
|
||||
'id': 'cvv',
|
||||
'validator': CardValidator.cvv,
|
||||
},
|
||||
},
|
||||
|
||||
handleChange: function(e) {
|
||||
handleChange = (e) => {
|
||||
var fieldId = e.target.id;
|
||||
var val = e.target.value;
|
||||
|
||||
var fieldProps = this.fieldProps[fieldId];
|
||||
var valData = fieldProps.validator(this.stripPlaceholder(val));
|
||||
fieldProps.hasVal = val.length > 0 || false;
|
||||
fieldProps.isValid = valData.isValid === true;
|
||||
fieldProps.showError = !valData.isValid && !valData.isPotentiallyValid;
|
||||
fieldProps.errorMessage = fieldProps.errors.invalid;
|
||||
var fieldData = fieldProps[fieldId];
|
||||
var valData = fieldData.validator(this.stripPlaceholder(val));
|
||||
fieldData.hasVal = val.length > 0 || false;
|
||||
fieldData.isValid = valData.isValid === true;
|
||||
fieldData.showError = !valData.isValid && !valData.isPotentiallyValid;
|
||||
fieldData.errorMessage = fieldData.errors.invalid;
|
||||
|
||||
var newState = {
|
||||
[e.target.id]: e.target.value,
|
||||
|
@ -106,9 +117,9 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
this.setState(newState);
|
||||
},
|
||||
}
|
||||
|
||||
handleSubmit: function(e) {
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
this.setState({isSubmitting: true});
|
||||
var that = this;
|
||||
|
@ -136,7 +147,7 @@ module.exports = React.createClass({
|
|||
}).done(function() {
|
||||
console.log('Successfully subscribed + completed payment');
|
||||
|
||||
reduxConfig.default.dispatch(
|
||||
reduxConfig.dispatch(
|
||||
purchaseActions.complete()
|
||||
);
|
||||
|
||||
|
@ -145,25 +156,9 @@ module.exports = React.createClass({
|
|||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
errorKeyToFieldMap: {
|
||||
'__all__': {
|
||||
field: 'card',
|
||||
error: 'declined',
|
||||
},
|
||||
'fraud': {
|
||||
field: 'card',
|
||||
error: 'declined',
|
||||
},
|
||||
'cvv': {
|
||||
field: 'cvv',
|
||||
error: 'invalid',
|
||||
},
|
||||
},
|
||||
|
||||
processApiErrors: function(errors) {
|
||||
var that = this;
|
||||
processApiErrors(errors) {
|
||||
if (errors.error_response && errors.error_response.braintree) {
|
||||
var apiErrors = errors.error_response.braintree;
|
||||
// Iterate over the error object and create a new data
|
||||
|
@ -171,10 +166,10 @@ module.exports = React.createClass({
|
|||
// a list of generic errors.
|
||||
Object.keys(apiErrors).forEach(function(key) {
|
||||
console.log('API ErrorMessage: ' + JSON.stringify(apiErrors[key]));
|
||||
var errorData = that.errorKeyToFieldMap[key] || {};
|
||||
var errorData = errorKeyToFieldMap[key] || {};
|
||||
var field = errorData.field;
|
||||
if (field) {
|
||||
var fieldData = that.fieldProps[field];
|
||||
var fieldData = fieldProps[field];
|
||||
fieldData.isValid = false;
|
||||
fieldData.showError = true;
|
||||
fieldData.errorMessage = fieldData.errors[errorData.error];
|
||||
|
@ -184,33 +179,31 @@ module.exports = React.createClass({
|
|||
this.setState({
|
||||
isSubmitting: false,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
stripPlaceholder: function(val) {
|
||||
stripPlaceholder(val) {
|
||||
return val ? val.replace(/_/g, '') : '';
|
||||
},
|
||||
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
var formIsValid = true;
|
||||
var that = this;
|
||||
|
||||
// Update form validity based on fieldProps.
|
||||
Object.keys(this.fieldProps).forEach(function(field) {
|
||||
if (!that.fieldProps[field].isValid) {
|
||||
Object.keys(fieldProps).forEach(function(field) {
|
||||
if (!fieldProps[field].isValid) {
|
||||
formIsValid = false;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<form {...this.props} onSubmit={this.handleSubmit}>
|
||||
<CardInput {...this.fieldProps.card}
|
||||
<CardInput {...fieldProps.card}
|
||||
cardType={this.state.cardType}
|
||||
onChangeHandler={this.handleChange} />
|
||||
<CardInput {...this.fieldProps.expiration}
|
||||
<CardInput {...fieldProps.expiration}
|
||||
cardType={this.state.cardType}
|
||||
onChangeHandler={this.handleChange} />
|
||||
<CardInput {...this.fieldProps.cvv}
|
||||
<CardInput {...fieldProps.cvv}
|
||||
cardType={this.state.cardType}
|
||||
onChangeHandler={this.handleChange} />
|
||||
<SubmitButton isDisabled={!formIsValid}
|
||||
|
@ -218,5 +211,5 @@ module.exports = React.createClass({
|
|||
text={gettext('Subscribe')} />
|
||||
</form>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
'use strict';
|
||||
import cx from 'classnames';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var cx = require('classnames');
|
||||
var React = require('react');
|
||||
// Just a convenience mapping for cards from card-validator
|
||||
// to shorted classes used in CSS.
|
||||
const cardTypeMap = {
|
||||
'american-express': 'amex',
|
||||
'diners-club': 'diners',
|
||||
'master-card': 'mastercard',
|
||||
};
|
||||
|
||||
export default class CardIcon extends Component {
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'CardIcon',
|
||||
|
||||
propTypes: {
|
||||
cardType: React.PropTypes.oneOf([
|
||||
static propTypes = {
|
||||
cardType: PropTypes.oneOf([
|
||||
'amex',
|
||||
'american-express',
|
||||
'diners-club',
|
||||
'discover',
|
||||
|
@ -18,23 +23,16 @@ module.exports = React.createClass({
|
|||
'master-card',
|
||||
'visa',
|
||||
]),
|
||||
},
|
||||
};
|
||||
|
||||
// Just a convenience mapping for cards from card-validator
|
||||
// to shorted classes used in CSS.
|
||||
cardTypeMap: {
|
||||
'american-express': 'amex',
|
||||
'diners-club': 'diners',
|
||||
'master-card': 'mastercard',
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
// This is only displayed if a cardType is passed-in.
|
||||
var cardType = this.props.cardType;
|
||||
var cardClassName = cx([
|
||||
'card-icon',
|
||||
'cctype-' + (this.cardTypeMap[cardType] || cardType),
|
||||
'cctype-' + (cardTypeMap[cardType] || cardType),
|
||||
]);
|
||||
return cardType ? <span className={cardClassName} /> : null;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,79 +1,74 @@
|
|||
'use strict';
|
||||
import classNames from 'classnames';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
import CardIcon from 'components/card-icon';
|
||||
import InputError from 'components/input-error';
|
||||
import MaskedInput from 'react-maskedinput';
|
||||
|
||||
var CardIcon = require('components/card-icon');
|
||||
var InputError = require('components/input-error');
|
||||
var MaskedInput = require('react-maskedinput');
|
||||
import { defaults, gettext } from 'utils';
|
||||
|
||||
var utils = require('utils');
|
||||
var gettext = utils.gettext;
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
displayName: 'CardInput',
|
||||
|
||||
propTypes: {
|
||||
attrs: React.PropTypes.object,
|
||||
cardType: React.PropTypes.string,
|
||||
classNames: React.PropTypes.array,
|
||||
errorMessage: React.PropTypes.string,
|
||||
errorModifier: React.PropTypes.string,
|
||||
hasVal: React.PropTypes.bool,
|
||||
id: React.PropTypes.string.isRequired,
|
||||
isValid: React.PropTypes.bool,
|
||||
label: React.PropTypes.string,
|
||||
onChangeHandler: React.PropTypes.func.isRequired,
|
||||
pattern: React.PropTypes.string,
|
||||
placeholder: React.PropTypes.string,
|
||||
showError: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
cardPatterns: {
|
||||
'default': {
|
||||
card: {
|
||||
pattern: '1111 1111 1111 1111',
|
||||
},
|
||||
cvv: {
|
||||
pattern: '111',
|
||||
placeholder: gettext('CVV'),
|
||||
},
|
||||
const cardPatterns = {
|
||||
'default': {
|
||||
card: {
|
||||
pattern: '1111 1111 1111 1111',
|
||||
},
|
||||
'american-express': {
|
||||
card: {
|
||||
pattern: '1111 111111 11111',
|
||||
},
|
||||
cvv: {
|
||||
pattern: '1111',
|
||||
placeholder: gettext('CID'),
|
||||
},
|
||||
},
|
||||
'diners-club': {
|
||||
card: {
|
||||
pattern: '1111 111111 1111',
|
||||
},
|
||||
cvv: {
|
||||
pattern: '111',
|
||||
placeholder: gettext('CVV'),
|
||||
},
|
||||
cvv: {
|
||||
pattern: '111',
|
||||
placeholder: gettext('CVV'),
|
||||
},
|
||||
},
|
||||
'american-express': {
|
||||
card: {
|
||||
pattern: '1111 111111 11111',
|
||||
},
|
||||
cvv: {
|
||||
pattern: '1111',
|
||||
placeholder: gettext('CID'),
|
||||
},
|
||||
},
|
||||
'diners-club': {
|
||||
card: {
|
||||
pattern: '1111 111111 1111',
|
||||
},
|
||||
cvv: {
|
||||
pattern: '111',
|
||||
placeholder: gettext('CVV'),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
updatePattern: function(fieldId, cardType) {
|
||||
|
||||
export default class CardInput extends Component {
|
||||
|
||||
static propTypes = {
|
||||
attrs: PropTypes.object,
|
||||
cardType: PropTypes.string,
|
||||
classNames: PropTypes.array,
|
||||
errorMessage: PropTypes.string,
|
||||
errorModifier: PropTypes.string,
|
||||
hasVal: PropTypes.bool,
|
||||
id: PropTypes.string.isRequired,
|
||||
isValid: PropTypes.bool,
|
||||
label: PropTypes.string,
|
||||
onChangeHandler: PropTypes.func.isRequired,
|
||||
pattern: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
showError: PropTypes.bool,
|
||||
};
|
||||
|
||||
updatePattern(fieldId, cardType) {
|
||||
// Update the pattern for card + cvv field if card was detected.
|
||||
if (cardType && this.cardPatterns[cardType]) {
|
||||
return utils.defaults(
|
||||
this.cardPatterns[cardType][fieldId] || {},
|
||||
this.cardPatterns.default[fieldId]
|
||||
if (cardType && cardPatterns[cardType]) {
|
||||
return defaults(
|
||||
cardPatterns[cardType][fieldId] || {},
|
||||
cardPatterns.default[fieldId]
|
||||
);
|
||||
} else {
|
||||
return this.cardPatterns.default[fieldId] || {};
|
||||
return cardPatterns.default[fieldId] || {};
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
|
||||
var labelClassNames = this.props.classNames || [];
|
||||
// Use a copy of the list to avoid appending ad infinitum.
|
||||
|
@ -95,8 +90,6 @@ module.exports = React.createClass({
|
|||
|
||||
var showCardIcon = this.props.id === 'card';
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<label className={labelClass} htmlFor={this.props.id} >
|
||||
<span className="vh">{label}</span>
|
||||
|
@ -114,5 +107,5 @@ module.exports = React.createClass({
|
|||
/>
|
||||
</label>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var CardIcon = require('components/card-icon');
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import CardIcon from 'components/card-icon';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class CardItem extends Component {
|
||||
|
||||
displayName: 'CardItem',
|
||||
static propTypes = {
|
||||
checked: PropTypes.bool.isRequired,
|
||||
id: PropTypes.number.isRequired,
|
||||
onChangeHandler: PropTypes.func.isRequired,
|
||||
resource_uri: PropTypes.string.isRequired,
|
||||
truncated_id: PropTypes.string.isRequired,
|
||||
type_name: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
checked: React.PropTypes.bool.isRequired,
|
||||
id: React.PropTypes.number.isRequired,
|
||||
onChangeHandler: React.PropTypes.func.isRequired,
|
||||
resource_uri: React.PropTypes.string.isRequired,
|
||||
truncated_id: React.PropTypes.string.isRequired,
|
||||
type_name: React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
var cardType = this.props.type_name.toLowerCase();
|
||||
var cardText = '●●●● ●●●● ●●●● ' + this.props.truncated_id;
|
||||
var inputId = 'card-' + this.props.id;
|
||||
|
@ -33,6 +29,5 @@ module.exports = React.createClass({
|
|||
className="text">{cardText}</label>
|
||||
</li>
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,34 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import CardItem from 'components/card-item';
|
||||
|
||||
var React = require('react');
|
||||
var CardItem = require('components/card-item');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'CardList',
|
||||
export default class CardList extends Component {
|
||||
|
||||
propTypes: {
|
||||
cards: React.PropTypes.arrayOf(
|
||||
React.PropTypes.shape({
|
||||
id: React.PropTypes.number,
|
||||
resource_uri: React.PropTypes.string,
|
||||
truncated_id: React.PropTypes.string,
|
||||
type_name: React.PropTypes.string,
|
||||
static propTypes = {
|
||||
cards: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
resource_uri: PropTypes.string,
|
||||
truncated_id: PropTypes.string,
|
||||
type_name: PropTypes.string,
|
||||
}
|
||||
)).isRequired,
|
||||
onCardChange: React.PropTypes.func.isRequired,
|
||||
},
|
||||
onCardChange: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
var cardData = this.props.cards;
|
||||
var cardList = [];
|
||||
|
||||
for (var i = 0; i < cardData.length; i += 1) {
|
||||
var { checked, ...card } = cardData[i];
|
||||
cardList.push(<CardItem {...card} key={'ci-' + i}
|
||||
onChangeHandler={this.props.onCardChange}
|
||||
checked={checked} />);
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="card-listing">
|
||||
{cardList}
|
||||
</ul>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var utils = require('utils');
|
||||
|
||||
var gettext = utils.gettext;
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { gettext } from 'utils';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Error',
|
||||
export default class ErrorMessage extends Component {
|
||||
|
||||
propTypes: {
|
||||
error: React.PropTypes.object.isRequired,
|
||||
},
|
||||
static propTypes = {
|
||||
error: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
console.log('rendering app error:', this.props.error);
|
||||
return (
|
||||
<div className="app-error">
|
||||
|
@ -23,6 +17,5 @@ module.exports = React.createClass({
|
|||
</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
var cx = require('classnames');
|
||||
var React = require('react');
|
||||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default React.createClass({
|
||||
|
||||
displayName: 'InputError',
|
||||
|
||||
propTypes: {
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var gettext = require('utils').gettext;
|
||||
var cx = require('classnames');
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { gettext } from 'utils';
|
||||
import cx from 'classnames';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class Modal extends Component {
|
||||
|
||||
displayName: 'Modal',
|
||||
static propTypes = {
|
||||
children: PropTypes.object.isRequired,
|
||||
handleClose: PropTypes.func.isRequired,
|
||||
title: PropTypes.string,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
children: React.PropTypes.object.isRequired,
|
||||
handleClose: React.PropTypes.func.isRequired,
|
||||
title: React.PropTypes.string,
|
||||
},
|
||||
|
||||
onClose: function(e) {
|
||||
onClose = (e) => {
|
||||
var targetClassName = e.target.getAttribute('class') || '';
|
||||
var classes = targetClassName.split(' ');
|
||||
// Only deal with closing the window if the event
|
||||
|
@ -27,9 +23,9 @@ module.exports = React.createClass({
|
|||
e.stopPropagation();
|
||||
this.props.handleClose();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
var classes = cx(['modal', {'active': true}]);
|
||||
|
||||
return (
|
||||
|
@ -47,5 +43,5 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import products from 'products';
|
||||
import { gettext } from 'utils';
|
||||
|
||||
var React = require('react');
|
||||
var products = require('products');
|
||||
var gettext = require('utils').gettext;
|
||||
export default class ProductDetail extends Component {
|
||||
|
||||
module.exports = React.createClass({
|
||||
static propTypes = {
|
||||
productId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
displayName: 'ProductDetail',
|
||||
|
||||
propTypes: {
|
||||
productId: React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
|
||||
var productId = this.props.productId;
|
||||
var productData = products[productId];
|
||||
|
@ -29,5 +25,5 @@ module.exports = React.createClass({
|
|||
<div>{gettext('per month')}</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { gettext } from 'utils';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var gettext = require('utils').gettext;
|
||||
export default class Spinner extends Component {
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Spinner',
|
||||
static propTypes = {
|
||||
text: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
propTypes: {
|
||||
text: React.PropTypes.string.isRequired,
|
||||
},
|
||||
static defaultProps = {
|
||||
text: gettext('Loading'),
|
||||
}
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
text: gettext('Loading'),
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div className="spinner-cont">
|
||||
<div className="spinner" />
|
||||
<span className="text">{this.props.text}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
var cx = require('classnames');
|
||||
var React = require('react');
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'SubmitButton',
|
||||
export default class SubmitButton extends Component {
|
||||
|
||||
propTypes: {
|
||||
isDisabled: React.PropTypes.bool,
|
||||
showSpinner: React.PropTypes.bool,
|
||||
text: React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
static propTypes = {
|
||||
isDisabled: PropTypes.bool,
|
||||
showSpinner: PropTypes.bool,
|
||||
text: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
var { isDisabled, text, showSpinner, ...buttonAttrs } = this.props;
|
||||
|
||||
var buttonClassNames = cx({
|
||||
|
@ -33,5 +29,5 @@ module.exports = React.createClass({
|
|||
disabled={isDisabled}
|
||||
type="submit">{text}</button>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
export const APP_ERROR = 'APP_ERROR';
|
||||
export const USER_SIGNED_IN = 'USER_SIGNED_IN';
|
||||
export const COMPLETE_PURCHASE = 'COMPLETE_PURCHASE';
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
'mozilla-concrete-brick': require('json!mozilla-concrete-brick'),
|
||||
'mozilla-concrete-mortar': require('json!mozilla-concrete-mortar'),
|
||||
};
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
var redux = require('redux');
|
||||
var dataStore = require('stores/index');
|
||||
console.log(dataStore);
|
||||
import { createRedux as createRedux_ } from 'redux';
|
||||
import * as stores from 'stores';
|
||||
|
||||
function createRedux() {
|
||||
return redux.createRedux(dataStore);
|
||||
return createRedux_(stores);
|
||||
}
|
||||
|
||||
exports.create = createRedux;
|
||||
exports.default = createRedux();
|
||||
export default createRedux();
|
||||
export { createRedux as create };
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
'supportedLanguages': [
|
||||
'ca',
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
import assign from 'object.assign';
|
||||
|
||||
assign.shim();
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
var actionTypes = require('constants/action-types');
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
export default function app(state, action) {
|
||||
if (action.type === actionTypes.APP_ERROR) {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
export { default as app } from './app';
|
||||
export { default as management } from './management';
|
||||
export { default as purchase } from './purchase';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
'use strict';
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
var actionTypes = require('constants/action-types');
|
||||
|
||||
export default function management(state, action) {
|
||||
console.log('management store: got action', action);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
'use strict';
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
var actionTypes = require('constants/action-types');
|
||||
|
||||
export default function purchase(state, action) {
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
var actionTypes = require('constants/action-types');
|
||||
import * as actionTypes from 'constants/action-types';
|
||||
|
||||
export default function user(state, action) {
|
||||
if (action.type === actionTypes.USER_SIGNED_IN) {
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
/* global ga */
|
||||
|
||||
var settings = require('settings');
|
||||
import settings from 'settings';
|
||||
|
||||
|
||||
class Tracking {
|
||||
export class Tracking {
|
||||
|
||||
constructor(opts) {
|
||||
opts = opts || {};
|
||||
|
@ -86,7 +84,7 @@ class Tracking {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = new Tracking({
|
||||
export default new Tracking({
|
||||
enabled: settings.tracking.enabled,
|
||||
trackingId: settings.tracking.id,
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Populates an object with defaults if the key is not yet defined.
|
||||
* Similar to _.defaults except this takes only a single defaults object.
|
||||
|
@ -8,30 +6,30 @@
|
|||
* @returns {object}
|
||||
*/
|
||||
|
||||
exports.defaults = (object, defaults) => {
|
||||
export function defaults(object, defaults_) {
|
||||
object = object || {};
|
||||
defaults = defaults || {};
|
||||
Object.keys(defaults).forEach(function(key) {
|
||||
defaults_ = defaults_ || {};
|
||||
Object.keys(defaults_).forEach(function(key) {
|
||||
if (typeof object[key] === 'undefined') {
|
||||
object[key] = defaults[key];
|
||||
object[key] = defaults_[key];
|
||||
}
|
||||
});
|
||||
return object;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
exports.getMountNode = (node) => {
|
||||
export function getMountNode(node){
|
||||
return node || document.getElementById('view');
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
exports.gettext = (string) => {
|
||||
export function gettext(string){
|
||||
// Initial no-op gettext stand-in.
|
||||
return string;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
exports.parseQuery = (url) => {
|
||||
export function parseQuery(url){
|
||||
//
|
||||
// Given a complete URL, parse the query string and return an
|
||||
// object of parameters->values. This doesn't bother with repeated
|
||||
|
@ -51,4 +49,4 @@ exports.parseQuery = (url) => {
|
|||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,33 +1,32 @@
|
|||
'use strict';
|
||||
import $ from 'jquery';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var $ = require('jquery');
|
||||
var React = require('react');
|
||||
import CardForm from 'components/card-form';
|
||||
import ProductDetail from 'components/product-detail';
|
||||
import Spinner from 'components/spinner';
|
||||
|
||||
var CardForm = require('components/card-form');
|
||||
var ProductDetail = require('components/product-detail');
|
||||
var Spinner = require('components/spinner');
|
||||
|
||||
var tracking = require('tracking');
|
||||
import { default as tracking } from 'tracking';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class CardDetailsView extends Component {
|
||||
|
||||
displayName: 'CardDetailsView',
|
||||
static propTypes = {
|
||||
productId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
productId: React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
braintree_token: false,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
componentDidMount: function() {
|
||||
componentDidMount() {
|
||||
console.log('Requesting braintree token');
|
||||
// TODO: move this to a purchase action.
|
||||
|
||||
this.mounted = true;
|
||||
|
||||
tracking.setPage('/card-details');
|
||||
|
||||
$.ajax({
|
||||
|
@ -35,16 +34,20 @@ module.exports = React.createClass({
|
|||
url: '/api/braintree/token/generate/',
|
||||
context: this,
|
||||
}).then(function(data) {
|
||||
if (this.isMounted()) {
|
||||
if (this.mounted) {
|
||||
this.setState({'braintree_token': data.token}); // eslint-disable-line
|
||||
}
|
||||
}).fail(function() {
|
||||
// TODO: some error state.
|
||||
console.log('failed to get braintree token');
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
render: function() {
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (this.state.braintree_token) {
|
||||
return (
|
||||
|
@ -61,5 +64,5 @@ module.exports = React.createClass({
|
|||
} else {
|
||||
return <Spinner />;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var React = require('react');
|
||||
import CardChoice from 'components/card-choice';
|
||||
import ProductDetail from 'components/product-detail';
|
||||
|
||||
var CardChoice = require('components/card-choice');
|
||||
var ProductDetail = require('components/product-detail');
|
||||
|
||||
var gettext = require('utils').gettext;
|
||||
var tracking = require('tracking');
|
||||
import { gettext } from 'utils';
|
||||
import tracking from 'tracking';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class CardListing extends Component {
|
||||
|
||||
displayName: 'CardListing',
|
||||
static propTypes = {
|
||||
payWithNewCard: PropTypes.func.isRequired,
|
||||
paymentMethods: PropTypes.array.isRequired,
|
||||
productId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
payWithNewCard: React.PropTypes.func.isRequired,
|
||||
paymentMethods: React.PropTypes.array.isRequired,
|
||||
productId: React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
componentDidMount() {
|
||||
tracking.setPage('/card-listing');
|
||||
},
|
||||
}
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<div className="card-listing">
|
||||
<ProductDetail productId={this.props.productId} />
|
||||
|
@ -37,5 +33,5 @@ module.exports = React.createClass({
|
|||
</a>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
'use strict';
|
||||
import React from 'react';
|
||||
|
||||
var React = require('react');
|
||||
import ProductDetail from 'components/product-detail';
|
||||
import SubmitButton from 'components/submit-button';
|
||||
|
||||
var ProductDetail = require('components/product-detail');
|
||||
var SubmitButton = require('components/submit-button');
|
||||
|
||||
var gettext = require('utils').gettext;
|
||||
var tracking = require('tracking');
|
||||
import { gettext } from 'utils';
|
||||
import tracking from 'tracking';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default React.createClass({
|
||||
|
||||
displayName: 'CompleteView',
|
||||
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var React = require('react');
|
||||
import Spinner from 'components/spinner';
|
||||
|
||||
var Spinner = require('components/spinner');
|
||||
|
||||
var gettext = require('utils').gettext;
|
||||
var tracking = require('tracking');
|
||||
import { gettext } from 'utils';
|
||||
import tracking from 'tracking';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class Login extends Component {
|
||||
|
||||
displayName: 'Login',
|
||||
static propTypes = {
|
||||
accessToken: PropTypes.string.isRequired,
|
||||
signIn: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
accessToken: React.PropTypes.string.isRequired,
|
||||
signIn: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
componentDidMount() {
|
||||
tracking.setPage('/login');
|
||||
this.props.signIn(this.props.accessToken);
|
||||
},
|
||||
}
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return <Spinner text={gettext('Signing in')}/>;
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var React = require('react');
|
||||
import Modal from 'components/modal';
|
||||
import CardList from 'components/card-list';
|
||||
|
||||
var Modal = require('components/modal');
|
||||
var CardList = require('components/card-list');
|
||||
|
||||
var gettext = require('utils').gettext;
|
||||
import { gettext } from 'utils';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class ManageCards extends Component {
|
||||
|
||||
displayName: 'ManageCards',
|
||||
static propTypes = {
|
||||
closeModal: PropTypes.func.isRequired,
|
||||
paymentMethods: PropTypes.array.isRequired,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
closeModal: React.PropTypes.func.isRequired,
|
||||
paymentMethods: React.PropTypes.array.isRequired,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<Modal
|
||||
handleClose={this.props.closeModal}
|
||||
|
@ -25,7 +21,6 @@ module.exports = React.createClass({
|
|||
<CardList cards={this.props.paymentMethods} />
|
||||
</Modal>
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,24 +1,20 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var {
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionSection,
|
||||
} = require('components/accordion');
|
||||
AccordionSection } from 'components/accordion';
|
||||
|
||||
var gettext = require('utils').gettext;
|
||||
import { gettext } from 'utils';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
displayName: 'ManagementApp',
|
||||
export default class Management extends Component {
|
||||
|
||||
propTypes: {
|
||||
getPayMethods: React.PropTypes.func.isRequired,
|
||||
},
|
||||
static propTypes = {
|
||||
getPayMethods: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
|
||||
<div>
|
||||
|
@ -75,5 +71,5 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,23 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var React = require('react');
|
||||
var Modal = require('components/modal');
|
||||
import Modal from 'components/modal';
|
||||
import ErrorMessage from 'components/error';
|
||||
|
||||
var ErrorMessage = require('components/error');
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class ModalError extends Component {
|
||||
|
||||
displayName: 'ModalError',
|
||||
static propTypes = {
|
||||
closeModal: PropTypes.func.isRequired,
|
||||
error: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
closeModal: React.PropTypes.func.isRequired,
|
||||
error: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
return (
|
||||
<Modal handleClose={this.props.closeModal}>
|
||||
<ErrorMessage error={this.props.error} />
|
||||
</Modal>
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,44 +1,55 @@
|
|||
'use strict';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
var React = require('react');
|
||||
var bindActionCreators = require('redux').bindActionCreators;
|
||||
var Connector = require('redux/react').Connector;
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { Connector } from 'redux/react';
|
||||
|
||||
var CardDetails = require('views/card-details');
|
||||
var CardListing = require('views/card-listing');
|
||||
var CompletePayment = require('views/complete-payment');
|
||||
var purchaseActions = require('actions/purchase');
|
||||
import * as purchaseActions from 'actions/purchase';
|
||||
|
||||
import CardDetails from 'views/card-details';
|
||||
import CardListing from 'views/card-listing';
|
||||
import CompletePayment from 'views/complete-payment';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
export default class Purchase extends Component {
|
||||
|
||||
displayName: 'Purchase',
|
||||
static propTypes = {
|
||||
CardDetails: PropTypes.object,
|
||||
CardListing: PropTypes.object,
|
||||
CompletePayment: PropTypes.object,
|
||||
productId: PropTypes.string.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
propTypes: {
|
||||
productId: React.PropTypes.string.isRequired,
|
||||
user: React.PropTypes.object.isRequired,
|
||||
},
|
||||
static defaultProps = {
|
||||
CardDetails: CardDetails,
|
||||
CardListing: CardListing,
|
||||
CompletePayment: CompletePayment,
|
||||
}
|
||||
|
||||
selectData: function(state) {
|
||||
selectData(state) {
|
||||
return {
|
||||
purchase: state.purchase,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
render () {
|
||||
var props = this.props;
|
||||
var CompletePayment_ = this.props.CompletePayment;
|
||||
var CardListing_ = this.props.CardListing;
|
||||
var CardDetails_ = this.props.CardDetails;
|
||||
return (
|
||||
<Connector select={this.selectData}>
|
||||
{function(result) {
|
||||
if (result.purchase.completed) {
|
||||
return (
|
||||
<CompletePayment productId={props.productId}
|
||||
userEmail={props.user.email} />
|
||||
<CompletePayment_
|
||||
productId={props.productId}
|
||||
userEmail={props.user.email} />
|
||||
);
|
||||
} else if (result.purchase.payment_methods.length > 0) {
|
||||
console.log('rendering card listing');
|
||||
return (
|
||||
<CardListing
|
||||
<CardListing_
|
||||
productId={props.productId}
|
||||
paymentMethods={result.purchase.payment_methods}
|
||||
{...bindActionCreators(purchaseActions, result.dispatch)}
|
||||
|
@ -46,10 +57,10 @@ module.exports = React.createClass({
|
|||
);
|
||||
} else {
|
||||
console.log('rendering card entry');
|
||||
return <CardDetails productId={props.productId} />;
|
||||
return <CardDetails_ productId={props.productId} />;
|
||||
}
|
||||
}}
|
||||
</Connector>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче