mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEATURE: SiteSetting for creation of small action on tag change (#20812)
This adds a SiteSetting, which when enabled, creates a small_action post for tag/category changes to the topic. It uses `topic.add_moderator_post, and passes raw text in, to describe the change.
This commit is contained in:
parent
852475dca4
commit
65f35e1ef2
@ -175,6 +175,8 @@ en:
|
|||||||
removed_user: "Removed %{who} %{when}"
|
removed_user: "Removed %{who} %{when}"
|
||||||
removed_group: "Removed %{who} %{when}"
|
removed_group: "Removed %{who} %{when}"
|
||||||
autobumped: "Automatically bumped %{when}"
|
autobumped: "Automatically bumped %{when}"
|
||||||
|
tags_changed: "Tags updated %{when}"
|
||||||
|
category_changed: "Category updated %{when}"
|
||||||
autoclosed:
|
autoclosed:
|
||||||
enabled: "Closed %{when}"
|
enabled: "Closed %{when}"
|
||||||
disabled: "Opened %{when}"
|
disabled: "Opened %{when}"
|
||||||
|
@ -61,6 +61,12 @@ en:
|
|||||||
redirect_warning: "We were unable to verify that the link you selected was actually posted to the forum. If you wish to proceed anyway, select the link below."
|
redirect_warning: "We were unable to verify that the link you selected was actually posted to the forum. If you wish to proceed anyway, select the link below."
|
||||||
on_another_topic: "On another topic"
|
on_another_topic: "On another topic"
|
||||||
|
|
||||||
|
topic_category_changed: "From %{from} to %{to}"
|
||||||
|
topic_tag_changed:
|
||||||
|
added_and_removed: "Added %{added} and removed %{removed}"
|
||||||
|
added: "Added %{added}"
|
||||||
|
removed: "Removed %{removed}"
|
||||||
|
|
||||||
inline_oneboxer:
|
inline_oneboxer:
|
||||||
topic_page_title_post_number: "#%{post_number}"
|
topic_page_title_post_number: "#%{post_number}"
|
||||||
topic_page_title_post_number_by_user: "#%{post_number} by %{username}"
|
topic_page_title_post_number_by_user: "#%{post_number} by %{username}"
|
||||||
@ -2353,6 +2359,7 @@ en:
|
|||||||
suppress_overlapping_tags_in_list: "If tags match exact words in topic titles, don't show the tag"
|
suppress_overlapping_tags_in_list: "If tags match exact words in topic titles, don't show the tag"
|
||||||
remove_muted_tags_from_latest: "Don't show topics tagged only with muted tags in the latest topic list."
|
remove_muted_tags_from_latest: "Don't show topics tagged only with muted tags in the latest topic list."
|
||||||
force_lowercase_tags: "Force all new tags to be entirely lowercase."
|
force_lowercase_tags: "Force all new tags to be entirely lowercase."
|
||||||
|
create_post_for_category_and_tag_changes: "Create a small action post when a topic's category or tags change"
|
||||||
|
|
||||||
company_name: "Company Name"
|
company_name: "Company Name"
|
||||||
governing_law: "Governing Law"
|
governing_law: "Governing Law"
|
||||||
|
@ -2788,6 +2788,8 @@ tags:
|
|||||||
force_lowercase_tags:
|
force_lowercase_tags:
|
||||||
default: true
|
default: true
|
||||||
client: true
|
client: true
|
||||||
|
create_post_for_category_and_tag_changes:
|
||||||
|
default: false
|
||||||
|
|
||||||
dashboard:
|
dashboard:
|
||||||
dashboard_hidden_reports:
|
dashboard_hidden_reports:
|
||||||
|
@ -79,25 +79,35 @@ class PostRevisor
|
|||||||
track_and_revise topic_changes, :archetype, attribute
|
track_and_revise topic_changes, :archetype, attribute
|
||||||
end
|
end
|
||||||
|
|
||||||
track_topic_field(:category_id) do |tc, category_id, fields|
|
track_topic_field(:category_id) do |tc, new_category_id, fields|
|
||||||
if category_id == 0 && tc.topic.private_message?
|
current_category = tc.topic.category
|
||||||
tc.record_change("category_id", tc.topic.category_id, nil)
|
new_category =
|
||||||
|
(new_category_id.nil? || new_category_id.zero?) ? nil : Category.find(new_category_id)
|
||||||
|
|
||||||
|
if new_category.nil? && tc.topic.private_message?
|
||||||
|
tc.record_change("category_id", current_category.id, nil)
|
||||||
tc.topic.category_id = nil
|
tc.topic.category_id = nil
|
||||||
elsif category_id == 0 || tc.guardian.can_move_topic_to_category?(category_id)
|
elsif new_category.nil? || tc.guardian.can_move_topic_to_category?(new_category_id)
|
||||||
tags = fields[:tags] || tc.topic.tags.map(&:name)
|
tags = fields[:tags] || tc.topic.tags.map(&:name)
|
||||||
if category_id != 0 &&
|
if new_category &&
|
||||||
!DiscourseTagging.validate_min_required_tags_for_category(
|
!DiscourseTagging.validate_min_required_tags_for_category(
|
||||||
tc.guardian,
|
tc.guardian,
|
||||||
tc.topic,
|
tc.topic,
|
||||||
Category.find(category_id),
|
new_category,
|
||||||
tags,
|
tags,
|
||||||
)
|
)
|
||||||
tc.check_result(false)
|
tc.check_result(false)
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
tc.record_change("category_id", tc.topic.category_id, category_id)
|
tc.record_change("category_id", current_category&.id, new_category&.id)
|
||||||
tc.check_result(tc.topic.change_category_to_id(category_id))
|
tc.check_result(tc.topic.change_category_to_id(new_category_id))
|
||||||
|
create_small_action_for_category_change(
|
||||||
|
topic: tc.topic,
|
||||||
|
user: tc.user,
|
||||||
|
old_category: current_category,
|
||||||
|
new_category: new_category,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -114,14 +124,25 @@ class PostRevisor
|
|||||||
DB.after_commit do
|
DB.after_commit do
|
||||||
post = tc.topic.ordered_posts.first
|
post = tc.topic.ordered_posts.first
|
||||||
notified_user_ids = [post.user_id, post.last_editor_id].uniq
|
notified_user_ids = [post.user_id, post.last_editor_id].uniq
|
||||||
|
|
||||||
|
added_tags = tags - prev_tags
|
||||||
|
removed_tags = prev_tags - tags
|
||||||
|
|
||||||
if !SiteSetting.disable_tags_edit_notifications
|
if !SiteSetting.disable_tags_edit_notifications
|
||||||
Jobs.enqueue(
|
Jobs.enqueue(
|
||||||
:notify_tag_change,
|
:notify_tag_change,
|
||||||
post_id: post.id,
|
post_id: post.id,
|
||||||
notified_user_ids: notified_user_ids,
|
notified_user_ids: notified_user_ids,
|
||||||
diff_tags: ((tags - prev_tags) | (prev_tags - tags)),
|
diff_tags: (added_tags | removed_tags),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_small_action_for_tag_changes(
|
||||||
|
topic: tc.topic,
|
||||||
|
user: tc.user,
|
||||||
|
added_tags: added_tags,
|
||||||
|
removed_tags: removed_tags,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -137,6 +158,58 @@ class PostRevisor
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.create_small_action_for_category_change(topic:, user:, old_category:, new_category:)
|
||||||
|
return if !SiteSetting.create_post_for_category_and_tag_changes
|
||||||
|
|
||||||
|
topic.add_moderator_post(
|
||||||
|
user,
|
||||||
|
I18n.t(
|
||||||
|
"topic_category_changed",
|
||||||
|
from: category_name_raw(old_category),
|
||||||
|
to: category_name_raw(new_category),
|
||||||
|
),
|
||||||
|
post_type: Post.types[:small_action],
|
||||||
|
action_code: "category_changed",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.category_name_raw(category)
|
||||||
|
"##{CategoryHashtagDataSource.category_to_hashtag_item(category).ref}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_small_action_for_tag_changes(topic:, user:, added_tags:, removed_tags:)
|
||||||
|
return if !SiteSetting.create_post_for_category_and_tag_changes
|
||||||
|
|
||||||
|
topic.add_moderator_post(
|
||||||
|
user,
|
||||||
|
tags_changed_raw(added: added_tags, removed: removed_tags),
|
||||||
|
post_type: Post.types[:small_action],
|
||||||
|
action_code: "tags_changed",
|
||||||
|
custom_fields: {
|
||||||
|
tags_added: added_tags,
|
||||||
|
tags_removed: removed_tags,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.tags_changed_raw(added:, removed:)
|
||||||
|
if removed.present? && added.present?
|
||||||
|
I18n.t(
|
||||||
|
"topic_tag_changed.added_and_removed",
|
||||||
|
added: tag_list_to_raw(added),
|
||||||
|
removed: tag_list_to_raw(removed),
|
||||||
|
)
|
||||||
|
elsif added.present?
|
||||||
|
I18n.t("topic_tag_changed.added", added: tag_list_to_raw(added))
|
||||||
|
elsif removed.present?
|
||||||
|
I18n.t("topic_tag_changed.removed", removed: tag_list_to_raw(removed))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.tag_list_to_raw(tag_list)
|
||||||
|
tag_list.sort.map { |tag_name| "##{tag_name}" }.join(", ")
|
||||||
|
end
|
||||||
|
|
||||||
# AVAILABLE OPTIONS:
|
# AVAILABLE OPTIONS:
|
||||||
# - revised_at: changes the date of the revision
|
# - revised_at: changes the date of the revision
|
||||||
# - force_new_version: bypass grace period edit window
|
# - force_new_version: bypass grace period edit window
|
||||||
|
@ -146,6 +146,76 @@ RSpec.describe PostRevisor do
|
|||||||
|
|
||||||
expect { subject.revise!(admin, tags: ["new-tag"]) }.not_to change { Notification.count }
|
expect { subject.revise!(admin, tags: ["new-tag"]) }.not_to change { Notification.count }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "doesn't create a small_action post when create_post_for_category_and_tag_changes is false" do
|
||||||
|
SiteSetting.create_post_for_category_and_tag_changes = false
|
||||||
|
|
||||||
|
expect { subject.revise!(admin, tags: ["new-tag"]) }.not_to change { Post.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when `create_post_for_category_and_tag_changes` site setting is enabled" do
|
||||||
|
fab!(:tag1) { Fabricate(:tag, name: "First tag") }
|
||||||
|
fab!(:tag2) { Fabricate(:tag, name: "Second tag") }
|
||||||
|
|
||||||
|
before { SiteSetting.create_post_for_category_and_tag_changes = true }
|
||||||
|
|
||||||
|
it "Creates a small_action post with correct translation when both adding and removing tags" do
|
||||||
|
post.topic.update!(tags: [tag1])
|
||||||
|
|
||||||
|
expect { subject.revise!(admin, tags: [tag2.name]) }.to change {
|
||||||
|
Post.where(topic_id: post.topic_id, action_code: "tags_changed").count
|
||||||
|
}.by(1)
|
||||||
|
|
||||||
|
expect(post.topic.ordered_posts.last.raw).to eq(
|
||||||
|
I18n.t(
|
||||||
|
"topic_tag_changed.added_and_removed",
|
||||||
|
added: "##{tag2.name}",
|
||||||
|
removed: "##{tag1.name}",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Creates a small_action post with correct translation when adding tags" do
|
||||||
|
post.topic.update!(tags: [])
|
||||||
|
|
||||||
|
expect { subject.revise!(admin, tags: [tag1.name]) }.to change {
|
||||||
|
Post.where(topic_id: post.topic_id, action_code: "tags_changed").count
|
||||||
|
}.by(1)
|
||||||
|
|
||||||
|
expect(post.topic.ordered_posts.last.raw).to eq(
|
||||||
|
I18n.t("topic_tag_changed.added", added: "##{tag1.name}"),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Creates a small_action post with correct translation when removing tags" do
|
||||||
|
post.topic.update!(tags: [tag1, tag2])
|
||||||
|
|
||||||
|
expect { subject.revise!(admin, tags: []) }.to change {
|
||||||
|
Post.where(topic_id: post.topic_id, action_code: "tags_changed").count
|
||||||
|
}.by(1)
|
||||||
|
|
||||||
|
expect(post.topic.ordered_posts.last.raw).to eq(
|
||||||
|
I18n.t("topic_tag_changed.removed", removed: "##{tag1.name}, ##{tag2.name}"),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Creates a small_action post when category is changed" do
|
||||||
|
current_category = post.topic.category
|
||||||
|
category = Fabricate(:category)
|
||||||
|
|
||||||
|
expect { subject.revise!(admin, category_id: category.id) }.to change {
|
||||||
|
Post.where(topic_id: post.topic_id, action_code: "category_changed").count
|
||||||
|
}.by(1)
|
||||||
|
|
||||||
|
expect(post.topic.ordered_posts.last.raw).to eq(
|
||||||
|
I18n.t(
|
||||||
|
"topic_category_changed",
|
||||||
|
to: "##{category.slug}",
|
||||||
|
from: "##{current_category.slug}",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "revise wiki" do
|
describe "revise wiki" do
|
||||||
|
Loading…
Reference in New Issue
Block a user