Eradicated Redux for MobX

This commit is contained in:
Jori Lallo
2016-06-04 18:28:14 -07:00
parent 19712a41f9
commit c2f1ea22b9
20 changed files with 177 additions and 505 deletions

View File

@ -1,59 +0,0 @@
import makeActionCreator from '../utils/actions';
import { client } from 'utils/ApiClient';
import { normalize, Schema, arrayOf } from 'normalizr';
const atlas = new Schema('atlases');
export const FETCH_ATLASES_PENDING = 'FETCH_ATLASES_PENDING';
export const FETCH_ATLASES_SUCCESS = 'FETCH_ATLASES_SUCCESS';
export const FETCH_ATLASES_FAILURE = 'FETCH_ATLASES_FAILURE';
const fetchAtlasesPending = makeActionCreator(FETCH_ATLASES_PENDING);
const fetchAtlasesSuccess = makeActionCreator(FETCH_ATLASES_SUCCESS, 'data', 'pagination');
const fetchAtlasesFailure = makeActionCreator(FETCH_ATLASES_FAILURE, 'error');
export function fetchAtlasesAsync(teamId) {
return (dispatch) => {
dispatch(fetchAtlasesPending());
client.post('/atlases.list', {
teamId: teamId,
})
.then(data => {
const response = normalize(data.data, arrayOf(atlas));
dispatch(fetchAtlasesSuccess(response, data.pagination));
})
.catch((err) => {
dispatch(fetchAtlasesFailure(err));
})
};
};
export const FETCH_ATLAS_PENDING = 'FETCH_ATLAS_PENDING';
export const FETCH_ATLAS_SUCCESS = 'FETCH_ATLAS_SUCCESS';
export const FETCH_ATLAS_FAILURE = 'FETCH_ATLAS_FAILURE';
const fetchAtlasPending = makeActionCreator(FETCH_ATLAS_PENDING);
const fetchAtlasSuccess = makeActionCreator(FETCH_ATLAS_SUCCESS, 'data');
const fetchAtlasFailure = makeActionCreator(FETCH_ATLAS_FAILURE, 'error');
export function fetchAtlasAsync(atlasId) {
return (dispatch) => {
dispatch(fetchAtlasPending());
client.post('/atlases.info', {
id: atlasId,
})
.then(data => {
const response = normalize(data.data, atlas);
dispatch(fetchAtlasSuccess(response));
})
.catch((err) => {
dispatch(fetchAtlasFailure(err));
})
};
};

View File

@ -1,91 +0,0 @@
import makeActionCreator from '../utils/actions';
import { replace } from 'react-router-redux';
import { client } from 'utils/ApiClient';
import { createAction } from 'redux-actions';
export const resetDocument = createAction('RESET_DOCUMENT');
// GET
export const FETCH_DOCUMENT_PENDING = 'FETCH_DOCUMENT_PENDING';
export const FETCH_DOCUMENT_SUCCESS = 'FETCH_DOCUMENT_SUCCESS';
export const FETCH_DOCUMENT_FAILURE = 'FETCH_DOCUMENT_FAILURE';
const fetchDocumentPending = makeActionCreator(FETCH_DOCUMENT_PENDING);
const fetchDocumentSuccess = makeActionCreator(FETCH_DOCUMENT_SUCCESS, 'data');
const fetchDocumentFailure = makeActionCreator(FETCH_DOCUMENT_FAILURE, 'error');
export function fetchDocumentAsync(documentId) {
return (dispatch) => {
dispatch(fetchDocumentPending());
client.post('/documents.info', {
id: documentId,
})
.then(data => {
dispatch(fetchDocumentSuccess(data.data));
})
.catch((err) => {
dispatch(fetchDocumentFailure(err));
})
};
};
// POST/UPDATE
export const SAVE_DOCUMENT_PENDING = 'SAVE_DOCUMENT_PENDING';
export const SAVE_DOCUMENT_SUCCESS = 'SAVE_DOCUMENT_SUCCESS';
export const SAVE_DOCUMENT_FAILURE = 'SAVE_DOCUMENT_FAILURE';
const saveDocumentPending = makeActionCreator(SAVE_DOCUMENT_PENDING);
const saveDocumentSuccess = makeActionCreator(SAVE_DOCUMENT_SUCCESS, 'data');
const saveDocumentFailure = makeActionCreator(SAVE_DOCUMENT_FAILURE, 'error');
export function saveDocumentAsync(atlasId, documentId, title, text) {
return (dispatch) => {
dispatch(saveDocumentPending());
let url;
let data = {
title,
text,
};
if (documentId) {
url = '/documents.update';
data.id = documentId;
} else {
url = '/documents.create';
data.atlas = atlasId;
}
client.post(url, data)
.then(data => {
dispatch(saveDocumentSuccess(data.data, data.pagination));
dispatch(replace(`/documents/${data.data.id}`));
})
.catch((err) => {
dispatch(saveDocumentFailure(err));
})
};
};
// documents.delete
export const deleteDocumentPending = createAction('DELETE_DOCUMENT_PENDING');
export const deleteDocumentSuccess = createAction('DELETE_DOCUMENT_SUCCESS');
export const deleteDocumentFailure = createAction('DELETE_DOCUMENT_FAILURE');
export const deleteDocument = (documentId, returnPath) => {
return (dispatch) => {
dispatch(deleteDocumentPending());
client.post('/documents.delete', { id: documentId })
.then(data => {
dispatch(deleteDocumentSuccess(documentId));
dispatch(replace(returnPath));
})
.catch((err) => {
dispatch(deleteDocumentFailure(err));
})
};
};

