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

Large diffs are not rendered by default.

23 changes: 22 additions & 1 deletion 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,
LOAD_ARTICLE_COMMENTS, START, SUCCESS, FAIL
LOAD_ARTICLE_COMMENTS, START, SUCCESS, FAIL,LOAD_COMMENTS
} from '../constants'

export function increment() {
Expand Down Expand Up @@ -82,4 +82,25 @@ export function loadArticleComments(articleId) {
payload: { articleId },
callAPI: `/api/comment?article=${articleId}`
}
}

export function loadComments(page) {
return (dispatch) => {
dispatch({
type: LOAD_COMMENTS + START,
payload: { page }
})

fetch("/api/comment?limit=5&offset="+(page * 5))
.then(res => res.json())
.then(response => dispatch({
type: LOAD_COMMENTS + SUCCESS,
payload: {page,response}
}))
.catch(error => dispatch({
type: LOAD_COMMENTS + FAIL,
payload: {page,error}
}))

}
}
3 changes: 3 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -19,12 +20,14 @@ class App extends Component {
<li><NavLink to = "/counter" activeStyle = {{ color: 'red' }}>counter</NavLink></li>
<li><NavLink to = "/filters" activeStyle = {{ color: 'red' }}>filters</NavLink></li>
<li><NavLink to = "/articles" activeStyle = {{ color: 'red' }}>articles</NavLink></li>
<li><NavLink to = "/comments/0" activeStyle = {{ color: 'red' }}>comments</NavLink></li>
</ul>
<Switch>
<Route path = "/counter" component = {Counter} exact />
<Route path = "/filters" component = {Filters} />
<Route path = "/articles/new" render = {() => <h1>New Article Form</h1>} />
<Route path = "/articles" component = {ArticlesPage} />
<Route path = "/comments/:id" component = {CommentsPage} />
<Route path = "*" render = {() => <h1>Not Found Page</h1>} />
</Switch>
</div>
Expand Down
48 changes: 48 additions & 0 deletions src/components/commentsWithPagination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react"
import {connect} from "react-redux";
import {loadComments} from "../AC/index";
import {NavLink} from 'react-router-dom'

import {commentsListSelector, loadedCommentsSelector, totalCommentsSelector} from "../selectors/index";
import Loader from "./loader";

class CommentsWithPagination extends React.Component{
componentWillMount(){
if(!this.props.loaded.includes(this.props.id)) {
this.props.loadComments(this.props.id)
}
}

render(){
const {comments, id, total} = this.props
const lastPage = Math.ceil(total/5)-1

if(!comments) return <Loader/>

return(<div>
<ul>
{id>0&&<li><NavLink to = {"/comments/" + (Number(id) - 1)} activeStyle = {{ color: 'red' }}>prev</NavLink></li>}
{id!=lastPage&&<li><NavLink to = {"/comments/" + (Number(id) + 1)} activeStyle = {{ color: 'red' }}>next</NavLink></li>}
</ul>
{comments.map(item=>{
return <Comment key={item.id} comment={item}/>
})}
</div>);
}
}

const Comment = ({comment}) =>{
return(
<div>
{comment.text} <b>by {comment.user}</b>
</div>
)
}

const mapStateToProps = (state, ownProps) => ({
comments:commentsListSelector(state, ownProps),
loaded:loadedCommentsSelector(state),
total:totalCommentsSelector(state)
})

export default connect(mapStateToProps,{loadComments})(CommentsWithPagination)
23 changes: 23 additions & 0 deletions src/components/routes/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { Component } from 'react'

import CommentsWithPagination from "../commentsWithPagination"


class Comments extends Component {
static propTypes = {

};


render() {
const id = this.props.match.params.id;
return (
<div>
<h2>Comments page</h2>
<CommentsWithPagination id={id} key={id}/>
</div>
)
}
}

export default Comments
1 change: 1 addition & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const DELETE_ARTICLE = 'DELETE_ARTICLE'
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_COMMENTS = 'LOAD_COMMENTS'

export const CHANGE_SELECTION = 'CHANGE_SELECTION'
export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE'
Expand Down
15 changes: 12 additions & 3 deletions src/reducer/comments.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ADD_COMMENT, LOAD_ARTICLE_COMMENTS, SUCCESS } from '../constants'
import {Record, OrderedMap} from 'immutable'
import {Record, OrderedMap, Set} from 'immutable'
import {arrToMap} from './utils'
import {LOAD_COMMENTS, START} from "../constants/index";

const CommentRecord = Record({
id: null,
Expand All @@ -9,7 +10,11 @@ const CommentRecord = Record({
})

const ReducerState = Record({
entities: new OrderedMap({})
entities: new OrderedMap({}),
pages: new OrderedMap({}),
loading: new Set([]),
loaded: new Set([]),
total:0
})

export default (state = new ReducerState(), action) => {
Expand All @@ -24,7 +29,11 @@ export default (state = new ReducerState(), action) => {

case LOAD_ARTICLE_COMMENTS + SUCCESS:
return state.mergeIn(['entities'], arrToMap(response, CommentRecord))

case LOAD_COMMENTS + START:
return state.mergeIn(['loading'], new Set([payload.page]))
case LOAD_COMMENTS + SUCCESS:
return state.setIn(['pages',payload.page], arrToMap(payload.response.records, CommentRecord))
.mergeIn(['loaded'],new Set([payload.page])).set('total',payload.response.total)
default:
return state
}
Expand Down
9 changes: 8 additions & 1 deletion src/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ export const loadingArticlesSelector = state => state.articles.loading
export const loadedArticlesSelector = state => state.articles.loaded

const commentsSelector = state => state.comments.entities
const pagesSelector = state => state.comments.pages
const filtersSelector = state => state.filters
const idSelector = (_, props) => props.id
export const loadedCommentsSelector = state => state.comments.loaded.toArray()
export const totalCommentsSelector = state => state.comments.total


export const filtratedArticles = createSelector(articleListSelector, filtersSelector, (articles, filters) => {
const {selected, dateRange: {from, to}} = filters
Expand All @@ -22,4 +26,7 @@ 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))
export const createCommentSelector = () => createSelector(commentsSelector, idSelector, (comments, id) => comments.get(id))

export const createCommentsByPageSelector = createSelector(pagesSelector,idSelector,(pages,pageNum) => pages.get(pageNum))
export const commentsListSelector = createSelector(createCommentsByPageSelector, articlesMap => articlesMap&&articlesMap.valueSeq().toArray())