From 3e97d46026765b8fcaf330b0a4e86900b0d9624b Mon Sep 17 00:00:00 2001 From: Sergey Breslavets Date: Wed, 7 Feb 2018 21:05:19 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D1=83=D1=80=D0=B0=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=BA=D1=83=20=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=20=D1=81=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AC/index.js | 36 ++++++++++++++++++++++++-- src/components/Article/index.js | 4 +-- src/components/Comment.js | 29 +++++++++++++-------- src/components/CommentList.js | 36 +++++++++++++++++++++----- src/constants/index.js | 2 ++ src/reducer/comments.js | 46 +++++++++++++++++++++++++++------ src/selectors/index.js | 21 ++++++++++++--- 7 files changed, 141 insertions(+), 33 deletions(-) diff --git a/src/AC/index.js b/src/AC/index.js index e3a996a..55fd54a 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -1,6 +1,15 @@ import { - INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, - START, SUCCESS, FAIL + INCREMENT, + DELETE_ARTICLE, + CHANGE_DATE_RANGE, + CHANGE_SELECTION, + ADD_COMMENT, + LOAD_ALL_ARTICLES, + LOAD_ARTICLE, + START, + SUCCESS, + FAIL, + LOAD_COMMENT } from '../constants' export function increment() { @@ -72,4 +81,27 @@ export function loadArticle(id) { }, 1000) } +} + + + +export function loadCommentForArticle(idArticle) { + + return (dispatch) => { + dispatch({ + type: LOAD_COMMENT + START, + payload: { idArticle } + }) + setTimeout(() => { + fetch(`/api/comment?article=${idArticle}`) + .then(res => res.json()) + .then(response => dispatch({ + type: LOAD_COMMENT + SUCCESS, + payload: { idArticle, response } + })) + }, 1000) + + + } + } \ No newline at end of file diff --git a/src/components/Article/index.js b/src/components/Article/index.js index 2e4a647..48f15f8 100644 --- a/src/components/Article/index.js +++ b/src/components/Article/index.js @@ -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} from '../../AC' import './style.css' class Article extends PureComponent { @@ -68,7 +68,7 @@ class Article extends PureComponent { return (
{article.text}
- +
) diff --git a/src/components/Comment.js b/src/components/Comment.js index 4b123ce..d768e00 100644 --- a/src/components/Comment.js +++ b/src/components/Comment.js @@ -1,9 +1,12 @@ import React from 'react' import PropTypes from 'prop-types' import {connect} from 'react-redux' -import {createCommentSelector} from '../selectors' +import {commentSelectorId} from '../selectors' function Comment({comment}) { + + + return (
{comment.text} by {comment.user} @@ -13,20 +16,24 @@ function Comment({comment}) { Comment.propTypes = { id: PropTypes.string, - //from connect + comment: PropTypes.shape({ text: PropTypes.string.isRequired, user: PropTypes.string }).isRequired } -const createMapStateToProps = () => { - const commentSelector = createCommentSelector() - return (state, ownProps) => { - return { - comment: commentSelector(state, ownProps) - } - } -} +// const createMapStateToProps = () => { +// const commentSelector = createCommentSelector() +// return (state, ownProps) => { +// return { +// comment: commentSelector(state, ownProps) +// } +// } +// } -export default connect(createMapStateToProps)(Comment) \ No newline at end of file +export default connect ( ( state, ownProps ) => { + return { + comment: commentSelectorId( state, ownProps ) + } +} ) (Comment) \ No newline at end of file diff --git a/src/components/CommentList.js b/src/components/CommentList.js index 3082942..20be033 100644 --- a/src/components/CommentList.js +++ b/src/components/CommentList.js @@ -4,6 +4,11 @@ import CommentForm from './CommentForm' import Comment from './Comment' import toggleOpen from '../decorators/toggleOpen' +import { connect } from 'react-redux' +import { loadCommentForArticle } from '../AC' +import {commentsSelector, commentsLoadingSelector} from '../selectors' + +import Loader from './common/Loader' class CommentList extends Component { static propTypes = { article: PropTypes.object.isRequired, @@ -11,9 +16,19 @@ class CommentList extends Component { isOpen: PropTypes.bool, toggleOpen: PropTypes.func } + + + + componentWillReceiveProps({ isOpen, article, loadCommentForArticle }){ + + if( !this.props.isOpen && isOpen ) loadCommentForArticle( article.id ) + + + + } render() { - const {isOpen, toggleOpen} = this.props + const {isOpen, toggleOpen , comments } = this.props const text = isOpen ? 'hide comments' : 'show comments' return (
@@ -24,23 +39,32 @@ class CommentList extends Component { } getBody() { - const {article: { comments, id }, isOpen} = this.props - if (!isOpen) return null + const { comments , article, isOpen, loading} = this.props + console.log(comments) + + + if (!isOpen) return null + if (loading) return const body = comments.length ? (
    - {comments.map(id =>
  • )} + {comments.map(comment =>
  • )}
) :

No comments yet

return (
{body} - +
) } } -export default toggleOpen(CommentList) \ No newline at end of file +export default connect( state => { + return { + comments : commentsSelector(state), + loading: commentsLoadingSelector(state) + } +}, { loadCommentForArticle } ) (toggleOpen(CommentList)) \ No newline at end of file diff --git a/src/constants/index.js b/src/constants/index.js index f34f842..3c27b52 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -8,6 +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_COMMENT = 'LOAD_COMMENT' + export const START = '_START' export const SUCCESS = '_SUCCESS' diff --git a/src/reducer/comments.js b/src/reducer/comments.js index 764e28c..f4f7053 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,17 +1,47 @@ -import { ADD_COMMENT } from '../constants' -import {normalizedComments} from '../fixtures' -import {arrToMap} from './utils' +import { ADD_COMMENT, LOAD_COMMENT, START, SUCCESS } from '../constants' -export default (state = arrToMap(normalizedComments), action) => { - const { type, payload, randomId } = action +import { arrToMap } from './utils' +import { Map, Record } from 'immutable' + + + +const CommentsRecord = Record({ + id: null, + text: null, + user: null, + loading: false +}) + +const ReducerRecord = Record({ + entities: arrToMap([], CommentsRecord), + loading: false, + loaded: false, + error: null +}) + + +export default (comments = new ReducerRecord(), action) => { + const { type, payload, randomId, response, error } = action switch (type) { case ADD_COMMENT: - return state.set(randomId, { + return comments.setIn(['entities', randomId], new CommentsRecord({ ...payload.comment, id: randomId - }) + })) + + case LOAD_COMMENT + START: + return comments.set('loading', true) + + case LOAD_COMMENT + SUCCESS: + { + console.log(payload.response) + return comments + .set('loading', false) + .set('loaded', true) + .set('entities', arrToMap(payload.response, CommentsRecord)) + } } - return state + return comments } \ No newline at end of file diff --git a/src/selectors/index.js b/src/selectors/index.js index c358756..a9ef66a 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -1,6 +1,9 @@ -import {createSelector} from 'reselect' +import { createSelector } from 'reselect' +import comments from '../reducer/comments'; 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 @@ -9,7 +12,7 @@ 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 + const { selected, dateRange: { from, to } } = filters return articles.filter(article => { const published = Date.parse(article.date) @@ -18,6 +21,16 @@ export const filtratedArticlesSelector = createSelector(articlesSelector, filter }) }) -export const createCommentSelector = () => createSelector(commentListSelector, idSelector, (comments, id) => { - return comments.get(id) +// export const createCommentSelector = () => createSelector(commentListSelector, idSelector, (comments, id) => { +// return comments.get(id) +// }) + +export const commentsMapSelector = state => state.comments.entities +export const commentsSelector = createSelector(commentsMapSelector, comments => comments.valueSeq().toArray()) + + +export const commentsLoadingSelector = state => state.comments.loading + +export const commentSelectorId = createSelector(commentsSelector, idSelector, (comments, id) => { + return comments.find(comment => comment.id == id) }) \ No newline at end of file From bad19841715d52fc98eb81e2e71b333f270ea49e Mon Sep 17 00:00:00 2001 From: Sergey Breslavets Date: Wed, 7 Feb 2018 22:55:40 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BA=D0=B0=20=D0=BD=D0=B5=20=D0=BF=D0=BE=D0=BD?= =?UTF-8?q?=D1=8F=D1=82=D0=BD=D0=BE=20=D0=BA=D0=B0=D0=BA=20=D1=81=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D1=82=D1=8C=20=D1=81=D0=B5=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AC/index.js | 12 ++++++++++- src/components/CommentList.js | 39 ++++++++++++++++++++++++++--------- src/constants/index.js | 4 +++- src/reducer/articles.js | 27 ++++++++++++++++++++---- src/selectors/index.js | 6 ++++++ 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/AC/index.js b/src/AC/index.js index 55fd54a..5295670 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -9,7 +9,8 @@ import { START, SUCCESS, FAIL, - LOAD_COMMENT + LOAD_COMMENT, + LOAD_COMMENT_TO_CASHE } from '../constants' export function increment() { @@ -104,4 +105,13 @@ export function loadCommentForArticle(idArticle) { } +} + +export function loadCommentToCashe(CasheComment, id) { + + return { + type: LOAD_COMMENT_TO_CASHE, + payload: { CasheComment, id } + } + } \ No newline at end of file diff --git a/src/components/CommentList.js b/src/components/CommentList.js index 20be033..a75beca 100644 --- a/src/components/CommentList.js +++ b/src/components/CommentList.js @@ -5,8 +5,8 @@ import Comment from './Comment' import toggleOpen from '../decorators/toggleOpen' import { connect } from 'react-redux' -import { loadCommentForArticle } from '../AC' -import {commentsSelector, commentsLoadingSelector} from '../selectors' +import { loadCommentForArticle , loadCommentToCashe } from '../AC' +import {commentsSelector, commentsLoadingSelector, commentsSelectorCashe} from '../selectors' import Loader from './common/Loader' class CommentList extends Component { @@ -21,9 +21,8 @@ class CommentList extends Component { componentWillReceiveProps({ isOpen, article, loadCommentForArticle }){ - if( !this.props.isOpen && isOpen ) loadCommentForArticle( article.id ) + if( !this.props.isOpen && isOpen && !article.get('commentInCashe') ) loadCommentForArticle( article.id ) - } @@ -39,9 +38,19 @@ class CommentList extends Component { } getBody() { - const { comments , article, isOpen, loading} = this.props + const { comments , article, isOpen, loading , loadCommentToCashe } = this.props + console.log(comments) - console.log(comments) + if( !article.get('commentInCashe') ) { + console.log( "before" + article.get('commentInCashe')) + loadCommentToCashe(comments, article.get('id')) + console.log( "after" + article.get('commentInCashe')) + // сейчас коменты в кеше + console.log(article.comments) + } + + + if (!isOpen) return null @@ -62,9 +71,19 @@ class CommentList extends Component { } -export default connect( state => { - return { - comments : commentsSelector(state), +export default connect( (state, ownProps ) => { + const { article } = ownProps + console.log(article.get('commentInCashe')) + if (! article.get('commentInCashe') ) { + return { + comments : commentsSelector(state), + loading: commentsLoadingSelector(state) + } + } + + return { + comments : commentsSelectorCashe(state, ownProps ), loading: commentsLoadingSelector(state) } -}, { loadCommentForArticle } ) (toggleOpen(CommentList)) \ No newline at end of file + +}, { loadCommentForArticle, loadCommentToCashe } ) (toggleOpen(CommentList)) \ No newline at end of file diff --git a/src/constants/index.js b/src/constants/index.js index 3c27b52..8ca132b 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -13,4 +13,6 @@ export const LOAD_COMMENT = 'LOAD_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_COMMENT_TO_CASHE = 'LOAD_COMMENT_TO_CASHE' \ No newline at end of file diff --git a/src/reducer/articles.js b/src/reducer/articles.js index fd5939a..0a25045 100644 --- a/src/reducer/articles.js +++ b/src/reducer/articles.js @@ -1,6 +1,6 @@ import { Map, Record } from 'immutable' -import { DELETE_ARTICLE, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, START, SUCCESS, FAIL } from '../constants' -import {arrToMap} from './utils' +import { DELETE_ARTICLE, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, START, SUCCESS, FAIL, LOAD_COMMENT_TO_CASHE } from '../constants' +import { arrToMap } from './utils' const ArticleRecord = Record({ id: null, @@ -8,7 +8,8 @@ const ArticleRecord = Record({ text: null, date: null, loading: false, - comments: [] + comments: [], + commentInCashe: false }) const ReducerRecord = Record({ @@ -50,7 +51,25 @@ export default (articles = new ReducerRecord(), action) => { case LOAD_ARTICLE + SUCCESS: return articles.setIn(['entities', payload.id], new ArticleRecord(payload.response)) - } + + + case LOAD_COMMENT_TO_CASHE: + { + + // console.log(payload.CasheComment) + // console.log(payload.id) + // articles: articles.updateIn( + // ['entities', payload.id, 'commentInCashe'], + // true + // ) + + return articles.updateIn( + ['entities', payload.id, 'comments'], + (comments) => payload.CasheComment + ).setIn(['entities', payload.id, 'commentInCashe'], true) + } + + } return articles } \ No newline at end of file diff --git a/src/selectors/index.js b/src/selectors/index.js index a9ef66a..d350147 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -1,5 +1,6 @@ import { createSelector } from 'reselect' import comments from '../reducer/comments'; +import articles from '../reducer/articles'; export const articlesMapSelector = state => state.articles.entities @@ -33,4 +34,9 @@ export const commentsLoadingSelector = state => state.comments.loading export const commentSelectorId = createSelector(commentsSelector, idSelector, (comments, id) => { return comments.find(comment => comment.id == id) +}) + +/// непонятно как получить комеенты кеша которые там есть в +export const commentsSelectorCasheArt = createSelector(articlesSelector, idSelector, (articles, id) => { + return (articles.find(article => article.id == id)).comments }) \ No newline at end of file