Skip to content
Open

HW-6 #80

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
9,001 changes: 9,001 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion src/AC/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
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() {
return {
type: INCREMENT
Expand Down Expand Up @@ -72,4 +73,12 @@ export function loadArticle(id) {

}, 1000)
}
}

export function loadComments(id) {
return {
type: LOAD_COMMENTS,
payload: {id},
callAPI: `/api/comment?article=${id}`
}
}
11 changes: 6 additions & 5 deletions src/components/Article/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import CSSTransition from 'react-addons-css-transition-group'
import {connect} from 'react-redux'
import CommentList from '../CommentList'
import Loader from '../common/Loader'
import {deleteArticle, loadArticle} from '../../AC'
import {deleteArticle, loadArticle, loadComments} from '../../AC'
import './style.css'

class Article extends PureComponent {
Expand Down Expand Up @@ -34,6 +34,7 @@ class Article extends PureComponent {

render() {
const {article, isOpen, toggleOpen} = this.props

return (
<div>
<h2 ref = {this.setTitleRef} onClick = {this.increment}>
Expand All @@ -45,7 +46,7 @@ class Article extends PureComponent {
delete
</button>
</h2>
<CSSTransition
<CSSTransition
transitionAppear
component = "div"
transitionName = "article"
Expand All @@ -62,13 +63,13 @@ class Article extends PureComponent {

getBody() {
const { isOpen, article } = this.props

if (!isOpen) return null
if (article.loading) return <Loader/>

return (
<div>
<section>{article.text}</section>
<CommentList article = {article} ref = {this.setCommentsRef} key = {this.state.count}/>
<CommentList article = {article} ref = {this.setCommentsRef} key = {this.state.count} loadComments={this.props.loadComments} />
</div>
)

Expand Down Expand Up @@ -98,4 +99,4 @@ class Article extends PureComponent {
}


export default connect(null, { deleteArticle, loadArticle })(Article)
export default connect(null, { deleteArticle, loadArticle, loadComments })(Article)
2 changes: 1 addition & 1 deletion src/components/ArticleList.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ class ArticleList extends Accordion {

render() {
const {articles, loading} = this.props

if (loading) return <Loader />
if (!articles.length) return <h3>No Articles</h3>

const articleElements = articles.map((article) => <li key={article.id}>
<Article article={article}
isOpen={article.id === this.state.openItemId}
Expand Down
11 changes: 4 additions & 7 deletions src/components/Comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ function Comment({comment}) {
}

Comment.propTypes = {
id: PropTypes.string,
//from connect
comment: PropTypes.shape({
text: PropTypes.string.isRequired,
user: PropTypes.string
Expand All @@ -22,11 +20,10 @@ Comment.propTypes = {

const createMapStateToProps = () => {
const commentSelector = createCommentSelector()
return (state, ownProps) => {
return {
comment: commentSelector(state, ownProps)
}
}

return (state, ownProps) => ({
comment: commentSelector(state, ownProps)
})
}

export default connect(createMapStateToProps)(Comment)
15 changes: 12 additions & 3 deletions src/components/CommentList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import React, {Component} from 'react'
import PropTypes from 'prop-types'
import CommentForm from './CommentForm'
import Comment from './Comment'
import {connect} from 'react-redux'
import toggleOpen from '../decorators/toggleOpen'
import {loadComments} from '../AC'
import Loader from './common/Loader'

class CommentList extends Component {
static propTypes = {
Expand All @@ -12,9 +15,14 @@ class CommentList extends Component {
toggleOpen: PropTypes.func
}

componentWillReceiveProps({isOpen, loadComments, article:{commentsLoading, commentsLoaded, id}}) {
if (isOpen && !commentsLoaded && !commentsLoading) loadComments(id)
}

render() {
const {isOpen, toggleOpen} = this.props
const text = isOpen ? 'hide comments' : 'show comments'

return (
<div>
<button onClick={toggleOpen}>{text}</button>
Expand All @@ -24,12 +32,14 @@ class CommentList extends Component {
}

getBody() {
const {article: { comments, id }, isOpen} = this.props
const {article: {id, comments, commentsLoaded, commentsLoading}, isOpen} = this.props

if (!isOpen) return null
if (commentsLoading || !commentsLoaded) return <Loader/>

const body = comments.length ? (
<ul>
{comments.map(id => <li key = {id}><Comment id = {id} /></li>)}
{comments.map(id => <li key={id}> <Comment id={id}/> </li>)}
</ul>
) : <h3>No comments yet</h3>

Expand All @@ -42,5 +52,4 @@ class CommentList extends Component {
}
}


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

export const LOAD_COMMENTS = 'LOAD_COMMENTS'
export const ADD_COMMENT = 'ADD_COMMENT'

export const START = '_START'
export const SUCCESS = '_SUCCESS'
export const FAIL = '_FAIL'
export const FAIL = '_FAIL'

18 changes: 16 additions & 2 deletions src/reducer/articles.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Map, Record } from 'immutable'
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, FAIL, LOAD_COMMENTS } from '../constants'
import {arrToMap} from './utils'

const ArticleRecord = Record({
Expand All @@ -8,7 +8,9 @@ const ArticleRecord = Record({
text: null,
date: null,
loading: false,
comments: []
comments: [],
commentsLoading: false,
commentsLoaded: false
})

const ReducerRecord = Record({
Expand Down Expand Up @@ -50,6 +52,18 @@ export default (articles = new ReducerRecord(), action) => {

case LOAD_ARTICLE + SUCCESS:
return articles.setIn(['entities', payload.id], new ArticleRecord(payload.response))

case LOAD_COMMENTS + START:
return articles.setIn(['entities', payload.id, 'commentsLoading'], true)

case LOAD_COMMENTS + FAIL:
return articles
.set('error', error)

case LOAD_COMMENTS + SUCCESS:
return articles
.setIn(['entities', payload.id, 'commentsLoading'], false)
.setIn(['entities', payload.id, 'commentsLoaded'], true)
}

return articles
Expand Down
22 changes: 14 additions & 8 deletions src/reducer/comments.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { ADD_COMMENT } from '../constants'
import {normalizedComments} from '../fixtures'
import { Map, Record } from 'immutable'
import { LOAD_COMMENTS, ADD_COMMENT, START, SUCCESS, FAIL } from '../constants'
import {arrToMap} from './utils'

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

export default (state = new CommentRecord(), action) => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ок, но я просил сделать структуру как у articles, для консистентности

const {type, payload, randomId, response} = action

switch (type) {
case LOAD_COMMENTS + SUCCESS:
return arrToMap(response, CommentRecord).mergeDeep(state)

case ADD_COMMENT:
return state.set(randomId, {
...payload.comment,
id: randomId
})
return state.set(randomId, new CommentRecord(payload.comment))
}

return state
Expand Down
7 changes: 5 additions & 2 deletions src/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ 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 commentListSelector = state => state.comments.toObject()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем, и почему listSelector, а возвращает объект


export const idSelector = (_, props) => props.id

export const articlesSelector = createSelector(articlesMapSelector, articles => articles.valueSeq().toArray())

export const filtratedArticlesSelector = createSelector(articlesSelector, filtersSelector, (articles, filters) => {

const {selected, dateRange: {from, to}} = filters

return articles.filter(article => {
Expand All @@ -19,5 +22,5 @@ export const filtratedArticlesSelector = createSelector(articlesSelector, filter
})

export const createCommentSelector = () => createSelector(commentListSelector, idSelector, (comments, id) => {
return comments.get(id)
return comments[id]
})