diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6 index c7ed4c474dd..d907a0f9475 100644 --- a/app/assets/javascripts/discourse/controllers/composer.js.es6 +++ b/app/assets/javascripts/discourse/controllers/composer.js.es6 @@ -507,7 +507,9 @@ export default Ember.Controller.extend({ }, cancel() { - this.cancelComposer(); + const differentDraftContext = + this.get("topic.id") !== this.get("model.topic.id"); + this.cancelComposer(differentDraftContext); }, save() { @@ -830,7 +832,12 @@ export default Ember.Controller.extend({ } // If it's a different draft, cancel it and try opening again. - return this.cancelComposer() + const differentDraftContext = + opts.post && composerModel.topic + ? composerModel.topic.id !== opts.post.topic_id + : true; + + return this.cancelComposer(differentDraftContext) .then(() => this.open(opts)) .then(resolve, reject); } @@ -984,11 +991,23 @@ export default Ember.Controller.extend({ } }, - cancelComposer() { + cancelComposer(differentDraft = false) { return new Ember.RSVP.Promise(resolve => { if (this.get("model.hasMetaData") || this.get("model.replyDirty")) { bootbox.dialog(I18n.t("post.abandon.confirm"), [ - { label: I18n.t("post.abandon.no_value") }, + { + label: differentDraft + ? I18n.t("post.abandon.no_save_draft") + : I18n.t("post.abandon.no_value"), + callback: () => { + // cancel composer without destroying draft on new draft context + if (differentDraft) { + this.model.clearState(); + this.close(); + resolve(); + } + } + }, { label: I18n.t("post.abandon.yes_value"), class: "btn-danger", diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index a1252f94406..2157f174f32 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2381,6 +2381,7 @@ en: abandon: confirm: "Are you sure you want to abandon your post?" no_value: "No, keep" + no_save_draft: "No, save draft" yes_value: "Yes, abandon" via_email: "this post arrived via email" diff --git a/test/javascripts/acceptance/composer-test.js.es6 b/test/javascripts/acceptance/composer-test.js.es6 index b055992135c..26ccba2be28 100644 --- a/test/javascripts/acceptance/composer-test.js.es6 +++ b/test/javascripts/acceptance/composer-test.js.es6 @@ -586,19 +586,48 @@ QUnit.test( await click(".topic-post:eq(0) button.reply"); await fillIn(".d-editor-input", "This is a dirty reply"); await click(".toggler"); - await click(".topic-post:eq(0) button.edit"); + await click(".topic-post:eq(1) button.edit"); assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); + assert.equal( + find(".modal-footer a:eq(1)").text(), + I18n.t("post.abandon.no_value") + ); await click(".modal-footer a:eq(0)"); assert.equal( find(".d-editor-input") .val() - .indexOf("This is the first post."), + .indexOf("This is the second post."), 0, "it populates the input with the post text" ); } ); +QUnit.test( + "Composer draft can switch to draft in new context without destroying current draft", + async assert => { + await visit("/t/this-is-a-test-topic/9"); + + await click(".topic-post:eq(0) button.reply"); + await fillIn(".d-editor-input", "This is a dirty reply"); + + await click("#site-logo"); + await click("#create-topic"); + + assert.ok(exists(".bootbox.modal"), "it pops up a confirmation dialog"); + assert.equal( + find(".modal-footer a:eq(1)").text(), + I18n.t("post.abandon.no_save_draft") + ); + await click(".modal-footer a:eq(1)"); + assert.equal( + find(".d-editor-input").val(), + "", + "it populates the input with the post text" + ); + } +); + QUnit.test("Checks for existing draft", async assert => { try { toggleCheckDraftPopup(true);