Allow category to auto-close topics in X hours instead of days. FIX: the system message that says a topic was automatically closed was only counting in days.
This commit is contained in:
parent
ec26063fdc
commit
9a24d2651d
|
@ -65,7 +65,7 @@ Discourse.Category = Discourse.Model.extend({
|
||||||
hotness: this.get('hotness'),
|
hotness: this.get('hotness'),
|
||||||
secure: this.get('secure'),
|
secure: this.get('secure'),
|
||||||
permissions: this.get('permissionsForUpdate'),
|
permissions: this.get('permissionsForUpdate'),
|
||||||
auto_close_days: this.get('auto_close_days'),
|
auto_close_hours: this.get('auto_close_hours'),
|
||||||
position: this.get('position'),
|
position: this.get('position'),
|
||||||
parent_category_id: this.get('parent_category_id')
|
parent_category_id: this.get('parent_category_id')
|
||||||
},
|
},
|
||||||
|
|
|
@ -92,7 +92,7 @@
|
||||||
<div>
|
<div>
|
||||||
<i class="icon icon-time"></i>
|
<i class="icon icon-time"></i>
|
||||||
{{i18n category.auto_close_label}}
|
{{i18n category.auto_close_label}}
|
||||||
{{textField value=auto_close_days}}
|
{{textField value=auto_close_hours}}
|
||||||
{{i18n category.auto_close_units}}
|
{{i18n category.auto_close_units}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -90,7 +90,7 @@ class CategoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
params.permit(*required_param_keys, :position, :hotness, :parent_category_id, :auto_close_days, :permissions => [*p.try(:keys)])
|
params.permit(*required_param_keys, :position, :hotness, :parent_category_id, :auto_close_hours, :permissions => [*p.try(:keys)])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ SQL
|
||||||
def create_category_definition
|
def create_category_definition
|
||||||
t = Topic.new(title: I18n.t("category.topic_prefix", category: name), user: user, pinned_at: Time.now, category_id: id)
|
t = Topic.new(title: I18n.t("category.topic_prefix", category: name), user: user, pinned_at: Time.now, category_id: id)
|
||||||
t.skip_callbacks = true
|
t.skip_callbacks = true
|
||||||
t.auto_close_days = nil
|
t.auto_close_hours = nil
|
||||||
t.save!
|
t.save!
|
||||||
update_column(:topic_id, t.id)
|
update_column(:topic_id, t.id)
|
||||||
t.posts.create(raw: post_template, user: user)
|
t.posts.create(raw: post_template, user: user)
|
||||||
|
@ -309,7 +309,7 @@ end
|
||||||
# text_color :string(6) default("FFFFFF"), not null
|
# text_color :string(6) default("FFFFFF"), not null
|
||||||
# hotness :float default(5.0), not null
|
# hotness :float default(5.0), not null
|
||||||
# read_restricted :boolean default(FALSE), not null
|
# read_restricted :boolean default(FALSE), not null
|
||||||
# auto_close_days :float
|
# auto_close_hours :float
|
||||||
# post_count :integer default(0), not null
|
# post_count :integer default(0), not null
|
||||||
# latest_post_id :integer
|
# latest_post_id :integer
|
||||||
# latest_topic_id :integer
|
# latest_topic_id :integer
|
||||||
|
|
|
@ -145,8 +145,8 @@ class Topic < ActiveRecord::Base
|
||||||
before_create do
|
before_create do
|
||||||
self.bumped_at ||= Time.now
|
self.bumped_at ||= Time.now
|
||||||
self.last_post_user_id ||= user_id
|
self.last_post_user_id ||= user_id
|
||||||
if !@ignore_category_auto_close and self.category and self.category.auto_close_days and self.auto_close_at.nil?
|
if !@ignore_category_auto_close and self.category and self.category.auto_close_hours and self.auto_close_at.nil?
|
||||||
set_auto_close(self.category.auto_close_days * 24)
|
set_auto_close(self.category.auto_close_hours)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -268,8 +268,8 @@ class Topic < ActiveRecord::Base
|
||||||
@post_numbers ||= posts.order(:post_number).pluck(:post_number)
|
@post_numbers ||= posts.order(:post_number).pluck(:post_number)
|
||||||
end
|
end
|
||||||
|
|
||||||
def age_in_days
|
def age_in_minutes
|
||||||
((Time.zone.now - created_at) / 1.day).round
|
((Time.zone.now - created_at) / 1.minute).round
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_meta_data_boolean?(key)
|
def has_meta_data_boolean?(key)
|
||||||
|
@ -602,10 +602,9 @@ class Topic < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: change this method, along with category's auto_close_days. Use hours.
|
def auto_close_hours=(num_hours)
|
||||||
def auto_close_days=(num_days)
|
|
||||||
@ignore_category_auto_close = true
|
@ignore_category_auto_close = true
|
||||||
set_auto_close( num_days ? num_days * 24 : nil)
|
set_auto_close( num_hours )
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.auto_close
|
def self.auto_close
|
||||||
|
|
|
@ -46,8 +46,17 @@ TopicStatusUpdate = Struct.new(:topic, :user) do
|
||||||
|
|
||||||
def message_for(status)
|
def message_for(status)
|
||||||
if status.autoclosed?
|
if status.autoclosed?
|
||||||
num_days = topic.auto_close_started_at ? ((Time.zone.now - topic.auto_close_started_at) / 1.day).round : topic.age_in_days
|
num_minutes = topic.auto_close_started_at ? ((Time.zone.now - topic.auto_close_started_at) / 1.minute).round : topic.age_in_minutes
|
||||||
I18n.t status.locale_key, count: num_days
|
if num_minutes.minutes >= 2.days
|
||||||
|
I18n.t "#{status.locale_key}_days", count: (num_minutes.minutes / 1.day).round
|
||||||
|
else
|
||||||
|
num_hours = (num_minutes.minutes / 1.hour).round
|
||||||
|
if num_hours >= 2
|
||||||
|
I18n.t "#{status.locale_key}_hours", count: num_hours
|
||||||
|
else
|
||||||
|
I18n.t "#{status.locale_key}_minutes", count: num_minutes
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
I18n.t status.locale_key
|
I18n.t status.locale_key
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class CategorySerializer < BasicCategorySerializer
|
class CategorySerializer < BasicCategorySerializer
|
||||||
|
|
||||||
attributes :read_restricted, :available_groups, :auto_close_days, :group_permissions, :position
|
attributes :read_restricted, :available_groups, :auto_close_hours, :group_permissions, :position
|
||||||
|
|
||||||
def group_permissions
|
def group_permissions
|
||||||
@group_permissions ||= begin
|
@group_permissions ||= begin
|
||||||
|
|
|
@ -977,7 +977,7 @@ en:
|
||||||
already_used: 'This color has been used by another category'
|
already_used: 'This color has been used by another category'
|
||||||
security: "Security"
|
security: "Security"
|
||||||
auto_close_label: "Auto-close topics after:"
|
auto_close_label: "Auto-close topics after:"
|
||||||
auto_close_units: "days"
|
auto_close_units: "hours"
|
||||||
edit_permissions: "Edit Permissions"
|
edit_permissions: "Edit Permissions"
|
||||||
add_permission: "Add Permission"
|
add_permission: "Add Permission"
|
||||||
this_year: "this year"
|
this_year: "this year"
|
||||||
|
|
|
@ -772,10 +772,18 @@ en:
|
||||||
archived_disabled: "This topic is now unarchived. It is no longer frozen, and can be changed."
|
archived_disabled: "This topic is now unarchived. It is no longer frozen, and can be changed."
|
||||||
closed_enabled: "This topic is now closed. New replies are no longer allowed."
|
closed_enabled: "This topic is now closed. New replies are no longer allowed."
|
||||||
closed_disabled: "This topic is now opened. New replies are allowed."
|
closed_disabled: "This topic is now opened. New replies are allowed."
|
||||||
autoclosed_enabled:
|
autoclosed_enabled_days:
|
||||||
zero: "This topic was automatically closed after 1 day. New replies are no longer allowed."
|
zero: "This topic was automatically closed after 1 day. New replies are no longer allowed."
|
||||||
one: "This topic was automatically closed after 1 day. New replies are no longer allowed."
|
one: "This topic was automatically closed after 1 day. New replies are no longer allowed."
|
||||||
other: "This topic was automatically closed after %{count} days. New replies are no longer allowed."
|
other: "This topic was automatically closed after %{count} days. New replies are no longer allowed."
|
||||||
|
autoclosed_enabled_hours:
|
||||||
|
zero: "This topic was automatically closed after 1 hour. New replies are no longer allowed."
|
||||||
|
one: "This topic was automatically closed after 1 hour. New replies are no longer allowed."
|
||||||
|
other: "This topic was automatically closed after %{count} hours. New replies are no longer allowed."
|
||||||
|
autoclosed_enabled_minutes:
|
||||||
|
zero: "This topic was automatically closed after 1 minute. New replies are no longer allowed."
|
||||||
|
one: "This topic was automatically closed after 1 minute. New replies are no longer allowed."
|
||||||
|
other: "This topic was automatically closed after %{count} minutes. New replies are no longer allowed."
|
||||||
autoclosed_disabled: "This topic is now opened. New replies are allowed."
|
autoclosed_disabled: "This topic is now opened. New replies are allowed."
|
||||||
pinned_enabled: "This topic is now pinned. It will appear at the top of its category until it is either unpinned by a moderator, or the Clear Pin button is pressed."
|
pinned_enabled: "This topic is now pinned. It will appear at the top of its category until it is either unpinned by a moderator, or the Clear Pin button is pressed."
|
||||||
pinned_disabled: "This topic is now unpinned. It will no longer appear at the top of its category."
|
pinned_disabled: "This topic is now unpinned. It will no longer appear at the top of its category."
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
class RenameAutoCloseDaysToHours < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
rename_column :categories, :auto_close_days, :auto_close_hours
|
||||||
|
execute "update categories set auto_close_hours = auto_close_hours * 24"
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
rename_column :categories, :auto_close_hours, :auto_close_days
|
||||||
|
execute "update categories set auto_close_days = auto_close_days / 24"
|
||||||
|
end
|
||||||
|
end
|
|
@ -51,7 +51,7 @@ describe CategoriesController do
|
||||||
|
|
||||||
xhr :post, :create, name: "hello", color: "ff0", text_color: "fff",
|
xhr :post, :create, name: "hello", color: "ff0", text_color: "fff",
|
||||||
hotness: 2,
|
hotness: 2,
|
||||||
auto_close_days: 3,
|
auto_close_hours: 72,
|
||||||
permissions: {
|
permissions: {
|
||||||
"everyone" => readonly,
|
"everyone" => readonly,
|
||||||
"staff" => create_post
|
"staff" => create_post
|
||||||
|
@ -65,7 +65,7 @@ describe CategoriesController do
|
||||||
category.name.should == "hello"
|
category.name.should == "hello"
|
||||||
category.color.should == "ff0"
|
category.color.should == "ff0"
|
||||||
category.hotness.should == 2
|
category.hotness.should == 2
|
||||||
category.auto_close_days.should == 3
|
category.auto_close_hours.should == 72
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -152,7 +152,7 @@ describe CategoriesController do
|
||||||
|
|
||||||
xhr :put, :update, id: @category.id, name: "hello", color: "ff0", text_color: "fff",
|
xhr :put, :update, id: @category.id, name: "hello", color: "ff0", text_color: "fff",
|
||||||
hotness: 2,
|
hotness: 2,
|
||||||
auto_close_days: 3,
|
auto_close_hours: 72,
|
||||||
permissions: {
|
permissions: {
|
||||||
"everyone" => readonly,
|
"everyone" => readonly,
|
||||||
"staff" => create_post
|
"staff" => create_post
|
||||||
|
@ -166,7 +166,7 @@ describe CategoriesController do
|
||||||
@category.name.should == "hello"
|
@category.name.should == "hello"
|
||||||
@category.color.should == "ff0"
|
@category.color.should == "ff0"
|
||||||
@category.hotness.should == 2
|
@category.hotness.should == 2
|
||||||
@category.auto_close_days.should == 3
|
@category.auto_close_hours.should == 72
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,7 @@ describe Topic do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'category without default auto-close' do
|
context 'category without default auto-close' do
|
||||||
Given(:category) { Fabricate(:category, auto_close_days: nil) }
|
Given(:category) { Fabricate(:category, auto_close_hours: nil) }
|
||||||
Then { topic.auto_close_at.should be_nil }
|
Then { topic.auto_close_at.should be_nil }
|
||||||
And { scheduled_jobs_for(:close_topic).should be_empty }
|
And { scheduled_jobs_for(:close_topic).should be_empty }
|
||||||
end
|
end
|
||||||
|
@ -50,8 +50,8 @@ describe Topic do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'category has a default auto-close' do
|
context 'category has a default auto-close' do
|
||||||
Given(:category) { Fabricate(:category, auto_close_days: 2.0) }
|
Given(:category) { Fabricate(:category, auto_close_hours: 2.0) }
|
||||||
Then { topic.auto_close_at.should == 2.days.from_now }
|
Then { topic.auto_close_at.should be_within_one_second_of(2.hours.from_now) }
|
||||||
And { topic.auto_close_started_at.should == Time.zone.now }
|
And { topic.auto_close_started_at.should == Time.zone.now }
|
||||||
And { scheduled_jobs_for(:close_topic, {topic_id: topic.id}).should have(1).job }
|
And { scheduled_jobs_for(:close_topic, {topic_id: topic.id}).should have(1).job }
|
||||||
And { scheduled_jobs_for(:close_topic, {topic_id: category.topic.id}).should be_empty }
|
And { scheduled_jobs_for(:close_topic, {topic_id: category.topic.id}).should be_empty }
|
||||||
|
@ -76,8 +76,8 @@ describe Topic do
|
||||||
Then { scheduled_jobs_for(:close_topic, {topic_id: regular_user_topic.id, user_id: system_user.id}).should have(1).job }
|
Then { scheduled_jobs_for(:close_topic, {topic_id: regular_user_topic.id, user_id: system_user.id}).should have(1).job }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'auto_close_days of topic was set to 0' do
|
context 'auto_close_hours of topic was set to 0' do
|
||||||
Given(:dont_close_topic) { Fabricate(:topic, auto_close_days: 0, category: category) }
|
Given(:dont_close_topic) { Fabricate(:topic, auto_close_hours: 0, category: category) }
|
||||||
Then { scheduled_jobs_for(:close_topic).should be_empty }
|
Then { scheduled_jobs_for(:close_topic).should be_empty }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ describe Category do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not set its description topic to auto-close" do
|
it "should not set its description topic to auto-close" do
|
||||||
category = Fabricate(:category, name: 'Closing Topics', auto_close_days: 1)
|
category = Fabricate(:category, name: 'Closing Topics', auto_close_hours: 1)
|
||||||
category.topic.auto_close_at.should be_nil
|
category.topic.auto_close_at.should be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -554,7 +554,7 @@ describe Topic do
|
||||||
it 'puts the autoclose duration in the moderator post' do
|
it 'puts the autoclose duration in the moderator post' do
|
||||||
@topic.created_at = 7.days.ago
|
@topic.created_at = 7.days.ago
|
||||||
Timecop.freeze(2.days.ago) do
|
Timecop.freeze(2.days.ago) do
|
||||||
@topic.set_auto_close(2)
|
@topic.set_auto_close(48)
|
||||||
end
|
end
|
||||||
@topic.update_status(status, true, @user)
|
@topic.update_status(status, true, @user)
|
||||||
expect(@topic.posts.last.raw).to include "closed after 2 days"
|
expect(@topic.posts.last.raw).to include "closed after 2 days"
|
||||||
|
@ -932,8 +932,8 @@ describe Topic do
|
||||||
context 'auto_close_at is set' do
|
context 'auto_close_at is set' do
|
||||||
it 'queues a job to close the topic' do
|
it 'queues a job to close the topic' do
|
||||||
Timecop.freeze(Time.zone.now) do
|
Timecop.freeze(Time.zone.now) do
|
||||||
Jobs.expects(:enqueue_at).with(7.days.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) ))
|
Jobs.expects(:enqueue_at).with(7.hours.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) ))
|
||||||
Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin))
|
Fabricate(:topic, auto_close_hours: 7, user: Fabricate(:admin))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -942,7 +942,7 @@ describe Topic do
|
||||||
Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args|
|
Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args|
|
||||||
job_args[:user_id] == topic_creator.id
|
job_args[:user_id] == topic_creator.id
|
||||||
end
|
end
|
||||||
Fabricate(:topic, auto_close_days: 7, user: topic_creator)
|
Fabricate(:topic, auto_close_hours: 7, user: topic_creator)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'when auto_close_user_id is set, it will use it as the topic closer' do
|
it 'when auto_close_user_id is set, it will use it as the topic closer' do
|
||||||
|
@ -951,19 +951,19 @@ describe Topic do
|
||||||
Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args|
|
Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args|
|
||||||
job_args[:user_id] == topic_closer.id
|
job_args[:user_id] == topic_closer.id
|
||||||
end
|
end
|
||||||
Fabricate(:topic, auto_close_days: 7, auto_close_user: topic_closer, user: topic_creator)
|
Fabricate(:topic, auto_close_hours: 7, auto_close_user: topic_closer, user: topic_creator)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "ignores the category's default auto-close" do
|
it "ignores the category's default auto-close" do
|
||||||
Timecop.freeze(Time.zone.now) do
|
Timecop.freeze(Time.zone.now) do
|
||||||
Jobs.expects(:enqueue_at).with(7.days.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) ))
|
Jobs.expects(:enqueue_at).with(7.hours.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) ))
|
||||||
Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin), category_id: Fabricate(:category, auto_close_days: 2).id)
|
Fabricate(:topic, auto_close_hours: 7, user: Fabricate(:admin), category_id: Fabricate(:category, auto_close_hours: 2).id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the time when auto_close timer starts' do
|
it 'sets the time when auto_close timer starts' do
|
||||||
Timecop.freeze(Time.zone.now) do
|
Timecop.freeze(Time.zone.now) do
|
||||||
topic = Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin))
|
topic = Fabricate(:topic, auto_close_hours: 7, user: Fabricate(:admin))
|
||||||
expect(topic.auto_close_started_at).to eq(Time.zone.now)
|
expect(topic.auto_close_started_at).to eq(Time.zone.now)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1048,7 +1048,7 @@ describe Topic do
|
||||||
Timecop.freeze(Time.zone.now) do
|
Timecop.freeze(Time.zone.now) do
|
||||||
mod = Fabricate(:moderator)
|
mod = Fabricate(:moderator)
|
||||||
# NOTE, only moderators can auto-close, if missing system user is used
|
# NOTE, only moderators can auto-close, if missing system user is used
|
||||||
topic = Fabricate(:topic, category: Fabricate(:category, auto_close_days: 14), user: mod)
|
topic = Fabricate(:topic, category: Fabricate(:category, auto_close_hours: 14), user: mod)
|
||||||
Jobs.expects(:enqueue_at).with(12.hours.from_now, :close_topic, has_entries(topic_id: topic.id, user_id: topic.user_id))
|
Jobs.expects(:enqueue_at).with(12.hours.from_now, :close_topic, has_entries(topic_id: topic.id, user_id: topic.user_id))
|
||||||
topic.auto_close_at = 12.hours.from_now
|
topic.auto_close_at = 12.hours.from_now
|
||||||
topic.save
|
topic.save
|
||||||
|
@ -1067,25 +1067,25 @@ describe Topic do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "auto_close_days=" do
|
describe "auto_close_hours=" do
|
||||||
subject(:topic) { Fabricate.build(:topic) }
|
subject(:topic) { Fabricate.build(:topic) }
|
||||||
|
|
||||||
it 'can take a number' do
|
it 'can take a number' do
|
||||||
Timecop.freeze(Time.zone.now) do
|
Timecop.freeze(Time.zone.now) do
|
||||||
topic.auto_close_days = 2
|
topic.auto_close_hours = 2
|
||||||
topic.auto_close_at.should be_within_one_second_of(2.days.from_now)
|
topic.auto_close_at.should be_within_one_second_of(2.hours.from_now)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'can take nil' do
|
it 'can take nil' do
|
||||||
topic.auto_close_days = nil
|
topic.auto_close_hours = nil
|
||||||
topic.auto_close_at.should be_nil
|
topic.auto_close_at.should be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'set_auto_close' do
|
describe 'set_auto_close' do
|
||||||
let(:topic) { Fabricate.build(:topic) }
|
let(:topic) { Fabricate.build(:topic) }
|
||||||
let(:closing_topic) { Fabricate.build(:topic, auto_close_days: 5) }
|
let(:closing_topic) { Fabricate.build(:topic, auto_close_hours: 5) }
|
||||||
let(:admin) { Fabricate.build(:user, id: 123) }
|
let(:admin) { Fabricate.build(:user, id: 123) }
|
||||||
|
|
||||||
before { Discourse.stubs(:system_user).returns(admin) }
|
before { Discourse.stubs(:system_user).returns(admin) }
|
||||||
|
|
Loading…
Reference in New Issue