Added more views and atlas APIs
This commit is contained in:
parent
84ba65f72a
commit
cbe9c0b6ee
|
@ -0,0 +1,52 @@
|
||||||
|
import Router from 'koa-router';
|
||||||
|
import httpErrors from 'http-errors';
|
||||||
|
|
||||||
|
import auth from './authentication';
|
||||||
|
import pagination from './middlewares/pagination';
|
||||||
|
import { presentAtlas } from '../presenters';
|
||||||
|
import { Team, Atlas } from '../models';
|
||||||
|
|
||||||
|
const router = new Router();
|
||||||
|
|
||||||
|
router.post('atlases.info', auth(), async (ctx) => {
|
||||||
|
let { id } = ctx.request.body;
|
||||||
|
ctx.assertPresent(id, 'id is required');
|
||||||
|
|
||||||
|
const team = await ctx.state.user.getTeam();
|
||||||
|
const atlas = await Atlas.findOne({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
teamId: team.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!atlas) throw httpErrors.NotFound();
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
data: presentAtlas(atlas),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.post('atlases.list', auth(), pagination(), async (ctx) => {
|
||||||
|
let { teamId } = ctx.request.body;
|
||||||
|
ctx.assertPresent(teamId, 'teamId is required');
|
||||||
|
|
||||||
|
const team = await ctx.state.user.getTeam();
|
||||||
|
const atlases = await Atlas.findAll({
|
||||||
|
where: {
|
||||||
|
teamId: teamId,
|
||||||
|
},
|
||||||
|
offset: ctx.state.pagination.offset,
|
||||||
|
limit: ctx.state.pagination.limit,
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
pagination: ctx.state.pagination,
|
||||||
|
data: atlases.map((atlas) => {
|
||||||
|
return presentAtlas(atlas);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
|
@ -6,6 +6,7 @@ import Sequelize from 'sequelize';
|
||||||
|
|
||||||
import auth from './auth';
|
import auth from './auth';
|
||||||
import user from './user';
|
import user from './user';
|
||||||
|
import atlases from './atlases';
|
||||||
|
|
||||||
import validation from './validation';
|
import validation from './validation';
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ api.use(validation());
|
||||||
|
|
||||||
router.use('/', auth.routes());
|
router.use('/', auth.routes());
|
||||||
router.use('/', user.routes());
|
router.use('/', user.routes());
|
||||||
|
router.use('/', atlases.routes());
|
||||||
|
|
||||||
// Router is embedded in a Koa application wrapper, because koa-router does not
|
// Router is embedded in a Koa application wrapper, because koa-router does not
|
||||||
// allow middleware to catch any routes which were not explicitly defined.
|
// allow middleware to catch any routes which were not explicitly defined.
|
||||||
|
|
|
@ -4,9 +4,19 @@ import {
|
||||||
} from '../sequelize';
|
} from '../sequelize';
|
||||||
import Team from './Team';
|
import Team from './Team';
|
||||||
|
|
||||||
|
const allowedAtlasTypes = [['atlas', 'journal']];
|
||||||
|
|
||||||
const Atlas = sequelize.define('atlas', {
|
const Atlas = sequelize.define('atlas', {
|
||||||
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true },
|
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true },
|
||||||
name: DataTypes.STRING,
|
name: DataTypes.STRING,
|
||||||
|
description: DataTypes.STRING,
|
||||||
|
type: { type: DataTypes.STRING, validate: { isIn: allowedAtlasTypes }},
|
||||||
|
}, {
|
||||||
|
instanceMethods: {
|
||||||
|
getRecentDocuments() {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Atlas.belongsTo(Team);
|
Atlas.belongsTo(Team);
|
||||||
|
|
|
@ -23,6 +23,9 @@ const User = sequelize.define('user', {
|
||||||
getJwtToken() {
|
getJwtToken() {
|
||||||
return JWT.sign({ id: this.id }, this.jwtSecret);
|
return JWT.sign({ id: this.id }, this.jwtSecret);
|
||||||
},
|
},
|
||||||
|
async getTeam() {
|
||||||
|
return this.team;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
indexes: [
|
indexes: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,3 +14,13 @@ export function presentTeam(team) {
|
||||||
name: team.name,
|
name: team.name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function presentAtlas(atlas) {
|
||||||
|
return {
|
||||||
|
id: atlas.id,
|
||||||
|
name: atlas.name,
|
||||||
|
description: atlas.description,
|
||||||
|
type: atlas.type,
|
||||||
|
recentDocuments: atlas.getRecentDocuments(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -106,6 +106,7 @@ const text = (state = textDefaultState, action) => {
|
||||||
|
|
||||||
import team from './team';
|
import team from './team';
|
||||||
import user from './user';
|
import user from './user';
|
||||||
|
import atlases from './atlases';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
activeEditors,
|
activeEditors,
|
||||||
|
@ -113,4 +114,5 @@ export default combineReducers({
|
||||||
text,
|
text,
|
||||||
user,
|
user,
|
||||||
team,
|
team,
|
||||||
|
atlases,
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import makeActionCreator from '../utils/actions';
|
||||||
|
import { client } from 'utils/ApiClient';
|
||||||
|
|
||||||
|
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, 'items', 'pagination');
|
||||||
|
const fetchAtlasesFailure = makeActionCreator(FETCH_ATLASES_FAILURE, 'error');
|
||||||
|
|
||||||
|
export function fetchAtlasesAsync(teamId) {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(fetchAtlasesPending());
|
||||||
|
|
||||||
|
client.post('/atlases.list', {
|
||||||
|
teamId: teamId,
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
dispatch(fetchAtlasesSuccess(data.data, 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 => {
|
||||||
|
dispatch(fetchAtlasSuccess(data.data,));
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
dispatch(fetchAtlasFailure(err));
|
||||||
|
})
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
import Link from 'react-router/lib/Link';
|
||||||
|
|
||||||
|
import styles from './AtlasPreview.scss';
|
||||||
|
import classNames from 'classnames/bind';
|
||||||
|
const cx = classNames.bind(styles);
|
||||||
|
|
||||||
|
class AtlasPreview extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
data: React.PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className={ styles.container }>
|
||||||
|
<h2><Link to={ `/atlas/${this.props.data.id}` } className={ styles.atlasLink }>{ this.props.data.name }</Link></h2>
|
||||||
|
<div>No documents. Why not <Link to='/new-document'>create one</Link>?</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AtlasPreview;
|
|
@ -0,0 +1,6 @@
|
||||||
|
@import '../../utils/constants.scss';
|
||||||
|
|
||||||
|
.atlasLink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: $textColor;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
import AtlasPreview from './AtlasPreview';
|
||||||
|
export default AtlasPreview;
|
|
@ -0,0 +1,27 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import styles from './CenteredContent.scss';
|
||||||
|
|
||||||
|
const CenteredContent = (props) => {
|
||||||
|
const style = {
|
||||||
|
maxWidth: props.maxWidth,
|
||||||
|
...props.style,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ styles.content } style={ style }>
|
||||||
|
{ props.children }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CenteredContent.defaultProps = {
|
||||||
|
maxWidth: '600px',
|
||||||
|
};
|
||||||
|
|
||||||
|
CenteredContent.propTypes = {
|
||||||
|
children: React.PropTypes.node.isRequired,
|
||||||
|
style: React.PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CenteredContent;
|
|
@ -0,0 +1,5 @@
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
margin: 40px 20px;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
import CenteredContent from './CenteredContent';
|
||||||
|
export default CenteredContent;
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import Link from 'react-router/lib/Link';
|
||||||
|
|
||||||
import HeaderMenu from './components/HeaderMenu';
|
import HeaderMenu from './components/HeaderMenu';
|
||||||
|
|
||||||
|
@ -14,7 +15,9 @@ class Layout extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className={ styles.container }>
|
<div className={ styles.container }>
|
||||||
<div className={ styles.header }>
|
<div className={ styles.header }>
|
||||||
<div className={ styles.teamName }>Coinbase</div>
|
<div className={ styles.teamName }>
|
||||||
|
<Link to="/">{ this.props.teamName }</Link>
|
||||||
|
</div>
|
||||||
<HeaderMenu>
|
<HeaderMenu>
|
||||||
<img src={ this.props.avatarUrl } />
|
<img src={ this.props.avatarUrl } />
|
||||||
</HeaderMenu>
|
</HeaderMenu>
|
||||||
|
@ -29,6 +32,7 @@ class Layout extends React.Component {
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
|
teamName: state.team ? state.team.name : null,
|
||||||
avatarUrl: state.user ? state.user.avatarUrl : null,
|
avatarUrl: state.user ? state.user.avatarUrl : null,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@import '../../utils/constants.scss';
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -16,9 +18,11 @@
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.teamName {
|
.teamName a {
|
||||||
font-family: 'Atlas Grotesk';
|
font-family: 'Atlas Grotesk';
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
color: $textColor;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
|
10
src/index.js
10
src/index.js
|
@ -22,6 +22,7 @@ import 'fonts/atlas/atlas.css';
|
||||||
import Home from 'scenes/Home';
|
import Home from 'scenes/Home';
|
||||||
// import App from 'scenes/App';
|
// import App from 'scenes/App';
|
||||||
import Dashboard from 'scenes/Dashboard';
|
import Dashboard from 'scenes/Dashboard';
|
||||||
|
import Atlas from 'scenes/Atlas';
|
||||||
import SlackAuth from 'scenes/SlackAuth';
|
import SlackAuth from 'scenes/SlackAuth';
|
||||||
|
|
||||||
// Redux
|
// Redux
|
||||||
|
@ -47,12 +48,10 @@ persistStore(store, {
|
||||||
<Route path="/">
|
<Route path="/">
|
||||||
<IndexRoute component={Home} />
|
<IndexRoute component={Home} />
|
||||||
|
|
||||||
<Route path="/dashboard" component={Dashboard
|
<Route path="/dashboard" component={ Dashboard } onEnter={ requireAuth } />
|
||||||
} onEnter={ requireAuth } />
|
<Route path="/atlas/:id" component={ Atlas } onEnter={ requireAuth } />
|
||||||
<Route path="/atlas/:id" component={Dashboard} onEnter={ requireAuth } />
|
|
||||||
<Route path="/atlas/:id/new" component={Dashboard} onEnter={ requireAuth } />
|
|
||||||
|
|
||||||
<Route path="/editor" component={Dashboard} />
|
<Route path="/editor" component={Dashboard} onEnter={ requireAuth } />
|
||||||
|
|
||||||
<Route path="/auth/slack" component={SlackAuth} />
|
<Route path="/auth/slack" component={SlackAuth} />
|
||||||
</Route>
|
</Route>
|
||||||
|
@ -69,4 +68,3 @@ function requireAuth(nextState, replace) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import {
|
||||||
|
FETCH_ATLASES_PENDING,
|
||||||
|
FETCH_ATLASES_SUCCESS,
|
||||||
|
FETCH_ATLASES_FAILURE,
|
||||||
|
} from 'actions/AtlasActions';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
items: [],
|
||||||
|
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,
|
||||||
|
items: action.items,
|
||||||
|
pagination: action.pagination,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case FETCH_ATLASES_FAILURE: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
error: action.error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default atlases;
|
|
@ -0,0 +1,85 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { replace } from 'react-router-redux';
|
||||||
|
import { fetchAtlasAsync } from 'actions/AtlasActions';
|
||||||
|
|
||||||
|
// Temp
|
||||||
|
import { client } from 'utils/ApiClient';
|
||||||
|
|
||||||
|
import Layout from 'components/Layout';
|
||||||
|
import AtlasPreviewLoading from 'components/AtlasPreviewLoading';
|
||||||
|
import CenteredContent from 'components/CenteredContent';
|
||||||
|
|
||||||
|
import styles from './Atlas.scss';
|
||||||
|
|
||||||
|
class Atlas extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
atlas: React.PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
isLoading: true,
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
const { id } = this.props.params;
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
const data = this.state.data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<CenteredContent>
|
||||||
|
{ this.state.isLoading ? (
|
||||||
|
<AtlasPreviewLoading />
|
||||||
|
) : (
|
||||||
|
<div className={ styles.container }>
|
||||||
|
<div className={ styles.atlasDetails }>
|
||||||
|
<h2>{ data.name }</h2>
|
||||||
|
<blockquote>
|
||||||
|
{ data.description }
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={ styles.divider }><span></span></div>
|
||||||
|
</div>
|
||||||
|
) }
|
||||||
|
</CenteredContent>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
isLoading: state.atlases.isLoading,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return bindActionCreators({
|
||||||
|
replace,
|
||||||
|
fetchAtlasAsync,
|
||||||
|
}, dispatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(Atlas);
|
|
@ -0,0 +1,31 @@
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atlasDetails {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
width: 50%;
|
||||||
|
margin: 20px 0;
|
||||||
|
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
import Atlas from './Atlas';
|
||||||
|
export default Atlas;
|
|
@ -1,37 +1,53 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { replace } from 'react-router-redux';
|
import { fetchAtlasesAsync } from 'actions/AtlasActions';
|
||||||
|
|
||||||
import { client } from 'utils/ApiClient';
|
|
||||||
|
|
||||||
import Layout from 'components/Layout';
|
import Layout from 'components/Layout';
|
||||||
|
import AtlasPreview from 'components/AtlasPreview';
|
||||||
import AtlasPreviewLoading from 'components/AtlasPreviewLoading';
|
import AtlasPreviewLoading from 'components/AtlasPreviewLoading';
|
||||||
|
import CenteredContent from 'components/CenteredContent';
|
||||||
|
|
||||||
import styles from './Dashboard.scss';
|
import styles from './Dashboard.scss';
|
||||||
|
|
||||||
class Dashboard extends React.Component {
|
class Dashboard extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
replace: React.PropTypes.func.isRequired,
|
}
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
this.props.fetchAtlasesAsync(this.props.teamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout
|
<Layout>
|
||||||
header={<div>header!</div>}
|
<CenteredContent>
|
||||||
>
|
{ this.props.isLoading ? (
|
||||||
<div className={ styles.content }>
|
<AtlasPreviewLoading />
|
||||||
<AtlasPreviewLoading />
|
) : this.props.items.map((item) => {
|
||||||
</div>
|
return (<AtlasPreview data={ item } />);
|
||||||
|
}) }
|
||||||
|
</CenteredContent>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
teamId: state.team ? state.team.id : null,
|
||||||
|
isLoading: state.atlases.isLoading,
|
||||||
|
items: state.atlases.items,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ replace }, dispatch)
|
return bindActionCreators({
|
||||||
|
fetchAtlasesAsync,
|
||||||
|
}, dispatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
null, mapDispatchToProps
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
)(Dashboard);
|
)(Dashboard);
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
.content {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
max-width: 600px;
|
|
||||||
|
|
||||||
margin: 40px 20px;
|
|
||||||
}
|
|
Reference in New Issue