New user store structure and updated packages
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
import React from 'react';
|
||||
import Link from 'react-router/lib/Link';
|
||||
import Helmet from 'react-helmet';
|
||||
import { observe } from 'mobx';
|
||||
|
||||
import store from 'stores/UserStore';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import DropdownMenu, { MenuItem } from 'components/DropdownMenu';
|
||||
import Flex from 'components/Flex';
|
||||
@@ -14,6 +12,7 @@ import styles from './Layout.scss';
|
||||
import classNames from 'classnames/bind';
|
||||
const cx = classNames.bind(styles);
|
||||
|
||||
@observer(['user'])
|
||||
class Layout extends React.Component {
|
||||
static propTypes = {
|
||||
actions: React.PropTypes.node,
|
||||
@@ -21,9 +20,12 @@ class Layout extends React.Component {
|
||||
titleText: React.PropTypes.node,
|
||||
fixed: React.PropTypes.bool,
|
||||
loading: React.PropTypes.bool,
|
||||
user: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const user = this.props.user;
|
||||
|
||||
return (
|
||||
<div className={ styles.container }>
|
||||
<Helmet
|
||||
@@ -39,7 +41,7 @@ class Layout extends React.Component {
|
||||
) : null }
|
||||
<div className={ cx(styles.header, { fixed: this.props.fixed }) }>
|
||||
<div className={ styles.headerLeft }>
|
||||
<Link to="/" className={ styles.team }>{ store.team.name }</Link>
|
||||
<Link to="/" className={ styles.team }>{ user.team.name }</Link>
|
||||
<span className={ styles.title }>
|
||||
{ this.props.title && (<span> / </span>) }{ this.props.title }
|
||||
</span>
|
||||
@@ -53,10 +55,10 @@ class Layout extends React.Component {
|
||||
<Avatar
|
||||
circle
|
||||
size={24}
|
||||
src={ store.user.avatarUrl }
|
||||
src={ user.user.avatarUrl }
|
||||
/>
|
||||
}>
|
||||
<MenuItem onClick={ store.logout }>Logout</MenuItem>
|
||||
<MenuItem onClick={ user.logout }>Logout</MenuItem>
|
||||
</DropdownMenu>
|
||||
</Flex>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React from 'react';
|
||||
import { observe } from 'mobx'
|
||||
import store from 'stores/UserStore';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import styles from './SlackAuthLink.scss';
|
||||
|
||||
@observer(['user'])
|
||||
class SlackAuthLink extends React.Component {
|
||||
static propTypes = {
|
||||
scopes: React.PropTypes.arrayOf(React.PropTypes.string),
|
||||
user: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
@@ -26,7 +27,7 @@ class SlackAuthLink extends React.Component {
|
||||
redirect_uri: __DEV__ ?
|
||||
'http://localhost:3000/auth/slack/' :
|
||||
'https://www.beautifulatlas.com/auth/slack/',
|
||||
state: store.getOauthState(),
|
||||
state: this.props.user.getOauthState(),
|
||||
};
|
||||
|
||||
const urlParams = Object.keys(params).map(function(key) {
|
||||
|
||||
32
src/index.js
32
src/index.js
@@ -1,11 +1,13 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { Provider } from 'mobx-react';
|
||||
import Router from 'react-router/lib/Router';
|
||||
import Route from 'react-router/lib/Route';
|
||||
import IndexRoute from 'react-router/lib/IndexRoute';
|
||||
import History from 'utils/History';
|
||||
|
||||
import userStore from 'stores/UserStore';
|
||||
import stores from 'stores';
|
||||
window.stores = stores;
|
||||
|
||||
import 'normalize.css/normalize.css';
|
||||
import 'utils/base-styles.scss';
|
||||
@@ -28,7 +30,7 @@ if (__DEV__) {
|
||||
}
|
||||
|
||||
function requireAuth(nextState, replace) {
|
||||
if (!userStore.authenticated) {
|
||||
if (!stores.user.authenticated) {
|
||||
replace({
|
||||
pathname: '/',
|
||||
state: { nextPathname: nextState.location.pathname },
|
||||
@@ -38,20 +40,22 @@ function requireAuth(nextState, replace) {
|
||||
|
||||
render((
|
||||
<div style={{ display: 'flex', flex: 1, }}>
|
||||
<Router history={History}>
|
||||
<Route path="/" component={ Application }>
|
||||
<IndexRoute component={Home} />
|
||||
<Provider user={ stores.user }>
|
||||
<Router history={History}>
|
||||
<Route path="/" component={ Application }>
|
||||
<IndexRoute component={Home} />
|
||||
|
||||
<Route path="/dashboard" component={ Dashboard } onEnter={ requireAuth } />
|
||||
<Route path="/atlas/:id" component={ Atlas } onEnter={ requireAuth } />
|
||||
<Route path="/atlas/:id/new" component={ DocumentEdit } onEnter={ requireAuth } newDocument={ true } />
|
||||
<Route path="/documents/:id" component={ DocumentScene } onEnter={ requireAuth } />
|
||||
<Route path="/documents/:id/edit" component={ DocumentEdit } onEnter={ requireAuth } />
|
||||
<Route path="/documents/:id/new" component={ DocumentEdit } onEnter={ requireAuth } newChildDocument={ true } />
|
||||
<Route path="/dashboard" component={ Dashboard } onEnter={ requireAuth } />
|
||||
<Route path="/atlas/:id" component={ Atlas } onEnter={ requireAuth } />
|
||||
<Route path="/atlas/:id/new" component={ DocumentEdit } onEnter={ requireAuth } newDocument={ true } />
|
||||
<Route path="/documents/:id" component={ DocumentScene } onEnter={ requireAuth } />
|
||||
<Route path="/documents/:id/edit" component={ DocumentEdit } onEnter={ requireAuth } />
|
||||
<Route path="/documents/:id/new" component={ DocumentEdit } onEnter={ requireAuth } newChildDocument={ true } />
|
||||
|
||||
<Route path="/auth/slack" component={SlackAuth} />
|
||||
</Route>
|
||||
</Router>
|
||||
<Route path="/auth/slack" component={SlackAuth} />
|
||||
</Route>
|
||||
</Router>
|
||||
</Provider>
|
||||
{ __DEV__ ? <DevTools position={{ bottom: 0, right: 0 }} /> : null }
|
||||
</div>
|
||||
), document.getElementById('root'));
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from "react";
|
||||
import { observer } from 'mobx-react';
|
||||
import Helmet from "react-helmet";
|
||||
|
||||
const Application = (props) => {
|
||||
const Application = observer((props) => {
|
||||
return (
|
||||
<div style={{ width: '100%' }}>
|
||||
<Helmet
|
||||
@@ -13,7 +14,7 @@ const Application = (props) => {
|
||||
{ props.children }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
Application.propTypes = {
|
||||
children: React.PropTypes.node.isRequired,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import userStore from 'stores/UserStore';
|
||||
import store from './DashboardStore';
|
||||
|
||||
import Flex from 'components/Flex';
|
||||
@@ -14,10 +13,14 @@ import FullscreenField from 'components/FullscreenField';
|
||||
|
||||
import styles from './Dashboard.scss';
|
||||
|
||||
@observer
|
||||
@observer(['user'])
|
||||
class Dashboard extends React.Component {
|
||||
static propTypes = {
|
||||
user: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
store.fetchAtlases(userStore.team.id);
|
||||
store.fetchAtlases(this.props.user.team.id);
|
||||
}
|
||||
|
||||
state = {
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import React from 'react';
|
||||
import store from 'stores/UserStore';
|
||||
import { observer } from 'mobx-react';
|
||||
import { browserHistory } from 'react-router'
|
||||
|
||||
import SlackAuthLink from 'components/SlackAuthLink';
|
||||
|
||||
import styles from './Home.scss';
|
||||
|
||||
@observer(['user'])
|
||||
export default class Home extends React.Component {
|
||||
static propTypes = {
|
||||
user: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
if (store.authenticated) {
|
||||
if (this.props.user.authenticated) {
|
||||
browserHistory.replace('/dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import React from 'react';
|
||||
import store from 'stores/UserStore';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
@observer(['user'])
|
||||
class SlackAuth extends React.Component {
|
||||
static propTypes = {
|
||||
user: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
export default class SlackAuth extends React.Component {
|
||||
componentDidMount = () => {
|
||||
const { code, state } = this.props.location.query;
|
||||
store.authWithSlack(code, state);
|
||||
this.props.user.authWithSlack(code, state);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -13,3 +18,5 @@ export default class SlackAuth extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SlackAuth;
|
||||
@@ -1,11 +1,10 @@
|
||||
import { observable, action, computed, autorun } from 'mobx';
|
||||
import { observable, action, computed } from 'mobx';
|
||||
import { browserHistory } from 'react-router';
|
||||
import { client } from 'utils/ApiClient';
|
||||
import localforage from 'localforage';
|
||||
|
||||
const USER_STORE = 'USER_STORE';
|
||||
|
||||
const store = new class UserStore {
|
||||
class UserStore {
|
||||
@observable user;
|
||||
@observable team;
|
||||
|
||||
@@ -71,12 +70,9 @@ const store = new class UserStore {
|
||||
this.token = data.token;
|
||||
this.oauthState = data.oauthState;
|
||||
}
|
||||
}();
|
||||
};
|
||||
|
||||
// Persist store to localStorage
|
||||
autorun(() => {
|
||||
localStorage.setItem(USER_STORE, store.asJson);
|
||||
});
|
||||
|
||||
|
||||
export default store;
|
||||
export default UserStore;
|
||||
export {
|
||||
USER_STORE,
|
||||
};
|
||||
|
||||
13
src/stores/index.js
Normal file
13
src/stores/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import UserStore, { USER_STORE } from './UserStore';
|
||||
import { autorun } from 'mobx';
|
||||
|
||||
const stores = {
|
||||
user: new UserStore(),
|
||||
};
|
||||
|
||||
// Persist store to localStorage
|
||||
autorun(() => {
|
||||
localStorage.setItem(USER_STORE, stores.user.asJson);
|
||||
});
|
||||
|
||||
export default stores;
|
||||
@@ -1,5 +1,5 @@
|
||||
import _map from 'lodash/map';
|
||||
import store from 'stores/UserStore';
|
||||
import stores from 'stores';
|
||||
|
||||
import constants from '../constants';
|
||||
|
||||
@@ -25,8 +25,8 @@ class ApiClient {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': this.userAgent,
|
||||
});
|
||||
if (store.authenticated) {
|
||||
headers.set('Authorization', `Bearer ${store.token}`);
|
||||
if (stores.user.authenticated) {
|
||||
headers.set('Authorization', `Bearer ${stores.user.token}`);
|
||||
}
|
||||
|
||||
// Construct request
|
||||
@@ -48,7 +48,7 @@ class ApiClient {
|
||||
|
||||
// Handle 401, log out user
|
||||
if (response.status === 401) {
|
||||
store.logout();
|
||||
stores.user.logout();
|
||||
}
|
||||
|
||||
// Handle failed responses
|
||||
|
||||
Reference in New Issue
Block a user