Last active
September 25, 2015 19:41
-
-
Save Polyrhythm/10b76ed44ddd51b82a89 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { Link } from 'react-router'; | |
import copy from 'shared/constants/copy'; | |
import PostComments from 'shared/components/PostComments'; | |
import PostCommentControls from 'shared/components/PostCommentControls'; | |
import FluxComponent from 'flummox/component'; | |
export default class PostComment extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
expanded: false, | |
controls: false | |
}; | |
} | |
shouldComponentUpdate(nextProps, nextState) { | |
const props = [ | |
'comment', | |
'author', | |
'points', | |
'replies', | |
'parentLevel', | |
'postId', | |
'nestingColor', | |
'commentId', | |
'activeComment' | |
]; | |
if ( | |
this.state.expanded !== nextState.expanded || | |
this.state.controls !== nextState.controls | |
) { | |
return true; | |
} | |
for (let i = 0; i < props.length; i++) { | |
if (this.props[props[i]] !== nextProps[props[i]]) { | |
return true; | |
} | |
} | |
return false; | |
} | |
_commentReplyCount() { | |
return ( | |
<span className="PostComment-replyCount"> | |
{`${this.props.replies.size} ${copy('commentReplies')}`} | |
</span> | |
); | |
} | |
_commentReplies() { | |
return ( | |
<PostComments | |
topLevel={false} | |
level={this.props.parentLevel + 1} | |
comments={this.props.replies}/> | |
); | |
} | |
_levelIndicator() { | |
return ( | |
<span | |
className="PostComment PostComment-levelIndicator" | |
style={{ backgroundColor: this.props.nestingColor }}> | |
</span> | |
); | |
} | |
_separator() { | |
return ( | |
<span | |
className="PostComment PostComment-levelIndicatorSeparator" | |
style={{ backgroundColor: this.props.nestingColor }}> | |
</span> | |
); | |
} | |
async handleCommentClick(e) { | |
e.stopPropagation(); | |
const postStore = this.context.flux.getStore('post'); | |
const commentActions = this.context.flux.getActions('comment'); | |
this.context.flux.getActions('comment').toggleReply(false); | |
// only load comments if the click happened on a top-level comment | |
// and comments are not currently loaded | |
if (this.props.parentLevel === 0 && postStore.getComments().size === 0) { | |
await commentActions.getComments(this.props.postId); | |
} | |
if ( | |
this.state.controls && | |
this.state.expanded && | |
postStore.getActiveComment() !== this.props.commentId | |
) { | |
commentActions.setActiveComment(this.props.commentId); | |
return; | |
} | |
// notify all other comments via PostStore that this comment | |
// is now active | |
commentActions.setActiveComment(this.props.commentId); | |
this.setState({ | |
expanded: !this.state.expanded, | |
controls: !this.state.controls | |
}); | |
} | |
render() { | |
const replyCount = this.props.replies.size ? | |
this._commentReplyCount() : | |
<span></span>; | |
const replies = this.props.replies.size && this.state.expanded ? | |
this._commentReplies() : | |
<span></span>; | |
const controls = (this.props.activeComment === this.props.commentId) && this.state.controls ? | |
// this component subscribes to replyActive | |
// so that it knows to have its reply textarea | |
// expanded or not | |
<FluxComponent connectToStores={{ | |
post: (store) => ({ | |
replyActive: store.getReplyActive() | |
}) | |
}}> | |
<PostCommentControls | |
commentId={this.props.commentId.toString()} | |
vote={this.props.vote}/> | |
</FluxComponent> : | |
<span></span>; | |
const levelIndicator = this.props.parentLevel ? | |
this._levelIndicator() : | |
<span></span>; | |
const separator = this.props.parentLevel ? | |
this._separator() : | |
<span></span>; | |
return ( | |
<div className="PostComment" | |
onClick={this.handleCommentClick.bind(this)}> | |
{separator} | |
<hr className="PostComments-separator"/> | |
<div className="PostComment-contentContainer"> | |
<div className="PostComment-metaContainer"> | |
{levelIndicator} | |
<a | |
className="PostComment-author" | |
href={`/user/${this.props.author}`}> | |
{this.props.author} | |
</a> | |
<span className="PostComment-points"> | |
{`${this.props.points} ${copy('postPoints')}`} | |
</span> | |
{replyCount} | |
</div> | |
<p className="PostComment-commentText">{this.props.comment}</p> | |
{controls} | |
</div> | |
{replies} | |
</div> | |
); | |
} | |
} | |
PostComment.contextTypes = { | |
flux: React.PropTypes.object | |
}; | |
PostComment.propTypes = { | |
comment: React.PropTypes.string, | |
author: React.PropTypes.string, | |
points: React.PropTypes.number, | |
replies: React.PropTypes.object, // Immutable list | |
parentLevel: React.PropTypes.number, | |
postId: React.PropTypes.string, | |
nestingColor: React.PropTypes.string, | |
commentId: React.PropTypes.number, | |
vote: React.PropTypes.string | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment