FEATURE: Per-category default slow mode duration for topics.

When configured, all topics in the category inherits the slow mode
duration from the category's default.

Note that currently there is no way to remove the slow mode from the
topics once it has been set.
This commit is contained in:
mintsaxon 2021-06-27 21:46:11 +02:00 committed by Alan Guo Xiang Tan
parent 0ea58fe51f
commit 7162ecfb04
12 changed files with 62 additions and 2 deletions

View File

@ -138,4 +138,10 @@ export default buildCategoryPanel("settings", {
let hours = minutes ? minutes / 60 : null; let hours = minutes ? minutes / 60 : null;
this.set("category.auto_close_hours", hours); this.set("category.auto_close_hours", hours);
}, },
@action
onDefaultSlowModeDurationChange(minutes) {
let seconds = minutes ? minutes * 60 : null;
this.set("category.default_slow_mode_seconds", seconds);
},
}); });

View File

@ -177,6 +177,11 @@ const Category = RestModel.extend({
return topicCount; return topicCount;
}, },
@discourseComputed("default_slow_mode_seconds")
defaultSlowModeMinutes(seconds) {
return seconds ? seconds / 60 : null;
},
save() { save() {
const id = this.id; const id = this.id;
const url = id ? `/categories/${id}` : "/categories"; const url = id ? `/categories/${id}` : "/categories";
@ -193,6 +198,7 @@ const Category = RestModel.extend({
auto_close_based_on_last_post: this.get( auto_close_based_on_last_post: this.get(
"auto_close_based_on_last_post" "auto_close_based_on_last_post"
), ),
default_slow_mode_seconds: this.default_slow_mode_seconds,
position: this.position, position: this.position,
email_in: this.email_in, email_in: this.email_in,
email_in_allow_strangers: this.email_in_allow_strangers, email_in_allow_strangers: this.email_in_allow_strangers,

View File

@ -116,6 +116,21 @@
</label> </label>
</section> </section>
<section class="field default-slow-mode">
<div class="control-group">
<label for="category-default-slow-mode">
{{i18n "category.default_slow_mode"}}
</label>
<div class="category-default-slow-mode-seconds">
{{relative-time-picker
id="category-default-slow-mode"
durationMinutes=category.defaultSlowModeMinutes
hiddenIntervals=hiddenRelativeIntervals
onChange=(action "onDefaultSlowModeDurationChange")}}
</div>
</div>
</section>
<section class="field auto-close"> <section class="field auto-close">
<div class="control-group"> <div class="control-group">
<label for="topic-auto-close"> <label for="topic-auto-close">

View File

@ -158,7 +158,8 @@ div.edit-category {
padding: 0 1.5em 2em 0; padding: 0 1.5em 2em 0;
} }
.category-topic-auto-close-hours { .category-topic-auto-close-hours,
.category-default-slow-mode-seconds {
width: 200px; width: 200px;
} }
} }

View File

@ -302,6 +302,7 @@ class CategoriesController < ApplicationController
:mailinglist_mirror, :mailinglist_mirror,
:all_topics_wiki, :all_topics_wiki,
:allow_unlimited_owner_edits_on_first_post, :allow_unlimited_owner_edits_on_first_post,
:default_slow_mode_seconds,
:parent_category_id, :parent_category_id,
:auto_close_hours, :auto_close_hours,
:auto_close_based_on_last_post, :auto_close_based_on_last_post,

View File

@ -1027,6 +1027,7 @@ end
# read_only_banner :string # read_only_banner :string
# default_list_filter :string(20) default("all") # default_list_filter :string(20) default("all")
# allow_unlimited_owner_edits_on_first_post :boolean default(FALSE), not null # allow_unlimited_owner_edits_on_first_post :boolean default(FALSE), not null
# default_slow_mode_seconds :integer
# #
# Indexes # Indexes
# #

View File

@ -334,6 +334,7 @@ class Topic < ActiveRecord::Base
if category_id_changed? || new_record? if category_id_changed? || new_record?
inherit_auto_close_from_category inherit_auto_close_from_category
inherit_slow_mode_from_category
end end
end end
@ -1251,6 +1252,12 @@ class Topic < ActiveRecord::Base
end end
end end
def inherit_slow_mode_from_category
if self.category&.default_slow_mode_seconds
self.slow_mode_seconds = self.category&.default_slow_mode_seconds
end
end
def inherit_auto_close_from_category(timer_type: :close) def inherit_auto_close_from_category(timer_type: :close)
auto_close_hours = self.category&.auto_close_hours auto_close_hours = self.category&.auto_close_hours

View File

@ -20,7 +20,8 @@ class CategorySerializer < SiteCategorySerializer
:custom_fields, :custom_fields,
:topic_featured_link_allowed, :topic_featured_link_allowed,
:search_priority, :search_priority,
:reviewable_by_group_name :reviewable_by_group_name,
:default_slow_mode_seconds
def reviewable_by_group_name def reviewable_by_group_name
object.reviewable_by_group.name object.reviewable_by_group.name

View File

@ -3217,6 +3217,7 @@ en:
position_disabled: "Categories will be displayed in order of activity. To control the order of categories in lists, " position_disabled: "Categories will be displayed in order of activity. To control the order of categories in lists, "
position_disabled_click: 'enable the "fixed category positions" setting.' position_disabled_click: 'enable the "fixed category positions" setting.'
minimum_required_tags: "Minimum number of tags required in a topic:" minimum_required_tags: "Minimum number of tags required in a topic:"
default_slow_mode: 'Enable "Slow Mode" for new topics in this category.'
parent: "Parent Category" parent: "Parent Category"
num_auto_bump_daily: "Number of open topics to automatically bump daily:" num_auto_bump_daily: "Number of open topics to automatically bump daily:"
navigate_to_first_post_after_read: "Navigate to first post after topics are read" navigate_to_first_post_after_read: "Navigate to first post after topics are read"

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddDefaultAutoCloseSecondsToCategory < ActiveRecord::Migration[6.1]
def change
add_column :categories, :default_slow_mode_seconds, :integer
end
end

View File

@ -170,6 +170,12 @@
"allow_unlimited_owner_edits_on_first_post": { "allow_unlimited_owner_edits_on_first_post": {
"type": "boolean" "type": "boolean"
}, },
"default_slow_mode_seconds": {
"type": [
"string",
"null"
]
},
"group_permissions": { "group_permissions": {
"type": "array", "type": "array",
"items": [ "items": [
@ -274,6 +280,7 @@
"auto_close_hours", "auto_close_hours",
"auto_close_based_on_last_post", "auto_close_based_on_last_post",
"allow_unlimited_owner_edits_on_first_post", "allow_unlimited_owner_edits_on_first_post",
"default_slow_mode_seconds",
"group_permissions", "group_permissions",
"email_in", "email_in",
"email_in_allow_strangers", "email_in_allow_strangers",

View File

@ -173,6 +173,12 @@
"allow_unlimited_owner_edits_on_first_post": { "allow_unlimited_owner_edits_on_first_post": {
"type": "boolean" "type": "boolean"
}, },
"default_slow_mode_seconds": {
"type": [
"string",
"null"
]
},
"group_permissions": { "group_permissions": {
"type": "array", "type": "array",
"items": [ "items": [
@ -277,6 +283,7 @@
"auto_close_hours", "auto_close_hours",
"auto_close_based_on_last_post", "auto_close_based_on_last_post",
"allow_unlimited_owner_edits_on_first_post", "allow_unlimited_owner_edits_on_first_post",
"default_slow_mode_seconds",
"group_permissions", "group_permissions",
"email_in", "email_in",
"email_in_allow_strangers", "email_in_allow_strangers",