diff --git a/RoboFile.php b/RoboFile.php
index b21ccbb709..1f12204f28 100644
--- a/RoboFile.php
+++ b/RoboFile.php
@@ -9,7 +9,9 @@ class RoboFile extends \Robo\Tasks {
private $js_files = array(
'assets/js/src/*.js',
- 'assets/js/src/**/*.js'
+ 'assets/js/src/*.jsx',
+ 'assets/js/src/**/*.js',
+ 'assets/js/src/**/*.jsx'
);
function install() {
diff --git a/assets/js/src/admin.js b/assets/js/src/admin.js
index a3364da6e3..05ebb877a9 100644
--- a/assets/js/src/admin.js
+++ b/assets/js/src/admin.js
@@ -1,12 +1,13 @@
define('admin', [
'mailpoet',
- 'jquery',
- 'handlebars',
- ], function(MailPoet, jQuery, Handlebars) {
- jQuery(function($) {
- // dom ready
- $(function() {
+ 'jquery'
+ ],
+ function(MailPoet, jQuery) {
+ jQuery(function($) {
+ // dom ready
+ $(function() {
+ });
});
- });
-});
+ }
+);
diff --git a/assets/js/src/public.js b/assets/js/src/public.js
index 795797306d..4b6c4ec814 100644
--- a/assets/js/src/public.js
+++ b/assets/js/src/public.js
@@ -1,6 +1,8 @@
-jQuery(function($) {
+define('public', ['jquery'], function(jQuery) {
+ jQuery(function($) {
// dom ready
$(function() {
});
-});
\ No newline at end of file
+ });
+});
diff --git a/assets/js/src/settings.jsx b/assets/js/src/settings.jsx
new file mode 100644
index 0000000000..0470001248
--- /dev/null
+++ b/assets/js/src/settings.jsx
@@ -0,0 +1,203 @@
+define('settings', ['react'], function(React) {
+
+ var STATES = [
+ 'AL', 'AK', 'AS', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FL', 'GA', 'HI',
+ 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS',
+ 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR',
+ 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'
+ ]
+
+ var Example = React.createClass({
+ getInitialState: function() {
+ return {
+ email: true
+ , question: true
+ , submitted: null
+ }
+ },
+ render: function() {
+ var submitted
+ if (this.state.submitted !== null) {
+ submitted =
+
ContactForm data:
+
{JSON.stringify(this.state.submitted, null, ' ')}
+
+ }
+
+ return
+ },
+ handleChange: function(field, e) {
+ var nextState = {}
+ nextState[field] = e.target.checked
+ this.setState(nextState)
+ },
+ handleSubmit: function() {
+ if (this.refs.contactForm.isValid()) {
+ this.setState({submitted: this.refs.contactForm.getFormData()})
+ }
+ }
+ })
+
+ /**
+ * A contact form with certain optional fields.
+ */
+ var ContactForm = React.createClass({
+ getDefaultProps: function() {
+ return {
+ email: true
+ , question: false
+ }
+ },
+ getInitialState: function() {
+ return {errors: {}}
+ },
+ isValid: function() {
+ var fields = ['firstName', 'lastName', 'phoneNumber', 'address', 'city', 'state', 'zipCode']
+ if (this.props.email) fields.push('email')
+ if (this.props.question) fields.push('question')
+
+ var errors = {}
+ fields.forEach(function(field) {
+ var value = trim(this.refs[field].getDOMNode().value)
+ if (!value) {
+ errors[field] = 'This field is required'
+ }
+ }.bind(this))
+ this.setState({errors: errors})
+
+ var isValid = true
+ for (var error in errors) {
+ isValid = false
+ break
+ }
+ return isValid
+ },
+ getFormData: function() {
+ var data = {
+ firstName: this.refs.firstName.getDOMNode().value
+ , lastName: this.refs.lastName.getDOMNode().value
+ , phoneNumber: this.refs.phoneNumber.getDOMNode().value
+ , address: this.refs.address.getDOMNode().value
+ , city: this.refs.city.getDOMNode().value
+ , state: this.refs.state.getDOMNode().value
+ , zipCode: this.refs.zipCode.getDOMNode().value
+ , currentCustomer: this.refs.currentCustomerYes.getDOMNode().checked
+ }
+ if (this.props.email) data.email = this.refs.email.getDOMNode().value
+ if (this.props.question) data.question = this.refs.question.getDOMNode().value
+ return data
+ },
+ render: function() {
+ return
+ {this.renderTextInput('firstName', 'First Name')}
+ {this.renderTextInput('lastName', 'Last Name')}
+ {this.renderTextInput('phoneNumber', 'Phone number')}
+ {this.props.email && this.renderTextInput('email', 'Email')}
+ {this.props.question && this.renderTextarea('question', 'Question')}
+ {this.renderTextInput('address', 'Address')}
+ {this.renderTextInput('city', 'City')}
+ {this.renderSelect('state', 'State', STATES)}
+ {this.renderTextInput('zipCode', 'Zip Code')}
+ {this.renderRadioInlines('currentCustomer', 'Are you currently a ' + this.props.company + ' Customer?', {
+ values: ['Yes', 'No']
+ , defaultCheckedValue: 'No'
+ })}
+
+ },
+ renderTextInput: function(id, label) {
+ return this.renderField(id, label,
+
+ )
+ },
+ renderTextarea: function(id, label) {
+ return this.renderField(id, label,
+