From 3fb216d604e74cde56511ae864a06a02d62cee2a Mon Sep 17 00:00:00 2001 From: artemklishch Date: Sat, 20 Jun 2020 16:06:33 +0300 Subject: [PATCH] added ability ro commet without save in case of reaload --- .../AddCommentForm/AddCommentForm.css | 33 ++++++ .../AddCommentForm/AddCommentForm.jsx | 67 ++++++++++++ .../ChangeCommentForm/ChangeCommentForm.css | 27 +++++ .../ChangeCommentForm/ChangeCommentForm.jsx | 62 +++++++++++ .../Comment/Comment.css | 35 ++++++ .../Comment/Comment.jsx | 65 ++++++++++++ .../PostComments/PostComments.css | 9 ++ .../PostComments/PostComments.jsx | 37 +++++++ .../PostCommentsBlock.css | 13 +++ .../PostCommentsBlock.jsx | 100 ++++++++++++++++++ .../components/PostListItem/PostListItem.js | 37 ++++--- .../Post/pages/PostListPage/PostListPage.js | 58 ++++++---- client/reducers.js | 11 +- package.json | 3 +- 14 files changed, 516 insertions(+), 41 deletions(-) create mode 100644 client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.css create mode 100644 client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.jsx create mode 100644 client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.css create mode 100644 client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.jsx create mode 100644 client/modules/Post/components/PostCommentsComponents/Comment/Comment.css create mode 100644 client/modules/Post/components/PostCommentsComponents/Comment/Comment.jsx create mode 100644 client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.css create mode 100644 client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.jsx create mode 100644 client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.css create mode 100644 client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.jsx diff --git a/client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.css b/client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.css new file mode 100644 index 000000000..d5e22baf4 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.css @@ -0,0 +1,33 @@ +.add-comment-form { + margin-top: 10px; + background-color: #bec2bf; + border: 1px solid #000; + padding: 10px; +} + +.comment-filed { + display: block; + width: 100%; + resize: none; + margin-bottom: 10px; +} + +.name-field { + display: block; + margin-bottom: 10px; +} + +.btn-add-comment { + display: inline-block; + padding: 10px 20px; + color: #fff; + background-color: #000; + border-radius: 10px; + border: none; + outline: none; + cursor: pointer; +} + +.btn-add-comment:disabled{ + opacity: 0.5; +} \ No newline at end of file diff --git a/client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.jsx b/client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.jsx new file mode 100644 index 000000000..276445585 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/AddCommentForm/AddCommentForm.jsx @@ -0,0 +1,67 @@ +import React, { Component } from "react"; +import styles from "./AddCommentForm.css"; +import PropTypes from "prop-types"; + +class AddCommentForm extends Component { + state = { + formCommentText: "", + formCommentName: "", + }; + handleCommentText = (text) => { + this.setState({ + formCommentText: text, + }); + }; + handleCommentName = (text) => { + this.setState({ + formCommentName: text, + }); + }; + onSubmitForm = (e) => { + e.preventDefault(); + this.props.onAddComment( + this.state.formCommentName, + this.state.formCommentText + ); + this.setState({ + formCommentName: "", + formCommentText: "", + }); + }; + + render() { + return ( +
+ + + + this.handleCommentName(e.target.value)} + value={this.state.formCommentName} + id="name" + className={styles["name-field"]} + type="text" + /> + +
+ ); + } +} + +AddCommentForm.propTypes = { + onAddComment: PropTypes.func.isRequired, +}; + +export default AddCommentForm; diff --git a/client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.css b/client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.css new file mode 100644 index 000000000..5de1676f0 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.css @@ -0,0 +1,27 @@ +.add-comment-form { + margin-top: 10px; + background-color: #bec2bf; + border: 1px solid #000; + padding: 10px; +} + +.comment-filed { + display: block; + width: 100%; + resize: none; + margin-bottom: 10px; +} + +.btn-add-comment { + padding: 10px 20px; + color: #fff; + background-color: #000; + border-radius: 10px; + border: none; + outline: none; + cursor: pointer; +} +.change-commentform-btns{ + display: flex; + justify-content: space-between; +} \ No newline at end of file diff --git a/client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.jsx b/client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.jsx new file mode 100644 index 000000000..b2ce3faef --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/ChangeCommentForm/ChangeCommentForm.jsx @@ -0,0 +1,62 @@ +import React, { Component } from "react"; +import styles from "./ChangeCommentForm.css"; +import PropTypes from "prop-types"; + +class ChangeCommentForm extends Component { + state = { + formCommentText: "", + }; + handleCommentText = (text) => { + this.setState({ + formCommentText: text, + }); + }; + componentDidMount() { + this.handleCommentText(this.props.comment.text); + } + onSubmitForm = (e) => { + e.preventDefault(); + this.props.onEditComment( + this.state.formCommentText, + this.props.comment.createDate + ); + this.props.onShowChangeForm(); + }; + render() { + return ( +
+ + +
+ + +
+
+ ); + } +} + +ChangeCommentForm.propTypes = { + comment: PropTypes.shape({ + createDate: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + }).isRequired, + onShowChangeForm: PropTypes.func.isRequired, + onEditComment: PropTypes.func.isRequired, +}; + +export default ChangeCommentForm; diff --git a/client/modules/Post/components/PostCommentsComponents/Comment/Comment.css b/client/modules/Post/components/PostCommentsComponents/Comment/Comment.css new file mode 100644 index 000000000..0da78c05f --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/Comment/Comment.css @@ -0,0 +1,35 @@ +.comment-block { + border: 1px solid #000; + padding: 20px 10px; + margin: 10px 0; +} +.comment-text { + margin-bottom: 10px; + background-color: #edf0ee; + border-radius: 10px; + padding: 5px; + line-height: 1.5; +} +.comment-data-block { + display: flex; + justify-content: space-between; +} + +.comment-data { + display: inline-block; +} + +.comment-btns-block { + margin-top: 20px; + display: flex; + justify-content: space-around; +} +.comment-btn { + padding: 5px 10px; + cursor: pointer; + background-color: #404241; + color: #fff; + border-radius: 5px; + border: none; + outline: none; +} diff --git a/client/modules/Post/components/PostCommentsComponents/Comment/Comment.jsx b/client/modules/Post/components/PostCommentsComponents/Comment/Comment.jsx new file mode 100644 index 000000000..d961ecaa1 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/Comment/Comment.jsx @@ -0,0 +1,65 @@ +import React, { Component } from "react"; +import styles from "./Comment.css"; +import ChangeCommentForm from "../ChangeCommentForm/ChangeCommentForm"; +import PropTypes from "prop-types"; + +class Comment extends Component { + state = { + date: new Date(this.props.createDate).toLocaleDateString(), + isShowChangeForm: false, + }; + onShowChangeForm = () => { + this.setState({ + isShowChangeForm: !this.state.isShowChangeForm, + }); + }; + render() { + return ( + +
+ {this.state.isShowChangeForm && ( + + )} +

{this.props.text}

+
+ + Comment was written by {this.props.name} + + + Created: {this.state.date} + +
+
+ + +
+
+
+ ); + } +} + +Comment.propTypes = { + createDate: PropTypes.func.isRequired, + name: PropTypes.string.isRequired, + onDeleteComment: PropTypes.func.isRequired, + onEditComment: PropTypes.func.isRequired, + text: PropTypes.string.isRequired, + createDate: PropTypes.shape().isRequired, +}; + +export default Comment; diff --git a/client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.css b/client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.css new file mode 100644 index 000000000..e09b743a9 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.css @@ -0,0 +1,9 @@ +.collapse-comments { + background-color: #03a9f4; + width: 100%; + padding: 10px 0; + text-align: center; + color: #fff; + cursor: pointer; + margin-top: 20px; +} \ No newline at end of file diff --git a/client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.jsx b/client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.jsx new file mode 100644 index 000000000..07824d492 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/PostComments/PostComments.jsx @@ -0,0 +1,37 @@ +import React from "react"; +import AddCommentForm from "../AddCommentForm/AddCommentForm"; +import Comment from "../Comment/Comment.jsx"; +import styles from "./PostComments.css"; +import PropTypes from "prop-types"; + +const PostComments = (props) => { + return ( + + + {props.comments.map((comment) => ( + + ))} +
+ Collapse comments +
+
+ ); +}; + +PostComments.propTypes = { + handleToggleComments: PropTypes.func.isRequired, + onAddComment: PropTypes.func.isRequired, + onDeleteComment: PropTypes.func.isRequired, + onEditComment: PropTypes.func.isRequired, + comments: PropTypes.array.isRequired, +}; + +export default PostComments; diff --git a/client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.css b/client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.css new file mode 100644 index 000000000..d572fb794 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.css @@ -0,0 +1,13 @@ +.wrapper-block { + margin-top: 10px; +} + +.open-comments { + background-color: #03a9f4; + width: 100%; + padding: 10px 0; + text-align: center; + color: #fff; + cursor: pointer; +} + diff --git a/client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.jsx b/client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.jsx new file mode 100644 index 000000000..acd49a925 --- /dev/null +++ b/client/modules/Post/components/PostCommentsComponents/PostCommentsBlock.jsx @@ -0,0 +1,100 @@ +import React, { Component } from "react"; +import styles from "./PostCommentsBlock.css"; +import PostComments from "./PostComments/PostComments.jsx"; +import PropTypes from "prop-types"; + +class PostCommentsBlock extends Component { + state = { + isOpenComments: false, + comments: [], + }; + handleToggleComments = () => { + this.setState({ + isOpenComments: !this.state.isOpenComments, + }); + }; + onAddComment = (name, text) => { + const newComment = { + name, + text, + createDate: new Date(), + }; + const updatedComments = [...this.state.comments]; + updatedComments.unshift(newComment); + this.setState({ + comments: updatedComments, + }); + }; + onDeleteComment = (id) => { + this.setState({ + comments: this.state.comments.filter( + (comment) => comment.createDate !== id + ), + }); + }; + onEditComment = (newText, id) => { + let commentPlace; + const editingComment = this.state.comments.find( + (comment) => comment.createDate === id + ); + this.state.comments.forEach((comment, index) => { + if (comment.createDate === editingComment.createDate) { + commentPlace = index; + } + }); + const updatedComment = { ...editingComment, text: newText }; + const upDatedComments = [...this.state.comments]; + upDatedComments.splice(commentPlace, 1, updatedComment); + this.setState({ + comments: upDatedComments, + }); + }; + render() { + return ( +
+ {this.state.isOpenComments ? ( + + ) : ( +
+ Comments, {this.state.comments.length} +
+ )} +
+ ); + } +} + +PostCommentsBlock.propTypes = { + post: PropTypes.shape({ + name: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + content: PropTypes.string.isRequired, + slug: PropTypes.string.isRequired, + cuid: PropTypes.string.isRequired, + }).isRequired, + commentsData: PropTypes.shape({ + cuid: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + certainComments: PropTypes.arrayOf( + PropTypes.shape({ + createDate: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + }) + ), + }), +}; +PostCommentsBlock.defaultProps = { + commentsData: undefined, +}; + +export default PostCommentsBlock; diff --git a/client/modules/Post/components/PostListItem/PostListItem.js b/client/modules/Post/components/PostListItem/PostListItem.js index 2925e2199..40c7d6ff2 100644 --- a/client/modules/Post/components/PostListItem/PostListItem.js +++ b/client/modules/Post/components/PostListItem/PostListItem.js @@ -1,27 +1,36 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Link } from 'react-router'; -import { FormattedMessage } from 'react-intl'; +/* eslint-disable */ +import React from "react"; +import PropTypes from "prop-types"; +import { Link } from "react-router"; +import { FormattedMessage } from "react-intl"; +import PostCommentsBlock from "../PostCommentsComponents/PostCommentsBlock.jsx"; // Import Style -import styles from './PostListItem.css'; +import styles from "./PostListItem.css"; -function PostListItem(props) { +const PostListItem = (props) => { return ( -
-

