Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/AC/index.js
Original file line number Diff line number Diff line change
@@ -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_ALL_COMMENTS
} from '../constants'

export function increment() {
Expand Down Expand Up @@ -74,4 +74,11 @@ export function loadArticleById(id) {
}))
}, 1000)
}
}
}

export function loadCommentsByArticle(article) {
return {
type: LOAD_ALL_COMMENTS,
callAPI: `/api/comment?article=${article}`
}
}
2 changes: 1 addition & 1 deletion src/components/comment-form/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ const limits = {

export default connect(null, (dispatch, ownProps) => ({
addComment: (comment) => dispatch(addComment(comment, ownProps.articleId))
}))(CommentForm)
}))(CommentForm)
48 changes: 36 additions & 12 deletions src/components/comment-list/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import CSSTransition from 'react-addons-css-transition-group'
import Comment from '../comment'
import CommentForm from '../comment-form'
import toggleOpen from '../../decorators/toggleOpen'
import { loadCommentsByArticle } from '../../AC'
import { createCommentSelector, loadingCommentsSelector, loadedCommentsSelector } from '../../selectors'
import Loader from '../loader'
import './style.css'

class CommentList extends Component {
Expand All @@ -18,6 +22,10 @@ class CommentList extends Component {
toggleOpen: PropTypes.func
}

componentWillReceiveProps({ isOpen }) {
if (!this.props.isOpen && isOpen) this.props.loadCommentsByArticle(this.props.article.id)
}

render() {
const {isOpen, toggleOpen} = this.props
const text = isOpen ? 'hide comments' : 'show comments'
Expand All @@ -36,19 +44,25 @@ class CommentList extends Component {
}

getBody() {
const {article: { comments, id }, isOpen} = this.props
const {article: { comments, id }, isOpen, loading, loaded} = this.props
if (!isOpen) return null
if (loading){
return <Loader/>
}
if (loaded) {
return (
<div className="test__comment-list--body">
{
comments.length
? this.getComments()
: <h3 className="test__comment-list--empty">No comments yet</h3>
}
<CommentForm articleId = {id} />
</div>
)
}

return (
<div className="test__comment-list--body">
{
comments.length
? this.getComments()
: <h3 className="test__comment-list--empty">No comments yet</h3>
}
<CommentForm articleId = {id} />
</div>
)
return <h6>error</h6>
}

getComments() {
Expand All @@ -65,5 +79,15 @@ class CommentList extends Component {
}
}

const mapStateToProps = state => {
return {
loading: loadingCommentsSelector(state),
loaded: loadedCommentsSelector(state)
}
}

const mapDispatchToProps = {
loadCommentsByArticle
}

export default toggleOpen(CommentList)
export default connect(mapStateToProps, mapDispatchToProps)(toggleOpen(CommentList))
9 changes: 7 additions & 2 deletions src/components/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { createCommentSelector } from '../selectors'

function Comment({comment}) {
function Comment(props) {
const { comment } = props;
return (
<div>
{comment.text} <b>by {comment.user}</b>
Expand All @@ -18,6 +19,10 @@ Comment.propTypes = {
}).isRequired
}

Comment.defaultProps = {
comment: {},
}

const createMapStateToProps = () => {
const commentSelector = createCommentSelector()

Expand All @@ -26,4 +31,4 @@ const createMapStateToProps = () => {
})
}

export default connect(createMapStateToProps)(Comment)
export default connect(createMapStateToProps)(Comment)
3 changes: 2 additions & 1 deletion src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export const CHANGE_SELECTION = 'CHANGE_SELECTION'
export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE'

export const ADD_COMMENT = 'ADD_COMMENT'
export const LOAD_ALL_COMMENTS = 'LOAD_ALL_COMMENTS'

export const START = '_START'
export const SUCCESS = '_SUCCESS'
export const FAIL = '_FAIL'
export const FAIL = '_FAIL'
2 changes: 1 addition & 1 deletion src/fixtures.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/reducer/articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ export default (articles = new ReducerState(), action) => {
default:
return articles
}
}
}
36 changes: 30 additions & 6 deletions src/reducer/comments.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
import { ADD_COMMENT } from '../constants'
import { ADD_COMMENT, START, SUCCESS, FAIL, LOAD_ALL_COMMENTS } from '../constants'
import {normalizedComments} from '../fixtures'
import {arrToMap} from './utils'
import { Record } from 'immutable'

export default (state = arrToMap(normalizedComments), action) => {
const { type, payload, randomId } = action
const CommentRecord = Record({
id: null,
user: null,
text: null,
})

const ReducerState = Record({
entities: arrToMap([], CommentRecord),
loading: false,
loaded: false,
error: null
})

export default (comments = new ReducerState(), action) => {
const { type, payload, randomId, response } = action

switch (type) {
case ADD_COMMENT:
return state.set(randomId, {
return comments.set(randomId, {
...payload.comment,
id: randomId
})

case LOAD_ALL_COMMENTS + START:
if (comments.loaded) return comments
return comments.set('loading', true)

case LOAD_ALL_COMMENTS + SUCCESS:
return comments
.set('entities', arrToMap(response, CommentRecord))
.set('loading', false)
.set('loaded', true)

default:
return state
return comments
}
}
}
8 changes: 6 additions & 2 deletions src/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ export const articlesMapSelector = state => state.articles.entities
export const articleListSelector = createSelector(articlesMapSelector, articlesMap => articlesMap.valueSeq().toArray())
export const loadingArticlesSelector = state => state.articles.loading

const commentsSelector = state => state.comments
const commentsMapSelector = state => state.comments.entities
export const loadingCommentsSelector = state => state.comments.loading
export const loadedCommentsSelector = state => state.comments.loaded


const filtersSelector = state => state.filters
const idSelector = (_, props) => props.id

Expand All @@ -19,4 +23,4 @@ export const filtratedArticles = createSelector(articleListSelector, filtersSele
})
})

export const createCommentSelector = () => createSelector(commentsSelector, idSelector, (comments, id) => comments.get(id))
export const createCommentSelector = () => createSelector(commentsMapSelector, idSelector, (comments, id) => comments.get(id))