Ivan - Use ES6 Classes in app components and fix session issues [skip ci]

This commit is contained in:
ivan 2016-08-13 17:23:40 -03:00
parent eaef9b42db
commit 04396db948
20 changed files with 114 additions and 108 deletions

View File

@ -31,7 +31,7 @@ export default {
logout() { logout() {
return { return {
type: 'LOG_OUT', type: 'LOGOUT',
payload: API.call({ payload: API.call({
path: '/user/logout', path: '/user/logout',
data: {} data: {}
@ -48,7 +48,9 @@ export default {
}).then((result) => { }).then((result) => {
if (!result.data.sessionActive) { if (!result.data.sessionActive) {
if (sessionStore.isRememberDataExpired()) { if (sessionStore.isRememberDataExpired()) {
store.dispatch(this.logout()); store.dispatch({
type: 'LOGOUT_FULFILLED'
});
} else { } else {
store.dispatch(this.autoLogin()); store.dispatch(this.autoLogin());
} }

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { browserHistory } from 'react-router';
class App extends React.Component { class App extends React.Component {
static contextTypes = { static contextTypes = {
@ -8,36 +9,12 @@ class App extends React.Component {
location: React.PropTypes.object location: React.PropTypes.object
}; };
constructor(props, context) { componentWillMount() {
super(props, context); this.redirectIfPathIsNotValid(this.props);
if (_.includes(props.location.pathname, '/app/dashboard') && !props.config.logged) {
context.router.push('/app');
}
if (!_.includes(props.location.pathname, '/app/dashboard') && props.config.logged) {
context.router.push('/app/dashboard');
}
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
const validations = { this.redirectIfPathIsNotValid(nextProps);
languageChanged: nextProps.config.language !== this.props.config.language,
loggedIn: nextProps.session.logged && !this.props.session.logged,
loggedOut: !nextProps.session.logged && this.props.session.logged
};
if (validations.languageChanged) {
this.context.router.push(this.props.location.pathname);
}
if (validations.loggedIn) {
this.context.router.push('/app/dashboard');
}
if (validations.loggedOut) {
this.context.router.push('/app');
}
} }
render() { render() {
@ -47,6 +24,26 @@ class App extends React.Component {
</div> </div>
); );
} }
redirectIfPathIsNotValid(props) {
const validations = {
languageChanged: props.config.language !== this.props.config.language,
loggedIn: !_.includes(props.location.pathname, '/app/dashboard') && props.session.logged,
loggedOut: _.includes(props.location.pathname, '/app/dashboard') && !props.session.logged
};
if (validations.languageChanged) {
browserHistory.push(props.location.pathname);
}
if (validations.loggedOut) {
browserHistory.push('/app');
}
if (validations.loggedIn) {
browserHistory.push('/app/dashboard');
}
}
} }
export default connect((store) => { export default connect((store) => {

View File

@ -1,27 +1,27 @@
const React = require('react'); import React from 'react';
const {Router, Route, IndexRoute, browserHistory} = require('react-router'); import {Router, Route, IndexRoute, browserHistory} from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux'; import { syncHistoryWithStore } from 'react-router-redux';
import store from 'app/store'; import store from 'app/store';
const App = require('app/App'); import App from 'app/App';
const DemoPage = require('app/demo/components-demo-page'); import DemoPage from 'app/demo/components-demo-page';
const MainLayout = require('app/main/main-layout'); import MainLayout from 'app/main/main-layout';
const MainHomePage = require('app/main/main-home/main-home-page'); import MainHomePage from 'app/main/main-home/main-home-page';
const MainSignUpPage = require('app/main/main-signup/main-signup-page'); import MainSignUpPage from 'app/main/main-signup/main-signup-page';
const MainRecoverPasswordPage = require('app/main/main-recover-password/main-recover-password-page'); import MainRecoverPasswordPage from 'app/main/main-recover-password/main-recover-password-page';
const DashboardLayout = require('app/main/dashboard/dashboard-layout'); import DashboardLayout from 'app/main/dashboard/dashboard-layout';
const DashboardListTicketsPage = require('app/main/dashboard/dashboard-list-tickets/dashboard-list-tickets-page'); import DashboardListTicketsPage from 'app/main/dashboard/dashboard-list-tickets/dashboard-list-tickets-page';
const DashboardListArticlesPage = require('app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page'); import DashboardListArticlesPage from 'app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page';
const DashboardCreateTicketPage = require('app/main/dashboard/dashboard-create-ticket/dashboard-create-ticket-page'); import DashboardCreateTicketPage from 'app/main/dashboard/dashboard-create-ticket/dashboard-create-ticket-page';
const DashboardEditProfilePage = require('app/main/dashboard/dashboard-edit-profile/dashboard-edit-profile-page'); import DashboardEditProfilePage from 'app/main/dashboard/dashboard-edit-profile/dashboard-edit-profile-page';
const DashboardArticlePage = require('app/main/dashboard/dashboard-article/dashboard-article-page'); import DashboardArticlePage from 'app/main/dashboard/dashboard-article/dashboard-article-page';
const DashboardTicketPage = require('app/main/dashboard/dashboard-ticket/dashboard-ticket-page'); import DashboardTicketPage from 'app/main/dashboard/dashboard-ticket/dashboard-ticket-page';
const history = syncHistoryWithStore(browserHistory, store); const history = syncHistoryWithStore(browserHistory, store);

View File

@ -18,7 +18,7 @@ if (noFixtures === 'disabled') {
let renderApplication = function () { let renderApplication = function () {
render(<Provider store={store}>{routes}</Provider>, document.getElementById('app')); render(<Provider store={store}>{routes}</Provider>, document.getElementById('app'));
}; };
window.store = store;
store.dispatch(SessionActions.initSession()); store.dispatch(SessionActions.initSession());
let unsubscribe = store.subscribe(() => { let unsubscribe = store.subscribe(() => {

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const DashboardArticlePage = React.createClass({ class DashboardArticlePage extends React.Component {
render() { render() {
return ( return (
@ -9,6 +9,6 @@ const DashboardArticlePage = React.createClass({
</div> </div>
); );
} }
}); }
export default DashboardArticlePage; export default DashboardArticlePage;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const DashboardCreateTicketPage = React.createClass({ class DashboardCreateTicketPage extends React.Component {
render() { render() {
return ( return (
@ -9,6 +9,6 @@ const DashboardCreateTicketPage = React.createClass({
</div> </div>
); );
} }
}); }
export default DashboardCreateTicketPage; export default DashboardCreateTicketPage;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const DashboardEditProfilePage = React.createClass({ class DashboardEditProfilePage extends React.Component {
render() { render() {
return ( return (
@ -9,6 +9,6 @@ const DashboardEditProfilePage = React.createClass({
</div> </div>
); );
} }
}); }
export default DashboardEditProfilePage; export default DashboardEditProfilePage;

View File

@ -3,7 +3,7 @@ import {connect} from 'react-redux';
import DashboardMenu from 'app/main/dashboard/dashboard-menu'; import DashboardMenu from 'app/main/dashboard/dashboard-menu';
const DashboardLayout = React.createClass({ class DashboardLayout extends React.Component {
render() { render() {
return (this.props.session.logged) ? ( return (this.props.session.logged) ? (
@ -13,7 +13,7 @@ const DashboardLayout = React.createClass({
</div> </div>
) : null; ) : null;
} }
}); }
export default connect((store) => { export default connect((store) => {
return { return {

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const DashboardListArticlesPage = React.createClass({ class DashboardListArticlesPage extends React.Component {
render() { render() {
return ( return (
@ -9,6 +9,6 @@ const DashboardListArticlesPage = React.createClass({
</div> </div>
); );
} }
}); }
export default DashboardListArticlesPage; export default DashboardListArticlesPage;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const DashboardListTicketsPage = React.createClass({ class DashboardListTicketsPage extends React.Component {
render() { render() {
return ( return (
@ -9,6 +9,6 @@ const DashboardListTicketsPage = React.createClass({
</div> </div>
); );
} }
}); }
export default DashboardListTicketsPage; export default DashboardListTicketsPage;

View File

@ -10,48 +10,48 @@ let dashboardRoutes = [
{ path: '/app/dashboard/edit-profile', text: 'Edit Profile' } { path: '/app/dashboard/edit-profile', text: 'Edit Profile' }
]; ];
const DashboardMenu = React.createClass({ class DashboardMenu extends React.Component {
contextTypes: { static contextTypes = {
router: React.PropTypes.object router: React.PropTypes.object
}, };
propTypes: { static propTypes = {
location: React.PropTypes.object location: React.PropTypes.object
}, };
render() { render() {
return ( return (
<Menu {...this.getProps()} /> <Menu {...this.getProps()} />
); );
}, }
getProps() { getProps() {
return { return {
items: this.getMenuItems(), items: this.getMenuItems(),
selectedIndex: this.getSelectedIndex(), selectedIndex: this.getSelectedIndex(),
onItemClick: this.goToPathByIndex onItemClick: this.goToPathByIndex.bind(this)
}; };
}, }
getMenuItems: function () { getMenuItems() {
return dashboardRoutes.map(this.getMenuItem); return dashboardRoutes.map(this.getMenuItem.bind(this));
}, }
getMenuItem(item) { getMenuItem(item) {
return { return {
content: item.text content: item.text
}; };
}, }
getSelectedIndex() { getSelectedIndex() {
let pathname = this.props.location.pathname; let pathname = this.props.location.pathname;
return _.findIndex(dashboardRoutes, {path: pathname}); return _.findIndex(dashboardRoutes, {path: pathname});
}, }
goToPathByIndex(itemIndex) { goToPathByIndex(itemIndex) {
this.context.router.push(dashboardRoutes[itemIndex].path); this.context.router.push(dashboardRoutes[itemIndex].path);
} }
}); }
export default DashboardMenu; export default DashboardMenu;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const DashboardTicketPage = React.createClass({ class DashboardTicketPage extends React.Component {
render() { render() {
return ( return (
@ -9,6 +9,6 @@ const DashboardTicketPage = React.createClass({
</div> </div>
); );
} }
}); }
export default DashboardTicketPage; export default DashboardTicketPage;

View File

@ -1,9 +1,9 @@
const React = require('react'); import React from 'react';
const classNames = require('classnames'); import classNames from 'classnames';
const Widget = require('core-components/widget'); import Widget from 'core-components/widget';
const MainHomePagePortal = React.createClass({ class MainHomePagePortal extends React.Component {
render() { render() {
return ( return (
<Widget className={classNames('main-home-page-portal', this.props.className)}> <Widget className={classNames('main-home-page-portal', this.props.className)}>
@ -11,6 +11,6 @@ const MainHomePagePortal = React.createClass({
</Widget> </Widget>
); );
} }
}); }
export default MainHomePagePortal; export default MainHomePagePortal;

View File

@ -3,7 +3,7 @@ import React from 'react';
import MainHomePageLoginWidget from 'app/main/main-home/main-home-page-login-widget'; import MainHomePageLoginWidget from 'app/main/main-home/main-home-page-login-widget';
import MainHomePagePortal from 'app/main/main-home/main-home-page-portal'; import MainHomePagePortal from 'app/main/main-home/main-home-page-portal';
const MainHomePage = React.createClass({ class MainHomePage extends React.Component {
render() { render() {
return ( return (
@ -13,6 +13,6 @@ const MainHomePage = React.createClass({
</div> </div>
); );
} }
}); }
export default MainHomePage; export default MainHomePage;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
let MainLayoutFooter = React.createClass({ class MainLayoutFooter extends React.Component {
render() { render() {
return ( return (
@ -11,6 +11,6 @@ let MainLayoutFooter = React.createClass({
</div> </div>
); );
} }
}); }
export default MainLayoutFooter; export default MainLayoutFooter;

View File

@ -36,7 +36,7 @@ class MainLayoutHeader extends React.Component {
result = ( result = (
<div className="main-layout-header--login-links"> <div className="main-layout-header--login-links">
Welcome, John Welcome, John
<Button type="clean" onClick={this.logout}>(Close Session)</Button> <Button type="clean" onClick={this.logout.bind(this)}>(Close Session)</Button>
</div> </div>
); );
} else { } else {

View File

@ -3,22 +3,19 @@ import React from 'react';
import MainHeader from 'app/main/main-layout-header'; import MainHeader from 'app/main/main-layout-header';
import MainFooter from 'app/main/main-layout-footer'; import MainFooter from 'app/main/main-layout-footer';
let MainLayout = React.createClass({ class MainLayout extends React.Component {
render() { render() {
return ( return (
<div className="main-layout"> <div className="main-layout">
<MainHeader /> <MainHeader />
<div className="main-layout--content"> <div className="main-layout--content">
{this.props.children} {this.props.children}
</div> </div>
<MainFooter /> <MainFooter />
</div> </div>
); );
} }
}); }
export default MainLayout; export default MainLayout;

View File

@ -90,7 +90,7 @@ class CheckBox extends React.Component {
if (event.keyCode == 32) { if (event.keyCode == 32) {
event.preventDefault(); event.preventDefault();
callback(this.handleChange, this.props.onChange)({ callback(this.handleChange.bind(this), this.props.onChange)({
target: { target: {
checked: !this.state.checked checked: !this.state.checked
} }

View File

@ -5,14 +5,14 @@ module.exports = [
response: function (data) { response: function (data) {
let response; let response;
if (data.password === 'valid' || (data.rememberToken === 'aa41efe0a1b3eeb9bf303e4561ff8392' && data.userId === 12)) { if (data.password === 'valid' || (data.rememberToken === 'aa41efe0a1b3eeb9bf303e4561ff8392' && data.userId == 12)) {
response = { response = {
status: 'success', status: 'success',
data: { data: {
'userId': 12, 'userId': 12,
'token': 'cc6b4921e6733d6aafe284ec0d7be57e', 'token': 'cc6b4921e6733d6aafe284ec0d7be57e',
'rememberToken': (data.remember) ? 'aa41efe0a1b3eeb9bf303e4561ff8392' : null, 'rememberToken': (data.remember) ? 'aa41efe0a1b3eeb9bf303e4561ff8392' : null,
'rememberExpiration': (data.remember) ? 2018 : 0 'rememberExpiration': (data.remember) ? 20180806 : 0
} }
}; };
} else { } else {
@ -42,7 +42,7 @@ module.exports = [
return { return {
status: 'success', status: 'success',
data: { data: {
sessionActive: true sessionActive: false
} }
}; };
} }

View File

@ -16,12 +16,12 @@ class SessionReducer extends Reducer {
getTypeHandlers() { getTypeHandlers() {
return { return {
'LOGIN_PENDING': this.onLoginPending, 'LOGIN_PENDING': this.onLoginPending,
'LOGIN_FULFILLED': this.onLoginCompleted, 'LOGIN_FULFILLED': this.onLoginCompleted.bind(this),
'LOGIN_REJECTED': this.onLoginFailed, 'LOGIN_REJECTED': this.onLoginFailed,
'LOGOUT_FULFILLED': this.onLogout, 'LOGOUT_FULFILLED': this.onLogout,
'CHECK_SESSION_REJECTED': (state) => { return _.extend({}, state, {initDone: true})}, 'CHECK_SESSION_REJECTED': (state) => { return _.extend({}, state, {initDone: true})},
'SESSION_CHECKED': (state) => { return _.extend({}, state, {initDone: true})}, 'SESSION_CHECKED': (state) => { return _.extend({}, state, {initDone: true, logged: true})},
'LOGIN_AUTO_FULFILLED': this.onAutoLogin, 'LOGIN_AUTO_FULFILLED': this.onAutoLogin.bind(this),
'LOGIN_AUTO_REJECTED': this.onAutoLoginFail 'LOGIN_AUTO_REJECTED': this.onAutoLoginFail
}; };
} }
@ -35,16 +35,8 @@ class SessionReducer extends Reducer {
} }
onLoginCompleted(state, payload) { onLoginCompleted(state, payload) {
if (payload.data.rememberToken) { this.storeLoginResultData(payload.data);
sessionStore.storeRememberData({
token: payload.data.rememberToken,
userId: payload.data.userId,
expiration: payload.data.rememberExpiration
});
} else {
sessionStore.createSession(payload.data.userId, payload.data.token);
}
return _.extend({}, state, { return _.extend({}, state, {
logged: true, logged: true,
pending: false, pending: false,
@ -65,19 +57,25 @@ class SessionReducer extends Reducer {
sessionStore.clearRememberData(); sessionStore.clearRememberData();
return _.extend({}, state, { return _.extend({}, state, {
initDone: true,
logged: false, logged: false,
pending: false, pending: false,
failed: false failed: false
}); });
} }
onAutoLogin() { onAutoLogin(state, payload) {
this.storeLoginResultData(payload.data);
return _.extend({}, state, { return _.extend({}, state, {
initDone: true initDone: true,
logged: true,
pending: false,
failed: false
}); });
} }
onAutoLoginFail() { onAutoLoginFail(state) {
sessionStore.closeSession(); sessionStore.closeSession();
sessionStore.clearRememberData(); sessionStore.clearRememberData();
@ -85,6 +83,18 @@ class SessionReducer extends Reducer {
initDone: true initDone: true
}); });
} }
storeLoginResultData(resultData) {
if (resultData.rememberToken) {
sessionStore.storeRememberData({
token: resultData.rememberToken,
userId: resultData.userId,
expiration: resultData.rememberExpiration
});
} else {
sessionStore.createSession(resultData.userId, resultData.token);
}
}
} }
export default SessionReducer.getInstance(); export default SessionReducer.getInstance();