mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 15:47:53 -05:00
Some updates to the redux structure
1. split `auth.js` up so it's 1 reducer per file 2. consolidate the conference schedule reducers 3. make conference reducer names more descriptive 4. add error handling for `body === 'undefined'` Thanks @rschamp for all the help!
This commit is contained in:
parent
bca90bd835
commit
a860b27941
11 changed files with 109 additions and 131 deletions
|
@ -2,7 +2,7 @@ var connect = require('react-redux').connect;
|
|||
var omit = require('lodash.omit');
|
||||
var React = require('react');
|
||||
|
||||
var actions = require('../../redux/auth.js');
|
||||
var sessionActions = require('../../redux/session.js');
|
||||
|
||||
var Modal = require('../modal/modal.jsx');
|
||||
var Registration = require('../registration/registration.jsx');
|
||||
|
@ -48,7 +48,7 @@ var Intro = React.createClass({
|
|||
this.setState({'registrationOpen': false});
|
||||
},
|
||||
completeRegistration: function () {
|
||||
this.props.dispatch(actions.refreshSession());
|
||||
this.props.dispatch(sessionActions.refreshSession());
|
||||
this.closeRegistration();
|
||||
},
|
||||
render: function () {
|
||||
|
|
|
@ -5,7 +5,7 @@ var ReactIntl = require('react-intl');
|
|||
var FormattedMessage = ReactIntl.FormattedMessage;
|
||||
var injectIntl = ReactIntl.injectIntl;
|
||||
|
||||
var actions = require('../../../redux/auth.js');
|
||||
var sessionActions = require('../../../redux/session.js');
|
||||
|
||||
var Api = require('../../../mixins/api.jsx');
|
||||
var Avatar = require('../../avatar/avatar.jsx');
|
||||
|
@ -132,7 +132,7 @@ var Navigation = React.createClass({
|
|||
this.showCanceledDeletion();
|
||||
}
|
||||
}.bind(this));
|
||||
this.props.dispatch(actions.refreshSession());
|
||||
this.props.dispatch(sessionActions.refreshSession());
|
||||
}
|
||||
}
|
||||
// JS error already logged by api mixin
|
||||
|
@ -149,7 +149,7 @@ var Navigation = React.createClass({
|
|||
}, function (err) {
|
||||
if (err) log.error(err);
|
||||
this.closeLogin();
|
||||
this.props.dispatch(actions.refreshSession());
|
||||
this.props.dispatch(sessionActions.refreshSession());
|
||||
}.bind(this));
|
||||
},
|
||||
handleAccountNavClick: function (e) {
|
||||
|
@ -169,7 +169,7 @@ var Navigation = React.createClass({
|
|||
this.setState({'registrationOpen': false});
|
||||
},
|
||||
completeRegistration: function () {
|
||||
this.props.dispatch(actions.refreshSession());
|
||||
this.props.dispatch(sessionActions.refreshSession());
|
||||
this.closeRegistration();
|
||||
},
|
||||
render: function () {
|
||||
|
|
|
@ -6,7 +6,7 @@ var ReactDOM = require('react-dom');
|
|||
var StoreProvider = require('react-redux').Provider;
|
||||
|
||||
var IntlProvider = require('./intl.jsx').IntlProvider;
|
||||
var authActions = require('../redux/auth.js');
|
||||
var sessionActions = require('../redux/session.js');
|
||||
var reducer = require('../redux/reducer.js');
|
||||
|
||||
require('../main.scss');
|
||||
|
@ -43,7 +43,7 @@ var render = function (jsx, element) {
|
|||
);
|
||||
|
||||
// Get initial session
|
||||
store.dispatch(authActions.refreshSession());
|
||||
store.dispatch(sessionActions.refreshSession());
|
||||
};
|
||||
|
||||
module.exports = render;
|
||||
|
|
|
@ -74,6 +74,9 @@ module.exports.getDetails = function (id) {
|
|||
dispatch(module.exports.setDetailsError('Not Found'));
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
dispatch(module.exports.setDetailsError('An unexpected error occurred'));
|
||||
return;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -2,30 +2,17 @@ var keyMirror = require('keymirror');
|
|||
var api = require('../mixins/api.jsx').api;
|
||||
|
||||
var Types = keyMirror({
|
||||
SET_DAY: null,
|
||||
SET_SCHEDULE: null,
|
||||
SET_SCHEDULE_FETCHING: null,
|
||||
SET_DAY_ERROR: null,
|
||||
SET_SCHEDULE_ERROR: null
|
||||
});
|
||||
|
||||
module.exports.dayReducer = function (state, action) {
|
||||
if (typeof state === 'undefined') {
|
||||
state = '';
|
||||
}
|
||||
switch (action.type) {
|
||||
case Types.SET_DAY:
|
||||
return action.day;
|
||||
case Types.SET_DAY_ERROR:
|
||||
return state;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.scheduleReducer = function (state, action) {
|
||||
if (typeof state === 'undefined') {
|
||||
state = [];
|
||||
state = {
|
||||
chunks: [],
|
||||
day: ''
|
||||
};
|
||||
}
|
||||
switch (action.type) {
|
||||
case Types.SET_SCHEDULE:
|
||||
|
@ -39,20 +26,6 @@ module.exports.scheduleReducer = function (state, action) {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports.setDayError = function (error) {
|
||||
return {
|
||||
type: Types.SET_DAY_ERROR,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.setDay = function (day) {
|
||||
return {
|
||||
type: Types.SET_DAY,
|
||||
day: day
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.setSchedule = function (schedule) {
|
||||
return {
|
||||
type: Types.SET_SCHEDULE,
|
||||
|
@ -93,7 +66,6 @@ module.exports.getDaySchedule = function (day) {
|
|||
uri: '/conference/schedule/' + day
|
||||
}, function (err, body) {
|
||||
if (err) {
|
||||
dispatch(module.exports.setDayError(err));
|
||||
dispatch(module.exports.setScheduleError(err));
|
||||
return;
|
||||
}
|
||||
|
@ -150,8 +122,13 @@ module.exports.getDaySchedule = function (day) {
|
|||
items: scheduleByChunk.chunks[scheduleByChunk.info[i].name]
|
||||
});
|
||||
}
|
||||
dispatch(module.exports.setDay(day));
|
||||
dispatch(module.exports.setSchedule(schedule));
|
||||
dispatch(module.exports.setSchedule({
|
||||
chunks: schedule,
|
||||
day: day
|
||||
}));
|
||||
return;
|
||||
} else {
|
||||
dispatch(module.exports.setScheduleError('An unexpected error occurred'));
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
var combineReducers = require('redux').combineReducers;
|
||||
|
||||
var authReducers = require('./auth.js');
|
||||
var conferenceScheduleReducers = require('./conference-schedule.js');
|
||||
var conferenceDetailsReducers = require('./conference-details.js');
|
||||
var scheduleReducer = require('./conference-schedule.js').scheduleReducer;
|
||||
var detailsReducer = require('./conference-details.js').detailsReducer;
|
||||
var sessionReducer = require('./session.js').sessionReducer;
|
||||
var tokenReducer = require('./token.js').tokenReducer;
|
||||
|
||||
var appReducer = combineReducers({
|
||||
session: authReducers.sessionReducer,
|
||||
token: authReducers.tokenReducer,
|
||||
day: conferenceScheduleReducers.dayReducer,
|
||||
schedule: conferenceScheduleReducers.scheduleReducer,
|
||||
details: conferenceDetailsReducers.detailsReducer
|
||||
session: sessionReducer,
|
||||
token: tokenReducer,
|
||||
conferenceSchedule: scheduleReducer,
|
||||
conferenceDetails: detailsReducer
|
||||
});
|
||||
|
||||
module.exports = appReducer;
|
||||
|
|
58
src/redux/session.js
Normal file
58
src/redux/session.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
var keyMirror = require('keymirror');
|
||||
var api = require('../mixins/api.jsx').api;
|
||||
|
||||
var Types = keyMirror({
|
||||
SET_SESSION: null,
|
||||
SET_SESSION_ERROR: null
|
||||
});
|
||||
|
||||
module.exports.sessionReducer = function (state, action) {
|
||||
// Reducer for handling changes to session state
|
||||
if (typeof state === 'undefined') {
|
||||
state = {};
|
||||
}
|
||||
switch (action.type) {
|
||||
case Types.SET_SESSION:
|
||||
return action.session;
|
||||
case Types.SET_SESSION_ERROR:
|
||||
// TODO: do something with action.error
|
||||
return state;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.setSessionError = function (error) {
|
||||
return {
|
||||
type: Types.SET_SESSION_ERROR,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.setSession = function (session) {
|
||||
return {
|
||||
type: Types.SET_SESSION,
|
||||
session: session
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.refreshSession = function () {
|
||||
return function (dispatch) {
|
||||
api({
|
||||
host: '',
|
||||
uri: '/session/'
|
||||
}, function (err, body) {
|
||||
if (err) return dispatch(module.exports.setSessionError(err));
|
||||
|
||||
if (typeof body !== 'undefined') {
|
||||
if (body.banned) {
|
||||
return window.location = body.url;
|
||||
} else {
|
||||
dispatch(module.exports.getToken());
|
||||
dispatch(module.exports.setSession(body));
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
|
@ -1,31 +1,12 @@
|
|||
var keyMirror = require('keymirror');
|
||||
var api = require('../mixins/api.jsx').api;
|
||||
var jar = require('../lib/jar.js');
|
||||
|
||||
var Types = keyMirror({
|
||||
SET_SESSION: null,
|
||||
SET_SESSION_ERROR: null,
|
||||
SET_TOKEN: null,
|
||||
SET_TOKEN_ERROR: null,
|
||||
USE_TOKEN: null
|
||||
});
|
||||
|
||||
module.exports.sessionReducer = function (state, action) {
|
||||
// Reducer for handling changes to session state
|
||||
if (typeof state === 'undefined') {
|
||||
state = {};
|
||||
}
|
||||
switch (action.type) {
|
||||
case Types.SET_SESSION:
|
||||
return action.session;
|
||||
case Types.SET_SESSION_ERROR:
|
||||
// TODO: do something with action.error
|
||||
return state;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.tokenReducer = function (state, action) {
|
||||
// Reducer for updating the api token
|
||||
if (typeof state === 'undefined') {
|
||||
|
@ -42,41 +23,6 @@ module.exports.tokenReducer = function (state, action) {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports.setSessionError = function (error) {
|
||||
return {
|
||||
type: Types.SET_SESSION_ERROR,
|
||||
error: error
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.setSession = function (session) {
|
||||
return {
|
||||
type: Types.SET_SESSION,
|
||||
session: session
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.refreshSession = function () {
|
||||
return function (dispatch) {
|
||||
api({
|
||||
host: '',
|
||||
uri: '/session/'
|
||||
}, function (err, body) {
|
||||
if (err) return dispatch(module.exports.setSessionError(err));
|
||||
|
||||
if (typeof body !== 'undefined') {
|
||||
if (body.banned) {
|
||||
return window.location = body.url;
|
||||
} else {
|
||||
dispatch(module.exports.getToken());
|
||||
dispatch(module.exports.setSession(body));
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.getToken = function () {
|
||||
return function (dispatch) {
|
||||
jar.get('scratchsessionsid', function (err, value) {
|
|
@ -13,7 +13,7 @@ var ConferenceDetails = React.createClass({
|
|||
type: 'ConferenceDetails',
|
||||
propTypes: {
|
||||
detailsId: React.PropTypes.number,
|
||||
details: React.PropTypes.object
|
||||
conferenceDetails: React.PropTypes.object
|
||||
},
|
||||
componentDidMount: function () {
|
||||
var pathname = window.location.pathname.toLowerCase();
|
||||
|
@ -26,13 +26,13 @@ var ConferenceDetails = React.createClass({
|
|||
},
|
||||
render: function () {
|
||||
var backUri = '/conference/schedule';
|
||||
if (!this.props.details.error && !this.props.details.fetching) {
|
||||
backUri = backUri + '#' + this.props.details.Day;
|
||||
if (!this.props.conferenceDetails.error && !this.props.conferenceDetails.fetching) {
|
||||
backUri = backUri + '#' + this.props.conferenceDetails.Day;
|
||||
}
|
||||
var classes = classNames({
|
||||
'inner': true,
|
||||
'details': true,
|
||||
'fetching': this.props.details.fetching
|
||||
'fetching': this.props.conferenceDetails.fetching
|
||||
});
|
||||
return (
|
||||
<div className={classes}>
|
||||
|
@ -41,33 +41,33 @@ var ConferenceDetails = React.createClass({
|
|||
← Back to Full Schedule
|
||||
</a>
|
||||
</div>
|
||||
{this.props.details.error ? [
|
||||
{this.props.conferenceDetails.error ? [
|
||||
<h2>Agenda Item Not Found</h2>
|
||||
] : [
|
||||
<h2>{this.props.details.Title}</h2>,
|
||||
<h2>{this.props.conferenceDetails.Title}</h2>,
|
||||
<ul className="logistics">
|
||||
<li>
|
||||
<img src="/svgs/conference/schedule/presenter-icon.svg" alt="presenter icon" />
|
||||
{this.props.details.Presenter}
|
||||
{this.props.conferenceDetails.Presenter}
|
||||
</li>
|
||||
<li>
|
||||
<img src="/svgs/conference/schedule/time-icon.svg" alt="time icon" />
|
||||
{this.props.details.Start} – {this.props.details.End}
|
||||
{this.props.conferenceDetails.Start} – {this.props.conferenceDetails.End}
|
||||
</li>
|
||||
<li>
|
||||
<img src="/svgs/conference/schedule/event-icon.svg" alt="event icon" />
|
||||
{this.props.details.Type}
|
||||
{this.props.conferenceDetails.Type}
|
||||
</li>
|
||||
<li>
|
||||
<img src="/svgs/conference/schedule/location-icon.svg" alt="location icon" />
|
||||
{this.props.details.Location}
|
||||
{this.props.conferenceDetails.Location}
|
||||
</li>
|
||||
</ul>,
|
||||
<div className="description">
|
||||
{this.props.details.Description}
|
||||
{this.props.conferenceDetails.Description}
|
||||
</div>,
|
||||
<div className="back">
|
||||
{this.props.details.fetching ? [] : [
|
||||
{this.props.conferenceDetails.fetching ? [] : [
|
||||
<a href={backUri}>
|
||||
← Back to Full Schedule
|
||||
</a>
|
||||
|
@ -81,9 +81,7 @@ var ConferenceDetails = React.createClass({
|
|||
|
||||
var mapStateToProps = function (state) {
|
||||
return {
|
||||
details: state.details,
|
||||
fetching: state.fetching,
|
||||
error: state.error
|
||||
conferenceDetails: state.conferenceDetails
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ require('./schedule.scss');
|
|||
var ConferenceSchedule = React.createClass({
|
||||
type: 'ConferenceSchedule',
|
||||
propTypes: {
|
||||
day: React.PropTypes.string,
|
||||
schedule: React.PropTypes.array
|
||||
conferenceSchedule: React.PropTypes.object
|
||||
},
|
||||
componentDidMount: function () {
|
||||
var day = window.location.hash.substr(1) || 'thursday';
|
||||
|
@ -71,14 +70,14 @@ var ConferenceSchedule = React.createClass({
|
|||
render: function () {
|
||||
var tabClasses = {
|
||||
'thursday': classNames({
|
||||
'selected': (this.props.day === 'thursday')
|
||||
'selected': (this.props.conferenceSchedule.day === 'thursday')
|
||||
}),
|
||||
'friday': classNames({
|
||||
'selected': (this.props.day === 'friday')
|
||||
'selected': (this.props.conferenceSchedule.day === 'friday')
|
||||
}),
|
||||
'saturday': classNames({
|
||||
'last': true,
|
||||
'selected': (this.props.day === 'saturday')
|
||||
'selected': (this.props.conferenceSchedule.day === 'saturday')
|
||||
})
|
||||
};
|
||||
return (
|
||||
|
@ -106,7 +105,7 @@ var ConferenceSchedule = React.createClass({
|
|||
</li>
|
||||
</SubNavigation>
|
||||
<div className="inner">
|
||||
{this.props.schedule.map(function (chunk) {
|
||||
{this.props.conferenceSchedule.chunks.map(function (chunk) {
|
||||
return ([
|
||||
<h2 key={chunk.info.name} className="breaking-title">
|
||||
<span>{chunk.info.name} – {chunk.info.time}</span>
|
||||
|
@ -122,10 +121,7 @@ var ConferenceSchedule = React.createClass({
|
|||
|
||||
var mapStateToProps = function (state) {
|
||||
return {
|
||||
day: state.day,
|
||||
schedule: state.schedule,
|
||||
fetching: state.fetching,
|
||||
error: state.error
|
||||
conferenceSchedule: state.conferenceSchedule
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ var omit = require('lodash.omit');
|
|||
var React = require('react');
|
||||
var render = require('../../lib/render.jsx');
|
||||
|
||||
var authActions = require('../../redux/actions.js');
|
||||
var sessionActions = require('../../redux/session.js');
|
||||
|
||||
var Api = require('../../mixins/api.jsx');
|
||||
|
||||
|
@ -167,7 +167,7 @@ var Splash = injectIntl(React.createClass({
|
|||
useCsrf: true,
|
||||
json: {cue: cue, value: false}
|
||||
}, function (err) {
|
||||
if (!err) this.props.dispatch(authActions.refreshSession());
|
||||
if (!err) this.props.dispatch(sessionActions.refreshSession());
|
||||
});
|
||||
},
|
||||
shouldShowWelcome: function () {
|
||||
|
|
Loading…
Reference in a new issue