diff --git a/README.md b/README.md
index e8a43c6..93c5a04 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+# basic-react-1902
+
## HT1.1 Сделать список комментариев, открывать/закрывать по нажатию на кнопку с помощью декоратора
## HT1.2 Подключить календарь с выбором диапазона дат, отображать диапазон текстом(https://github.com/gpbl/react-day-picker)
## HT1.3 для всего написать propTypes
@@ -11,4 +13,5 @@
## HT4.1 Сделать форму добавления коммента в CommentList
## HT4.2 Переписать articles редюсер на хранилище id -> статья(аналогично comments)
## HT4.3 Написать мидлвару для генерации случайных id
-## HT4.4 Реализовать добавление коммента к статье
\ No newline at end of file
+## HT4.4 Реализовать добавление коммента к статье
+
diff --git a/package.json b/package.json
index d2d8832..84f3b98 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"prop-types": "^15.6.0",
+ "randomstring": "^1.1.5",
"react": "^16.2.0",
"react-addons-css-transition-group": "^15.6.2",
"react-day-picker": "^7.0.7",
@@ -14,6 +15,7 @@
"react-scripts": "1.1.1",
"react-select": "^1.2.1",
"redux": "^3.7.2",
+ "redux-logger": "^3.0.6",
"reselect": "^3.0.1"
},
"scripts": {
diff --git a/src/AC/index.js b/src/AC/index.js
index dda2dd6..3ac8041 100644
--- a/src/AC/index.js
+++ b/src/AC/index.js
@@ -1,4 +1,7 @@
-import {INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION} from '../constants'
+import {
+ INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_NEW_COMMENT,
+ UPDATE_ARTICLE_COMMENTS
+} from '../constants'
export function increment() {
return {
@@ -26,3 +29,23 @@ export function changeSelection(selected) {
payload: { selected }
}
}
+
+export function addNewComment(user, text, articleId) {
+ return {
+ type: ADD_NEW_COMMENT,
+ payload: {
+ data: {user, text},
+ articleId
+ }
+ };
+}
+
+export function updateArticleComments(articleId, commentId) {
+ return {
+ type: UPDATE_ARTICLE_COMMENTS,
+ payload: {
+ articleId,
+ commentId
+ }
+ }
+}
diff --git a/src/components/add-new-comment-form.js b/src/components/add-new-comment-form.js
new file mode 100644
index 0000000..942c0fc
--- /dev/null
+++ b/src/components/add-new-comment-form.js
@@ -0,0 +1,79 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { addNewComment } from '../AC';
+
+class AddNewCommentForm extends Component {
+
+ state = {
+ userName: '',
+ text: ''
+ };
+
+ static propTypes = {
+ articleId: PropTypes.string.isRequired,
+ addComment: PropTypes.func.isRequired
+ };
+
+ static defaultProps = {};
+
+ handleSubmit = (e) => {
+ e.preventDefault();
+ this.props.addComment(this.state.userName, this.state.text, this.props.articleId);
+ this.setState({
+ userName: '',
+ text: ''
+ })
+ };
+
+ handleUsernameInput = (e) => {
+ this.setState({
+ userName: e.target.value
+ });
+ };
+
+ handleTextInput = (e) => {
+ this.setState({
+ text: e.target.value
+ });
+ };
+
+ render() {
+ return (
+
+ );
+ }
+
+}
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ articleId: ownProps.articleId
+ }
+};
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ addComment(user, text, articleId) {
+ dispatch(addNewComment(user, text, articleId));
+ }
+ }
+};
+
+export default connect(mapStateToProps, mapDispatchToProps)(AddNewCommentForm);
diff --git a/src/components/article-list/index.js b/src/components/article-list/index.js
index f2cebc8..6da912b 100644
--- a/src/components/article-list/index.js
+++ b/src/components/article-list/index.js
@@ -7,29 +7,30 @@ import { filtratedArticles } from '../../selectors'
export class ArticleList extends Component {
static propTypes = {
- articles: PropTypes.array.isRequired,
+ articles: PropTypes.object.isRequired,
//from accordion decorator
openItemId: PropTypes.string,
toggleItem: PropTypes.func
};
- componentDidMount() {
+ /*componentDidMount() {
this.props.fetchData && this.props.fetchData()
- }
+ }*/
render() {
- const { articles, openItemId, toggleItem } = this.props
- console.log('---', 'rendering ArticlList')
- const articleElements = articles.map(article =>
-
-
-
- )
+ const { articles, openItemId, toggleItem } = this.props;
+ console.log('---', 'rendering ArticleList');
+ const articleElements = Object.keys(articles).map((articleId) => {
+ return (
+
+ );
+ });
return (
{articleElements}
@@ -43,4 +44,4 @@ export default connect(state => {
return {
articles: filtratedArticles(state)
}
-})(accordion(ArticleList))
\ No newline at end of file
+})(accordion(ArticleList))
diff --git a/src/components/article/index.js b/src/components/article/index.js
index 96261d8..6de10cb 100644
--- a/src/components/article/index.js
+++ b/src/components/article/index.js
@@ -1,4 +1,4 @@
-import React, {PureComponent, Fragment} from 'react'
+import React, {PureComponent, Fragment, Component} from 'react'
import PropTypes from 'prop-types'
import CSSTransition from 'react-addons-css-transition-group'
import { connect } from 'react-redux'
@@ -11,6 +11,15 @@ class Article extends PureComponent {
error: null
}
+ /*componentWillReceiveProps(nextProps) {
+ console.log('WillReceive Props => ', nextProps);
+ }*/
+
+ /*shouldComponentUpdate(nextProps, nextState) {
+ console.log('ShouldUpdate => ', nextProps);
+ return true;
+ }*/
+
componentDidCatch(error) {
console.log('---', error)
this.setState({ error })
@@ -18,8 +27,9 @@ class Article extends PureComponent {
render() {
if (this.state.error) return {this.state.error.message}
-
const { isOpen, article, onButtonClick } = this.props
+ console.log('---Article is rendering');
+
return (
@@ -58,7 +68,7 @@ function getBody(article) {
return (
)
}
@@ -66,11 +76,8 @@ function getBody(article) {
Article.propTypes = {
isOpen: PropTypes.bool,
- article: PropTypes.shape({
- title: PropTypes.string.isRequired,
- text: PropTypes.string
- }).isRequired,
+ article: PropTypes.object.isRequired,
onButtonClick: PropTypes.func
-}
+};
-export default connect(null, { deleteArticle })(Article)
\ No newline at end of file
+export default connect(null, { deleteArticle })(Article)
diff --git a/src/components/comment-list/index.js b/src/components/comment-list/index.js
index 91c4f08..f3db165 100644
--- a/src/components/comment-list/index.js
+++ b/src/components/comment-list/index.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
import CSSTransition from 'react-addons-css-transition-group'
import Comment from '../comment'
import toggleOpen from '../../decorators/toggleOpen'
+import AddNewCommentForm from '../add-new-comment-form';
import './style.css'
class CommentList extends Component {
@@ -14,7 +15,8 @@ class CommentList extends Component {
comments: PropTypes.array.isRequired,
//from toggleOpen decorator
isOpen: PropTypes.bool,
- toggleOpen: PropTypes.func
+ toggleOpen: PropTypes.func,
+ articleId: PropTypes.string.isRequired
}
render() {
@@ -45,6 +47,7 @@ class CommentList extends Component {
? this.getComments()
: No comments yet
}
+
)
}
@@ -59,9 +62,10 @@ class CommentList extends Component {
)
}
+
)
}
}
-export default toggleOpen(CommentList)
\ No newline at end of file
+export default toggleOpen(CommentList)
diff --git a/src/components/filters/select.js b/src/components/filters/select.js
index 1a91857..cee2be8 100644
--- a/src/components/filters/select.js
+++ b/src/components/filters/select.js
@@ -8,17 +8,17 @@ 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 { articles, selected } = this.props;
+ const options = Object.keys(articles).map(articleId => ({
+ label: articles[articleId].title,
+ value: articleId
+ }));
return