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

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion src/AC/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION} from '../constants'
import {INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT} from '../constants'

export function increment() {
return {
Expand Down Expand Up @@ -26,3 +26,10 @@ export function changeSelection(selected) {
payload: { selected }
}
}

export function addComment(articleId, comment) {
return {
type: ADD_COMMENT,
payload: { articleId, comment }
}
}
28 changes: 19 additions & 9 deletions src/components/Article/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import CSSTransition from 'react-addons-css-transition-group'
import {connect} from 'react-redux'
import CommentList from '../CommentList'
import {deleteArticle} from '../../AC'
import {createFiltratedArticlesSelector} from '../../selectors'
import './style.css'

class Article extends PureComponent {
static propTypes = {
article: PropTypes.shape({
title: PropTypes.string.isRequired,
text: PropTypes.string,
comments: PropTypes.array
}).isRequired,
id: PropTypes.string.isRequired,
article: PropTypes.object.isRequired,
isOpen: PropTypes.bool,
toggleOpen: PropTypes.func
}
Expand All @@ -30,10 +28,13 @@ class Article extends PureComponent {
render() {
console.log('---', 'rerendering')
const {article, isOpen, toggleOpen} = this.props

if(!Object.keys(article).length) return null

const body = isOpen && (
<div>
<section>{article.text}</section>
<CommentList comments = {article.comments} ref = {this.setCommentsRef} key = {this.state.count}/>
<CommentList articleId = {article.id} comments = {article.comments} ref = {this.setCommentsRef} key = {this.state.count}/>
</div>
)
return (
Expand Down Expand Up @@ -63,8 +64,8 @@ class Article extends PureComponent {
}

handleDelete = () => {
const {deleteArticle,article} = this.props
deleteArticle(article.id)
const {deleteArticle, id} = this.props
deleteArticle(id)
}

increment = () => this.setState({
Expand All @@ -85,5 +86,14 @@ class Article extends PureComponent {

}

const mapStateToProps = (state, ownProps) => {
const filtratedArticlesSelector = createFiltratedArticlesSelector()
return (state, ownProps) => {
return {
article: filtratedArticlesSelector(state, ownProps)
}
}
}


export default connect(null, { deleteArticle })(Article)
export default connect(mapStateToProps, { deleteArticle })(Article)
26 changes: 13 additions & 13 deletions src/components/ArticleList.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,39 @@ import PropTypes from 'prop-types'
import Article from './Article'
import Accordion from './common/Accordion'
import {connect} from 'react-redux'
import {filtratedArticlesSelector} from '../selectors'
import {articlesSelector} from '../selectors'

class ArticleList extends Accordion {
render() {
console.log('---', 'rerendering article list')
const {articles} = this.props
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}
toggleOpen={this.toggleOpenItemMemoized(article.id)}
/>
</li>)
if (!Object.keys(articles).length) return <h3>No Articles</h3>
Copy link
Owner

Choose a reason for hiding this comment

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

Лучше селектор, который достанет из в виде массива


const articleElements = Object.keys(articles).map(id =>
<Article id={id} key={id}
isOpen={id === this.state.openItemId}
toggleOpen={this.toggleOpenItemMemoized(id)}
/>)
return (
<ul>
<div>
{articleElements}
</ul>
</div>
)
}
}


ArticleList.defaultProps = {
articles: []
articles: {}
}

ArticleList.propTypes = {
articles: PropTypes.array.isRequired
articles: PropTypes.object.isRequired
}

export default connect(state => {
console.log('---', 'connect updated')
return {
articles: filtratedArticlesSelector(state)
articles: articlesSelector(state)
}
})(ArticleList)
9 changes: 8 additions & 1 deletion src/components/CommentForm/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React, { Component } from 'react'
import {connect} from 'react-redux'
import { addComment } from '../../AC'
import './style.css'

class CommentForm extends Component {
Expand Down Expand Up @@ -26,6 +28,11 @@ class CommentForm extends Component {

handleSubmit = ev => {
ev.preventDefault()
const { addComment, articleId } = this.props
const { user, text } = this.state

addComment(articleId, { user, text })

this.setState({
user: '',
text: ''
Expand Down Expand Up @@ -58,4 +65,4 @@ const limits = {
}
}

export default CommentForm
export default connect(null, {addComment})(CommentForm)
8 changes: 6 additions & 2 deletions src/components/CommentList.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class CommentList extends Component {
toggleOpen: PropTypes.func
}

static defaultProps = {
comments: []
}

render() {
const {isOpen, toggleOpen} = this.props
const text = isOpen ? 'hide comments' : 'show comments'
Expand All @@ -24,7 +28,7 @@ class CommentList extends Component {
}

getBody() {
const {comments, isOpen} = this.props
const {comments, isOpen, articleId} = this.props
if (!isOpen) return null

const body = comments.length ? (
Expand All @@ -36,7 +40,7 @@ class CommentList extends Component {
return (
<div>
{body}
<CommentForm />
<CommentForm articleId={articleId} />
</div>
)
}
Expand Down
13 changes: 7 additions & 6 deletions src/components/Filters/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@ import PropTypes from 'prop-types'
import Select from 'react-select'
import { connect } from 'react-redux'
import { changeSelection } from '../../AC'
import { articlesSelector, filtersSelector } from '../../selectors'

import 'react-select/dist/react-select.css'

class SelectFilter extends Component {
static propTypes = {
articles: PropTypes.array.isRequired
articles: PropTypes.object.isRequired
};

handleChange = selected => this.props.changeSelection(selected.map(option => option.value))

render() {
const { articles, selected } = this.props
const options = articles.map(article => ({
label: article.title,
value: article.id
const options = Object.keys(articles).map(id => ({
label: articles[id].title,
value: id
}))

return <Select
Expand All @@ -30,6 +31,6 @@ class SelectFilter extends Component {
}

export default connect(state => ({
selected: state.filters.selected,
articles: state.articles
selected: filtersSelector(state).selected,
articles: articlesSelector(state)
}), { changeSelection })(SelectFilter)
4 changes: 3 additions & 1 deletion src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ export const INCREMENT = 'INCREMENT'
export const DELETE_ARTICLE = 'DELETE_ARTICLE'

export const CHANGE_SELECTION = 'CHANGE_SELECTION'
export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE'
export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE'

export const ADD_COMMENT = 'ADD_COMMENT'
20 changes: 20 additions & 0 deletions src/middlewares/uniqueIds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ADD_COMMENT } from '../constants'

function generateId() {
return Math.random().toString(16).slice(2)
}

export default store => next => action => {
const { type, payload } = action

switch (type) {
case ADD_COMMENT: {
Copy link
Owner

Choose a reason for hiding this comment

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

через мидлвары будет проходить каждый экшин, они должны быть максимально общими, завязывать на конкретные экшины - не лучшее решение

action.payload = {
...payload,
comment: {...payload.comment, id: generateId()}
}
}
}

return next(action)
}
28 changes: 25 additions & 3 deletions src/reducer/articles.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
import { DELETE_ARTICLE } from '../constants'
import { DELETE_ARTICLE, ADD_COMMENT } from '../constants'
import {normalizedArticles as defaultArticles} from '../fixtures'

export default (articlesState = defaultArticles, action) => {
const articlesMap = defaultArticles.reduce((acc, article) => ({
...acc,
[article.id]: article
}), {})

export default (articlesState = articlesMap, action) => {
const { type, payload } = action

switch (type) {
case DELETE_ARTICLE:
return articlesState.filter(article => article.id !== payload.id)
return Object.keys(articlesState).reduce((acc, id) => {
if (id !== payload.id) {
return {...acc, [id]: articlesState[id]}
}
return acc;
}, {})

case ADD_COMMENT: {
const { articleId, comment } = payload
const { comments = [] } = articlesState[articleId]
return {
...articlesState,
[articleId]: {
...articlesState[articleId],
comments: [...comments, comment.id]
}
}
}
}

return articlesState
Expand Down
11 changes: 9 additions & 2 deletions src/reducer/comments.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { } from '../constants'
import { ADD_COMMENT } from '../constants'
import {normalizedComments as defaultComments} from '../fixtures'

const commentsMap = defaultComments.reduce((acc, comment) => ({
Expand All @@ -7,10 +7,17 @@ const commentsMap = defaultComments.reduce((acc, comment) => ({
}), {})

export default (state = commentsMap, action) => {
const { type } = action
const { type, payload } = action

switch (type) {
case ADD_COMMENT: {
const { comment } = payload

return {
...state,
[comment.id]: { ...comment, id: comment.id}
}
}
}

return state
Expand Down
12 changes: 6 additions & 6 deletions src/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ export const createCommentSelector = () => createSelector(commentsSelector, idSe
return comments[id]
})

export const filtratedArticlesSelector = createSelector(articlesSelector, filtersSelector, (articles, filters) => {
export const createFiltratedArticlesSelector = () => createSelector(articlesSelector, filtersSelector, idSelector, (articles, filters, id) => {
console.log('---', 'computing filters')
const {selected, dateRange: {from, to}} = filters

return articles.filter(article => {
const published = Date.parse(article.date)
return (!selected.length || selected.includes(article.id)) &&
(!from || !to || (published > from && published < to))
})
const published = Date.parse(articles[id].date)
if ((!selected.length || selected.includes(id)) &&
(!from || !to || (published > from && published < to))) return articles[id]

return {}
})
3 changes: 2 additions & 1 deletion src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {createStore, applyMiddleware, compose} from 'redux'
import rootReducer from '../reducer'
import logger from '../middlewares/logger'
import uniqueIds from '../middlewares/uniqueIds'

const composeEnhancers =
typeof window === 'object' &&
Expand All @@ -10,7 +11,7 @@ const composeEnhancers =
}) : compose

const enhancer = composeEnhancers(
applyMiddleware(logger)
applyMiddleware(logger, uniqueIds)
Copy link
Owner

Choose a reason for hiding this comment

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

лучше логгер в конце ставить

)
const store = createStore(rootReducer, enhancer)

Expand Down