FEATURE: Allow choice of category when making a PM public (#7907)

FEATURE: Allow choice of category when making a PM public (#7907)

  • FEATURE: Allow choice of category when making a PM public

Previously it would default to uncategorized, which was not ideal on some forums. This gives the staff member more choice about what they’d like to do.

  • Make the optional category more explicit

  • Joffrey’s feedback

diff --git a/app/assets/javascripts/discourse/controllers/convert-to-public-topic.js.es6 b/app/assets/javascripts/discourse/controllers/convert-to-public-topic.js.es6
new file mode 100644
index 0000000..58ccfbc
--- /dev/null
+++ b/app/assets/javascripts/discourse/controllers/convert-to-public-topic.js.es6
@@ -0,0 +1,26 @@
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import ModalFunctionality from "discourse/mixins/modal-functionality";
+
+export default Ember.Controller.extend(ModalFunctionality, {
+  publicCategoryId: null,
+  saving: true,
+
+  onShow() {
+    this.setProperties({ publicCategoryId: null, saving: false });
+  },
+
+  actions: {
+    makePublic() {
+      let topic = this.model;
+      topic
+        .convertTopic("public", { categoryId: this.publicCategoryId })
+        .then(() => {
+          topic.set("archetype", "regular");
+          topic.set("category_id", this.publicCategoryId);
+          this.appEvents.trigger("header:show-topic", topic);
+          this.send("closeModal");
+        })
+        .catch(popupAjaxError);
+    }
+  }
+});
diff --git a/app/assets/javascripts/discourse/controllers/topic.js.es6 b/app/assets/javascripts/discourse/controllers/topic.js.es6
index 1e86063..d4ef29a 100644
--- a/app/assets/javascripts/discourse/controllers/topic.js.es6
+++ b/app/assets/javascripts/discourse/controllers/topic.js.es6
@@ -1073,11 +1073,17 @@ export default Ember.Controller.extend(bufferedProperty("model"), {
     },
 
     convertToPublicTopic() {
-      this.model.convertTopic("public");
+      showModal("convert-to-public-topic", {
+        model: this.model,
+        modalClass: "convert-to-public-topic"
+      });
     },
 
     convertToPrivateMessage() {
-      this.model.convertTopic("private");
+      this.model
+        .convertTopic("private")
+        .then(() => window.location.reload())
+        .catch(popupAjaxError);
     },
 
     removeFeaturedLink() {
diff --git a/app/assets/javascripts/discourse/models/topic.js.es6 b/app/assets/javascripts/discourse/models/topic.js.es6
index 4d3056b..ca2c435 100644
--- a/app/assets/javascripts/discourse/models/topic.js.es6
+++ b/app/assets/javascripts/discourse/models/topic.js.es6
@@ -599,10 +599,12 @@ const Topic = RestModel.extend({
     });
   },
 
-  convertTopic(type) {
-    return ajax(`/t/${this.id}/convert-topic/${type}`, { type: "PUT" })
-      .then(() => window.location.reload())
-      .catch(popupAjaxError);
+  convertTopic(type, opts) {
+    let args = { type: "PUT" };
+    if (opts && opts.categoryId) {
+      args.data = { category_id: opts.categoryId };
+    }
+    return ajax(`/t/${this.id}/convert-topic/${type}`, args);
   },
 
   resetBumpDate() {
diff --git a/app/assets/javascripts/discourse/templates/modal/convert-to-public-topic.hbs b/app/assets/javascripts/discourse/templates/modal/convert-to-public-topic.hbs
new file mode 100644
index 0000000..b13804b
--- /dev/null
+++ b/app/assets/javascripts/discourse/templates/modal/convert-to-public-topic.hbs
@@ -0,0 +1,13 @@
+{{#d-modal-body title="topic.make_public.title"}}
+
+  <div class='instructions'>
+    {{i18n "topic.make_public.choose_category"}}
+  </div>
+  {{category-chooser value=publicCategoryId}}
+
+{{/d-modal-body}}
+
+<div class='modal-footer'>
+  {{d-button class="btn-primary" action=(action "makePublic") label="composer.modal_ok" disabled=saving}}
+  {{d-modal-cancel close=(route-action "closeModal")}}
+</div>
diff --git a/app/assets/stylesheets/common/components/convert-to-public-topic-modal.scss b/app/assets/stylesheets/common/components/convert-to-public-topic-modal.scss
new file mode 100644
index 0000000..50a32a8
--- /dev/null
+++ b/app/assets/stylesheets/common/components/convert-to-public-topic-modal.scss
@@ -0,0 +1,5 @@
+.convert-to-public-topic .modal-body {
+  .instructions {
+    margin-bottom: 1em;
+  }
+}
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
index 74789f5..8116dfb 100644
--- a/app/controllers/topics_controller.rb
+++ b/app/controllers/topics_controller.rb
@@ -821,7 +821,7 @@ class TopicsController < ApplicationController
     guardian.ensure_can_convert_topic!(topic)
 
     if params[:type] == "public"
-      converted_topic = topic.convert_to_public_topic(current_user)
+      converted_topic = topic.convert_to_public_topic(current_user, category_id: params[:category_id])
     else
       converted_topic = topic.convert_to_private_message(current_user)
     end
diff --git a/app/models/topic.rb b/app/models/topic.rb
index 648da51..cb12508 100644
--- a/app/models/topic.rb
+++ b/app/models/topic.rb
@@ -1307,8 +1307,8 @@ class Topic < ActiveRecord::Base
     builder.query_single.first.to_i
   end
 
-  def convert_to_public_topic(user)
-    public_topic = TopicConverter.new(self, user).convert_to_public_topic
+  def convert_to_public_topic(user, category_id: nil)
+    public_topic = TopicConverter.new(self, user).convert_to_public_topic(category_id)
     add_small_action(user, "public_topic") if public_topic
     public_topic
   end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index ce17389..c092fd6 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -2171,6 +2171,9 @@ en:
         title: "Flag"
         help: "privately flag this topic for attention or send a private notification about it"
         success_message: "You successfully flagged this topic."
+      make_public:
+        title: "Convert to Public Topic"
+        choose_category: "Please choose a category for the public topic:"
 
       feature_topic:
         title: "Feature this topic"
diff --git a/spec/requests/topics_controller_spec.rb b/spec/requests/topics_controller_spec.rb
index ad718e8..a5440b1 100644
--- a/spec/requests/topics_controller_spec.rb
+++ b/spec/requests/topics_controller_spec.rb
@@ -2230,12 +2230,15 @@ RSpec.describe TopicsController do
       end
 
       context "success" do
+        fab!(:category) { Fabricate(:category) }
+
         it "returns success" do
           sign_in(admin)
-          put "/t/#{topic.id}/convert-topic/public.json"
+          put "/t/#{topic.id}/convert-topic/public.json?category_id=#{category.id}"
 
           topic.reload
           expect(topic.archetype).to eq(Archetype.default)
+          expect(topic.category_id).to eq(category.id)
           expect(response.status).to eq(200)
 
           result = ::JSON.parse(response.body)
diff --git a/test/javascripts/acceptance/topic-test.js.es6 b/test/javascripts/acceptance/topic-test.js.es6
index 0e9c235..3a3b6de 100644
--- a/test/javascripts/acceptance/topic-test.js.es6
+++ b/test/javascripts/acceptance/topic-test.js.es6
@@ -213,6 +213,20 @@ QUnit.test("remove featured link", async assert => {
   // assert.ok(!exists('.title-wrapper .topic-featured-link'), 'link is gone');
 });
 
+QUnit.test("Converting to a public topic", async assert => {
+  await visit("/t/test-pm/34");
+  assert.ok(exists(".private_message"));
+  await click(".toggle-admin-menu");
+  await click(".topic-admin-convert button");
+
+  let categoryChooser = selectKit(".convert-to-public-topic .category-chooser");
+  await categoryChooser.expand();
+  await categoryChooser.selectRowByValue(21);
+
+  await click(".convert-to-public-topic .btn-primary");
+  assert.ok(!exists(".private_message"));
+});
+
 QUnit.test("Unpinning unlisted topic", async assert => {
   await visit("/t/internationalization-localization/280");
 
diff --git a/test/javascripts/helpers/create-pretender.js.es6 b/test/javascripts/helpers/create-pretender.js.es6
index 64a70cc..781cdb9 100644
--- a/test/javascripts/helpers/create-pretender.js.es6
+++ b/test/javascripts/helpers/create-pretender.js.es6
@@ -150,6 +150,10 @@ export default function() {
       });
     });
 
+    this.put("/t/34/convert-topic/public", () => {
+      return response({});
+    });
+
     this.put("/t/280/make-banner", () => {
       return response({});
     });

GitHub sha: 8dd3cbfc

1 Like