FEATURE: Add message to bulk close topics (#26535)

This will allow you to type a single message when bulk closing topics
that will be applied to every topic, that way they all have the same
message.
This commit is contained in:
Blake Erickson 2024-04-05 14:56:52 -06:00 committed by GitHub
parent 570e3f7a1a
commit 8da49b5664
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 65 additions and 2 deletions

View File

@ -1,6 +1,7 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { Input } from "@ember/component";
import { on } from "@ember/modifier";
import { action, computed } from "@ember/object";
import { service } from "@ember/service";
import { Promise } from "rsvp";
@ -10,6 +11,7 @@ import DModal from "discourse/components/d-modal";
import RadioButton from "discourse/components/radio-button";
import { topicLevels } from "discourse/lib/notification-levels";
import Topic from "discourse/models/topic";
import autoFocus from "discourse/modifiers/auto-focus";
import htmlSafe from "discourse-common/helpers/html-safe";
import i18n from "discourse-common/helpers/i18n";
import CategoryChooser from "select-kit/components/category-chooser";
@ -30,6 +32,7 @@ export default class BulkTopicActions extends Component {
@tracked loading;
@tracked errors;
@tracked isSilent = false;
@tracked closeNote = null;
notificationLevelId = null;
@ -84,6 +87,10 @@ export default class BulkTopicActions extends Component {
operation = { type: "silent_close" };
}
if (this.isCloseAction && this.closeNote) {
operation["message"] = this.closeNote;
}
const tasks = topicChunks.map((topics) => async () => {
const result = await Topic.bulkOperation(topics, operation, options);
this.processedTopicCount += topics.length;
@ -246,6 +253,17 @@ export default class BulkTopicActions extends Component {
return this.args.model.action === "update-category";
}
@computed("action")
get isCloseAction() {
return this.args.model.action === "close";
}
@action
updateCloseNote(event) {
event.preventDefault();
this.closeNote = event.target.value;
}
get notificationLevels() {
return topicLevels.map((level) => ({
id: level.id.toString(),
@ -322,6 +340,22 @@ export default class BulkTopicActions extends Component {
onRegisterAction=this.registerCustomAction
}}
{{/if}}
{{#if this.isCloseAction}}
<div class="bulk-close-note-section">
<label>
{{i18n "topic_bulk_actions.close_topics.note"}}&nbsp;<span
class="label-optional"
>{{i18n "topic_bulk_actions.close_topics.optional"}}</span>
</label>
<textarea
id="bulk-close-note"
{{on "input" this.updateCloseNote}}
{{autoFocus}}
>{{this.closeNote}}</textarea>
</div>
{{/if}}
</ConditionalLoadingSection>
</:body>

View File

@ -230,6 +230,9 @@
#bulk-topics-cancel {
margin-left: auto;
}
.bulk-close-note-section {
margin-top: 1em;
}
}
.d-modal.edit-slow-mode-modal {

View File

@ -1010,6 +1010,7 @@ class TopicsController < ApplicationController
:group,
:category_id,
:notification_level_id,
:message,
*DiscoursePluginRegistry.permitted_bulk_action_parameters,
tags: [],
)

View File

@ -3028,6 +3028,8 @@ en:
topic_bulk_actions:
close_topics:
name: "Close Topics"
note: "Note"
optional: (optional)
archive_topics:
name: "Archive Topics"
unlist_topics:

View File

@ -165,7 +165,7 @@ class TopicsBulkAction
def close
topics.each do |t|
if guardian.can_moderate?(t)
t.update_status("closed", true, @user)
t.update_status("closed", true, @user, { message: @operation[:message] })
@changed_ids << t.id
end
end
@ -174,7 +174,7 @@ class TopicsBulkAction
def silent_close
topics.each do |t|
if guardian.can_moderate?(t)
t.update_status("autoclosed", true, @user)
t.update_status("autoclosed", true, @user, { message: @operation[:message] })
@changed_ids << t.id
end
end

View File

@ -50,6 +50,10 @@ module PageObjects
find("#topic-bulk-action-options__silent").click
end
def fill_in_close_note(message)
find("#bulk-close-note").set(message)
end
def click_dismiss_read_confirm
find("#dismiss-read-confirm").click
end

View File

@ -88,6 +88,25 @@ describe "Topic bulk select", type: :system do
expect(topic_list).to have_no_unread_badge(topics.first)
end
it "closes topics with message" do
# Bulk close the topic with a message
sign_in(admin)
visit("/latest")
topic = topics.first
topic_list_header.click_bulk_select_button
topic_list.click_topic_checkbox(topics.first)
topic_list_header.click_bulk_select_topics_dropdown
topic_list_header.click_close_topics_button
# Fill in message
topic_list_header.fill_in_close_note("My message")
topic_list_header.click_bulk_topics_confirm
# Check that the topic now has the message
visit("/t/#{topic.slug}/#{topic.id}")
expect(topic_page).to have_content("My message")
end
it "works with keyboard shortcuts" do
sign_in(admin)
visit("/latest")