Merge pull request #227 from LLK/2.2.3-hotfix

2.2.3 hotfix
This commit is contained in:
Ray Schamp 2015-11-12 14:28:35 -05:00
commit 2596dc04d8
18 changed files with 132 additions and 14 deletions

View file

@ -46,6 +46,7 @@
"lodash.clone": "3.0.3",
"lodash.defaultsdeep": "3.10.0",
"lodash.omit": "3.1.0",
"lodash.range": "3.0.1",
"minilog": "2.0.8",
"node-sass": "3.3.3",
"po2icu": "git://github.com/LLK/po2icu.git#develop",

View file

@ -18,6 +18,9 @@ module.exports = {
// Analytics & Monitoring
ga_tracker: process.env.GA_TRACKER || '',
// Error handling
sentry_dsn: process.env.SENTRY_DSN || '',
// Use minified JS libraries
min: (process.env.NODE_ENV === 'production') ? '.min' : ''
};

View file

@ -48,10 +48,16 @@
<!-- Scripts -->
<script src="/js/lib/react{{min}}.js"></script>
<script src="/js/lib/react-dom{{min}}.js"></script>
<script src="/js/lib/raven.min.js"></script>
<script src="/js/main.bundle.js"></script>
<script src="/js/{{view}}.bundle.js"></script>
<!-- Error logging (Sentry) -->
<script>
Raven.config('{{&sentry_dsn}}').install()
</script>
<!-- Analytics (GA) -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){

View file

@ -9,6 +9,7 @@ $background-color: hsla(0, 0, 99, 1); //#FDFDFD
/* UI Secondary Colors */
$ui-aqua: hsla(170, 70, 50, 1); //#26D9BB
$ui-purple: hsla(265, 55, 55, 1); //#824DCB
$ui-white: #fff;
$ui-border: hsla(0, 0, 85, 1); //#D9D9D9

View file

@ -34,7 +34,7 @@ var Activity = React.createClass({
title={formatMessage(defaultMessages.whatsHappening)}>
{this.props.items && this.props.items.length > 0 ? [
<ul>
<ul key="activity-ul">
{this.props.items.map(function (item) {
if (item.message.replace(/\s/g, '')) {
var actorProfileUrl = '/users/' + item.actor.username + '/';
@ -60,7 +60,7 @@ var Activity = React.createClass({
})}
</ul>
] : [
<div className="empty">
<div className="empty" key="activity-empty">
<h4>
<FormattedMessage
id="activity.seeUpdates"

View file

@ -2,8 +2,11 @@ var React = require('react');
var ReactDOM = require('react-dom');
var FormattedMessage = require('react-intl').FormattedMessage;
var log = require('../../lib/log.js');
var Input = require('../forms/input.jsx');
var Button = require('../forms/button.jsx');
var Spinner = require('../spinner/spinner.jsx');
require('./login.scss');
@ -13,12 +16,21 @@ var Login = React.createClass({
onLogIn: React.PropTypes.func,
error: React.PropTypes.string
},
getInitialState: function () {
return {
waiting: false
};
},
handleSubmit: function (event) {
event.preventDefault();
this.setState({waiting: true});
this.props.onLogIn({
'username': ReactDOM.findDOMNode(this.refs.username).value,
'password': ReactDOM.findDOMNode(this.refs.password).value
});
}, function (err) {
if (err) log.error(err);
this.setState({waiting: false});
}.bind(this));
},
render: function () {
var error;
@ -40,11 +52,17 @@ var Login = React.createClass({
defaultMessage={'Password'} />
</label>
<Input type="password" ref="password" name="password" />
<Button className="submit-button white" type="submit">
<FormattedMessage
id='general.signIn'
defaultMessage={'Sign in'} />
</Button>
{this.state.waiting ? [
<Button className="submit-button white" type="submit" disabled="disabled">
<Spinner />
</Button>
] : [
<Button className="submit-button white" type="submit">
<FormattedMessage
id='general.signIn'
defaultMessage={'Sign in'} />
</Button>
]}
<a className="right" href="/accounts/password_reset/">
<FormattedMessage
id='login.forgotPassword'

View file

@ -8,6 +8,12 @@
font-weight: bold;
}
.spinner {
margin: 0 .8rem;
width: 1rem;
height: 1rem;
}
.submit-button {
margin-top: 5px;
}

View file

@ -116,7 +116,7 @@ var Navigation = React.createClass({
closeLogin: function () {
this.setState({'loginOpen': false});
},
handleLogIn: function (formData) {
handleLogIn: function (formData, callback) {
this.setState({'loginError': null});
formData['useMessages'] = true;
this.api({
@ -126,12 +126,14 @@ var Navigation = React.createClass({
json: formData,
useCsrf: true
}, function (err, body) {
if (err) this.setState({'loginError': err.message});
if (body) {
body = body[0];
if (!body.success) {
if (body.redirect) {
window.location = body.redirect;
}
// Update login error message to a friendlier one if it exists
this.setState({'loginError': body.msg});
} else {
this.closeLogin();
@ -143,6 +145,8 @@ var Navigation = React.createClass({
window.refreshSession();
}
}
// JS error already logged by api mixin
callback();
}.bind(this));
},
handleLogOut: function (e) {

View file

@ -0,0 +1,20 @@
var range = require('lodash.range');
var React = require('react');
require('./spinner.scss');
var Spinner = React.createClass({
// Adapted from http://tobiasahlin.com/spinkit/
type: 'Spinner',
render: function () {
return (
<div className="spinner">
{range(1,13).map(function (id) {
return <div className={'circle' + id + ' circle'}></div>;
})}
</div>
);
}
});
module.exports = Spinner;

View file

@ -0,0 +1,47 @@
@import "../../colors";
.spinner {
position: relative;
width: 20px;
height: 20px;
.circle {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
&:before {
display: block;
animation: circleFadeDelay 1.2s infinite ease-in-out both;
margin: 0 auto;
border-radius: 100%;
background-color: darken($ui-blue, 8%);
width: 15%;
height: 15%;
content: "";
-webkit-animation: circleFadeDelay 1.2s infinite ease-in-out both;
}
}
@for $i from 1 through 12 {
$rotation: 30deg * ($i - 1);
$delay: -1.3s + $i * .1;
.circle#{$i} {
transform: rotate($rotation);
-ms-transform: rotate($rotation);
-webkit-transform: rotate($rotation);
}
.circle#{$i}:before {
animation-delay: $delay;
-webkit-animation-delay: $delay;
}
}
}
@keyframes circleFadeDelay {
0%, 39%, 100% { opacity: 0; }
40% { opacity: 1; }
}

View file

@ -26,6 +26,12 @@ var Api = {
opts.uri = opts.host + opts.uri;
var apiRequest = function (opts) {
if (opts.host !== '') {
// For IE < 10, we must use XDR for cross-domain requests. XDR does not support
// custom headers.
defaults(opts, {useXDR: true});
delete opts.headers;
}
xhr(opts, function (err, res, body) {
if (err) log.error(err);
callback(err, body);

View file

@ -6,6 +6,7 @@ var Box = require('../../components/box/box.jsx');
var Button = require('../../components/forms/button.jsx');
var Carousel = require('../../components/carousel/carousel.jsx');
var Input = require('../../components/forms/input.jsx');
var Spinner = require('../../components/spinner/spinner.jsx');
require('./components.scss');
@ -37,6 +38,8 @@ var Components = React.createClass({
<Activity />
<h1>{'Nothing!!!'}</h1>
<Activity items={[]} />
<h1>This is a Spinner</h1>
<Spinner />
</div>
);
}

View file

@ -122,7 +122,7 @@ var Hoc = React.createClass({
<div className="inner">
<Box title={''}>
<section className="one-up">
<section id="teacher" className="one-up">
<div className="column">
<h3>
<FormattedMessage
@ -272,13 +272,13 @@ var Hoc = React.createClass({
</div>
<div className="card">
<a href="/projects/editor/?tip_bar=pong">
<a href="/hoops">
<div className="card-info">
<img src="/images/hoc2015/pong-tutorial.jpg" />
<img src="/images/hoc2015/bball-tutorial.jpg" />
<Button>
<FormattedMessage
id='general.tipsPongGame'
defaultMessage={'Create a Pong Game'} />
id='general.tipsBBallHoops'
defaultMessage={'B-Ball Hoops'} />
</Button>
</div>
</a>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 94 KiB

3
static/js/lib/raven.min.js vendored Normal file

File diff suppressed because one or more lines are too long