diff --git a/backend/app/rest/httperrors.go b/backend/app/rest/httperrors.go index f682b3ec..60d4bcb8 100644 --- a/backend/app/rest/httperrors.go +++ b/backend/app/rest/httperrors.go @@ -25,7 +25,7 @@ const ( ErrReadOnly = 8 // write failed on read only ErrCommentRejected = 9 // general error on rejected comment change ErrCommentEditExpired = 10 // too late for edit - ErrCommentEditChanged = 11 // parent commend changed + ErrCommentEditChanged = 11 // parent comment cannot be changed ErrVoteRejected = 12 // general error on vote rejected ErrVoteSelf = 13 // vote for own comment ErrVoteDbl = 14 // already voted for the comment diff --git a/web/app/components/comment/__vote/comment__vote.scss b/web/app/components/comment/__vote/comment__vote.scss index 12084446..813609c6 100644 --- a/web/app/components/comment/__vote/comment__vote.scss +++ b/web/app/components/comment/__vote/comment__vote.scss @@ -9,3 +9,11 @@ background-size: contain; cursor: pointer; } + +.voting__error { + color: #9a0000; + text-align: right; + font-size: 14px; + line-height: 1; + margin-top: -10px; +} diff --git a/web/app/components/comment/comment.jsx b/web/app/components/comment/comment.jsx index 5d30816a..d7b47b12 100644 --- a/web/app/components/comment/comment.jsx +++ b/web/app/components/comment/comment.jsx @@ -8,6 +8,7 @@ import { url } from 'common/settings'; import store from 'common/store'; import copy from 'common/copy'; import debounce from 'utils/debounce'; +import { extractErrorMessageFromResponse } from 'utils/errorUtils'; import Input from 'components/input'; @@ -23,6 +24,7 @@ export default class Comment extends Component { isEditing: false, isUserVerified: false, editTimeLeft: null, + voteErrorMessage: null, }; this.votingPromise = Promise.resolve(); @@ -49,6 +51,8 @@ export default class Comment extends Component { this.isGuest = this.isGuest.bind(this); this.getUpvoteDisabledReason = this.getUpvoteDisabledReason.bind(this); this.getDownvoteDisabledReason = this.getDownvoteDisabledReason.bind(this); + this.handleVoteError = this.handleVoteError.bind(this); + this.sendVotingRequest = this.sendVotingRequest.bind(this); } componentWillReceiveProps(nextProps) { @@ -264,6 +268,23 @@ export default class Comment extends Component { } } + handleVoteError(e, originalVotingState) { + this.setState({ + ...originalVotingState, + voteErrorMessage: extractErrorMessageFromResponse(e.response), + }); + } + + sendVotingRequest(id, votingValue, originalVotingState) { + this.votingPromise = this.votingPromise + .then(() => { + return api.putCommentVote({ id, url, value: votingValue }).then(() => { + api.getComment({ id }).then(comment => store.replaceComment(comment)); + }); + }) + .catch(e => this.handleVoteError(e, originalVotingState)); + } + increaseScore() { const { score, scoreIncreased, scoreDecreased } = this.state; const { id } = this.props.data; @@ -274,13 +295,10 @@ export default class Comment extends Component { scoreIncreased: !scoreDecreased, scoreDecreased: false, score: score + 1, + voteErrorMessage: null, }); - this.votingPromise = this.votingPromise.then(() => { - return api.putCommentVote({ id, url, value: 1 }).then(() => { - api.getComment({ id }).then(comment => store.replaceComment(comment)); - }); - }); + this.sendVotingRequest(id, 1, { score, scoreIncreased, scoreDecreased }); } decreaseScore() { @@ -293,13 +311,10 @@ export default class Comment extends Component { scoreDecreased: !scoreIncreased, scoreIncreased: false, score: score - 1, + voteErrorMessage: null, }); - this.votingPromise = this.votingPromise.then(() => { - return api.putCommentVote({ id, url, value: -1 }).then(() => { - api.getComment({ id }).then(comment => store.replaceComment(comment)); - }); - }); + this.sendVotingRequest(id, -1, { score, scoreIncreased, scoreDecreased }); } onReply(...rest) { @@ -412,6 +427,7 @@ export default class Comment extends Component { isEditing, isUserVerified, editTimeLeft, + voteErrorMessage, } ) { const { data, mods = {}, isCommentsDisabled } = props; @@ -607,6 +623,12 @@ export default class Comment extends Component { + {!!voteErrorMessage && ( +