FEATURE: Automatically disable slow mode. (#11461)

Staff and TL4 users can decide the slow mode duration. We'll internally set a topic timer to disable it.
This commit is contained in:
Roman Rizzi 2020-12-14 14:06:50 -03:00 committed by GitHub
parent 773c51a633
commit c7b9f044a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 115 additions and 6 deletions

View File

@ -17,6 +17,7 @@ export default Component.extend({
isBasedOnLastPost: equal("selection", "set_based_on_last_post"),
displayDateAndTimePicker: and("includeDateTime", "isCustom"),
displayLabel: null,
labelClasses: null,
displayNumberInput: or("isBasedOnLastPost", "isBasedOnDuration"),
init() {

View File

@ -14,6 +14,7 @@ export default Controller.extend(ModalFunctionality, {
minutes: null,
seconds: null,
saveDisabled: false,
enabledUntil: null,
showCustomSelect: equal("selectedSlowMode", "custom"),
init() {
@ -99,7 +100,7 @@ export default Controller.extend(ModalFunctionality, {
this._parseValue(this.seconds)
);
Topic.setSlowMode(this.model.id, seconds)
Topic.setSlowMode(this.model.id, seconds, this.enabledUntil)
.catch(popupAjaxError)
.then(() => {
this.set("model.slow_mode_seconds", seconds);

View File

@ -837,8 +837,10 @@ Topic.reopenClass({
return ajax(`/t/id_for/${slug}`);
},
setSlowMode(topicId, seconds) {
setSlowMode(topicId, seconds, enabledUntil) {
const data = { seconds };
data.enabled_until = enabledUntil;
return ajax(`/t/${topicId}/slow_mode`, { type: "PUT", data });
},
});

View File

@ -1,7 +1,7 @@
<div class="future-date-input">
{{#unless isBasedOnDuration}}
<div class="control-group">
<label>{{displayLabel}}</label>
<label class={{labelClasses}}>{{displayLabel}}</label>
{{future-date-input-selector
minimumResultsForSearch=-1
statusType=statusType

View File

@ -25,6 +25,18 @@
{{input value=seconds type="number" class="input-small"}}
</div>
{{/if}}
<div class="control-group">
{{future-date-input
class="enabled-until"
label="topic.slow_mode_update.enabled_until"
labelClasses="slow-mode-label"
includeFarFuture=false
clearable=true
input=enabledUntil
onChangeInput=(action (mut enabledUntil))
}}
</div>
{{/d-modal-body}}
<div class="modal-footer">

View File

@ -938,9 +938,20 @@ class TopicsController < ApplicationController
def set_slow_mode
topic = Topic.find(params[:topic_id])
slow_mode_type = TopicTimer.types[:clear_slow_mode]
timer = TopicTimer.find_by(topic: topic, status_type: slow_mode_type)
guardian.ensure_can_moderate!(topic)
topic.update!(slow_mode_seconds: params[:seconds])
enabled = params[:seconds].to_i > 0
time = enabled && params[:enabled_until].present? ? params[:enabled_until] : nil
topic.set_or_create_timer(
slow_mode_type,
time,
by_user: timer&.user
)
head :ok
end

View File

@ -0,0 +1,24 @@
# frozen_string_literal: true
module Jobs
class ClearSlowMode < ::Jobs::Base
def execute(args)
topic_timer = TopicTimer.find_by(id: args[:topic_timer_id] || args[:topic_status_update_id])
if topic_timer.nil? || topic_timer.execute_at > Time.zone.now
return
end
topic = topic_timer&.topic
if topic.nil?
topic_timer.destroy!
return
end
topic.update!(slow_mode_seconds: 0)
topic_timer.trash!(Discourse.system_user)
end
end
end

View File

@ -51,16 +51,17 @@ class TopicTimer < ActiveRecord::Base
reminder: 5,
bump: 6,
delete_replies: 7,
silent_close: 8
silent_close: 8,
clear_slow_mode: 9
)
end
def self.public_types
@_public_types ||= types.except(:reminder)
@_public_types ||= types.except(:reminder, :clear_slow_mode)
end
def self.private_types
@_private_types ||= types.only(:reminder)
@_private_types ||= types.only(:reminder, :clear_slow_mode)
end
def self.ensure_consistency!
@ -122,6 +123,10 @@ class TopicTimer < ActiveRecord::Base
Jobs.cancel_scheduled_job(:delete_replies, topic_timer_id: id)
end
def cancel_auto_clear_slow_mode_job
Jobs.cancel_scheduled_job(:clear_slow_mode, topic_timer_id: id)
end
def schedule_auto_delete_replies_job(time)
Jobs.enqueue_at(time, :delete_replies, topic_timer_id: id)
end
@ -173,6 +178,10 @@ class TopicTimer < ActiveRecord::Base
def schedule_auto_reminder_job(time)
# noop, TODO(martin 2021-03-11): Remove this after timers migrated and outstanding jobs cancelled
end
def schedule_auto_clear_slow_mode_job(time)
Jobs.enqueue_at(time, :clear_slow_mode, topic_timer_id: id)
end
end
# == Schema Information

View File

@ -2333,6 +2333,7 @@ en:
select: "Users may only post in this topic once every:"
description: "To promote thoughtful discussion in fast moving or contentious discussions, users must wait before posting again in this topic."
save: "Enable"
enabled_until: "(Optional) Enabled until:"
remove: "Disable"
hours: "Hours:"
minutes: "Minutes:"

View File

@ -3227,6 +3227,54 @@ RSpec.describe TopicsController do
expect(topic.slow_mode_seconds).to eq(3600)
end
end
context 'auto-disable slow mode' do
before { sign_in(admin) }
let(:timestamp) { 1.week.from_now.to_formatted_s(:iso8601) }
it 'sets a topic timer to clear the slow mode automatically' do
put "/t/#{topic.id}/slow_mode.json", params: {
seconds: '3600', enabled_until: timestamp
}
created_timer = TopicTimer.find_by(topic: topic)
execute_at = created_timer.execute_at.to_formatted_s(:iso8601)
expect(execute_at).to eq(timestamp)
end
it 'deletes the topic timer' do
put "/t/#{topic.id}/slow_mode.json", params: {
seconds: '3600', enabled_until: timestamp
}
put "/t/#{topic.id}/slow_mode.json", params: {
seconds: '0', enabled_until: timestamp
}
created_timer = TopicTimer.find_by(topic: topic)
expect(created_timer).to be_nil
end
it 'updates the existing timer' do
put "/t/#{topic.id}/slow_mode.json", params: {
seconds: '3600', enabled_until: timestamp
}
updated_timestamp = 1.hour.from_now.to_formatted_s(:iso8601)
put "/t/#{topic.id}/slow_mode.json", params: {
seconds: '3600', enabled_until: updated_timestamp
}
created_timer = TopicTimer.find_by(topic: topic)
execute_at = created_timer.execute_at.to_formatted_s(:iso8601)
expect(execute_at).to eq(updated_timestamp)
end
end
end
describe '#invite' do