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
76 changes: 76 additions & 0 deletions client/modules/Post/CommentActions.js
Original file line number Diff line number Diff line change
@@ -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)));
};
}
60 changes: 60 additions & 0 deletions client/modules/Post/CommentReducer.js
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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 (
<div className={cls}>
<div className={styles['form-title']}>Comment</div>
<div className={styles['form-content']}>
<input className={styles['form-field']} ref="author" />
<textarea className={styles['form-field']} ref="content" />
<a className={styles['post-submit-button']} href="#" onClick={this.addComment}><FormattedMessage id="submit" /></a>
</div>
</div>
);
}
}

CommentCreateWidget.propTypes = {
addComment: PropTypes.func.isRequired,
};

export default injectIntl(CommentCreateWidget);
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.form {
background: #FAFAFA;
padding: 32px;
border: 1px solid #eee;
border-radius: 4px;
}

.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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage } from 'react-intl';

// Import Style
import styles from './CommentEditWidget.css';

export class CommentEditWidget extends Component {
updateComment = () => {
const contentRef = this.refs.content;
if (contentRef.value) {
this.props.onUpdate(contentRef.value);
}
};

render() {
return (
<div>
<textarea
className={styles['form-field']}
ref="content"
defaultValue={this.props.comment.content}
/>
<a
className={styles['post-submit-button']}
href="#"
onClick={this.updateComment}
>
<FormattedMessage id="submit" />
</a>
</div>
);
}
}

CommentEditWidget.propTypes = {
onUpdate: PropTypes.func.isRequired,
comment: PropTypes.shape({
content: PropTypes.string.isRequired,
}).isRequired,
};

export default injectIntl(CommentEditWidget);
37 changes: 37 additions & 0 deletions client/modules/Post/components/CommentList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';

// Import Components
import CommentListItem from './CommentListItem/CommentListItem';

function CommentList(props) {
return (
<div className="listView">
{props.comments.map(comment => (
<div>
<CommentListItem
comment={comment}
key={comment.cuid}
onUpdate={content => props.handleOnUpdate(comment.cuid, content)}
onEdit={() => props.handleOnEdit(comment.cuid)}
onDelete={() => props.handleDeleteComment(comment.cuid)}
/>
</div>
))}
</div>
);
}

CommentList.propTypes = {
comments: PropTypes.arrayOf(
PropTypes.shape({
author: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
slug: PropTypes.string.isRequired,
cuid: PropTypes.string.isRequired,
})
).isRequired,
handleDeleteComment: PropTypes.func.isRequired,
};

export default CommentList;
45 changes: 45 additions & 0 deletions client/modules/Post/components/CommentListItem/CommentListItem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.single-comment {
background: #fafafa;
padding: 32px;
border: 1px solid #eee;
border-radius: 4px;
margin: 16px 0px;
}

.author-name {
font-size: 16px;
margin-bottom: 16px;
color: #757575;
}

.post-submit-button {
display: inline-block;
padding: 8px 16px;
font-size: 18px;
color: #fff;
background: #03a9f4;
text-decoration: none;
border-radius: 4px;
}

.comment-delete-button {
color: red;
}

.comment-edit-button {
color: #03a9f4;
margin-right: 8px;
}

.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;
}
Loading