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
This commit is contained in:
Robin Ward 2019-07-19 11:52:50 -04:00 committed by GitHub
parent 9075789783
commit 8dd3cbfcb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 86 additions and 10 deletions

View File

@ -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);
}
}
});

View File

@ -1073,11 +1073,17 @@ export default Ember.Controller.extend(bufferedProperty("model"), {
}, },
convertToPublicTopic() { convertToPublicTopic() {
this.model.convertTopic("public"); showModal("convert-to-public-topic", {
model: this.model,
modalClass: "convert-to-public-topic"
});
}, },
convertToPrivateMessage() { convertToPrivateMessage() {
this.model.convertTopic("private"); this.model
.convertTopic("private")
.then(() => window.location.reload())
.catch(popupAjaxError);
}, },
removeFeaturedLink() { removeFeaturedLink() {

View File

@ -599,10 +599,12 @@ const Topic = RestModel.extend({
}); });
}, },
convertTopic(type) { convertTopic(type, opts) {
return ajax(`/t/${this.id}/convert-topic/${type}`, { type: "PUT" }) let args = { type: "PUT" };
.then(() => window.location.reload()) if (opts && opts.categoryId) {
.catch(popupAjaxError); args.data = { category_id: opts.categoryId };
}
return ajax(`/t/${this.id}/convert-topic/${type}`, args);
}, },
resetBumpDate() { resetBumpDate() {

View File

@ -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>

View File

@ -0,0 +1,5 @@
.convert-to-public-topic .modal-body {
.instructions {
margin-bottom: 1em;
}
}

View File

@ -821,7 +821,7 @@ class TopicsController < ApplicationController
guardian.ensure_can_convert_topic!(topic) guardian.ensure_can_convert_topic!(topic)
if params[:type] == "public" 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 else
converted_topic = topic.convert_to_private_message(current_user) converted_topic = topic.convert_to_private_message(current_user)
end end

View File

@ -1307,8 +1307,8 @@ class Topic < ActiveRecord::Base
builder.query_single.first.to_i builder.query_single.first.to_i
end end
def convert_to_public_topic(user) def convert_to_public_topic(user, category_id: nil)
public_topic = TopicConverter.new(self, user).convert_to_public_topic public_topic = TopicConverter.new(self, user).convert_to_public_topic(category_id)
add_small_action(user, "public_topic") if public_topic add_small_action(user, "public_topic") if public_topic
public_topic public_topic
end end

View File

@ -2171,6 +2171,9 @@ en:
title: "Flag" title: "Flag"
help: "privately flag this topic for attention or send a private notification about it" help: "privately flag this topic for attention or send a private notification about it"
success_message: "You successfully flagged this topic." 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: feature_topic:
title: "Feature this topic" title: "Feature this topic"

View File

@ -2230,12 +2230,15 @@ RSpec.describe TopicsController do
end end
context "success" do context "success" do
fab!(:category) { Fabricate(:category) }
it "returns success" do it "returns success" do
sign_in(admin) 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 topic.reload
expect(topic.archetype).to eq(Archetype.default) expect(topic.archetype).to eq(Archetype.default)
expect(topic.category_id).to eq(category.id)
expect(response.status).to eq(200) expect(response.status).to eq(200)
result = ::JSON.parse(response.body) result = ::JSON.parse(response.body)

View File

@ -213,6 +213,20 @@ QUnit.test("remove featured link", async assert => {
// assert.ok(!exists('.title-wrapper .topic-featured-link'), 'link is gone'); // 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 => { QUnit.test("Unpinning unlisted topic", async assert => {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");

View File

@ -150,6 +150,10 @@ export default function() {
}); });
}); });
this.put("/t/34/convert-topic/public", () => {
return response({});
});
this.put("/t/280/make-banner", () => { this.put("/t/280/make-banner", () => {
return response({}); return response({});
}); });