View File

@ -1,7 +0,0 @@
import { createAction } from 'redux-actions';
export const resetEditor = createAction('EDITOR_RESET');
export const updateText = createAction('EDITOR_UPDATE_TEXT');
export const updateTitle = createAction('EDITOR_UPDATE_TITLE');
export const replaceText = createAction('EDITOR_REPLACE_TEXT');

View File

@ -1,5 +0,0 @@
import makeActionCreator from '../utils/actions';
export const UPDATE_TEAM = 'UPDATE_TEAM';
export const updateTeam = makeActionCreator(UPDATE_TEAM, 'team');

View File

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react';
import Link from 'react-router/lib/Link'; import Link from 'react-router/lib/Link';
import DocumentLink from './components/DocumentLink'; import DocumentLink from './components/DocumentLink';
@ -7,6 +8,7 @@ import styles from './AtlasPreview.scss';
import classNames from 'classnames/bind'; import classNames from 'classnames/bind';
const cx = classNames.bind(styles); const cx = classNames.bind(styles);
@observer
class AtlasPreview extends React.Component { class AtlasPreview extends React.Component {
static propTypes = { static propTypes = {
data: React.PropTypes.object.isRequired, data: React.PropTypes.object.isRequired,

View File

@ -1,17 +1,18 @@
import React from 'react'; import React from 'react';
import { observer } from "mobx-react"
import moment from 'moment'; import moment from 'moment';
import Link from 'react-router/lib/Link'; import Link from 'react-router/lib/Link';
import styles from './DocumentLink.scss'; import styles from './DocumentLink.scss';
const DocumentLink = (props) => { const DocumentLink = observer((props) => {
return ( return (
<Link to={ `/documents/${props.document.id}` } className={ styles.link }> <Link to={ `/documents/${props.document.id}` } className={ styles.link }>
<h3 className={ styles.title }>{ props.document.title }</h3> <h3 className={ styles.title }>{ props.document.title }</h3>
<span className={ styles.timestamp }>{ moment(props.document.updatedAt).fromNow() }</span> <span className={ styles.timestamp }>{ moment(props.document.updatedAt).fromNow() }</span>
</Link> </Link>
); );
}; });
export default DocumentLink; export default DocumentLink;

View File

@ -98,7 +98,6 @@ class MarkdownAtlas extends React.Component {
onPaddingTopClick = () => { onPaddingTopClick = () => {
const cm = this.getEditorInstance(); const cm = this.getEditorInstance();
console.log(cm)
cm.setCursor(0, 0); cm.setCursor(0, 0);
cm.focus(); cm.focus();
} }

View File

@ -11,9 +11,7 @@ import createLogger from 'redux-logger';
import History from 'utils/History'; import History from 'utils/History';
import DevTools from 'mobx-react-devtools'; import DevTools from 'mobx-react-devtools';
import auth from 'utils/auth'; import userStore from 'stores/UserStore';
import reducers from 'reducers';
import 'normalize.css/normalize.css'; import 'normalize.css/normalize.css';
import 'utils/base-styles.scss'; import 'utils/base-styles.scss';
@ -31,49 +29,30 @@ import DocumentScene from 'scenes/DocumentScene';
import DocumentEdit from 'scenes/DocumentEdit'; import DocumentEdit from 'scenes/DocumentEdit';
import SlackAuth from 'scenes/SlackAuth'; import SlackAuth from 'scenes/SlackAuth';
// Redux
let store;
const routerMiddlewareWithHistory = routerMiddleware(History);
if (__DEV__) {
const loggerMiddleware = createLogger();
store = createStore(reducers, applyMiddleware(
thunkMiddleware,
routerMiddlewareWithHistory,
loggerMiddleware,
));
} else {
store = createStore(reducers, applyMiddleware(
thunkMiddleware,
routerMiddlewareWithHistory,
));
}
render((
<div style={{ display: 'flex', flex: 1, }}>
<Provider store={store}>
<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={ Editor } onEnter={ requireAuth } />
<Route path="/documents/:id" component={ DocumentScene } onEnter={ requireAuth } />
<Route path="/documents/:id/edit" component={ DocumentEdit } onEnter={ requireAuth } />
<Route path="/auth/slack" component={SlackAuth} />
</Route>
</Router>
</Provider>
{ __DEV__ ? <DevTools position={{ bottom: 0, right: 0 }} /> : null }
</div>
), document.getElementById('root'));
function requireAuth(nextState, replace) { function requireAuth(nextState, replace) {
if (!auth.loggedIn()) { if (!userStore.authenticated) {
replace({ replace({
pathname: '/', pathname: '/',
state: { nextPathname: nextState.location.pathname }, state: { nextPathname: nextState.location.pathname },
}); });
} }
} }
render((
<div style={{ display: 'flex', flex: 1, }}>
<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={ Editor } onEnter={ requireAuth } />
<Route path="/documents/:id" component={ DocumentScene } onEnter={ requireAuth } />
<Route path="/documents/:id/edit" component={ DocumentEdit } onEnter={ requireAuth } />
<Route path="/auth/slack" component={SlackAuth} />
</Route>
</Router>
{ __DEV__ ? <DevTools position={{ bottom: 0, right: 0 }} /> : null }
</div>
), document.getElementById('root'));

View File

@ -1,66 +0,0 @@
import {
FETCH_ATLASES_PENDING,
FETCH_ATLASES_SUCCESS,
FETCH_ATLASES_FAILURE,
FETCH_ATLAS_PENDING,
FETCH_ATLAS_SUCCESS,
FETCH_ATLAS_FAILURE,
} from 'actions/AtlasActions';
const initialState = {
pagination: null,
isLoading: false,
}
const atlases = (state = initialState, action) => {
switch (action.type) {
case FETCH_ATLASES_PENDING: {
return {
...state,
isLoading: true,
};
}
case FETCH_ATLASES_SUCCESS: {
return {
...state,
...action.data,
pagination: action.pagination,
isLoading: false,
};
}
case FETCH_ATLASES_FAILURE: {
return {
...state,
isLoading: false,
error: action.error,
};
}
case FETCH_ATLAS_PENDING: {
return {
...state,
isLoading: true,
};
}
case FETCH_ATLAS_SUCCESS: {
return {
...state,
...action.data,
isLoading: false,
};
}
case FETCH_ATLAS_FAILURE: {
return {
...state,
isLoading: false,
error: action.error,
};
}
default:
return state;
}
};
export default atlases;

View File

@ -1,69 +0,0 @@
import {
FETCH_DOCUMENT_PENDING,
FETCH_DOCUMENT_SUCCESS,
FETCH_DOCUMENT_FAILURE,
SAVE_DOCUMENT_PENDING,
SAVE_DOCUMENT_SUCCESS,
SAVE_DOCUMENT_FAILURE,
} from 'actions/DocumentActions';
const initialState = {
data: null,
error: null,
isLoading: false,
isSaving: false,
}
const doc = (state = initialState, action) => {
switch (action.type) {
case 'RESET_DOCUMENT': {
return {
...initialState,
}
}
case FETCH_DOCUMENT_PENDING: {
return {
...state,
isLoading: true,
};
}
case FETCH_DOCUMENT_SUCCESS: {
return {
data: action.data,
isLoading: false,
};
}
case FETCH_DOCUMENT_FAILURE: {
return {
...state,
error: action.error,
isLoading: false,
};
}
case SAVE_DOCUMENT_PENDING: {
return {
...state,
isSaving: true,
};
}
case SAVE_DOCUMENT_SUCCESS: {
return {
data: action.date,
isSaving: false,
};
}
case SAVE_DOCUMENT_FAILURE: {
return {
...state,
error: action.error,
isSaving: false,
};
}
default:
return state;
}
};
export default doc;

View File

@ -1,9 +0,0 @@
import { combineReducers } from 'redux';
import atlases from './atlases';
import document from './document';
export default combineReducers({
atlases,
document,
});

View File

@ -1,12 +1,8 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react';
import Link from 'react-router/lib/Link'; import Link from 'react-router/lib/Link';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { replace } from 'react-router-redux';
import { fetchAtlasAsync } from 'actions/AtlasActions';
// Temp import store from './AtlasStore';
import { client } from 'utils/ApiClient';
import Layout, { Title, HeaderAction } from 'components/Layout'; import Layout, { Title, HeaderAction } from 'components/Layout';
import AtlasPreviewLoading from 'components/AtlasPreviewLoading'; import AtlasPreviewLoading from 'components/AtlasPreviewLoading';
@ -16,25 +12,20 @@ import Divider from 'components/Divider';
import styles from './Atlas.scss'; import styles from './Atlas.scss';
@observer
class Atlas extends React.Component { class Atlas extends React.Component {
static propTypes = {
isLoading: React.PropTypes.bool,
atlas: React.PropTypes.object,
}
componentDidMount = () => { componentDidMount = () => {
const { id } = this.props.params; const { id } = this.props.params;
store.fetchAtlas(id);
this.props.fetchAtlasAsync(id);
} }
render() { render() {
const atlas = this.props.atlas; const atlas = store.atlas;
let actions; let actions;
let title; let title;
if (!this.props.isLoading) { if (atlas) {
actions = <HeaderAction> actions = <HeaderAction>
<Link to={ `/atlas/${atlas.id}/new` }>New document</Link> <Link to={ `/atlas/${atlas.id}/new` }>New document</Link>
</HeaderAction>; </HeaderAction>;
@ -47,7 +38,7 @@ class Atlas extends React.Component {
title={ title } title={ title }
> >
<CenteredContent> <CenteredContent>
{ this.props.isLoading ? ( { store.isFetching ? (
<AtlasPreviewLoading /> <AtlasPreviewLoading />
) : ( ) : (
<div className={ styles.container }> <div className={ styles.container }>
@ -68,24 +59,4 @@ class Atlas extends React.Component {
); );
} }
} }
export default Atlas;
const mapStateToProps = (state, currentProps) => {
const id = currentProps.params.id;
return {
isLoading: state.atlases.isLoading,
atlas: state.atlases.entities ? state.atlases.entities.atlases[id] : null, // reselect
}
};
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
replace,
fetchAtlasAsync,
}, dispatch)
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Atlas);

View File

@ -0,0 +1,25 @@
import { observable, action } from 'mobx';
import { client } from 'utils/ApiClient';
const store = new class AtlasStore {
@observable atlas;
@observable isFetching;
/* Actions */
@action fetchAtlas = async (id) => {
this.isFetching = true;
try {
const res = await client.post('/atlases.info', { id: id });
const { data } = res;
this.atlas = data;
} catch (e) {
console.error("Something went wrong");
}
this.isFetching = false;
}
}();
export default store;

View File

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { observer } from 'mobx-react';
import { bindActionCreators } from 'redux';
import { fetchAtlasesAsync } from 'actions/AtlasActions'; import userStore from 'stores/UserStore';
import store from './DashboardStore';
import Flex from 'components/Flex'; import Flex from 'components/Flex';
import Layout from 'components/Layout'; import Layout from 'components/Layout';
@ -11,12 +12,10 @@ import CenteredContent from 'components/CenteredContent';
import styles from './Dashboard.scss'; import styles from './Dashboard.scss';
@observer
class Dashboard extends React.Component { class Dashboard extends React.Component {
static propTypes = {
}
componentDidMount = () => { componentDidMount = () => {
this.props.fetchAtlasesAsync(this.props.teamId); store.fetchAtlases(userStore.team.id);
} }
render() { render() {
@ -24,10 +23,10 @@ class Dashboard extends React.Component {
<Layout> <Layout>
<CenteredContent> <CenteredContent>
<Flex direction="column" flex={ true }> <Flex direction="column" flex={ true }>
{ this.props.isLoading ? ( { store.isFetching ? (
<AtlasPreviewLoading /> <AtlasPreviewLoading />
) : this.props.items.map((item) => { ) : store.atlases.map((atlas) => {
return (<AtlasPreview key={ item.id } data={ item } />); return (<AtlasPreview key={ atlas.id } data={ atlas } />);
}) } }) }
</Flex> </Flex>
</CenteredContent> </CenteredContent>
@ -36,21 +35,4 @@ class Dashboard extends React.Component {
} }
} }
const mapStateToProps = (state) => { export default Dashboard;
return {
teamId: state.team ? state.team.id : null,
isLoading: state.atlases.isLoading,
items: Array.isArray(state.atlases.result) ? state.atlases.result.map((id) => state.atlases.entities.atlases[id]) : [], // reselect
}
};
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
fetchAtlasesAsync,
}, dispatch)
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Dashboard);

View File

@ -0,0 +1,27 @@
import { observable, action } from 'mobx';
import { client } from 'utils/ApiClient';
const store = new class DashboardStore {
@observable atlases;
@observable pagination;
@observable isFetching;
/* Actions */
@action fetchAtlases = async (teamId) => {
this.isFetching = true;
try {
const res = await client.post('/atlases.list', { id: teamId });
const { data, pagination } = res;
this.atlases = data;
this.pagination = pagination;
} catch (e) {
console.error("Something went wrong");
}
this.isFetching = false;
}
}();
export default store;

View File

@ -1,11 +1,8 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { Link } from 'react-router';
import Link from 'react-router/lib/Link'; import { observer } from 'mobx-react';
import { bindActionCreators } from 'redux';
import { import store from './DocumentSceneStore';
fetchDocumentAsync,
deleteDocument,
} from 'actions/DocumentActions';
import Layout, { HeaderAction } from 'components/Layout'; import Layout, { HeaderAction } from 'components/Layout';
import AtlasPreviewLoading from 'components/AtlasPreviewLoading'; import AtlasPreviewLoading from 'components/AtlasPreviewLoading';
@ -15,25 +12,26 @@ import DropdownMenu, { MenuItem } from 'components/DropdownMenu';
import styles from './DocumentScene.scss'; import styles from './DocumentScene.scss';
@observer
class DocumentScene extends React.Component { class DocumentScene extends React.Component {
state = { state = {
didScroll: false, didScroll: false,
} }
componentDidMount = () => { componentDidMount = () => {
const documentId = this.props.routeParams.id; const { id } = this.props.routeParams;
this.props.fetchDocumentAsync(documentId); store.fetchDocument(id);
} }
componentWillReceiveProps = (nextProps) => { componentWillReceiveProps = (nextProps) => {
// Scroll to anchor after loading, and only once // Scroll to anchor after loading, and only once
const hash = this.props.location.hash; const { hash } = this.props.location;
if (nextProps.document && hash && !this.state.didScroll) { if (nextProps.doc && hash && !this.state.didScroll) {
const name = hash.split('#')[1]; const name = hash.split('#')[1];
setTimeout(() => { setTimeout(() => {
this.setState({ didScroll: true }); this.setState({ didScroll: true });
const element = document.getElementsByName(name)[0]; const element = doc.getElementsByName(name)[0];
if (element) element.scrollIntoView() if (element) element.scrollIntoView()
}, 0); }, 0);
} }
@ -41,29 +39,26 @@ class DocumentScene extends React.Component {
onDelete = () => { onDelete = () => {
if (confirm("Are you sure you want to delete this document?")) { if (confirm("Are you sure you want to delete this document?")) {
this.props.deleteDocument( store.deleteDocument();
this.props.document.id,
`/atlas/${ this.props.document.atlas.id }`,
);
}; };
} }
render() { render() {
const document = this.props.document; const doc = store.document;
let title; let title;
let actions; let actions;
if (document) { if (doc) {
actions = ( actions = (
<div className={ styles.actions }> <div className={ styles.actions }>
<HeaderAction> <HeaderAction>
<Link to={ `/documents/${document.id}/edit` }>Edit</Link> <Link to={ `/documents/${doc.id}/edit` }>Edit</Link>
</HeaderAction> </HeaderAction>
<DropdownMenu label="More"> <DropdownMenu label="More">
<MenuItem onClick={ this.onDelete }>Delete</MenuItem> <MenuItem onClick={ this.onDelete }>Delete</MenuItem>
</DropdownMenu> </DropdownMenu>
</div> </div>
); );
title = `${document.atlas.name} - ${document.title}`; title = `${doc.atlas.name} - ${doc.title}`;
} }
return ( return (
@ -72,10 +67,10 @@ class DocumentScene extends React.Component {
actions={ actions } actions={ actions }
> >
<CenteredContent> <CenteredContent>
{ this.props.isLoading || !document ? ( { store.isFetching ? (
<AtlasPreviewLoading /> <AtlasPreviewLoading />
) : ( ) : (
<Document document={ document } /> <Document document={ doc } />
) } ) }
</CenteredContent> </CenteredContent>
</Layout> </Layout>
@ -83,22 +78,4 @@ class DocumentScene extends React.Component {
} }
}; };
export default DocumentScene;
const mapStateToProps = (state) => {
return {
isLoading: state.document.isLoading,
document: state.document.data,
}
};
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
fetchDocumentAsync,
deleteDocument,
}, dispatch)
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(DocumentScene);

View File

@ -0,0 +1,39 @@
import { observable, action } from 'mobx';
import { client } from 'utils/ApiClient';
import { browserHistory } from 'react-router';
const store = new class DocumentSceneStore {
@observable document;
@observable isFetching = true;
@observable isDeleting;
/* Actions */
@action fetchDocument = async (id) => {
this.isFetching = true;
try {
const res = await client.post('/documents.info', { id: id });
const { data } = res;
this.document = data;
} catch (e) {
console.error("Something went wrong");
}
this.isFetching = false;
}
@action deleteDocument = async () => {
this.isFetching = true;
try {
const res = await client.post('/documents.delete', { id: this.document.id });
browserHistory.push(`/atlas/${this.document.atlas.id}`);
} catch (e) {
console.error("Something went wrong");
}
this.isFetching = false;
}
}();
export default store;

View File

@ -2,14 +2,14 @@ import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { // import {
resetEditor, // resetEditor,
updateText, // updateText,
replaceText, // replaceText,
} from 'actions/EditorActions'; // } from 'actions/EditorActions';
import { // import {
saveDocumentAsync, // saveDocumentAsync,
} from 'actions/DocumentActions'; // } from 'actions/DocumentActions';
import Layout, { Title, HeaderAction } from 'components/Layout'; import Layout, { Title, HeaderAction } from 'components/Layout';
import Flex from 'components/Flex'; import Flex from 'components/Flex';
@ -81,26 +81,21 @@ class Editor extends Component {
} }
} }
const mapStateToProps = (state) => { // const mapStateToProps = (state) => {
return { // return {
text: state.editor.text, // text: state.editor.text,
title: state.editor.title, // title: state.editor.title,
isSaving: state.document.isSaving, // isSaving: state.document.isSaving,
}; // };
}; // };
const mapDispatchToProps = (dispatch) => { // const mapDispatchToProps = (dispatch) => {
return bindActionCreators({ // return bindActionCreators({
resetEditor, // resetEditor,
updateText, // updateText,
replaceText, // replaceText,
saveDocumentAsync, // saveDocumentAsync,
}, dispatch) // }, dispatch)
}; // };
Editor = connect(
mapStateToProps,
mapDispatchToProps,
)(Editor);
export default Editor; export default Editor;

View File

@ -1,19 +0,0 @@
import constants from '../constants';
export default {
setToken(token) {
localStorage.setItem(constants.JWT_STORE_KEY, token);
},
getToken() {
return localStorage.getItem(constants.JWT_STORE_KEY);
},
logout() {
localStorage.removeItem(constants.JWT_STORE_KEY);
},
loggedIn() {
return !!localStorage.getItem(constants.JWT_STORE_KEY);
},
};

View File

@ -54,5 +54,5 @@ module.exports = {
'fetch': 'imports?this=>global!exports?global.fetch!isomorphic-fetch' 'fetch': 'imports?this=>global!exports?global.fetch!isomorphic-fetch'
}), }),
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en)$/) new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en)$/)
] ],
}; };