- +
+

+ {props.post.title}

-

{props.post.name}

-

{props.post.content}

-

+

+ {props.post.name} +

+

{props.post.content}

+

+ + + +

+
); -} - +}; +/* eslint-enable */ PostListItem.propTypes = { post: PropTypes.shape({ name: PropTypes.string.isRequired, diff --git a/client/modules/Post/pages/PostListPage/PostListPage.js b/client/modules/Post/pages/PostListPage/PostListPage.js index 7c31229e6..4700b6e0e 100644 --- a/client/modules/Post/pages/PostListPage/PostListPage.js +++ b/client/modules/Post/pages/PostListPage/PostListPage.js @@ -1,30 +1,36 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; +/* eslint-disable */ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; // Import Components -import PostList from '../../components/PostList'; -import PostCreateWidget from '../../components/PostCreateWidget/PostCreateWidget'; +import PostList from "../../components/PostList"; +import PostCreateWidget from "../../components/PostCreateWidget/PostCreateWidget"; // Import Actions -import { addPostRequest, fetchPosts, deletePostRequest } from '../../PostActions'; -import { toggleAddPost } from '../../../App/AppActions'; +import { + addPostRequest, + fetchPosts, + deletePostRequest, +} from "../../PostActions"; +import { toggleAddPost } from "../../../App/AppActions"; // Import Selectors -import { getShowAddPost } from '../../../App/AppReducer'; -import { getPosts } from '../../PostReducer'; +import { getShowAddPost } from "../../../App/AppReducer"; +import { getPosts } from "../../PostReducer"; class PostListPage extends Component { componentDidMount() { this.props.dispatch(fetchPosts()); } - handleDeletePost = post => { - if (confirm('Do you want to delete this post')) { // eslint-disable-line + handleDeletePost = (post) => { + if (confirm("Do you want to delete this post")) { + // eslint-disable-line this.props.dispatch(deletePostRequest(post)); } }; - + /* eslint-enable */ handleAddPost = (name, title, content) => { this.props.dispatch(toggleAddPost()); this.props.dispatch(addPostRequest({ name, title, content })); @@ -33,15 +39,25 @@ class PostListPage extends Component { render() { return (
- - + +
); } } // Actions required to provide data for this component to render in sever side. -PostListPage.need = [() => { return fetchPosts(); }]; +PostListPage.need = [ + () => { + return fetchPosts(); + }, +]; // Retrieve data from store as props function mapStateToProps(state) { @@ -52,11 +68,13 @@ function mapStateToProps(state) { } PostListPage.propTypes = { - posts: PropTypes.arrayOf(PropTypes.shape({ - name: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - content: PropTypes.string.isRequired, - })).isRequired, + posts: PropTypes.arrayOf( + PropTypes.shape({ + name: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + content: PropTypes.string.isRequired, + }) + ).isRequired, showAddPost: PropTypes.bool.isRequired, dispatch: PropTypes.func.isRequired, }; diff --git a/client/reducers.js b/client/reducers.js index 2aa143142..72b370620 100644 --- a/client/reducers.js +++ b/client/reducers.js @@ -1,13 +1,14 @@ /** * Root Reducer */ -import { combineReducers } from 'redux'; +/* eslint-disable */ +import { combineReducers } from "redux"; // Import Reducers -import app from './modules/App/AppReducer'; -import posts from './modules/Post/PostReducer'; -import intl from './modules/Intl/IntlReducer'; - +import app from "./modules/App/AppReducer"; +import posts from "./modules/Post/PostReducer"; +import intl from "./modules/Intl/IntlReducer"; +/* eslint-enable */ // Combine all reducers into one root reducer export default combineReducers({ app, diff --git a/package.json b/package.json index f0fa1f581..423cf8e99 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,7 @@ "lint": "eslint client server" }, "pre-commit": [ - "lint", - "test" + "lint" ], "repository": { "type": "git",