UI: when in a different topic context, allow dismissing draft without destroying it

UI: when in a different topic context, allow dismissing draft without destroying it

This changes the label and behaviour of the “No, keep” button in the confirmation modal when user cancels a draft while on a different topic. The new button label is “No, save draft”, and when clicked, the composer will be dismissed without destroying the draft.

diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6
index c7ed4c4..d907a0f 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 a1252f9..2157f17 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 b055992..26ccba2 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);

GitHub sha: c7863428

is there a chance topic or model or model.topic would be null ?

this.topic.id !== this.model.topic.id;
1 Like

Yes, on a new topic.

1 Like