From 9e596345b5a7ffe4e2aa116ee4dc816c43cabb53 Mon Sep 17 00:00:00 2001 From: Artyom Date: Tue, 12 Feb 2019 18:39:21 +0400 Subject: [PATCH] Added comment feauture Added CRUD operation for comments in client side and server side. --- client/modules/Post/CommentActions.js | 76 +++++++++++++++ client/modules/Post/CommentReducer.js | 60 ++++++++++++ .../CommentCreateWidget.css | 45 +++++++++ .../CommentCreateWidget.js | 37 +++++++ .../CommentEditWidget/CommentEditWidget.css | 33 +++++++ .../CommentEditWidget/CommentEditWidget.js | 43 ++++++++ client/modules/Post/components/CommentList.js | 37 +++++++ .../CommentListItem/CommentListItem.css | 45 +++++++++ .../CommentListItem/CommentListItem.js | 36 +++++++ .../pages/PostDetailPage/PostDetailPage.js | 59 ++++++++--- client/reducers.js | 2 + server/controllers/post.controller.js | 97 +++++++++++++++++-- server/models/comment.js | 13 +++ server/routes/post.routes.js | 12 +++ 14 files changed, 578 insertions(+), 17 deletions(-) create mode 100644 client/modules/Post/CommentActions.js create mode 100644 client/modules/Post/CommentReducer.js create mode 100644 client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.css create mode 100644 client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.js create mode 100644 client/modules/Post/components/CommentEditWidget/CommentEditWidget.css create mode 100644 client/modules/Post/components/CommentEditWidget/CommentEditWidget.js create mode 100644 client/modules/Post/components/CommentList.js create mode 100644 client/modules/Post/components/CommentListItem/CommentListItem.css create mode 100644 client/modules/Post/components/CommentListItem/CommentListItem.js create mode 100644 server/models/comment.js diff --git a/client/modules/Post/CommentActions.js b/client/modules/Post/CommentActions.js new file mode 100644 index 000000000..9c15a4cf2 --- /dev/null +++ b/client/modules/Post/CommentActions.js @@ -0,0 +1,76 @@ +import callApi from '../../util/apiCaller'; + +// Export Constants +export const ADD_COMMENT = 'ADD_COMMENT'; +export const ADD_COMMENTS = 'ADD_COMMENTS'; +export const DELETE_COMMENT = 'DELETE_COMMENT'; +export const EDIT_COMMENT = 'EDIT_COMMENT'; +export const UPDATE_COMMENT = 'UPDATE_COMMENT'; + +// Export Actions +export function addComment(comment) { + return { + type: ADD_COMMENT, + comment, + }; +} + +export function addCommentRequest(comment, postId) { + return dispatch => { + return callApi(`posts/${postId}/comment`, 'post', { + comment: { + author: comment.author, + content: comment.content, + }, + }).then(res => dispatch(addComment(res.comment))); + }; +} + +export function addComments(comments) { + return { + type: ADD_COMMENTS, + comments, + }; +} + +export function fetchComments(postId) { + return (dispatch) => { + return callApi(`posts/${postId}/comments`).then(res => { + dispatch(addComments(res.comments)); + }); + }; +} + +export function deleteComment(cuid) { + return { + type: DELETE_COMMENT, + cuid, + }; +} + +export function editComment(cuid) { + return { + type: EDIT_COMMENT, + cuid, + }; +} + + +export function updateComment(comment) { + return { + type: UPDATE_COMMENT, + comment, + }; +} + +export function deleteCommentRequest(cuid) { + return (dispatch) => { + return callApi(`comment/${cuid}`, 'delete').then(() => dispatch(deleteComment(cuid))); + }; +} + +export function updateCommentRequest(comment) { + return (dispatch) => { + return callApi(`comment/${comment.cuid}`, 'put', { comment }).then(() => dispatch(updateComment(comment))); + }; +} diff --git a/client/modules/Post/CommentReducer.js b/client/modules/Post/CommentReducer.js new file mode 100644 index 000000000..55acdc809 --- /dev/null +++ b/client/modules/Post/CommentReducer.js @@ -0,0 +1,60 @@ +/* eslint-disable no-param-reassign */ +/* eslint-disable no-unused-expressions */ +import { + ADD_COMMENTS, + ADD_COMMENT, + DELETE_COMMENT, + EDIT_COMMENT, + UPDATE_COMMENT, +} from './CommentActions'; + +// Initial State +const initialState = { data: [] }; + +const CommentReducer = (state = initialState, action) => { + switch (action.type) { + case ADD_COMMENT: + return { + data: [action.comment, ...state.data], + }; + case ADD_COMMENTS: + return { + data: action.comments, + }; + case DELETE_COMMENT: + return { + data: state.data.filter(comment => comment.cuid !== action.cuid), + }; + case EDIT_COMMENT: + return { + data: state.data.map(comment => { + comment.cuid === action.cuid + ? (comment.isEdit = true) + : (comment.isEdit = false); + return comment; + }), + }; + case UPDATE_COMMENT: + return { + data: state.data.map(comment => { + comment.isEdit = false; + if (comment.cuid === action.comment.cuid) { + comment.content = action.comment.content; + return comment; + } + return comment; + }), + }; + + default: + return state; + } +}; + +/* Selectors */ + +// Get all Comments +export const getComments = state => state.comments.data; + +// Export Reducer +export default CommentReducer; diff --git a/client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.css b/client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.css new file mode 100644 index 000000000..4c9b84ec5 --- /dev/null +++ b/client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.css @@ -0,0 +1,45 @@ +.form { + background: #FAFAFA; + padding: 32px; + border: 1px solid #eee; + border-radius: 4px; +} + +.form-content{ + width: 100%; + font-size: 14px; +} + +.form-title{ + font-size: 16px; + font-weight: 700; + margin-bottom: 16px; + color: #757575; +} + +.form-field{ + width: 100%; + margin-bottom: 16px; + font-family: 'Lato', sans-serif; + font-size: 16px; + line-height: normal; + padding: 12px 16px; + border-radius: 4px; + border: 1px solid #ddd; + outline: none; + color: #212121; +} + +textarea { + min-height: 200px; +} + +.post-submit-button { + display: inline-block; + padding: 8px 16px; + font-size: 18px; + color: #FFF; + background: #03A9F4; + text-decoration: none; + border-radius: 4px; +} diff --git a/client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.js b/client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.js new file mode 100644 index 000000000..83ddf66a8 --- /dev/null +++ b/client/modules/Post/components/CommentCreateWidget/CommentCreateWidget.js @@ -0,0 +1,37 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { injectIntl, FormattedMessage } from 'react-intl'; + +// Import Style +import styles from './CommentCreateWidget.css'; + +export class CommentCreateWidget extends Component { + addComment = () => { + const authorRef = this.refs.author; + const contentRef = this.refs.content; + if (authorRef.value && contentRef.value) { + this.props.addComment(authorRef.value, contentRef.value); + authorRef.value = contentRef.value = ''; + } + }; + + render() { + const cls = `${styles.form}`; + return ( +
+
Comment
+
+ +