diff --git a/src/AC/index.js b/src/AC/index.js index e3a996a..8df36e5 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -1,6 +1,6 @@ import { INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, - START, SUCCESS, FAIL + START, SUCCESS, FAIL, LOAD_COMMENTS } from '../constants' export function increment() { @@ -72,4 +72,22 @@ export function loadArticle(id) { }, 1000) } +} + +export function loadComments(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 } + })) + }, 1000) + } } \ No newline at end of file diff --git a/src/components/Comment.js b/src/components/Comment.js index 4b123ce..3750c04 100644 --- a/src/components/Comment.js +++ b/src/components/Comment.js @@ -1,7 +1,8 @@ import React from 'react' import PropTypes from 'prop-types' import {connect} from 'react-redux' -import {createCommentSelector} from '../selectors' +import {commentSelector} from '../selectors' +import { loadComments } from '../AC' function Comment({comment}) { return ( @@ -20,13 +21,8 @@ Comment.propTypes = { }).isRequired } -const createMapStateToProps = () => { - const commentSelector = createCommentSelector() - return (state, ownProps) => { - return { - comment: commentSelector(state, ownProps) - } +export default connect((state, ownProps) => { + return { + comment: commentSelector(state, ownProps) } -} - -export default connect(createMapStateToProps)(Comment) \ No newline at end of file +})(Comment) \ No newline at end of file diff --git a/src/components/CommentList.js b/src/components/CommentList.js index 3082942..e287396 100644 --- a/src/components/CommentList.js +++ b/src/components/CommentList.js @@ -1,8 +1,12 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' +import { connect } from 'react-redux' import CommentForm from './CommentForm' import Comment from './Comment' import toggleOpen from '../decorators/toggleOpen' +import { loadComments } from '../AC' +import Loader from './common/Loader' +import { commentsLoadingSelector, commentListSelector, commentsLoadedIDSelector } from '../selectors' class CommentList extends Component { static propTypes = { @@ -12,6 +16,11 @@ class CommentList extends Component { toggleOpen: PropTypes.func } + componentWillReceiveProps({ isOpen, article, loadComments }) { + console.log(this.props.loadedID) + if (!this.props.isOpen && isOpen && (this.props.loadedID != article.id)) loadComments(article.id) + } + render() { const {isOpen, toggleOpen} = this.props const text = isOpen ? 'hide comments' : 'show comments' @@ -24,12 +33,15 @@ class CommentList extends Component { } getBody() { - const {article: { comments, id }, isOpen} = this.props + const { comments, article: { id }, isOpen, loading, loaded} = this.props + if (!isOpen) return null + if (loading) return + const body = comments.length ? ( ) :

No comments yet

@@ -43,4 +55,10 @@ class CommentList extends Component { } -export default toggleOpen(CommentList) \ No newline at end of file +export default connect(state => { + return { + loading: commentsLoadingSelector(state), + loadedID: commentsLoadedIDSelector(state), + comments: commentListSelector(state) + } +}, {loadComments})(toggleOpen(CommentList)) \ No newline at end of file diff --git a/src/constants/index.js b/src/constants/index.js index f34f842..c14d871 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -11,4 +11,6 @@ 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' + +export const LOAD_COMMENTS = 'LOAD_COMMENTS' \ No newline at end of file diff --git a/src/reducer/comments.js b/src/reducer/comments.js index 764e28c..5831088 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,16 +1,38 @@ -import { ADD_COMMENT } from '../constants' -import {normalizedComments} from '../fixtures' +import { Record } from 'immutable' +import { ADD_COMMENT, LOAD_COMMENTS, START, SUCCESS } from '../constants' import {arrToMap} from './utils' -export default (state = arrToMap(normalizedComments), action) => { +const commentRecord = Record({ + id: null, + user: null, + text: null +}) + +const ReducerRecord = Record({ + entities: arrToMap([], commentRecord), + loading: false, + loaded: false, + error: null, + articleID: null, +}) + +export default (state = new ReducerRecord(), action) => { const { type, payload, randomId } = action switch (type) { case ADD_COMMENT: - return state.set(randomId, { - ...payload.comment, - id: randomId - }) + return state.setIn(['entities', randomId], new commentRecord({ ...payload.comment, id: randomId})) + + case LOAD_COMMENTS + START: + return state + .set('loading', true) + .set('articleID', payload.id) + + case LOAD_COMMENTS + SUCCESS: + return state + .set('entities', arrToMap(payload.response, commentRecord)) + .set('loading', false) + .set('loaded', true) } return state diff --git a/src/selectors/index.js b/src/selectors/index.js index c358756..441d6ce 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -3,7 +3,9 @@ import {createSelector} from 'reselect' export const articlesMapSelector = state => state.articles.entities export const articlesLoadingSelector = state => state.articles.loading export const filtersSelector = state => state.filters -export const commentListSelector = state => state.comments +export const commentListMapSelector = state => state.comments.entities +export const commentsLoadingSelector = state => state.comments.loading +export const commentsLoadedIDSelector = state => state.comments.articleID export const idSelector = (_, props) => props.id export const articlesSelector = createSelector(articlesMapSelector, articles => articles.valueSeq().toArray()) @@ -18,6 +20,8 @@ export const filtratedArticlesSelector = createSelector(articlesSelector, filter }) }) -export const createCommentSelector = () => createSelector(commentListSelector, idSelector, (comments, id) => { - return comments.get(id) +export const commentListSelector = createSelector(commentListMapSelector, comments => comments.valueSeq().toArray()) + +export const commentSelector = createSelector(commentListSelector, idSelector, (comments, id) => { + return comments.find(item => item.id == id) }) \ No newline at end of file