merge remote. can reply to a comment

This commit is contained in:
Riley Davis
2017-01-23 16:52:16 -07:00
parent 9e22c100f0
commit 6282c39f3a
8 changed files with 245 additions and 160 deletions
+140 -86
View File
@@ -11,103 +11,157 @@ import PermalinkButton from 'coral-plugin-permalinks/PermalinkButton';
// import AuthorName from '../../coral-plugin-author-name/AuthorName';
import Content from '../../coral-plugin-commentcontent/CommentContent';
import PubDate from '../../coral-plugin-pubdate/PubDate';
// import {ReplyBox, ReplyButton} from '../../coral-plugin-replies';
import {ReplyBox, ReplyButton} from 'coral-plugin-replies';
import FlagComment from '../../coral-plugin-flags/FlagComment';
import LikeButton from '../../coral-plugin-likes/LikeButton';
const getAction = (type, comment) => comment.actions.filter((a) => a.type === type)[0];
const Comment = ({comment, currentUser, asset, depth, showSignInDialog, postAction, deleteAction}) => {
const like = getAction('LIKE', comment);
const flag = getAction('FLAG', comment);
return (
<div
className="comment"
id={`c_${comment.id}`}
style={{marginLeft: depth * 30}}>
<hr aria-hidden={true} />
{/* <AuthorName
author={comment.user}
addNotification={this.props.addNotification}
id={comment.id}
author_id={comment.user.id}
postAction={this.props.postAction}
showSignInDialog={this.props.showSignInDialog}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={currentUser}/>*/}
<PubDate created_at={comment.created_at} />
<Content body={comment.body} />
<div className="commentActionsLeft">
{/*
<ReplyButton/>
*/}
<LikeButton
like={like}
id={comment.id}
postAction={postAction}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
currentUser={currentUser}
/>
</div>
<div className="commentActionsRight">
<FlagComment
flag={flag}
class Comment extends React.Component {
constructor(props) {
super(props);
this.state = {replyBoxVisible: false};
}
static propTypes = {
showSignInDialog: PropTypes.func.isRequired,
postAction: PropTypes.func.isRequired,
deleteAction: PropTypes.func.isRequired,
parentId: PropTypes.string,
addNotification: PropTypes.func.isRequired,
postItem: PropTypes.func.isRequired,
depth: PropTypes.number.isRequired,
asset: PropTypes.shape({
id: PropTypes.string,
title: PropTypes.string,
url: PropTypes.string
}).isRequired,
currentUser: PropTypes.shape({
id: PropTypes.string.isRequired
}),
comment: PropTypes.shape({
depth: PropTypes.number,
actions: PropTypes.array.isRequired,
body: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
replies: PropTypes.arrayOf(
PropTypes.shape({
body: PropTypes.string.isRequired,
id: PropTypes.string.isRequired
})
),
user: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired
}).isRequired
}).isRequired
}
render () {
const {
comment,
currentUser,
asset,
depth,
postItem,
addNotification,
showSignInDialog,
postAction,
deleteAction
} = this.props;
const like = getAction('LIKE', comment);
const flag = getAction('FLAG', comment);
return (
<div
className="comment"
id={`c_${comment.id}`}
style={{marginLeft: depth * 30}}>
<hr aria-hidden={true} />
{/* <AuthorName
author={comment.user}
addNotification={this.props.addNotification}
id={comment.id}
author_id={comment.user.id}
postAction={postAction}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
currentUser={currentUser}
/>
<PermalinkButton articleURL={asset.url} commentId={comment.id} />
</div>
{
comment.replies &&
comment.replies.map(reply => {
return <Comment
depth={depth + 1}
asset={asset}
currentUser={currentUser}
currentUser={currentUser}
postAction={this.props.postAction}
showSignInDialog={this.props.showSignInDialog}
deleteAction={this.props.deleteAction}
addItem={this.props.addItem}
updateItem={this.props.updateItem}
currentUser={currentUser}/>*/}
<PubDate created_at={comment.created_at} />
<Content body={comment.body} />
{
currentUser
? <div className="commentActionsLeft">
<ReplyButton
onClick={() => {
console.log('reply button click');
this.setState({replyBoxVisible: !this.state.replyBoxVisible});
}}
parentCommentId={comment.id}
currentUserId={currentUser.id}
banned={false} />
<LikeButton
like={like}
id={comment.id}
postAction={postAction}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
currentUser={currentUser} />
</div>
: null
}
<div className="commentActionsRight">
{
currentUser
? <FlagComment
flag={flag}
id={comment.id}
author_id={comment.user.id}
postAction={postAction}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
key={reply.id}
comment={reply} />;
})
}
currentUser={currentUser} />
: null
}
</div>
);
};
<PermalinkButton articleURL={asset.url} commentId={comment.id} />
</div>
{
this.state.replyBoxVisible
? <ReplyBox
parentId={comment.id}
addNotification={addNotification}
authorId={currentUser.id}
postItem={postItem}
assetId={asset.id} />
: null
}
{
comment.replies &&
comment.replies.map(reply => {
return <Comment
addNotification={addNotification}
parentId={comment.id}
postItem={postItem}
depth={depth + 1}
asset={asset}
currentUser={currentUser}
postAction={postAction}
deleteAction={deleteAction}
showSignInDialog={showSignInDialog}
key={reply.id}
comment={reply} />;
})
}
Comment.propTypes = {
depth: PropTypes.number.isRequired,
asset: PropTypes.shape({
id: PropTypes.string,
title: PropTypes.string,
url: PropTypes.string
}).isRequired,
currentUser: PropTypes.object,
comment: PropTypes.shape({
depth: PropTypes.number,
actions: PropTypes.array.isRequired,
body: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
replies: PropTypes.arrayOf(
PropTypes.shape({
body: PropTypes.string.isRequired,
id: PropTypes.string.isRequired
})
),
user: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired
}).isRequired
}).isRequired
};
</div>
);
}
}
export default Comment;
+20 -13
View File
@@ -102,7 +102,7 @@ class Embed extends Component {
// const banned = (this.props.userData.status === 'banned');
const {loading, asset} = this.props.data;
const {loading, asset, refetch} = this.props.data;
// const {status, moderation, closedMessage, charCount, charCountEnable} = asset.settings;
@@ -129,24 +129,31 @@ class Embed extends Component {
enable={asset.settings.infoBoxEnable}
/>
<RestrictedContent restricted={false} restrictedComp={<SuspendedAccount />}>
<CommentBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
id={asset.id}
premod={asset.settings.moderation}
reply={false}
currentUser={this.props.auth.user}
banned={false}
author={user}
charCount={asset.settings.charCountEnable && asset.settings.charCount}/>
{
user
? <CommentBox
addNotification={this.props.addNotification}
postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem}
assetId={asset.id}
premod={asset.settings.moderation}
isReply={false}
currentUser={this.props.auth.user}
banned={false}
authorId={user.id}
charCount={asset.settings.charCountEnable && asset.settings.charCount} />
: null
}
</RestrictedContent>
</div>
: <p>{asset.settings.closedMessage}</p>
}
{!loggedIn && <SignInContainer offset={signInOffset}/>}
<Stream
refetch={refetch}
addNotification={this.props.addNotification}
postItem={this.props.postItem}
asset={asset}
currentUser={user}
postAction={this.props.postAction}
+5 -1
View File
@@ -1,13 +1,15 @@
import React, {PropTypes} from 'react';
import Comment from './Comment';
const Stream = ({comments, currentUser, asset, postAction, deleteAction, showSignInDialog}) => {
const Stream = ({comments, currentUser, asset, postItem, addNotification, postAction, deleteAction, showSignInDialog}) => {
return (
<div>
{
comments.map(comment => {
return <Comment
addNotification={addNotification}
depth={0}
postItem={postItem}
asset={asset}
currentUser={currentUser}
postAction={postAction}
@@ -22,6 +24,8 @@ const Stream = ({comments, currentUser, asset, postAction, deleteAction, showSig
};
Stream.propTypes = {
addNotification: PropTypes.func.isRequired,
postItem: PropTypes.func.isRequired,
asset: PropTypes.object.isRequired,
comments: PropTypes.array.isRequired,
currentUser: PropTypes.shape({
@@ -5,12 +5,12 @@ import DELETE_ACTION from './deleteAction.graphql';
export const postComment = graphql(POST_COMMENT, {
props: ({mutate}) => ({
postItem: ({asset_id, body}) => {
postItem: ({asset_id, body, parent_id} /*, type */) => {
return mutate({
variables: {
asset_id,
body,
parent_id: null
parent_id
}
});
}}),
+38 -33
View File
@@ -8,11 +8,13 @@ const name = 'coral-plugin-commentbox';
class CommentBox extends Component {
static propTypes = {
postItem: PropTypes.func,
updateItem: PropTypes.func,
id: PropTypes.string,
comments: PropTypes.array,
reply: PropTypes.bool,
postItem: PropTypes.func.isRequired,
// updateItem: PropTypes.func,
assetId: PropTypes.string.isRequired,
parentId: PropTypes.string,
authorId: PropTypes.string.isRequired,
// comments: PropTypes.array,
isReply: PropTypes.bool.isRequired,
canPost: PropTypes.bool,
currentUser: PropTypes.object
}
@@ -25,33 +27,36 @@ class CommentBox extends Component {
postComment = () => {
const {
postItem,
updateItem,
id,
parent_id,
child_id,
// updateItem,
assetId,
parentId,
// child_id,
addNotification,
appendItemArray,
author
// appendItemArray,
authorId
} = this.props;
let comment = {
body: this.state.body,
asset_id: id,
author_id: author.id
asset_id: assetId,
author_id: authorId,
parent_id: parentId
};
let related;
let parent_type;
if (parent_id) {
comment.parent_id = parent_id;
related = 'children';
parent_type = 'comments';
} else {
related = 'comments';
parent_type = 'assets';
}
if (child_id || parent_id) {
updateItem(child_id || parent_id, 'showReply', false, 'comments');
}
console.log('CommentBox.parentId', parentId);
// let related;
// let parent_type;
// if (parent_id) {
// comment.parent_id = parent_id;
// related = 'children';
// parent_type = 'comments';
// } else {
// related = 'comments';
// parent_type = 'assets';
// }
// if (child_id || parent_id) {
// updateItem(child_id || parent_id, 'showReply', false, 'comments');
// }
if (this.props.charCount && this.state.body.length > this.props.charCount) {
return;
@@ -59,13 +64,13 @@ class CommentBox extends Component {
postItem(comment, 'comments')
.then(({data}) => {
const postedComment = data.createComment;
const commentId = postedComment.id;
// const commentId = postedComment.id;
if (postedComment.status === 'rejected') {
addNotification('error', lang.t('comment-post-banned-word'));
} else if (postedComment.status === 'PREMOD') {
addNotification('success', lang.t('comment-post-notif-premod'));
} else {
appendItemArray(parent_id || id, related, commentId, !parent_id, parent_type);
// appendItemArray(parent_id || id, related, commentId, !parent_id, parent_type);
addNotification('success', 'Your comment has been posted.');
}
})
@@ -74,23 +79,23 @@ class CommentBox extends Component {
}
render () {
const {styles, reply, author, charCount} = this.props;
const {styles, isReply, authorId, charCount} = this.props;
const length = this.state.body.length;
return <div>
<div
className={`${name}-container`}>
<label
htmlFor={ reply ? 'replyText' : 'commentText'}
htmlFor={ isReply ? 'replyText' : 'commentText'}
className="screen-reader-text"
aria-hidden={true}>
{reply ? lang.t('reply') : lang.t('comment')}
{isReply ? lang.t('reply') : lang.t('comment')}
</label>
<textarea
className={`${name}-textarea`}
style={styles && styles.textarea}
value={this.state.body}
placeholder={lang.t('comment')}
id={reply ? 'replyText' : 'commentText'}
id={isReply ? 'replyText' : 'commentText'}
onChange={(e) => this.setState({body: e.target.value})}
rows={3}/>
</div>
@@ -101,7 +106,7 @@ class CommentBox extends Component {
}
</div>
<div className={`${name}-button-container`}>
{ author && (
{ authorId && (
<Button
cStyle={!length || (charCount && length > charCount) ? 'lightGrey' : 'darkGrey'}
className={`${name}-button`}
+1 -1
View File
@@ -115,7 +115,7 @@ class FlagButton extends Component {
{
flagged
? <span className={`${name}-button-text`}>{lang.t('reported')}</span>
: <span className={`${name}-button-text`}>{lang.t('report')}</span>
: <span className={`${name}-button-text`}>{lang.t('report')}</span>
}
<i className={`${name}-icon material-icons ${flagged && 'flaggedIcon'}`}
style={flagged ? styles.flaggedIcon : {}}
+20 -11
View File
@@ -1,17 +1,26 @@
import React from 'react';
import React, {PropTypes} from 'react';
import CommentBox from '../coral-plugin-commentbox/CommentBox';
const name = 'coral-plugin-replies';
const ReplyBox = (props) => <div
className={`${name}-textarea`}
style={props.styles && props.styles.container}>
{
props.showReply && <CommentBox
{...props}
comments = {props.child}
reply = {true}/>
}
</div>;
const ReplyBox = ({styles, postItem, assetId, authorId, addNotification, parentId}) => (
<div className={`${name}-textarea`} style={styles && styles.container}>
<CommentBox
parentId={parentId}
addNotification={addNotification}
authorId={authorId}
assetId={assetId}
postItem={postItem}
isReply={true} />
</div>
);
ReplyBox.propTypes = {
parentId: PropTypes.string,
addNotification: PropTypes.func.isRequired,
authorId: PropTypes.string.isRequired,
postItem: PropTypes.func.isRequired,
assetId: PropTypes.string.isRequired
};
export default ReplyBox;
+19 -13
View File
@@ -1,21 +1,27 @@
import React from 'react';
import React, {PropTypes} from 'react';
import {I18n} from '../coral-framework';
import translations from './translations.json';
const name = 'coral-plugin-replies';
const ReplyButton = (props) => <button
className={`${name}-reply-button`}
onClick={() => {
if (props.banned) {
return;
}
props.updateItem(props.id, 'showReply', !props.showReply, 'comments');
}}>
{lang.t('reply')}
<i className={`${name}-icon material-icons`}
aria-hidden={true}>reply</i>
</button>;
const ReplyButton = ({banned, parentCommentId, currentUserId, onClick}) => {
return (
<button
className={`${name}-reply-button`}
onClick={onClick}>
{lang.t('reply')}
<i className={`${name}-icon material-icons`}
aria-hidden={true}>{banned ? 'BANNED' : 'reply'}</i>
</button>
);
};
ReplyButton.propTypes = {
onClick: PropTypes.func.isRequired,
banned: PropTypes.bool.isRequired,
parentCommentId: PropTypes.string.isRequired,
currentUserId: PropTypes.string.isRequired
};
export default ReplyButton;