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

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions src/AC/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION} from '../constants'
import {ADD_COMMENT, CHANGE_USERNAME} from "../constants/index";

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

export function addComment(articleId, user, text) {
return {
type: ADD_COMMENT,
payload: { articleId, user, text }
}
}

export function changeUsername(username) {
return {
type: CHANGE_USERNAME,
payload: {username}
}
}
14 changes: 7 additions & 7 deletions src/components/article-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { filtratedArticles } from '../../selectors'

export class ArticleList extends Component {
static propTypes = {
articles: PropTypes.array.isRequired,
articlesId: PropTypes.array.isRequired,

//from accordion decorator
openItemId: PropTypes.string,
Expand All @@ -19,14 +19,14 @@ export class ArticleList extends Component {
}

render() {
const { articles, openItemId, toggleItem } = this.props
const { articlesId, openItemId, toggleItem } = this.props
console.log('---', 'rendering ArticlList')
const articleElements = articles.map(article =>
<li key = {article.id} className = "test__article-list--item">
const articleElements = articlesId.map(id =>
<li key = {id} className = "test__article-list--item">
<Article
article = {article}
id = {id}
onButtonClick = {toggleItem}
isOpen = {openItemId === article.id}
isOpen = {openItemId === id}
/>
</li>
)
Expand All @@ -41,6 +41,6 @@ export class ArticleList extends Component {
export default connect(state => {
console.log('---', 'article list connect')
return {
articles: filtratedArticles(state)
articlesId: filtratedArticles(state)
}
})(accordion(ArticleList))
13 changes: 11 additions & 2 deletions src/components/article/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { connect } from 'react-redux'
import CommentList from '../comment-list'
import { deleteArticle } from '../../AC'
import './style.css'
import {createArticlesSelector} from "../../selectors/index";

class Article extends PureComponent {
state = {
Expand Down Expand Up @@ -58,7 +59,7 @@ function getBody(article) {
return (
<section className = "test__article--body">
{article.text}
<CommentList comments={article.comments}/>
<CommentList articleId={article.id} comments={article.comments}/>
</section>
)
}
Expand All @@ -73,4 +74,12 @@ Article.propTypes = {
onButtonClick: PropTypes.func
}

export default connect(null, { deleteArticle })(Article)
const createMapStateToProps = () => {
const articleSelector = createArticlesSelector()

return (state, ownProps) => ({
article: articleSelector(state, ownProps)
})
}

export default connect(createMapStateToProps, { deleteArticle })(Article)
30 changes: 30 additions & 0 deletions src/components/comment-input/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import {addComment} from "../../AC/index";
import {connect} from "react-redux";

class CommentInput extends React.Component{
state={
newComment:""
}

render(){
return (
<div>
<h3>Add comment</h3>
<span>text:
<input value={this.state.newComment} onChange={(e)=>{this.setState({newComment:e.target.value})}}/>
</span>
<button onClick={()=>{
this.props.addComment(this.props.articleId,this.props.username,this.state.newComment);
this.setState({newComment:""})}
}>add comment</button>
</div>
);
}
}

const mapStateToProps = state => {
return {username:state.user.username}
}

export default connect(mapStateToProps,{addComment})(CommentInput);
4 changes: 3 additions & 1 deletion src/components/comment-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CSSTransition from 'react-addons-css-transition-group'
import Comment from '../comment'
import toggleOpen from '../../decorators/toggleOpen'
import './style.css'
import CommentInput from "../comment-input/index";

class CommentList extends Component {
static defaultProps = {
Expand Down Expand Up @@ -45,6 +46,7 @@ class CommentList extends Component {
? this.getComments()
: <h3 className="test__comment-list--empty">No comments yet</h3>
}
<CommentInput articleId={this.props.articleId}/>
</div>
)
}
Expand All @@ -55,7 +57,7 @@ class CommentList extends Component {
{
this.props.comments.map(id =>
<li key = {id} className = "test__comment-list--item">
<Comment id = {id}/>
<Comment id = {id} />
</li>)
}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion src/components/filters/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ class SelectFilter extends Component {

export default connect(state => ({
selected: state.filters.selected,
articles: state.articles
articles: Object.values(state.articles)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Сделай селектор

}), { changeSelection })(SelectFilter)
21 changes: 9 additions & 12 deletions src/components/user-form.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import React, { Component } from 'react'
import {changeUsername} from "../AC/index";
import {connect} from "react-redux";

class UserForm extends Component {
static propTypes = {

};

state = {
username: ''
}

render() {
return (
<div>
username: <input value = {this.state.username} onChange = {this.handleChange}/>
username: <input value = {this.props.username} onChange = {this.handleChange}/>
</div>
)
}
Expand All @@ -22,10 +17,12 @@ class UserForm extends Component {
return
}

this.setState({
username: ev.target.value
})
this.props.changeUsername(ev.target.value)
}
}

export default UserForm
const mapStateToProps = state => {
return {username:state.user.username}
}

export default connect(mapStateToProps,{changeUsername})(UserForm)
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'
export const CHANGE_USERNAME = 'CHANGE_USERNAME'
8 changes: 8 additions & 0 deletions src/middlewares/generateId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {ADD_COMMENT} from "../constants/index";

export default store => next => action => {
if(action.type === ADD_COMMENT) {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

action.payload.newCommentId = Math.random().toString(36).slice(2);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

лучше не мутировать payload, мало-ли что там станут передавать

}
next(action)
}
16 changes: 15 additions & 1 deletion src/reducer/articles.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import { normalizedArticles as defaultArticles } from '../fixtures'
import { normalizedArticles } from '../fixtures'
import { DELETE_ARTICLE } from '../constants'
import {ADD_COMMENT} from "../constants/index";

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

switch (type) {
case DELETE_ARTICLE:
return articlesState.filter(article => article.id !== payload.id)
case ADD_COMMENT:{

const {articleId,newCommentId} = action.payload;
const article = {...articlesState[articleId]}
article.comments.push(newCommentId)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

здесь ты мутируешь стейт. Возвращаешь новый объект, но внутри меняешь объекты по ссылке

return {
...articlesState,
[articleId]:article
}
}
default:
return articlesState
}
Expand Down
10 changes: 9 additions & 1 deletion src/reducer/comments.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {} from '../constants'
import { normalizedComments } from '../fixtures'
import {ADD_COMMENT} from "../constants/index";

const defaultComments = normalizedComments.reduce((acc, comment) => ({
...acc,
Expand All @@ -11,7 +12,14 @@ export default (commentsState = defaultComments, action) => {
const {type} = action

switch (type) {

case ADD_COMMENT:{
console.log(action.payload)
const {newCommentId,user,text} = action.payload;
return {
...commentsState,
[newCommentId]:{id:newCommentId,user,text}
}
}
default:
return commentsState
}
Expand Down
3 changes: 2 additions & 1 deletion src/reducer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import counterReducer from './counter'
import articles from './articles'
import comments from './comments'
import filters from './filters'
import user from "./user";

export default combineReducers({
counter: counterReducer,
articles, comments, filters
articles, comments, filters,user
})
17 changes: 17 additions & 0 deletions src/reducer/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CHANGE_USERNAME} from "../constants/index";

const initState = {
username:""
}

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

switch (type) {
case CHANGE_USERNAME:
return {username:payload.username}

default:
return state
}
}
6 changes: 4 additions & 2 deletions src/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ export const filtratedArticles = createSelector(articleListSelector, filtersSele
const {selected, dateRange: {from, to}} = filters
console.log('---', 'recomputing filtration')

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

export const createCommentSelector = () => createSelector(commentsSelector, idSelector, (comments, id) => comments[id])
export const createCommentSelector = () => createSelector(commentsSelector, idSelector, (comments, id) => comments[id])
export const createArticlesSelector = () => createSelector(articleListSelector, idSelector, (articles, id) => articles[id])
3 changes: 2 additions & 1 deletion src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createStore, applyMiddleware } from 'redux'
import reducer from '../reducer'
import logger from '../middlewares/logger'
import generateId from "../middlewares/generateId";

const enhancer = applyMiddleware(logger)
const enhancer = applyMiddleware(logger,generateId)

const store = createStore(reducer, enhancer)

Expand Down