UX: Warn users if the post that's currently edited has changed. (#6498)

This commit is contained in:
Bianca Nenciu 2018-10-17 16:35:32 +03:00 committed by Régis Hanol
parent 065bf0762c
commit f60b10d090
6 changed files with 55 additions and 6 deletions

View File

@ -387,9 +387,14 @@ const Composer = RestModel.extend({
return SAVE_ICONS[action];
},
@computed("action", "whisper")
saveLabel(action, whisper) {
return whisper ? "composer.create_whisper" : SAVE_LABELS[action];
@computed("action", "whisper", "editConflict")
saveLabel(action, whisper, editConflict) {
if (editConflict) {
return "composer.overwrite_edit";
} else if (whisper) {
return "composer.create_whisper";
}
return SAVE_LABELS[action];
},
hasMetaData: function() {
@ -727,7 +732,8 @@ const Composer = RestModel.extend({
composerOpened: null,
composerTotalOpened: 0,
featuredLink: null,
noBump: false
noBump: false,
editConflict: false
});
},
@ -762,6 +768,7 @@ const Composer = RestModel.extend({
const props = {
raw: this.get("reply"),
raw_old: this.get("editConflict") ? null : this.get("originalText"),
edit_reason: opts.editReason,
image_sizes: opts.imageSizes,
cooked: this.getCookedHtml()
@ -769,9 +776,12 @@ const Composer = RestModel.extend({
this.set("composeState", SAVING);
let rollback = throwAjaxError(() => {
let rollback = throwAjaxError(error => {
post.set("cooked", oldCooked);
this.set("composeState", OPEN);
if (error.jqXHR && error.jqXHR.status === 409) {
this.set("editConflict", true);
}
});
return promise

View File

@ -200,7 +200,7 @@ class PostsController < ApplicationController
post.image_sizes = params[:image_sizes] if params[:image_sizes].present?
if !guardian.send("can_edit?", post) && post.user_id == current_user.id && post.edit_time_limit_expired?
return render json: { errors: [I18n.t('too_late_to_edit')] }, status: 422
return render_json_error(I18n.t('too_late_to_edit'))
end
guardian.ensure_can_edit!(post)
@ -210,6 +210,11 @@ class PostsController < ApplicationController
edit_reason: params[:post][:edit_reason]
}
raw_old = params[:post][:raw_old]
if raw_old.present? && raw_old != post.raw
return render_json_error(I18n.t('edit_conflict'), status: 409)
end
# to stay consistent with the create api, we allow for title & category changes here
if post.is_first_post?
changes[:title] = params[:title] if params[:title]

View File

@ -1372,6 +1372,7 @@ en:
tags_missing: "You must choose at least {{count}} tags"
save_edit: "Save Edit"
overwrite_edit: "Overwrite Edit"
reply_original: "Reply on Original Topic"
reply_here: "Reply Here"
reply: "Reply"

View File

@ -304,6 +304,7 @@ en:
badge: "%{display_name} badge on %{site_title}"
too_late_to_edit: "That post was created too long ago. It can no longer be edited or deleted."
edit_conflict: "That post was edited by another user and your changes can no longer be saved."
revert_version_same: "The current version is same as the version you are trying to revert to."
excerpt_image: "image"

View File

@ -295,6 +295,13 @@ describe PostsController do
expect(post.raw).to eq("edited body")
end
it 'checks for an edit conflict' do
update_params[:post][:raw_old] = 'old body'
put "/posts/#{post.id}.json", params: update_params
expect(response.status).to eq(409)
end
it "raises an error when the post parameter is missing" do
update_params.delete(:post)
put "/posts/#{post.id}.json", params: update_params

View File

@ -0,0 +1,25 @@
import { acceptance } from "helpers/qunit-helpers";
acceptance("Composer - Edit conflict", {
loggedIn: true,
pretend(server, helper) {
server.put("/posts/398", () => {
return helper.response(409, { errors: ["edit conflict"] });
});
}
});
QUnit.test("Edit a post that causes an edit conflict", async assert => {
await visit("/t/internationalization-localization/280");
await click(".topic-post:eq(0) button.show-more-actions");
await click(".topic-post:eq(0) button.edit");
await click("#reply-control button.create");
assert.equal(
find("#reply-control button.create")
.text()
.trim(),
I18n.t("composer.overwrite_edit"),
"it shows the overwrite button"
);
});