-
-
Save captainill/5b5167a69afe7698f06a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @jsx React.DOM */ | |
/* jshint trailing:false, quotmark:false, newcap:false */ | |
define(function (require) { | |
'use strict'; | |
var React = require('react'), | |
Promise = require('bluebird'), | |
$ = require('jquery'); | |
var UNSENT_FEEDBACK_KEY = 'common.views.FeedbackWidget.unsentFeedback'; | |
var STATUS = { | |
INITIAL: 'initial', | |
SENDING: 'sending', | |
SENT: 'sent' | |
}; | |
var FeedbackWidget = React.createClass({ | |
propTypes: { | |
closeModal: React.PropTypes.func.isRequired | |
}, | |
getInitialState: function () { | |
return { | |
text: this.getFeedbackFromLocalStorage() || '', | |
status: STATUS.INITIAL | |
}; | |
}, | |
render: function () { | |
var status = this.state.status, | |
footer; | |
footer = (status === STATUS.SENT) ? | |
<span>Thank you for your feedback.</span> : | |
<a className='Btn Btn--large' onClick={this.beginSend} | |
data-disabled={status !== STATUS.INITIAL}> | |
Send | |
</a>; | |
return ( | |
<div className='Feedback'> | |
<div onClick={this.props.showModal} className='Modal-close'> | |
<i className='icon-cross'></i> | |
</div> | |
<h3 className='Modal-title'> | |
Send Feedback | |
</h3> | |
<p className='Modal-message'> | |
Got ideas, problems, or just want to say hi? | |
</p> | |
<div className='Form'> | |
<div className='Form-group'> | |
<textarea className='Form-control Feedback-field' | |
placeholder='Jot it down here and press Send' | |
value={this.state.text} | |
onChange={this.handleChange} | |
ref='textarea' | |
autoFocus | |
disabled={status !== STATUS.INITIAL} /> | |
</div> | |
</div> | |
<div className='Modal-footer'> | |
{footer} | |
</div> | |
</div> | |
); | |
}, | |
handleChange: function (e) { | |
var text = e.target.value; | |
if (this.state.status === STATUS.INITIAL) { | |
this.saveFeedbackInLocalStorage(text); | |
} | |
this.setState({ | |
text: text | |
}); | |
}, | |
setStatus: function (status) { | |
if (!status) { | |
throw new Error('Empty status'); | |
} | |
this.setState({ | |
status: status | |
}); | |
}, | |
beginSend: function () { | |
if (this.state.status !== STATUS.INITIAL) { | |
throw new Error('Gotta be in initial state.'); | |
} | |
this.setStatus(STATUS.SENDING); | |
this.postFeedback(this.state.text) | |
.bind(this) | |
.then(function () { | |
this.setStatus(STATUS.SENT); | |
this.clearFeedbackInLocalStorage(); | |
}) | |
.catch(function (err) { | |
this.setStatus(STATUS.INITIAL); | |
this.refs.textarea.getDOMNode().focus(); | |
console.log('Error sending feedback', err); | |
}); | |
}, | |
postFeedback: function (text) { | |
var data = { | |
'feedback': text, | |
'current_url': window.location.href | |
}; | |
return Promise.cast($.ajax({ | |
url: '/api/feedback', | |
type: 'POST', | |
data: JSON.stringify(data), | |
contentType: 'application/json; charset=utf-8', | |
dataType: 'json' | |
})); | |
}, | |
getFeedbackFromLocalStorage: function () { | |
return localStorage.getItem(UNSENT_FEEDBACK_KEY); | |
}, | |
saveFeedbackInLocalStorage: function (text) { | |
localStorage.setItem(UNSENT_FEEDBACK_KEY, text); | |
}, | |
clearFeedbackInLocalStorage: function () { | |
localStorage.removeItem(UNSENT_FEEDBACK_KEY); | |
} | |
}); | |
return FeedbackWidget; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @jsx React.DOM */ | |
/* jshint trailing:false, quotmark:false, newcap:false */ | |
define(function (require) { | |
'use strict'; | |
var React = require('react'), | |
Promise = require('bluebird'), | |
$ = require('jquery'), | |
_ = require('underscore'); | |
var STATUS = { | |
INITIAL: 'initial', | |
SENDING: 'sending', | |
SENT: 'sent' | |
}; | |
var JoinWidget = React.createClass({ | |
mixins: [React.addons.LinkedStateMixin], | |
propTypes: { | |
closeModal: React.PropTypes.func.isRequired, | |
showLogin: React.PropTypes.func.isRequired | |
}, | |
getInitialState: function () { | |
return { | |
name: '', | |
email: '', | |
website: '', | |
status: STATUS.INITIAL | |
}; | |
}, | |
maySend: function () { | |
return this.state.status === STATUS.INITIAL && | |
this.state.name && | |
this.state.email && | |
this.state.website; | |
}, | |
getFooter: function (status) { | |
if (status === STATUS.SENT) { | |
return ( | |
<div className='Modal-footer'> | |
Thank you! We will contact you soon. | |
</div> | |
); | |
} | |
return ( | |
<div className='Modal-footer'> | |
<span className='Modal-footer-text'> | |
Already invited? | |
<a onClick={this.props.showLogin}>Sign in</a>. | |
</span> | |
<a className='Btn Btn--large' onClick={this.beginSend} | |
data-disabled={!this.maySend()}> | |
Send | |
</a> | |
</div> | |
); | |
}, | |
render: function () { | |
var status = this.state.status, | |
footer = this.getFooter(status); | |
return ( | |
<div className='social-Join'> | |
<div className='Modal-close' onClick={this.props.closeModal}> | |
<i className='icon-cross'></i> | |
</div> | |
<h3 className='Modal-title'> | |
Request Invite | |
</h3> | |
<p className='Modal-message'> | |
Want to be a part of (redacted)? Awesome! | |
<br/><br/> | |
For now we’re invite-only. Fill in the application and hit Send. | |
</p> | |
<div className='Form'> | |
<div className='Form-group'> | |
<input valueLink={this.linkState('name')} disabled={status !== STATUS.INITIAL} autofocus | |
type='text' className='Form-control' placeholder='Name' /> | |
<input valueLink={this.linkState('email')} disabled={status !== STATUS.INITIAL} | |
type='email' className='Form-control' placeholder='Email' /> | |
<input valueLink={this.linkState('website')} disabled={status !== STATUS.INITIAL} | |
type='url' className='Form-control' placeholder='Website' /> | |
</div> | |
</div> | |
{footer} | |
</div> | |
); | |
}, | |
setStatus: function (status) { | |
if (!status) { | |
throw new Error('Empty status'); | |
} | |
this.setState({ | |
status: status | |
}); | |
}, | |
beginSend: function () { | |
if (this.state.status !== STATUS.INITIAL) { | |
throw new Error('Gotta be in initial state.'); | |
} | |
this.setStatus(STATUS.SENDING); | |
this.sendInviteRequest(_.pick(this.state, 'email', 'name', 'website')) | |
.bind(this) | |
.then(function () { | |
this.setStatus(STATUS.SENT); | |
}) | |
.catch(function (err) { | |
this.setStatus(STATUS.INITIAL); | |
console.log('Error requesting invite', err); | |
}); | |
}, | |
sendInviteRequest: function (options) { | |
var data = _.extend(options, { | |
'current_url': window.location.href | |
}); | |
return Promise.cast($.ajax({ | |
url: '/api/invite_requests', | |
type: 'POST', | |
data: JSON.stringify(data), | |
contentType: 'application/json; charset=utf-8', | |
dataType: 'json' | |
})); | |
} | |
}); | |
return JoinWidget; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment