From 48b8e58de6b6e7d6d0a0ea78c7e72ca3f868dc4f Mon Sep 17 00:00:00 2001 From: sleepymoonlight Date: Tue, 11 Aug 2020 23:34:12 +0300 Subject: [PATCH 01/10] Add commentSchema to server --- server/models/comment.js | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 server/models/comment.js diff --git a/server/models/comment.js b/server/models/comment.js new file mode 100644 index 000000000..0ec510ad4 --- /dev/null +++ b/server/models/comment.js @@ -0,0 +1,11 @@ +import mongoose from 'mongoose'; +const Schema = mongoose.Schema; + +const commentSchema = new Schema({ + content: { type: 'String', required: true }, + postId: { type: 'String' }, + createdBy: { type: 'String', required: true }, + dateAdded: { type: 'Date', default: Date.now, required: true }, +}); + +export default mongoose.model('Comment', commentSchema); From 93ae4b093c4aab089b74123143f1a43271e001cc Mon Sep 17 00:00:00 2001 From: sleepymoonlight Date: Tue, 11 Aug 2020 23:38:03 +0300 Subject: [PATCH 02/10] Add comment controllers to server(partly) --- server/controllers/comment.controller.js | 82 ++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 server/controllers/comment.controller.js diff --git a/server/controllers/comment.controller.js b/server/controllers/comment.controller.js new file mode 100644 index 000000000..08c86be5e --- /dev/null +++ b/server/controllers/comment.controller.js @@ -0,0 +1,82 @@ +import sanitizeHtml from 'sanitize-html'; + +import Comment from '../models/comment'; + +/** + * Get all comments for some post + * @param req + * @param res + * @returns void + */ +export const getComments = (req, res) => { + Comment.find({ postId: req.params.id }) + .exec((err, comments) => { + if (err) { + res.status(500) + .send(err); + } + res.json({ comments }); + }); +}; + +/** + * Save a comment + * @param req + * @param res + * @returns void + */ +export const addComment = (req, res) => { + if (!req.body.comment || !req.body.comment.content || !req.body.comment.createdBy) { + res.status(403).send(); + } + const newComment = new Comment(req.body.comment); + + newComment.content = sanitizeHtml(newComment.content); + newComment.createdBy = sanitizeHtml(newComment.createdBy); + newComment.postId = req.params.id; + + newComment.save((error, saved) => { + if (error) { + res.status(500).send(error); + } + res.json({ comment: saved }); + }); +}; + +/** + * Get a single comment + * @param req + * @param res + * @returns void + */ +export const getComment = (req, res) => { + Comment.findOne({ postId: req.params.id }) + .exec((err, comment) => { + if (err) { + res.status(500) + .send(err); + } + res.json({ comment }); + }); +}; + +/** + * Delete a post + * @param req + * @param res + * @returns void + */ +export function deleteComment(req, res) { + Comment.findOne({ postId: req.params.id }) + .exec((err, comment) => { + if (err || !comment) { + res.status(500) + .send(err); + } + + comment.remove(() => { + res.status(200) + .end(); + }); + }); +} From a42c0e3813708c463825d494df3cef06b0c31a20 Mon Sep 17 00:00:00 2001 From: sleepymoonlight Date: Tue, 11 Aug 2020 23:39:36 +0300 Subject: [PATCH 03/10] Add comment routes and use it in server --- server/routes/comment.routes.js | 17 +++++++++++++++++ server/server.js | 3 +++ 2 files changed, 20 insertions(+) create mode 100644 server/routes/comment.routes.js diff --git a/server/routes/comment.routes.js b/server/routes/comment.routes.js new file mode 100644 index 000000000..885374fef --- /dev/null +++ b/server/routes/comment.routes.js @@ -0,0 +1,17 @@ +import { Router } from 'express'; +import * as CommentController from '../controllers/comment.controller'; +const router = new Router(); + +// Get all Comments for current post +router.route('/posts/:id/comments').get(CommentController.getComments); + +// Add a new Comment +router.route('/posts/:id/comment').post(CommentController.addComment); + +// Get one Comment +router.route('/comment/:id').get(CommentController.getComment); + +// Delete a Comment +router.route('/comment/:id').delete(CommentController.deleteComment); + +export default router; diff --git a/server/server.js b/server/server.js index 382249c91..34f1b613a 100644 --- a/server/server.js +++ b/server/server.js @@ -46,6 +46,7 @@ import Helmet from 'react-helmet'; import routes from '../client/routes'; import { fetchComponentData } from './util/fetchData'; import posts from './routes/post.routes'; +import comments from './routes/comment.routes'; import dummyData from './dummyData'; import serverConfig from './config'; @@ -71,6 +72,8 @@ app.use(bodyParser.json({ limit: '20mb' })); app.use(bodyParser.urlencoded({ limit: '20mb', extended: false })); app.use(Express.static(path.resolve(__dirname, '../dist/client'))); app.use('/api', posts); +app.use('/api', comments); + // Render Initial HTML const renderFullPage = (html, initialState) => { From 53a0390d0c3e6be4333e7c86a8cc8969805dc107 Mon Sep 17 00:00:00 2001 From: sleepymoonlight Date: Tue, 11 Aug 2020 23:41:40 +0300 Subject: [PATCH 04/10] upgrade react version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f0fa1f581..38e382cc0 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "limax": "^1.3.0", "mongoose": "^4.4.20", "prop-types": "^15.6.2", - "react": "^16.4.1", - "react-dom": "^16.4.1", + "react": "16.7.0-alpha.0", + "react-dom": "16.7.0-alpha.0", "react-helmet": "^5.2.0", "react-intl": "^2.1.2", "react-redux": "^4.4.5", From e78be3e9159495e22a8ad08ed3fe448109630dd3 Mon Sep 17 00:00:00 2001 From: sleepymoonlight Date: Tue, 11 Aug 2020 23:45:54 +0300 Subject: [PATCH 05/10] create getAll and add comment actions and reducer --- client/modules/Comment/CommentActions.js | 40 ++++++++++++++++++++++++ client/modules/Comment/CommentReducer.js | 24 ++++++++++++++ client/reducers.js | 2 ++ 3 files changed, 66 insertions(+) create mode 100644 client/modules/Comment/CommentActions.js create mode 100644 client/modules/Comment/CommentReducer.js diff --git a/client/modules/Comment/CommentActions.js b/client/modules/Comment/CommentActions.js new file mode 100644 index 000000000..bf35eef14 --- /dev/null +++ b/client/modules/Comment/CommentActions.js @@ -0,0 +1,40 @@ +import callApi from '../../util/apiCaller'; + +// Export Constants +export const GET_COMMENTS = 'GET_COMMENTS'; +export const ADD_COMMENT = 'ADD_COMMENT'; + +// Export Actions + +export function getComments(comments) { + return { + type: GET_COMMENTS, + comments, + }; +} + +export function fetchComments(id) { + return (dispatch) => { + return callApi(`/posts/${id}/comments`).then(res => { + dispatch(getComments(res.comments)); + }); + }; +} + +export function addComment(comment) { + return { + type: ADD_COMMENT, + comment, + }; +} + +export function addCommentRequest(comment, id) { + return (dispatch) => { + return callApi(`posts/${id}/comment`, 'post', { + comment: { + content: comment.content, + createdBy: comment.createdBy, + }, + }).then(res => dispatch(addComment(res.comment))); + }; +} diff --git a/client/modules/Comment/CommentReducer.js b/client/modules/Comment/CommentReducer.js new file mode 100644 index 000000000..20d3ed305 --- /dev/null +++ b/client/modules/Comment/CommentReducer.js @@ -0,0 +1,24 @@ +import { GET_COMMENTS, ADD_COMMENT } from './CommentActions'; + +// Initial State +const initialState = { comments: [] }; + +const CommentReducer = (state = initialState, action) => { + switch (action.type) { + case GET_COMMENTS : + return { + comments: [action.comments, ...state.comments], + }; + + case ADD_COMMENT : + return { + comments: [action.comment, ...state.comments], + }; + + default: + return state; + } +}; + +// Export Reducer +export default CommentReducer; diff --git a/client/reducers.js b/client/reducers.js index 2aa143142..9aadfe79d 100644 --- a/client/reducers.js +++ b/client/reducers.js @@ -7,10 +7,12 @@ import { combineReducers } from 'redux'; import app from './modules/App/AppReducer'; import posts from './modules/Post/PostReducer'; import intl from './modules/Intl/IntlReducer'; +import comments from './modules/Comment/CommentReducer'; // Combine all reducers into one root reducer export default combineReducers({ app, posts, intl, + comments, }); From 734019675f2114206b12ee7d88129b0eefdd39ab Mon Sep 17 00:00:00 2001 From: sleepymoonlight Date: Tue, 11 Aug 2020 23:48:42 +0300 Subject: [PATCH 06/10] add comment components and use it with add and getAll actions --- .../CommentCreateWidget.css | 55 +++++++++++++ .../CommentCreateWidget.js | 49 +++++++++++ .../CommentListItem/CommentListItem.css | 81 +++++++++++++++++++ .../CommentListItem/CommentListItem.js | 80 ++++++++++++++++++ .../Comment/components/CommentsList.js | 30 +++++++ client/modules/Post/components/PostList.js | 9 +++ .../components/PostListItem/PostListItem.css | 24 ++++++ .../components/PostListItem/PostListItem.js | 65 +++++++++++++-- .../Post/pages/PostListPage/PostListPage.js | 22 ++++- 9 files changed, 408 insertions(+), 7 deletions(-) create mode 100644 client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.css create mode 100644 client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.js create mode 100644 client/modules/Comment/components/CommentListItem/CommentListItem.css create mode 100644 client/modules/Comment/components/CommentListItem/CommentListItem.js create mode 100644 client/modules/Comment/components/CommentsList.js diff --git a/client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.css b/client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.css new file mode 100644 index 000000000..7d6c370ff --- /dev/null +++ b/client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.css @@ -0,0 +1,55 @@ +.form { + display: block; + background: #FAFAFA; + padding: 32px 0; + border: 1px solid #eee; + border-radius: 4px; +} + +.form-content{ + width: 100%; + margin: auto; + font-size: 14px; +} + +.form-title{ + font-size: 16px; + font-weight: 700; + margin-bottom: 16px; + color: #757575; +} + +.form-field{ + width: 100%; + margin-bottom: 12px; + font-family: 'Lato', sans-serif; + font-size: 13px; + line-height: normal; + padding: 6px 10px; + border-radius: 4px; + border: 1px solid #ddd; + outline: none; + color: #212121; +} + +.form-field-large { + min-height: 120px; +} + +.comment-button { + display: inline-block; + padding: 6px 10px; + margin-left: 10px; + font-size: 14px; + color: #FFF; + text-decoration: none; + border-radius: 4px; +} + +.comment-submit-button { + background: #03A9F4; +} + +.comment-cancel-button { + background: #9a533c; +} diff --git a/client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.js b/client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.js new file mode 100644 index 000000000..db886b959 --- /dev/null +++ b/client/modules/Comment/components/CommentCreateWidget/CommentCreateWidget.js @@ -0,0 +1,49 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; + +// Import Style +import styles from './CommentCreateWidget.css'; + +const CommentCreateWidget = ({ addComment, closeForm }) => { + const [authorName, changeAuthor] = useState(''); + const [content, changeContent] = useState(''); + + const addNewComment = () => { + addComment(authorName, content); + closeForm(); + }; + + return ( +
+
+

+ changeAuthor(e.target.value)} /> +