diff --git a/app/assets/javascripts/discourse/app/controllers/topic.js b/app/assets/javascripts/discourse/app/controllers/topic.js index c99adc7a100..3354a0cfaaa 100644 --- a/app/assets/javascripts/discourse/app/controllers/topic.js +++ b/app/assets/javascripts/discourse/app/controllers/topic.js @@ -980,7 +980,7 @@ export default Controller.extend(bufferedProperty("model"), { // save the modifications const props = this.get("buffered.buffer"); - Topic.update(this.model, props) + Topic.update(this.model, props, { fastEdit: true }) .then(() => { // We roll back on success here because `update` saves the properties to the topic this.rollbackBuffer(); diff --git a/app/assets/javascripts/discourse/app/models/topic.js b/app/assets/javascripts/discourse/app/models/topic.js index e17c723d29f..ae74d2ea637 100644 --- a/app/assets/javascripts/discourse/app/models/topic.js +++ b/app/assets/javascripts/discourse/app/models/topic.js @@ -661,7 +661,7 @@ Topic.reopenClass({ } }, - update(topic, props) { + update(topic, props, opts = {}) { // We support `category_id` and `categoryId` for compatibility if (typeof props.categoryId !== "undefined") { props.category_id = props.categoryId; @@ -673,9 +673,13 @@ Topic.reopenClass({ delete props.category_id; } + const data = { ...props }; + if (opts.fastEdit) { + data.keep_existing_draft = true; + } return ajax(topic.get("url"), { type: "PUT", - data: JSON.stringify(props), + data: JSON.stringify(data), contentType: "application/json", }).then((result) => { // The title can be cleaned up server side diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 73fb6838f41..41ad745d6ad 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -397,7 +397,13 @@ class TopicsController < ApplicationController bypass_bump = should_bypass_bump?(changes) first_post = topic.ordered_posts.first - success = PostRevisor.new(first_post, topic).revise!(current_user, changes, validate_post: false, bypass_bump: bypass_bump) + success = PostRevisor.new(first_post, topic).revise!( + current_user, + changes, + validate_post: false, + bypass_bump: bypass_bump, + keep_existing_draft: params[:keep_existing_draft].to_s == "true" + ) if !success && topic.errors.blank? topic.errors.add(:base, :unable_to_update) diff --git a/lib/post_revisor.rb b/lib/post_revisor.rb index 8c046392a4e..03e3ede96bc 100644 --- a/lib/post_revisor.rb +++ b/lib/post_revisor.rb @@ -159,7 +159,16 @@ class PostRevisor end end - return false unless should_revise? + if !should_revise? + # the draft sequence is advanced here to handle the edge case where a + # user opens the composer to edit a post and makes some changes (which + # saves a draft), but then un-does the changes and clicks save. In this + # case, should_revise? returns false because nothing has really changed + # in the post, but we want to get rid of the draft so we advance the + # sequence. + advance_draft_sequence if !opts[:keep_existing_draft] + return false + end @post.acting_user = @editor @topic.acting_user = @editor @@ -204,7 +213,7 @@ class PostRevisor plugin_callbacks revise_topic - advance_draft_sequence + advance_draft_sequence if !opts[:keep_existing_draft] end # Lock the post by default if the appropriate setting is true @@ -271,7 +280,6 @@ class PostRevisor return true end end - advance_draft_sequence false end diff --git a/spec/lib/post_revisor_spec.rb b/spec/lib/post_revisor_spec.rb index e45e95de338..f69b1180aaa 100644 --- a/spec/lib/post_revisor_spec.rb +++ b/spec/lib/post_revisor_spec.rb @@ -1236,6 +1236,33 @@ describe PostRevisor do end end end + + context 'with drafts' do + it "does not advance draft sequence if keep_existing_draft option is true" do + post = Fabricate(:post, user: user) + topic = post.topic + draft_key = "topic_#{topic.id}" + data = { reply: "test 12222" }.to_json + Draft.set(user, draft_key, 0, data) + Draft.set(user, draft_key, 0, data) + expect { + PostRevisor.new(post).revise!( + post.user, + { title: "updated title for my topic" }, + keep_existing_draft: true + ) + }.to change { Draft.where(user: user, draft_key: draft_key).first.sequence }.by(0) + .and change { DraftSequence.where(user_id: user.id, draft_key: draft_key).first.sequence }.by(0) + + expect { + PostRevisor.new(post).revise!( + post.user, + { title: "updated title for my topic" }, + ) + }.to change { Draft.where(user: user, draft_key: draft_key).count }.from(1).to(0) + .and change { DraftSequence.where(user_id: user.id, draft_key: draft_key).first.sequence }.by(1) + end + end end context 'when the review_every_post setting is enabled' do