FEATURE: Report edit conflicts when saving draft. (#6585)
This commit is contained in:
parent
d078808144
commit
34e4d82f1a
|
@ -977,6 +977,7 @@ const Composer = RestModel.extend({
|
|||
|
||||
const data = {
|
||||
reply: this.get("reply"),
|
||||
originalText: this.get("originalText"),
|
||||
action: this.get("action"),
|
||||
title: this.get("title"),
|
||||
categoryId: this.get("categoryId"),
|
||||
|
@ -991,22 +992,35 @@ const Composer = RestModel.extend({
|
|||
noBump: this.get("noBump")
|
||||
};
|
||||
|
||||
this.set("draftStatus", I18n.t("composer.saving_draft_tip"));
|
||||
|
||||
const composer = this;
|
||||
this.setProperties({
|
||||
draftStatus: I18n.t("composer.saving_draft_tip"),
|
||||
draftConflictUser: null
|
||||
});
|
||||
|
||||
if (this._clearingStatus) {
|
||||
Em.run.cancel(this._clearingStatus);
|
||||
this._clearingStatus = null;
|
||||
}
|
||||
|
||||
// try to save the draft
|
||||
return Draft.save(this.get("draftKey"), this.get("draftSequence"), data)
|
||||
.then(function() {
|
||||
composer.set("draftStatus", I18n.t("composer.saved_draft_tip"));
|
||||
.then(result => {
|
||||
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() {
|
||||
composer.set("draftStatus", I18n.t("composer.drafts_offline"));
|
||||
.catch(() => {
|
||||
this.setProperties({
|
||||
draftStatus: I18n.t("composer.drafts_offline"),
|
||||
draftConflictUser: null
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -1019,6 +1033,7 @@ const Composer = RestModel.extend({
|
|||
this,
|
||||
function() {
|
||||
self.set("draftStatus", null);
|
||||
self.set("draftConflictUser", null);
|
||||
self._clearingStatus = null;
|
||||
},
|
||||
1000
|
||||
|
|
|
@ -25,13 +25,15 @@ Draft.reopenClass({
|
|||
},
|
||||
|
||||
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", {
|
||||
type: "POST",
|
||||
data: {
|
||||
draft_key: key,
|
||||
data: data,
|
||||
sequence: sequence
|
||||
data: dataJson,
|
||||
sequence,
|
||||
post_id: data.postId,
|
||||
original_text: data.originalText
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -149,6 +149,9 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
<div id='draft-status' class="{{if isUploading 'hidden'}}">
|
||||
{{#if model.draftConflictUser}}
|
||||
{{avatar model.draftConflictUser imageSize="small"}}
|
||||
{{/if}}
|
||||
{{model.draftStatus}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,15 @@ class DraftController < ApplicationController
|
|||
|
||||
def update
|
||||
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
|
||||
end
|
||||
|
||||
|
|
|
@ -1356,6 +1356,7 @@ en:
|
|||
saved_local_draft_tip: "saved locally"
|
||||
similar_topics: "Your topic is similar to..."
|
||||
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:
|
||||
|
|
|
@ -13,6 +13,34 @@ describe DraftController do
|
|||
expect(Draft.get(user, 'xyz', 0)).to eq('my data')
|
||||
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
|
||||
user = sign_in(Fabricate(:user))
|
||||
Draft.set(user, 'xxx', 0, 'hi')
|
||||
|
|
Loading…
Reference in New Issue