mirror of
https://github.com/wassname/talk.git
synced 2026-06-30 09:24:53 +08:00
Edit UI sends editComment mutation, handles errors
This commit is contained in:
@@ -106,6 +106,9 @@ class Comment extends React.Component {
|
||||
|
||||
// dispatch action to ignore another user
|
||||
ignoreUser: React.PropTypes.func,
|
||||
|
||||
// edit a comment, passed (id, { body })
|
||||
editComment: React.PropTypes.func,
|
||||
}
|
||||
|
||||
onClickEdit (e) {
|
||||
@@ -215,12 +218,14 @@ class Comment extends React.Component {
|
||||
{
|
||||
this.state.isEditing
|
||||
? <EditableCommentContent
|
||||
editComment={this.props.editComment.bind(null, comment.id)}
|
||||
addNotification={addNotification}
|
||||
asset={asset}
|
||||
comment={comment}
|
||||
currentUser={currentUser}
|
||||
maxCharCount={maxCharCount}
|
||||
parentId={parentId}
|
||||
stopEditing={() => this.setState({isEditing: false})}
|
||||
/>
|
||||
: <Content body={comment.body} />
|
||||
}
|
||||
@@ -303,6 +308,7 @@ class Comment extends React.Component {
|
||||
addNotification={addNotification}
|
||||
parentId={comment.id}
|
||||
postItem={postItem}
|
||||
editComment={this.props.editComment}
|
||||
depth={depth + 1}
|
||||
asset={asset}
|
||||
highlighted={highlighted}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
import {CommentForm} from 'coral-plugin-commentbox/CommentBox';
|
||||
|
||||
import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from 'coral-framework/translations';
|
||||
const lang = new I18n(translations);
|
||||
|
||||
/**
|
||||
* Renders a Comment's body in such a way that the end-user can edit it and save changes
|
||||
*/
|
||||
@@ -12,7 +16,6 @@ export class EditableCommentContent extends React.Component {
|
||||
// show notification to the user (e.g. for errors)
|
||||
addNotification: PropTypes.func.isRequired,
|
||||
asset: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
settings: PropTypes.shape({
|
||||
charCountEnable: PropTypes.bool,
|
||||
}),
|
||||
@@ -29,14 +32,47 @@ export class EditableCommentContent extends React.Component {
|
||||
}),
|
||||
maxCharCount: PropTypes.number,
|
||||
|
||||
parentId: PropTypes.string,
|
||||
// edit a comment, passed {{ body }}
|
||||
editComment: React.PropTypes.func,
|
||||
|
||||
// called when editing should be stopped
|
||||
stopEditing: React.PropTypes.func,
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.editComment = this.editComment.bind(this);
|
||||
}
|
||||
async editComment(edit) {
|
||||
const {editComment, addNotification, stopEditing} = this.props;
|
||||
if (typeof editComment !== 'function') {return;}
|
||||
let response;
|
||||
let successfullyEdited = false;
|
||||
try {
|
||||
response = await editComment(edit);
|
||||
const errors = (response && response.data && response.data.editComment)
|
||||
? response.data.editComment.errors
|
||||
: null;
|
||||
if (errors && (errors.length === 1)) {
|
||||
throw errors[0];
|
||||
}
|
||||
successfullyEdited = true;
|
||||
} catch (error) {
|
||||
if (error.translation_key) {
|
||||
addNotification('error', lang.t(error.translation_key) || error.translation_key);
|
||||
} else if (error.networkError) {
|
||||
addNotification('error', lang.t('error.networkError'));
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
if (successfullyEdited && typeof stopEditing === 'function') {
|
||||
stopEditing();
|
||||
}
|
||||
}
|
||||
stopEditing() {
|
||||
this.setState({resetCounter: this.state.resetCounter + 1});
|
||||
}
|
||||
render() {
|
||||
const saveComment = function () {
|
||||
};
|
||||
const originalBody = this.props.comment.body;
|
||||
return (
|
||||
<div style={{marginBottom: '10px'}}>
|
||||
@@ -50,7 +86,7 @@ export class EditableCommentContent extends React.Component {
|
||||
// original comment
|
||||
return comment.body !== originalBody;
|
||||
}}
|
||||
saveComment={saveComment}
|
||||
saveComment={this.editComment}
|
||||
bodyLabel={'Edit this comment' /* @TODO (bengo) i18n */}
|
||||
bodyPlaceholder=""
|
||||
submitText={'Save changes' /* @TODO (bengo) i18n */}
|
||||
|
||||
@@ -14,7 +14,7 @@ const {fetchAssetSuccess} = assetActions;
|
||||
import {NEW_COMMENT_COUNT_POLL_INTERVAL} from 'coral-framework/constants/comments';
|
||||
|
||||
import {queryStream} from 'coral-framework/graphql/queries';
|
||||
import {postComment, postFlag, postLike, postDontAgree, deleteAction, addCommentTag, removeCommentTag, ignoreUser} from 'coral-framework/graphql/mutations';
|
||||
import {postComment, postFlag, postLike, postDontAgree, deleteAction, addCommentTag, removeCommentTag, ignoreUser, editComment} from 'coral-framework/graphql/mutations';
|
||||
import {editName} from 'coral-framework/actions/user';
|
||||
import {updateCountCache, viewAllComments} from 'coral-framework/actions/asset';
|
||||
import {notificationActions, authActions, assetActions, pym} from 'coral-framework';
|
||||
@@ -73,6 +73,9 @@ class Embed extends React.Component {
|
||||
|
||||
// dispatch action to ignore another user
|
||||
ignoreUser: React.PropTypes.func,
|
||||
|
||||
// edit a comment, passed (id, { body })
|
||||
editComment: React.PropTypes.func,
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
@@ -265,6 +268,7 @@ class Embed extends React.Component {
|
||||
open={openStream}
|
||||
addNotification={this.props.addNotification}
|
||||
postItem={this.props.postItem}
|
||||
editComment={this.props.editComment}
|
||||
setActiveReplyBox={this.setActiveReplyBox}
|
||||
activeReplyBox={this.state.activeReplyBox}
|
||||
asset={asset}
|
||||
@@ -344,5 +348,6 @@ export default compose(
|
||||
removeCommentTag,
|
||||
ignoreUser,
|
||||
deleteAction,
|
||||
editComment,
|
||||
queryStream,
|
||||
)(Embed);
|
||||
|
||||
@@ -28,7 +28,10 @@ class Stream extends React.Component {
|
||||
ignoreUser: React.PropTypes.func,
|
||||
|
||||
// list of user ids that should be rendered as ignored
|
||||
ignoredUsers: React.PropTypes.arrayOf(React.PropTypes.string)
|
||||
ignoredUsers: React.PropTypes.arrayOf(React.PropTypes.string),
|
||||
|
||||
// edit a comment, passed (id, { body })
|
||||
editComment: React.PropTypes.func,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
@@ -74,6 +77,7 @@ class Stream extends React.Component {
|
||||
addNotification={addNotification}
|
||||
depth={0}
|
||||
postItem={postItem}
|
||||
editComment={this.props.editComment}
|
||||
asset={asset}
|
||||
currentUser={currentUser}
|
||||
postLike={postLike}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
mutation EditComment ($id: ID!, $edit: EditCommentInput) {
|
||||
editComment(id:$id, edit:$edit) {
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import ADD_COMMENT_TAG from './addCommentTag.graphql';
|
||||
import REMOVE_COMMENT_TAG from './removeCommentTag.graphql';
|
||||
import IGNORE_USER from './ignoreUser.graphql';
|
||||
import STOP_IGNORING_USER from './stopIgnoringUser.graphql';
|
||||
import EDIT_COMMENT from './editComment.graphql';
|
||||
|
||||
import MY_IGNORED_USERS from '../queries/myIgnoredUsers.graphql';
|
||||
import STREAM_QUERY from '../queries/streamQuery.graphql';
|
||||
@@ -191,3 +192,24 @@ export const stopIgnoringUser = graphql(STOP_IGNORING_USER, {
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export const editComment = graphql(EDIT_COMMENT, {
|
||||
props: ({mutate, ownProps}) => {
|
||||
return {
|
||||
editComment: (id, edit) => {
|
||||
return mutate({
|
||||
variables: {
|
||||
id,
|
||||
edit,
|
||||
},
|
||||
refetchQueries: [
|
||||
{
|
||||
query: STREAM_QUERY,
|
||||
variables: variablesForStreamQuery(ownProps),
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
"comments": "comments",
|
||||
"commentIsIgnored": "This comment is hidden because you ignored this user.",
|
||||
"error": {
|
||||
"editWindowExpired": "You can no longer edit this comment. The time window to do so has expired.",
|
||||
"emailNotVerified": "Email address {0} not verified.",
|
||||
"email": "Not a valid E-Mail",
|
||||
"networkError": "Failed to connect to server. Check your internet connection and try again.",
|
||||
"password": "Password must be at least 8 characters",
|
||||
"username": "Usernames can contain letters, numbers and _ only",
|
||||
"confirmPassword": "Passwords don't match. Please, check again",
|
||||
|
||||
@@ -251,7 +251,10 @@ const editComment = async ({user, loaders: {Comments}}, {id, edit}) => {
|
||||
} catch (error) {
|
||||
switch (error.name) {
|
||||
case 'EditWindowExpired':
|
||||
throw errors.ErrNotAuthorized;
|
||||
throw new errors.APIError('You can no longer edit this comment. The window to do so has expired.', {
|
||||
status: 401,
|
||||
translation_key: 'error.editWindowExpired',
|
||||
});
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const STATUSES = [
|
||||
'NONE',
|
||||
];
|
||||
|
||||
const EDIT_WINDOW_MS = 5 * 60 * 60; // 5 minutes
|
||||
const EDIT_WINDOW_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
module.exports = class CommentsService {
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ describe('graph.mutations.editComment', () => {
|
||||
});
|
||||
expect(response.errors).to.be.empty;
|
||||
expect(response.data.editComment.errors).to.not.be.empty;
|
||||
expect(response.data.editComment.errors[0].translation_key).to.equal('NOT_AUTHORIZED');
|
||||
expect(response.data.editComment.errors[0].translation_key).to.equal('error.editWindowExpired');
|
||||
const commentAfterEdit = await CommentsService.findById(comment.id);
|
||||
|
||||
// it *hasn't* changed from the original
|
||||
|
||||
Reference in New Issue
Block a user