mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 07:38:07 -05:00
Add restore functionality to comments for admins
This commit is contained in:
parent
b0ac4018ee
commit
592c0e5703
7 changed files with 87 additions and 16 deletions
|
@ -206,6 +206,7 @@
|
|||
|
||||
"comments.report": "Report",
|
||||
"comments.delete": "Delete",
|
||||
"comments.restore": "Restore",
|
||||
"comments.reportModal.title": "Report Comment",
|
||||
"comments.reportModal.reported": "The comment has been reported, and the Scratch Team has been notified.",
|
||||
"comments.reportModal.prompt": "Are you sure you want to report this comment?",
|
||||
|
|
|
@ -246,6 +246,15 @@ module.exports.setCommentReported = (commentId, topLevelCommentId) => ({
|
|||
}
|
||||
});
|
||||
|
||||
module.exports.setCommentRestored = (commentId, topLevelCommentId) => ({
|
||||
type: 'UPDATE_COMMENT',
|
||||
commentId: commentId,
|
||||
topLevelCommentId: topLevelCommentId,
|
||||
comment: {
|
||||
visibility: 'visible'
|
||||
}
|
||||
});
|
||||
|
||||
module.exports.addNewComment = (comment, topLevelCommentId) => ({
|
||||
type: 'ADD_NEW_COMMENT',
|
||||
comment: comment,
|
||||
|
@ -659,6 +668,22 @@ module.exports.reportComment = (projectId, commentId, topLevelCommentId, token)
|
|||
});
|
||||
});
|
||||
|
||||
module.exports.restoreComment = (projectId, commentId, topLevelCommentId, token) => (dispatch => {
|
||||
api({
|
||||
uri: `/proxy/admin/project/${projectId}/comment/${commentId}/undelete`,
|
||||
authentication: token,
|
||||
withCredentials: true,
|
||||
method: 'PUT',
|
||||
useCsrf: true
|
||||
}, (err, body, res) => {
|
||||
if (err || res.statusCode !== 200) {
|
||||
log.error(err || res.body);
|
||||
return;
|
||||
}
|
||||
dispatch(module.exports.setCommentRestored(commentId, topLevelCommentId));
|
||||
});
|
||||
});
|
||||
|
||||
module.exports.reportProject = (id, jsonData, token) => (dispatch => {
|
||||
dispatch(module.exports.setFetchStatus('report', module.exports.Status.FETCHING));
|
||||
// scratchr2 will fail if no thumbnail base64 string provided. We don't yet have
|
||||
|
|
|
@ -13,10 +13,6 @@ const ReportCommentModal = require('../../../components/modal/comments/report-co
|
|||
|
||||
require('./comment.scss');
|
||||
|
||||
const CommentVisibility = {
|
||||
VISIBLE: 'visible' // Has to match the server response for visibility
|
||||
};
|
||||
|
||||
class Comment extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
@ -28,7 +24,8 @@ class Comment extends React.Component {
|
|||
'handleConfirmReport',
|
||||
'handleCancelReport',
|
||||
'handlePostReply',
|
||||
'handleToggleReplying'
|
||||
'handleToggleReplying',
|
||||
'handleRestore'
|
||||
]);
|
||||
this.state = {
|
||||
deleting: false,
|
||||
|
@ -64,6 +61,10 @@ class Comment extends React.Component {
|
|||
this.setState({reporting: true});
|
||||
}
|
||||
|
||||
handleRestore () {
|
||||
this.props.onRestore(this.props.id);
|
||||
}
|
||||
|
||||
handleConfirmReport () {
|
||||
this.setState({
|
||||
reporting: false,
|
||||
|
@ -93,7 +94,7 @@ class Comment extends React.Component {
|
|||
visibility
|
||||
} = this.props;
|
||||
|
||||
const visible = visibility === CommentVisibility.VISIBLE;
|
||||
const visible = visibility === 'visible';
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -128,10 +129,19 @@ class Comment extends React.Component {
|
|||
</span>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
<span className="comment-visibility">
|
||||
<FormattedMessage id={`comments.status.${visibility}`} />
|
||||
{/* TODO restore action will go here */}
|
||||
</span>
|
||||
{this.props.onRestore && (
|
||||
<span
|
||||
className="comment-restore"
|
||||
onClick={this.handleRestore}
|
||||
>
|
||||
<FormattedMessage id="comments.restore" />
|
||||
</span>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
</FlexRow>
|
||||
|
@ -210,6 +220,7 @@ Comment.propTypes = {
|
|||
onAddComment: PropTypes.func,
|
||||
onDelete: PropTypes.func,
|
||||
onReport: PropTypes.func,
|
||||
onRestore: PropTypes.func,
|
||||
projectId: PropTypes.string,
|
||||
visibility: PropTypes.string
|
||||
};
|
||||
|
|
|
@ -78,7 +78,8 @@
|
|||
}
|
||||
|
||||
.comment-delete,
|
||||
.comment-report {
|
||||
.comment-report,
|
||||
.comment-restore {
|
||||
opacity: .5;
|
||||
font-size: .75rem;
|
||||
font-weight: 500;
|
||||
|
@ -119,6 +120,18 @@
|
|||
vertical-align: -.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
.comment-restore {
|
||||
margin-left: 1rem;
|
||||
|
||||
&:before {
|
||||
margin-right: .25rem;
|
||||
background-image: url("/svgs/project/restore-gray.svg");
|
||||
width: .75rem;
|
||||
height: .75rem;
|
||||
vertical-align: -.125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
|
|
|
@ -16,7 +16,8 @@ class TopLevelComment extends React.Component {
|
|||
'handleExpandThread',
|
||||
'handleAddComment',
|
||||
'handleDeleteReply',
|
||||
'handleReportReply'
|
||||
'handleReportReply',
|
||||
'handleRestoreReply'
|
||||
]);
|
||||
this.state = {
|
||||
expanded: false
|
||||
|
@ -29,16 +30,20 @@ class TopLevelComment extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
handleDeleteReply (commentId) {
|
||||
handleDeleteReply (replyId) {
|
||||
// Only apply topLevelCommentId for deleting replies
|
||||
// The top level comment itself just gets passed onDelete directly
|
||||
this.props.onDelete(commentId, this.props.id);
|
||||
this.props.onDelete(replyId, this.props.id);
|
||||
}
|
||||
|
||||
handleReportReply (commentId) {
|
||||
handleReportReply (replyId) {
|
||||
// Only apply topLevelCommentId for reporting replies
|
||||
// The top level comment itself just gets passed onReport directly
|
||||
this.props.onReport(commentId, this.props.id);
|
||||
this.props.onReport(replyId, this.props.id);
|
||||
}
|
||||
|
||||
handleRestoreReply (replyId) {
|
||||
this.props.onRestore(replyId, this.props.id);
|
||||
}
|
||||
|
||||
handleAddComment (comment) {
|
||||
|
@ -55,6 +60,7 @@ class TopLevelComment extends React.Component {
|
|||
id,
|
||||
onDelete,
|
||||
onReport,
|
||||
onRestore,
|
||||
replies,
|
||||
projectId,
|
||||
visibility
|
||||
|
@ -74,6 +80,7 @@ class TopLevelComment extends React.Component {
|
|||
id,
|
||||
onDelete,
|
||||
onReport,
|
||||
onRestore,
|
||||
visibility
|
||||
}}
|
||||
/>
|
||||
|
@ -100,6 +107,7 @@ class TopLevelComment extends React.Component {
|
|||
onAddComment={this.handleAddComment}
|
||||
onDelete={this.handleDeleteReply}
|
||||
onReport={this.handleReportReply}
|
||||
onRestore={this.handleRestoreReply}
|
||||
/>
|
||||
))}
|
||||
</FlexRow>
|
||||
|
@ -136,6 +144,7 @@ TopLevelComment.propTypes = {
|
|||
onAddComment: PropTypes.func,
|
||||
onDelete: PropTypes.func,
|
||||
onReport: PropTypes.func,
|
||||
onRestore: PropTypes.func,
|
||||
parentId: PropTypes.number,
|
||||
projectId: PropTypes.string,
|
||||
replies: PropTypes.arrayOf(PropTypes.object),
|
||||
|
|
|
@ -78,6 +78,7 @@ const PreviewPresentation = ({
|
|||
onReportClose,
|
||||
onReportComment,
|
||||
onReportSubmit,
|
||||
onRestoreComment,
|
||||
onAddToStudioClicked,
|
||||
onAddToStudioClosed,
|
||||
onToggleStudio,
|
||||
|
@ -375,6 +376,7 @@ const PreviewPresentation = ({
|
|||
onAddComment={onAddComment}
|
||||
onDelete={onDeleteComment}
|
||||
onReport={onReportComment}
|
||||
onRestore={onRestoreComment}
|
||||
/>
|
||||
))}
|
||||
{comments.length < projectInfo.stats.comments &&
|
||||
|
@ -431,6 +433,7 @@ PreviewPresentation.propTypes = {
|
|||
onReportClose: PropTypes.func.isRequired,
|
||||
onReportComment: PropTypes.func.isRequired,
|
||||
onReportSubmit: PropTypes.func.isRequired,
|
||||
onRestoreComment: PropTypes.func,
|
||||
onSeeInside: PropTypes.func,
|
||||
onShare: PropTypes.func,
|
||||
onToggleComments: PropTypes.func,
|
||||
|
|
|
@ -44,6 +44,7 @@ class Preview extends React.Component {
|
|||
'handleReportClose',
|
||||
'handleReportComment',
|
||||
'handleReportSubmit',
|
||||
'handleRestoreComment',
|
||||
'handleAddToStudioClick',
|
||||
'handleAddToStudioClose',
|
||||
'handleSeeInside',
|
||||
|
@ -188,6 +189,9 @@ class Preview extends React.Component {
|
|||
handleReportComment (id, topLevelCommentId) {
|
||||
this.props.handleReportComment(this.state.projectId, id, topLevelCommentId, this.props.user.token);
|
||||
}
|
||||
handleRestoreComment (id, topLevelCommentId) {
|
||||
this.props.handleRestoreComment(this.state.projectId, id, topLevelCommentId, this.props.user.token);
|
||||
}
|
||||
handleReportClick () {
|
||||
this.setState({reportOpen: true});
|
||||
}
|
||||
|
@ -379,6 +383,7 @@ class Preview extends React.Component {
|
|||
onReportClose={this.handleReportClose}
|
||||
onReportComment={this.handleReportComment}
|
||||
onReportSubmit={this.handleReportSubmit}
|
||||
onRestoreComment={this.props.isAdmin && this.handleRestoreComment}
|
||||
onSeeInside={this.handleSeeInside}
|
||||
onShare={this.handleShare}
|
||||
onToggleComments={this.handleToggleComments}
|
||||
|
@ -448,6 +453,7 @@ Preview.propTypes = {
|
|||
handleLogOut: PropTypes.func,
|
||||
handleOpenRegistration: PropTypes.func,
|
||||
handleReportComment: PropTypes.func,
|
||||
handleRestoreComment: PropTypes.func,
|
||||
handleToggleLoginOpen: PropTypes.func,
|
||||
isAdmin: PropTypes.bool,
|
||||
isEditable: PropTypes.bool,
|
||||
|
@ -588,6 +594,9 @@ const mapDispatchToProps = dispatch => ({
|
|||
handleReportComment: (projectId, commentId, topLevelCommentId, token) => {
|
||||
dispatch(previewActions.reportComment(projectId, commentId, topLevelCommentId, token));
|
||||
},
|
||||
handleRestoreComment: (projectId, commentId, topLevelCommentId, token) => {
|
||||
dispatch(previewActions.restoreComment(projectId, commentId, topLevelCommentId, token));
|
||||
},
|
||||
handleOpenRegistration: event => {
|
||||
event.preventDefault();
|
||||
dispatch(navigationActions.setRegistrationOpen(true));
|
||||
|
|
Loading…
Reference in a new issue