diff --git a/src/AC/index.js b/src/AC/index.js index 401b5b1..1f187cf 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -1,5 +1,6 @@ import { - INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, + INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, + LOAD_ALL_ARTICLES, LOAD_ARTICLE, LOAD_COMMENTS, START, SUCCESS, FAIL } from '../constants' @@ -74,4 +75,26 @@ export function loadArticleById(id) { })) }, 1000) } -} \ No newline at end of file +} + +export function loadCommentsById(id) { + return (dispatch) => { + dispatch({ + type: LOAD_COMMENTS + START, + payload: { id } + }) + + setTimeout(() => { + fetch(`/api/comment/?article=${id}`) + .then(res => res.json()) + .then(response => dispatch({ + type: LOAD_COMMENTS + SUCCESS, + payload: { id, response } + })) + .catch(error => dispatch({ + type: LOAD_COMMENTS + FAIL, + payload: { id, error } + })) + }, 1000) + } +} diff --git a/src/components/comment-list/index.js b/src/components/comment-list/index.js index 173cb68..8ad7a9e 100644 --- a/src/components/comment-list/index.js +++ b/src/components/comment-list/index.js @@ -3,9 +3,13 @@ import PropTypes from 'prop-types' import CSSTransition from 'react-addons-css-transition-group' import Comment from '../comment' import CommentForm from '../comment-form' +import Loader from '../loader' import toggleOpen from '../../decorators/toggleOpen' import './style.css' +import { connect } from 'react-redux' +import { loadCommentsById } from '../../AC' + class CommentList extends Component { static defaultProps = { comments: [] @@ -13,11 +17,16 @@ class CommentList extends Component { static propTypes = { article: PropTypes.object.isRequired, - //from toggleOpen decorator isOpen: PropTypes.bool, toggleOpen: PropTypes.func } + + componentWillReceiveProps({ isOpen, loadCommentsById, article}) { + if (!this.props.isOpen && isOpen && !this.props.loaded) + loadCommentsById(article.id) + } + render() { const {isOpen, toggleOpen} = this.props const text = isOpen ? 'hide comments' : 'show comments' @@ -52,12 +61,14 @@ class CommentList extends Component { } getComments() { + if (this.props.loading) return + return ( @@ -65,5 +76,10 @@ class CommentList extends Component { } } +const mapStateToProps = state => ({ + comments: state.comments.get('entities'), + loading: state.comments.get('loading'), + loaded: state.comments.get('loaded') +}) -export default toggleOpen(CommentList) \ No newline at end of file +export default connect(mapStateToProps, { loadCommentsById })(toggleOpen(CommentList)) diff --git a/src/components/comment.js b/src/components/comment.js index dba04b4..75e10ed 100644 --- a/src/components/comment.js +++ b/src/components/comment.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' -import { createCommentSelector } from '../selectors' +// import { createCommentSelector } from '../selectors' function Comment({comment}) { return ( @@ -18,12 +18,22 @@ Comment.propTypes = { }).isRequired } -const createMapStateToProps = () => { - const commentSelector = createCommentSelector() +// const createMapStateToProps = () => { +// const commentSelector = createCommentSelector() +// +// return ((state, ownProps) => { +// // console.log('COMMENT createMapStateToProps', ownProps); +// return ({ +// // comment: commentSelector(state, ownProps) +// comment: ownProps.comment +// }) +// }) +// +// // return (state, ownProps) => ({ +// // comment: commentSelector(state, ownProps) +// // }) +// } +// +// export default connect(createMapStateToProps)(Comment) - return (state, ownProps) => ({ - comment: commentSelector(state, ownProps) - }) -} - -export default connect(createMapStateToProps)(Comment) \ No newline at end of file +export default connect(null)(Comment) diff --git a/src/constants/index.js b/src/constants/index.js index f34f842..0851d7c 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -3,6 +3,7 @@ export const INCREMENT = 'INCREMENT' export const DELETE_ARTICLE = 'DELETE_ARTICLE' export const LOAD_ALL_ARTICLES = 'LOAD_ALL_ARTICLES' export const LOAD_ARTICLE = 'LOAD_ARTICLE' +export const LOAD_COMMENTS = 'LOAD_COMMENTS' export const CHANGE_SELECTION = 'CHANGE_SELECTION' export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE' @@ -11,4 +12,4 @@ export const ADD_COMMENT = 'ADD_COMMENT' export const START = '_START' export const SUCCESS = '_SUCCESS' -export const FAIL = '_FAIL' \ No newline at end of file +export const FAIL = '_FAIL' diff --git a/src/middlewares/logger.js b/src/middlewares/logger.js index 634d901..7c80aff 100644 --- a/src/middlewares/logger.js +++ b/src/middlewares/logger.js @@ -5,4 +5,4 @@ export default store => next => action => { next(action) console.log('---', 'state after: ', store.getState()) -} \ No newline at end of file +} diff --git a/src/reducer/articles.js b/src/reducer/articles.js index 26166cc..da891f7 100644 --- a/src/reducer/articles.js +++ b/src/reducer/articles.js @@ -1,4 +1,4 @@ -import { DELETE_ARTICLE, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, START, SUCCESS, FAIL } from '../constants' +import { DELETE_ARTICLE, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, START, SUCCESS} from '../constants' import { arrToMap } from './utils' import { Record } from 'immutable' @@ -46,8 +46,7 @@ export default (articles = new ReducerState(), action) => { case LOAD_ARTICLE + SUCCESS: return articles.setIn(['entities', payload.id], new ArticleRecord(payload.response)) - default: return articles } -} \ No newline at end of file +} diff --git a/src/reducer/comments.js b/src/reducer/comments.js index 9f32503..76d83fe 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,18 +1,43 @@ -import { ADD_COMMENT } from '../constants' -import {normalizedComments} from '../fixtures' +import { ADD_COMMENT, LOAD_COMMENTS, START, SUCCESS, FAIL} from '../constants' import {arrToMap} from './utils' +import { Record } from 'immutable' -export default (state = arrToMap(normalizedComments), action) => { +const CommentRecord = Record({ + id: null, + user: null, + text: null, +}) + +const ReducerState = Record({ + entities: arrToMap([], CommentRecord), + loading: false, + loaded: false, + error: null +}) + +export default (state = new ReducerState(), action) => { const { type, payload, randomId } = action switch (type) { case ADD_COMMENT: - return state.set(randomId, { - ...payload.comment, - id: randomId - }) + return state.set( + ['entities', 'comments', randomId], + new CommentRecord(payload.comment) + ) + + case LOAD_COMMENTS + START: + return state.set('loading', true); + + case LOAD_COMMENTS + FAIL: + return arrToMap(state) + + case LOAD_COMMENTS + SUCCESS: + return state + .set('entities', arrToMap(payload.response, CommentRecord)) + .set('loading', false) + .set('loaded', true) default: return state } -} \ No newline at end of file +}