diff --git a/src/AC/index.js b/src/AC/index.js
index b6fc854..a056806 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_ALL_COMMENTS, LOAD_ALL_ARTICLES, LOAD_ARTICLE, LOAD_ARTICLE_COMMENTS,
+ START, SUCCESS, FAIL
} from '../constants'
export function increment() {
@@ -73,4 +74,12 @@ export function loadArticleComments(articleId) {
payload: { articleId },
callAPI: `/api/comment?article=${articleId}`
}
-}
\ No newline at end of file
+}
+
+export function loadAllComments(page, {limit, offset}) {
+ return {
+ type: LOAD_ALL_COMMENTS,
+ payload: {page},
+ callAPI: `/api/comment?limit=${limit}&offset=${offset}`
+ }
+}
diff --git a/src/components/App.js b/src/components/App.js
index 64c1c09..e032c8d 100644
--- a/src/components/App.js
+++ b/src/components/App.js
@@ -3,6 +3,7 @@ import ArticleListPage from './routes/ArticleList'
import UserForm from './UserForm'
import FiltersPage from './routes/Filters'
import CounterPage from './routes/Counter'
+import CommentListPage from './routes/CommentList'
import { Route, Switch, NavLink } from 'react-router-dom'
class App extends Component {
@@ -14,6 +15,7 @@ class App extends Component {
Articles
Filters
Counter
+ Comments
@@ -21,6 +23,8 @@ class App extends Component {
Add new Article form
}/>
+
+
Nor found
}/>
diff --git a/src/components/Pagination.js b/src/components/Pagination.js
new file mode 100644
index 0000000..8ba6322
--- /dev/null
+++ b/src/components/Pagination.js
@@ -0,0 +1,44 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import {connect} from 'react-redux'
+import { Route, Switch, NavLink } from 'react-router-dom'
+import {loadAllComments} from '../AC'
+import {contentSelector} from '../selectors'
+
+class Pagination extends Component {
+ static propTypes = {
+ currentPage: PropTypes.string,
+ pages: PropTypes.number,
+ perPage: PropTypes.number,
+ contentLoading: PropTypes.bool,
+ contentLoaded: PropTypes.bool
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (this.props.currentPage === nextProps.currentPage) return
+ const limit = nextProps.perPage
+ const currentPage = nextProps.currentPage
+ const offset = (currentPage-1) * limit
+ if (!nextProps.contentLoading && !nextProps.contentLoaded) {
+ this.props.loadAllComments(currentPage || 1, {limit, offset})
+ }
+ }
+
+ render() {
+ const {pages} = this.props
+ const body = new Array(pages).fill(0).map((_, i) => i+1).map(page =>
+ {page}
+ )
+ return (
+
+ )
+ }
+
+}
+
+export default connect(null, {loadAllComments})(Pagination)
\ No newline at end of file
diff --git a/src/components/routes/CommentList.js b/src/components/routes/CommentList.js
new file mode 100644
index 0000000..a27c63b
--- /dev/null
+++ b/src/components/routes/CommentList.js
@@ -0,0 +1,49 @@
+import React, { Component } from 'react'
+import {connect} from 'react-redux'
+import Comment from '../Comment'
+import Pagination from '../Pagination'
+import Loader from '../common/Loader'
+import {Route} from 'react-router-dom'
+import {loadAllComments} from '../../AC'
+import {contentSelector} from '../../selectors'
+
+class CommentListPage extends Component {
+ state = {
+ perPage: 5
+ }
+
+ componentDidMount() {
+ const limit = this.state.perPage
+ const currentPage = this.props.match.params.page
+ const offset = (currentPage-1) * limit
+ this.props.loadAllComments(currentPage || 1, {limit, offset})
+ }
+
+ render() {
+ const { total, comments} = this.props
+ const {perPage} = this.state
+
+ const body = comments.contentLoaded && comments.records.length ? (
+
+ {comments.records.map(id => )}
+
+ ) : comments.contentLoading && !comments.contentLoaded ? : No comments yet
+ return (
+
+
Comment list
+ {body}
+
+
+ )
+ }
+}
+
+export default connect((state, props) => ({
+ comments: contentSelector(state, props),
+ total: state.pages.total
+}), {loadAllComments} )(CommentListPage)
\ No newline at end of file
diff --git a/src/constants/index.js b/src/constants/index.js
index c71387f..4acb610 100644
--- a/src/constants/index.js
+++ b/src/constants/index.js
@@ -9,6 +9,7 @@ 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'
diff --git a/src/reducer/comments.js b/src/reducer/comments.js
index 8cff558..9eadee6 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, START, SUCCESS, LOAD_ALL_COMMENTS } from '../constants'
import { arrToMap } from './utils'
import { OrderedMap, Record } from 'immutable'
@@ -12,7 +12,6 @@ const ReducerState = Record({
entities: new OrderedMap({})
})
-
export default (state = new ReducerState(), action) => {
const { type, payload, response, randomId } = action
@@ -22,6 +21,9 @@ export default (state = new ReducerState(), action) => {
case LOAD_ARTICLE_COMMENTS + SUCCESS:
return state.mergeIn(['entities'], arrToMap(response, CommentRecord))
+
+ case LOAD_ALL_COMMENTS + SUCCESS:
+ return state.mergeIn(['entities'], arrToMap(response.records, CommentRecord))
}
return state
diff --git a/src/reducer/index.js b/src/reducer/index.js
index 25a0b0b..cd43b6d 100644
--- a/src/reducer/index.js
+++ b/src/reducer/index.js
@@ -3,8 +3,10 @@ import counterReducer from './counter'
import articles from './articles'
import comments from './comments'
import filters from './filters'
+import pagination from './pagination'
export default combineReducers({
counter: counterReducer,
- articles, comments, filters
+ articles, comments, filters,
+ pages: pagination
})
\ No newline at end of file
diff --git a/src/reducer/pagination.js b/src/reducer/pagination.js
new file mode 100644
index 0000000..fd546b3
--- /dev/null
+++ b/src/reducer/pagination.js
@@ -0,0 +1,35 @@
+import { Record } from 'immutable'
+import { LOAD_ALL_COMMENTS, START, SUCCESS, FAIL } from '../constants'
+import {arrToMap} from './utils'
+
+const PagesRecord = Record({
+ records: [],
+ contentLoading: false,
+ contentLoaded: false
+})
+
+const ReducerRecord = Record({
+ entities: arrToMap([], PagesRecord),
+ total: 0,
+ loading: false,
+ loaded: false,
+ error: null
+})
+
+export default (pages = new ReducerRecord(), action) => {
+ const { type, payload, response, error } = action
+
+ switch (type) {
+ case LOAD_ALL_COMMENTS + START:
+ return pages.setIn(['entities', payload.page, 'contentLoading'], true)
+
+ case LOAD_ALL_COMMENTS + SUCCESS:
+ return pages
+ .setIn(['entities', payload.page, 'contentLoading'], false)
+ .setIn(['entities', payload.page, 'contentLoaded'], true)
+ .setIn(['entities', payload.page, 'records'], arrToMap(response.records, PagesRecord).keySeq())
+ .set('total', response.total)
+ }
+
+ return pages
+}
\ No newline at end of file
diff --git a/src/selectors/index.js b/src/selectors/index.js
index 95a4230..5441d1a 100644
--- a/src/selectors/index.js
+++ b/src/selectors/index.js
@@ -3,10 +3,18 @@ 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 commentMapSelector = state => state.comments.get('entities')
export const idSelector = (_, props) => props.id
+export const commentMapSelector = state => state.comments.get('entities')
+export const contentMapSelector = state => state.pages.entities
+export const pageSelector = (_, props) => props.match.params.page || 1
export const articlesSelector = createSelector(articlesMapSelector, articles => articles.valueSeq().toArray())
+export const contentSelector = createSelector(contentMapSelector, pageSelector, (content, page) => {
+ return content.has(page) ? content.get(page).toJS() : []
+})
+export const loadingContentSelector = (state, props) => {
+ return state.pages.entities.size ? state.pages.entities.get(props.match.params.page).contentLoading : true
+}
export const filtratedArticlesSelector = createSelector(articlesSelector, filtersSelector, (articles, filters) => {
const {selected, dateRange: {from, to}} = filters