Better data management for atlases

This commit is contained in:
Jori Lallo
2016-05-18 01:13:52 -07:00
parent 582b937961
commit 6b3e56a4cf
6 changed files with 63 additions and 34 deletions

View File

@@ -83,6 +83,7 @@
"node-sass": "^3.4.2", "node-sass": "^3.4.2",
"nodemon": "^1.9.1", "nodemon": "^1.9.1",
"normalize.css": "^3.0.3", "normalize.css": "^3.0.3",
"normalizr": "^2.0.1",
"react": "^0.14.7", "react": "^0.14.7",
"react-codemirror": "^0.2.5", "react-codemirror": "^0.2.5",
"react-dropzone": "^3.3.2", "react-dropzone": "^3.3.2",

View File

@@ -1,12 +1,15 @@
import makeActionCreator from '../utils/actions'; import makeActionCreator from '../utils/actions';
import { client } from 'utils/ApiClient'; 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_PENDING = 'FETCH_ATLASES_PENDING';
export const FETCH_ATLASES_SUCCESS = 'FETCH_ATLASES_SUCCESS'; export const FETCH_ATLASES_SUCCESS = 'FETCH_ATLASES_SUCCESS';
export const FETCH_ATLASES_FAILURE = 'FETCH_ATLASES_FAILURE'; export const FETCH_ATLASES_FAILURE = 'FETCH_ATLASES_FAILURE';
const fetchAtlasesPending = makeActionCreator(FETCH_ATLASES_PENDING); const fetchAtlasesPending = makeActionCreator(FETCH_ATLASES_PENDING);
const fetchAtlasesSuccess = makeActionCreator(FETCH_ATLASES_SUCCESS, 'items', 'pagination'); const fetchAtlasesSuccess = makeActionCreator(FETCH_ATLASES_SUCCESS, 'data', 'pagination');
const fetchAtlasesFailure = makeActionCreator(FETCH_ATLASES_FAILURE, 'error'); const fetchAtlasesFailure = makeActionCreator(FETCH_ATLASES_FAILURE, 'error');
export function fetchAtlasesAsync(teamId) { export function fetchAtlasesAsync(teamId) {
@@ -17,7 +20,9 @@ export function fetchAtlasesAsync(teamId) {
teamId: teamId, teamId: teamId,
}) })
.then(data => { .then(data => {
dispatch(fetchAtlasesSuccess(data.data, data.pagination)); const response = normalize(data.data, arrayOf(atlas));
dispatch(fetchAtlasesSuccess(response, data.pagination));
}) })
.catch((err) => { .catch((err) => {
dispatch(fetchAtlasesFailure(err)); dispatch(fetchAtlasesFailure(err));
@@ -43,7 +48,9 @@ export function fetchAtlasAsync(atlasId) {
id: atlasId, id: atlasId,
}) })
.then(data => { .then(data => {
dispatch(fetchAtlasSuccess(data.data,)); const response = normalize(data.data, atlas);
dispatch(fetchAtlasSuccess(response));
}) })
.catch((err) => { .catch((err) => {
dispatch(fetchAtlasFailure(err)); dispatch(fetchAtlasFailure(err));

View File

@@ -11,10 +11,12 @@ class AtlasPreview extends React.Component {
} }
render() { render() {
const data = this.props.data;
return ( return (
<div className={ styles.container }> <div className={ styles.container }>
<h2><Link to={ `/atlas/${this.props.data.id}` } className={ styles.atlasLink }>{ this.props.data.name }</Link></h2> <h2><Link to={ `/atlas/${data.id}` } className={ styles.atlasLink }>{ data.name }</Link></h2>
<div>No documents. Why not <Link to='/new-document'>create one</Link>?</div> <div>No documents. Why not <Link to={ `/atlas/${data.id}/new` }>create one</Link>?</div>
</div> </div>
); );
} }

View File

@@ -2,10 +2,13 @@ import {
FETCH_ATLASES_PENDING, FETCH_ATLASES_PENDING,
FETCH_ATLASES_SUCCESS, FETCH_ATLASES_SUCCESS,
FETCH_ATLASES_FAILURE, FETCH_ATLASES_FAILURE,
FETCH_ATLAS_PENDING,
FETCH_ATLAS_SUCCESS,
FETCH_ATLAS_FAILURE,
} from 'actions/AtlasActions'; } from 'actions/AtlasActions';
const initialState = { const initialState = {
items: [],
pagination: null, pagination: null,
isLoading: false, isLoading: false,
} }
@@ -21,7 +24,7 @@ const atlases = (state = initialState, action) => {
case FETCH_ATLASES_SUCCESS: { case FETCH_ATLASES_SUCCESS: {
return { return {
...state, ...state,
items: action.items, ...action.data,
pagination: action.pagination, pagination: action.pagination,
isLoading: false, isLoading: false,
}; };
@@ -33,6 +36,28 @@ const atlases = (state = initialState, action) => {
error: action.error, 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: default:
return state; return state;
} }

View File

@@ -16,50 +16,41 @@ import styles from './Atlas.scss';
class Atlas extends React.Component { class Atlas extends React.Component {
static propTypes = { static propTypes = {
isLoading: React.PropTypes.bool,
atlas: React.PropTypes.object, atlas: React.PropTypes.object,
} }
state = {
isLoading: true,
data: null,
}
componentDidMount = () => { componentDidMount = () => {
const { id } = this.props.params; const { id } = this.props.params;
// this.props.fetchAtlasAsync(id); this.props.fetchAtlasAsync(id);
// Temp before breaking out redux store
client.post('/atlases.info', {
id: id,
})
.then(data => {
this.setState({
isLoading: false,
data: data.data
});
})
} }
render() { render() {
const data = this.state.data; const atlas = this.props.atlas;
let actions;
let title;
if (this.props.isLoading === false) {
actions = <Link to={ `/atlas/${atlas.id}/new` }>New document</Link>;
title = <Title>{ atlas.name }</Title>;
}
return ( return (
<Layout <Layout
actions={( actions={ actions }
<Link to={ `/atlas/${data.id}/new` }>New document</Link> title={ title }
)}
title={ <Title>{ data.name }</Title> }
> >
<CenteredContent> <CenteredContent>
{ this.state.isLoading ? ( { this.props.isLoading ? (
<AtlasPreviewLoading /> <AtlasPreviewLoading />
) : ( ) : (
<div className={ styles.container }> <div className={ styles.container }>
<div className={ styles.atlasDetails }> <div className={ styles.atlasDetails }>
<h2>{ data.name }</h2> <h2>{ atlas.name }</h2>
<blockquote> <blockquote>
{ data.description } { atlas.description }
</blockquote> </blockquote>
</div> </div>
@@ -72,9 +63,12 @@ class Atlas extends React.Component {
} }
} }
const mapStateToProps = (state) => { const mapStateToProps = (state, currentProps) => {
const id = currentProps.params.id;
return { return {
isLoading: state.atlases.isLoading, isLoading: state.atlases.isLoading,
atlas: state.atlases.entities ? state.atlases.entities.atlases[id] : null, // reselect
} }
}; };

View File

@@ -37,7 +37,7 @@ const mapStateToProps = (state) => {
return { return {
teamId: state.team ? state.team.id : null, teamId: state.team ? state.team.id : null,
isLoading: state.atlases.isLoading, isLoading: state.atlases.isLoading,
items: state.atlases.items, items: Array.isArray(state.atlases.result) ? state.atlases.result.map((id) => state.atlases.entities.atlases[id]) : [], // reselect
} }
}; };