mirror of
https://github.com/discourse/discourse.git
synced 2025-04-24 15:04:37 +08:00
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:
parent
570e3f7a1a
commit
8da49b5664
app
assets
javascripts/discourse/app/components/modal
stylesheets/common/modal
controllers
config/locales
lib
spec/system
@ -1,6 +1,7 @@
|
|||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
import { Input } from "@ember/component";
|
import { Input } from "@ember/component";
|
||||||
|
import { on } from "@ember/modifier";
|
||||||
import { action, computed } from "@ember/object";
|
import { action, computed } from "@ember/object";
|
||||||
import { service } from "@ember/service";
|
import { service } from "@ember/service";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
@ -10,6 +11,7 @@ import DModal from "discourse/components/d-modal";
|
|||||||
import RadioButton from "discourse/components/radio-button";
|
import RadioButton from "discourse/components/radio-button";
|
||||||
import { topicLevels } from "discourse/lib/notification-levels";
|
import { topicLevels } from "discourse/lib/notification-levels";
|
||||||
import Topic from "discourse/models/topic";
|
import Topic from "discourse/models/topic";
|
||||||
|
import autoFocus from "discourse/modifiers/auto-focus";
|
||||||
import htmlSafe from "discourse-common/helpers/html-safe";
|
import htmlSafe from "discourse-common/helpers/html-safe";
|
||||||
import i18n from "discourse-common/helpers/i18n";
|
import i18n from "discourse-common/helpers/i18n";
|
||||||
import CategoryChooser from "select-kit/components/category-chooser";
|
import CategoryChooser from "select-kit/components/category-chooser";
|
||||||
@ -30,6 +32,7 @@ export default class BulkTopicActions extends Component {
|
|||||||
@tracked loading;
|
@tracked loading;
|
||||||
@tracked errors;
|
@tracked errors;
|
||||||
@tracked isSilent = false;
|
@tracked isSilent = false;
|
||||||
|
@tracked closeNote = null;
|
||||||
|
|
||||||
notificationLevelId = null;
|
notificationLevelId = null;
|
||||||
|
|
||||||
@ -84,6 +87,10 @@ export default class BulkTopicActions extends Component {
|
|||||||
operation = { type: "silent_close" };
|
operation = { type: "silent_close" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isCloseAction && this.closeNote) {
|
||||||
|
operation["message"] = this.closeNote;
|
||||||
|
}
|
||||||
|
|
||||||
const tasks = topicChunks.map((topics) => async () => {
|
const tasks = topicChunks.map((topics) => async () => {
|
||||||
const result = await Topic.bulkOperation(topics, operation, options);
|
const result = await Topic.bulkOperation(topics, operation, options);
|
||||||
this.processedTopicCount += topics.length;
|
this.processedTopicCount += topics.length;
|
||||||
@ -246,6 +253,17 @@ export default class BulkTopicActions extends Component {
|
|||||||
return this.args.model.action === "update-category";
|
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() {
|
get notificationLevels() {
|
||||||
return topicLevels.map((level) => ({
|
return topicLevels.map((level) => ({
|
||||||
id: level.id.toString(),
|
id: level.id.toString(),
|
||||||
@ -322,6 +340,22 @@ export default class BulkTopicActions extends Component {
|
|||||||
onRegisterAction=this.registerCustomAction
|
onRegisterAction=this.registerCustomAction
|
||||||
}}
|
}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.isCloseAction}}
|
||||||
|
<div class="bulk-close-note-section">
|
||||||
|
<label>
|
||||||
|
{{i18n "topic_bulk_actions.close_topics.note"}} <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>
|
</ConditionalLoadingSection>
|
||||||
</:body>
|
</:body>
|
||||||
|
|
||||||
|
@ -230,6 +230,9 @@
|
|||||||
#bulk-topics-cancel {
|
#bulk-topics-cancel {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
.bulk-close-note-section {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.d-modal.edit-slow-mode-modal {
|
.d-modal.edit-slow-mode-modal {
|
||||||
|
@ -1010,6 +1010,7 @@ class TopicsController < ApplicationController
|
|||||||
:group,
|
:group,
|
||||||
:category_id,
|
:category_id,
|
||||||
:notification_level_id,
|
:notification_level_id,
|
||||||
|
:message,
|
||||||
*DiscoursePluginRegistry.permitted_bulk_action_parameters,
|
*DiscoursePluginRegistry.permitted_bulk_action_parameters,
|
||||||
tags: [],
|
tags: [],
|
||||||
)
|
)
|
||||||
|
@ -3028,6 +3028,8 @@ en:
|
|||||||
topic_bulk_actions:
|
topic_bulk_actions:
|
||||||
close_topics:
|
close_topics:
|
||||||
name: "Close Topics"
|
name: "Close Topics"
|
||||||
|
note: "Note"
|
||||||
|
optional: (optional)
|
||||||
archive_topics:
|
archive_topics:
|
||||||
name: "Archive Topics"
|
name: "Archive Topics"
|
||||||
unlist_topics:
|
unlist_topics:
|
||||||
|
@ -165,7 +165,7 @@ class TopicsBulkAction
|
|||||||
def close
|
def close
|
||||||
topics.each do |t|
|
topics.each do |t|
|
||||||
if guardian.can_moderate?(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
|
@changed_ids << t.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -174,7 +174,7 @@ class TopicsBulkAction
|
|||||||
def silent_close
|
def silent_close
|
||||||
topics.each do |t|
|
topics.each do |t|
|
||||||
if guardian.can_moderate?(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
|
@changed_ids << t.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -50,6 +50,10 @@ module PageObjects
|
|||||||
find("#topic-bulk-action-options__silent").click
|
find("#topic-bulk-action-options__silent").click
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fill_in_close_note(message)
|
||||||
|
find("#bulk-close-note").set(message)
|
||||||
|
end
|
||||||
|
|
||||||
def click_dismiss_read_confirm
|
def click_dismiss_read_confirm
|
||||||
find("#dismiss-read-confirm").click
|
find("#dismiss-read-confirm").click
|
||||||
end
|
end
|
||||||
|
@ -88,6 +88,25 @@ describe "Topic bulk select", type: :system do
|
|||||||
expect(topic_list).to have_no_unread_badge(topics.first)
|
expect(topic_list).to have_no_unread_badge(topics.first)
|
||||||
end
|
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
|
it "works with keyboard shortcuts" do
|
||||||
sign_in(admin)
|
sign_in(admin)
|
||||||
visit("/latest")
|
visit("/latest")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user