mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-27 09:35:56 -05:00
Use topLevelCommentId to simplify adding and deleting comments
This fixes the nested comment deletion problem: https://github.com/LLK/scratch-www/issues/2151
This commit is contained in:
parent
744c90501e
commit
24fe4fef65
4 changed files with 56 additions and 48 deletions
|
@ -87,6 +87,19 @@ module.exports.previewReducer = (state, action) => {
|
|||
comments: [...state.comments, ...action.items] // TODO: consider a different way of doing this?
|
||||
});
|
||||
case 'SET_COMMENT_DELETED':
|
||||
if (action.topLevelCommentId) {
|
||||
return Object.assign({}, state, {
|
||||
replies: Object.assign({}, state.replies, {
|
||||
[action.topLevelCommentId]: state.replies[action.topLevelCommentId].map(comment => {
|
||||
if (comment.id === action.commentId) {
|
||||
return Object.assign({}, comment, {deleted: true});
|
||||
}
|
||||
return comment;
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return Object.assign({}, state, {
|
||||
comments: state.comments.map(comment => {
|
||||
if (comment.id === action.commentId) {
|
||||
|
@ -96,30 +109,13 @@ module.exports.previewReducer = (state, action) => {
|
|||
})
|
||||
});
|
||||
case 'ADD_NEW_COMMENT':
|
||||
if (action.comment.parent_id) {
|
||||
let topLevelParent = action.comment.parent_id;
|
||||
|
||||
// If this is a nested reply, we need to look up which top level comment
|
||||
// to put this new reply under.
|
||||
if (!state.replies[topLevelParent]) {
|
||||
Object.keys(state.replies).forEach(topLevelCommentId => {
|
||||
state.replies[topLevelCommentId].forEach(reply => {
|
||||
if (reply.id === action.comment.parent_id) {
|
||||
topLevelParent = topLevelCommentId;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (state.replies[topLevelParent]) {
|
||||
const replies = JSON.parse(JSON.stringify(state.replies));
|
||||
// Replies to comments go at the end of the thread
|
||||
replies[topLevelParent] = replies[topLevelParent].concat(action.comment);
|
||||
return Object.assign({}, state, {replies: replies});
|
||||
}
|
||||
|
||||
log.error('Could not find top level parent to put reply in');
|
||||
return state;
|
||||
if (action.topLevelCommentId) {
|
||||
return Object.assign({}, state, {
|
||||
replies: Object.assign({}, state.replies, {
|
||||
// Replies to comments go at the end of the thread
|
||||
[action.topLevelCommentId]: state.replies[action.topLevelCommentId].concat(action.comment)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Reply to the top level project, put the reply at the beginning
|
||||
|
@ -232,14 +228,16 @@ module.exports.setStudioFetchStatus = (studioId, status) => ({
|
|||
status: status
|
||||
});
|
||||
|
||||
module.exports.setCommentDeleted = commentId => ({
|
||||
module.exports.setCommentDeleted = (commentId, topLevelCommentId) => ({
|
||||
type: 'SET_COMMENT_DELETED',
|
||||
commentId: commentId
|
||||
commentId: commentId,
|
||||
topLevelCommentId: topLevelCommentId
|
||||
});
|
||||
|
||||
module.exports.addNewComment = comment => ({
|
||||
module.exports.addNewComment = (comment, topLevelCommentId) => ({
|
||||
type: 'ADD_NEW_COMMENT',
|
||||
comment: comment
|
||||
comment: comment,
|
||||
topLevelCommentId: topLevelCommentId
|
||||
});
|
||||
|
||||
module.exports.getProjectInfo = (id, token) => (dispatch => {
|
||||
|
|
|
@ -15,6 +15,7 @@ class Comment extends React.Component {
|
|||
super(props);
|
||||
|
||||
bindAll(this, [
|
||||
'handleDelete',
|
||||
'handlePostReply',
|
||||
'handleToggleReplying'
|
||||
]);
|
||||
|
@ -33,6 +34,10 @@ class Comment extends React.Component {
|
|||
this.setState({replying: !this.state.replying});
|
||||
}
|
||||
|
||||
handleDelete () {
|
||||
this.props.onDelete(this.props.id);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
author,
|
||||
|
@ -41,7 +46,6 @@ class Comment extends React.Component {
|
|||
canReply,
|
||||
content,
|
||||
datetimeCreated,
|
||||
onDelete,
|
||||
id,
|
||||
projectId
|
||||
} = this.props;
|
||||
|
@ -64,7 +68,7 @@ class Comment extends React.Component {
|
|||
{deletable ? (
|
||||
<span
|
||||
className="comment-delete"
|
||||
onClick={onDelete}
|
||||
onClick={this.handleDelete}
|
||||
>
|
||||
Delete {/* TODO internationalize */}
|
||||
</span>
|
||||
|
|
|
@ -13,7 +13,8 @@ class TopLevelComment extends React.Component {
|
|||
super(props);
|
||||
bindAll(this, [
|
||||
'handleExpandThread',
|
||||
'handleDelete'
|
||||
'handleAddComment',
|
||||
'handleDeleteComment'
|
||||
]);
|
||||
this.state = {
|
||||
expanded: false
|
||||
|
@ -26,8 +27,14 @@ class TopLevelComment extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
handleDelete () {
|
||||
this.props.onDelete(this.props.id);
|
||||
handleDeleteReply (commentId) {
|
||||
// Only apply topLevelCommentId for deleting replies
|
||||
// The top level comment itself just gets passed onDelete directly
|
||||
this.props.onDelete(commentId, this.props.id);
|
||||
}
|
||||
|
||||
handleAddComment (comment) {
|
||||
this.props.onAddComment(comment, this.props.id);
|
||||
}
|
||||
|
||||
render () {
|
||||
|
@ -39,18 +46,17 @@ class TopLevelComment extends React.Component {
|
|||
deletable,
|
||||
deleted,
|
||||
id,
|
||||
onDelete,
|
||||
replies,
|
||||
projectId,
|
||||
onAddComment
|
||||
projectId
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FlexRow className="comment-container">
|
||||
<Comment
|
||||
projectId={projectId}
|
||||
onAddComment={onAddComment}
|
||||
onDelete={this.handleDelete}
|
||||
{...{author, content, datetimeCreated, deletable, deleted, canReply, id}}
|
||||
onAddComment={this.handleAddComment}
|
||||
{...{author, content, datetimeCreated, deletable, deleted, canReply, id, onDelete}}
|
||||
/>
|
||||
{replies.length > 0 &&
|
||||
<FlexRow
|
||||
|
@ -72,8 +78,8 @@ class TopLevelComment extends React.Component {
|
|||
id={reply.id}
|
||||
key={reply.id}
|
||||
projectId={projectId}
|
||||
onAddComment={this.props.onAddComment}
|
||||
onDelete={this.handleDelete}
|
||||
onAddComment={this.handleAddComment}
|
||||
onDelete={this.handleDeleteReply}
|
||||
/>
|
||||
))}
|
||||
</FlexRow>
|
||||
|
|
|
@ -167,11 +167,11 @@ class Preview extends React.Component {
|
|||
});
|
||||
});
|
||||
}
|
||||
handleAddComment (comment) {
|
||||
this.props.handleAddComment(comment);
|
||||
handleAddComment (comment, topLevelCommentId) {
|
||||
this.props.handleAddComment(comment, topLevelCommentId);
|
||||
}
|
||||
handleDeleteComment (id) {
|
||||
this.props.handleDeleteComment(this.state.projectId, id, this.props.user.token);
|
||||
handleDeleteComment (id, topLevelCommentId) {
|
||||
this.props.handleDeleteComment(this.state.projectId, id, topLevelCommentId, this.props.user.token);
|
||||
}
|
||||
handleReportClick () {
|
||||
this.setState({reportOpen: true});
|
||||
|
@ -532,11 +532,11 @@ const mapStateToProps = state => {
|
|||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
handleAddComment: comment => {
|
||||
dispatch(previewActions.addNewComment(comment));
|
||||
handleAddComment: (comment, topLevelCommentId) => {
|
||||
dispatch(previewActions.addNewComment(comment, topLevelCommentId));
|
||||
},
|
||||
handleDeleteComment: (projectId, commentId, token) => {
|
||||
dispatch(previewActions.deleteComment(projectId, commentId, token));
|
||||
handleDeleteComment: (projectId, commentId, topLevelCommentId, token) => {
|
||||
dispatch(previewActions.deleteComment(projectId, commentId, topLevelCommentId, token));
|
||||
},
|
||||
handleOpenRegistration: event => {
|
||||
event.preventDefault();
|
||||
|
|
Loading…
Reference in a new issue