diff --git a/src/AC/index.js b/src/AC/index.js index d3d7bdb..3f4c096 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -1,6 +1,7 @@ import { INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, - LOAD_ARTICLE_COMMENTS, START, SUCCESS, FAIL + LOAD_ARTICLE_COMMENTS, LOAD_ALL_COMMENTS, LOAD_PAGE_COMMENTS, + START, SUCCESS, FAIL, PER_PAGE } from '../constants' export function increment() { @@ -82,4 +83,21 @@ export function loadArticleComments(articleId) { payload: { articleId }, callAPI: `/api/comment?article=${articleId}` } -} \ No newline at end of file +} + +export function loadAllComments() { + return { + type: LOAD_ALL_COMMENTS, + payload: {}, + callAPI: `/api/comment` + } +} + +export function loadPageComments(no) { + const limit = PER_PAGE, offset = (no-1)*limit; + return { + type: LOAD_PAGE_COMMENTS, + payload: {no}, + callAPI: `/api/comment?limit=${limit}&offset=${offset}` + } +} diff --git a/src/App.js b/src/App.js index e7c257c..ab6dd75 100644 --- a/src/App.js +++ b/src/App.js @@ -2,6 +2,7 @@ import React, { Component } from 'react' import {findDOMNode} from 'react-dom' import {Route, NavLink, Switch} from 'react-router-dom' import ArticlesPage from './components/routes/articles' +import CommentsPage from './components/routes/comments' import UserForm from './components/user-form' import Filters from './components/filters' import Counter from './components/counter' @@ -19,12 +20,15 @@ class App extends Component {
  • counter
  • filters
  • articles
  • +
  • comments
  • New Article Form

    } /> + +

    Not Found Page

    } />
    @@ -32,4 +36,4 @@ class App extends Component { } } -export default App \ No newline at end of file +export default App diff --git a/src/components/routes/comments.js b/src/components/routes/comments.js new file mode 100644 index 0000000..f09df65 --- /dev/null +++ b/src/components/routes/comments.js @@ -0,0 +1,75 @@ +import React, { Component } from 'react' +import {connect} from 'react-redux' +import { NavLink, Route } from 'react-router-dom' +import Comment from '../comment' +import Loader from '../loader' +import { commentPagesSelector, commentsListSelector, commentsTotalSelector } from '../../selectors' +import { PER_PAGE } from '../../constants' +import { loadAllComments, loadPageComments } from '../../AC' + +class CommentsRoute extends Component { + static propTypes = { + + }; + + componentDidMount() { + const { loadAllComments, loaded} = this.props + if (!loaded) loadPageComments() + } + + render() { + const { pages, total} = this.props + const pageCount = Math.ceil(total / PER_PAGE); + const range = Array.apply(null, Array(pageCount)).map(function (_, i) {return i+1;}); + const pageElements = range.map(no => +
  • {no}
  • + ) + return ( +
    +

    Comments page

    + {pageElements} + + {this.getPage()} +
    + ) + } + + getPage() { + const {match, loadPageComments} = this.props; + const no = match.params && match.params.id || '1'; + const { pages } = this.props + const page = pages.get(no) + const { loaded, loading, comments } = page || {} + + if (loading) + return + + if (!loaded) { + loadPageComments(no) + return
    + } + return
    {this.getComments(comments)}
    + } + + getComments(comments) { + return ( + + ) + } + +} + +const createMapStateToProps = (state) => ({ + comments: commentsListSelector(state), + pages: commentPagesSelector(state), + total: commentsTotalSelector(state), +}) + +export default connect(createMapStateToProps, {loadAllComments, loadPageComments})(CommentsRoute) diff --git a/src/constants/index.js b/src/constants/index.js index c71387f..2c3ed7a 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -5,6 +5,10 @@ export const LOAD_ALL_ARTICLES = 'LOAD_ALL_ARTICLES' export const LOAD_ARTICLE = 'LOAD_ARTICLE' export const LOAD_ARTICLE_COMMENTS = 'LOAD_ARTICLE_COMMENTS' +export const LOAD_PAGE_COMMENTS = 'LOAD_PAGE_COMMENTS' + +export const LOAD_ALL_COMMENTS = 'LOAD_ALL_COMMENTS' + export const CHANGE_SELECTION = 'CHANGE_SELECTION' export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE' @@ -12,4 +16,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 PER_PAGE = 5 diff --git a/src/reducer/comments.js b/src/reducer/comments.js index 6586253..139b67a 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,4 +1,4 @@ -import { ADD_COMMENT, LOAD_ARTICLE_COMMENTS, SUCCESS } from '../constants' +import { ADD_COMMENT, LOAD_ARTICLE_COMMENTS, LOAD_PAGE_COMMENTS, START, SUCCESS } from '../constants' import {Record, OrderedMap} from 'immutable' import {arrToMap} from './utils' @@ -8,12 +8,21 @@ const CommentRecord = Record({ user: null }) +const PageRecord = Record({ + no: null, + comments: [], + loading: false, + loaded: false +}) + const ReducerState = Record({ - entities: new OrderedMap({}) + entities: new OrderedMap({}), + pages: new OrderedMap({}), + total: 0 }) export default (state = new ReducerState(), action) => { - const { type, payload, randomId, response } = action + const { type, payload, randomId, response} = action switch (type) { case ADD_COMMENT: @@ -25,7 +34,25 @@ export default (state = new ReducerState(), action) => { case LOAD_ARTICLE_COMMENTS + SUCCESS: return state.mergeIn(['entities'], arrToMap(response, CommentRecord)) + case LOAD_PAGE_COMMENTS + START: + return state + .setIn(['pages', payload.no], new PageRecord( { + no: payload.no, + comment: [], + loading: true, + loaded: false } + )) + + case LOAD_PAGE_COMMENTS + SUCCESS: + console.log('LOAD_PAGE_COMMENTS + SUCCESS', response); + return state + .mergeIn(['entities'], arrToMap(response.records, CommentRecord)) + .setIn(['pages', payload.no, 'comments'], response.records.map(comment => comment.id)) + .setIn(['total'], response.total) + .setIn(['pages', payload.no, 'loading'], false) + .setIn(['pages', payload.no, 'loaded'], true) + default: return state } -} \ No newline at end of file +} diff --git a/src/selectors/index.js b/src/selectors/index.js index 421e61a..dc92ed9 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -5,7 +5,14 @@ export const articleListSelector = createSelector(articlesMapSelector, articlesM export const loadingArticlesSelector = state => state.articles.loading export const loadedArticlesSelector = state => state.articles.loaded -const commentsSelector = state => state.comments.entities +export const commentPagesSelector = state => state.comments.pages + +export const commentsSelector = state => state.comments.entities +export const commentsMapSelector = state => state.comments.entities +export const commentsListSelector = createSelector(commentsMapSelector, commentsMap => commentsMap.valueSeq().toArray()) +export const commentsTotalSelector = state => state.comments.total + + const filtersSelector = state => state.filters const idSelector = (_, props) => props.id @@ -22,4 +29,4 @@ export const filtratedArticles = createSelector(articleListSelector, filtersSele export const articleSelector = createSelector(articlesMapSelector, idSelector, (articles, id) => articles.get(id)) -export const createCommentSelector = () => createSelector(commentsSelector, idSelector, (comments, id) => comments.get(id)) \ No newline at end of file +export const createCommentSelector = () => createSelector(commentsSelector, idSelector, (comments, id) => comments.get(id))