FEATURE: Report edit conflicts when saving draft. (#6585)

This commit is contained in:
Bianca Nenciu 2018-11-14 13:56:25 +02:00 committed by Régis Hanol
parent d078808144
commit 34e4d82f1a
6 changed files with 69 additions and 11 deletions

View File

@ -977,6 +977,7 @@ const Composer = RestModel.extend({
const data = { const data = {
reply: this.get("reply"), reply: this.get("reply"),
originalText: this.get("originalText"),
action: this.get("action"), action: this.get("action"),
title: this.get("title"), title: this.get("title"),
categoryId: this.get("categoryId"), categoryId: this.get("categoryId"),
@ -991,22 +992,35 @@ const Composer = RestModel.extend({
noBump: this.get("noBump") noBump: this.get("noBump")
}; };
this.set("draftStatus", I18n.t("composer.saving_draft_tip")); this.setProperties({
draftStatus: I18n.t("composer.saving_draft_tip"),
const composer = this; draftConflictUser: null
});
if (this._clearingStatus) { if (this._clearingStatus) {
Em.run.cancel(this._clearingStatus); Em.run.cancel(this._clearingStatus);
this._clearingStatus = null; this._clearingStatus = null;
} }
// try to save the draft
return Draft.save(this.get("draftKey"), this.get("draftSequence"), data) return Draft.save(this.get("draftKey"), this.get("draftSequence"), data)
.then(function() { .then(result => {
composer.set("draftStatus", I18n.t("composer.saved_draft_tip")); if (result.conflict_user) {
this.setProperties({
draftStatus: I18n.t("composer.edit_conflict"),
draftConflictUser: result.conflict_user
});
} else {
this.setProperties({
draftStatus: I18n.t("composer.saved_draft_tip"),
draftConflictUser: null
});
}
}) })
.catch(function() { .catch(() => {
composer.set("draftStatus", I18n.t("composer.drafts_offline")); this.setProperties({
draftStatus: I18n.t("composer.drafts_offline"),
draftConflictUser: null
});
}); });
}, },
@ -1019,6 +1033,7 @@ const Composer = RestModel.extend({
this, this,
function() { function() {
self.set("draftStatus", null); self.set("draftStatus", null);
self.set("draftConflictUser", null);
self._clearingStatus = null; self._clearingStatus = null;
}, },
1000 1000

View File

@ -25,13 +25,15 @@ Draft.reopenClass({
}, },
save(key, sequence, data) { save(key, sequence, data) {
data = typeof data === "string" ? data : JSON.stringify(data); const dataJson = typeof data === "string" ? dataJson : JSON.stringify(data);
return ajax("/draft.json", { return ajax("/draft.json", {
type: "POST", type: "POST",
data: { data: {
draft_key: key, draft_key: key,
data: data, data: dataJson,
sequence: sequence sequence,
post_id: data.postId,
original_text: data.originalText
} }
}); });
} }

View File

@ -149,6 +149,9 @@
</div> </div>
{{/if}} {{/if}}
<div id='draft-status' class="{{if isUploading 'hidden'}}"> <div id='draft-status' class="{{if isUploading 'hidden'}}">
{{#if model.draftConflictUser}}
{{avatar model.draftConflictUser imageSize="small"}}
{{/if}}
{{model.draftStatus}} {{model.draftStatus}}
</div> </div>
</div> </div>

View File

@ -10,6 +10,15 @@ class DraftController < ApplicationController
def update def update
Draft.set(current_user, params[:draft_key], params[:sequence].to_i, params[:data]) Draft.set(current_user, params[:draft_key], params[:sequence].to_i, params[:data])
if params[:post_id] && params[:original_text]
post = Post.find_by(id: params[:post_id])
if post && post.raw != params[:original_text]
conflict_user = BasicUserSerializer.new(post.last_editor, root: false)
return render json: success_json.merge(conflict_user: conflict_user)
end
end
render json: success_json render json: success_json
end end

View File

@ -1356,6 +1356,7 @@ en:
saved_local_draft_tip: "saved locally" saved_local_draft_tip: "saved locally"
similar_topics: "Your topic is similar to..." similar_topics: "Your topic is similar to..."
drafts_offline: "drafts offline" drafts_offline: "drafts offline"
edit_conflict: 'edit conflict'
group_mentioned_limit: "<b>Warning!</b> You mentioned <a href='{{group_link}}'>{{group}}</a>, however this group has more members than the administrator configured mention limit of {{max}} users. Nobody will be notified. " group_mentioned_limit: "<b>Warning!</b> You mentioned <a href='{{group_link}}'>{{group}}</a>, however this group has more members than the administrator configured mention limit of {{max}} users. Nobody will be notified. "
group_mentioned: group_mentioned:

View File

@ -13,6 +13,34 @@ describe DraftController do
expect(Draft.get(user, 'xyz', 0)).to eq('my data') expect(Draft.get(user, 'xyz', 0)).to eq('my data')
end end
it 'checks for an conflict on update' do
user = sign_in(Fabricate(:user))
post = Fabricate(:post, user: user)
post "/draft.json", params: {
username: user.username,
draft_key: "topic",
sequence: 0,
data: "{}",
post_id: post.id,
original_text: post.raw
}
expect(JSON.parse(response.body)['conflict_user']).to eq(nil)
post "/draft.json", params: {
username: user.username,
draft_key: "topic",
sequence: 0,
data: "{}",
post_id: post.id,
original_text: "something else"
}
expect(JSON.parse(response.body)['conflict_user']['id']).to eq(post.last_editor.id)
expect(JSON.parse(response.body)['conflict_user']).to include('avatar_template')
end
it 'destroys drafts when required' do it 'destroys drafts when required' do
user = sign_in(Fabricate(:user)) user = sign_in(Fabricate(:user))
Draft.set(user, 'xxx', 0, 'hi') Draft.set(user, 'xxx', 0, 'hi')