From 9a24d2651dfd005df961ee56928af1ab84c5bbc9 Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Fri, 6 Dec 2013 16:39:35 -0500 Subject: [PATCH] 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. --- .../javascripts/discourse/models/category.js | 2 +- .../modal/edit_category.js.handlebars | 2 +- app/controllers/categories_controller.rb | 2 +- app/models/category.rb | 4 +-- app/models/topic.rb | 13 ++++----- app/models/topic_status_update.rb | 13 +++++++-- app/serializers/category_serializer.rb | 2 +- config/locales/client.en.yml | 2 +- config/locales/server.en.yml | 10 ++++++- ...6200009_rename_auto_close_days_to_hours.rb | 11 ++++++++ .../controllers/categories_controller_spec.rb | 8 +++--- spec/integration/topic_auto_close_spec.rb | 10 +++---- spec/models/category_spec.rb | 2 +- spec/models/topic_spec.rb | 28 +++++++++---------- 14 files changed, 68 insertions(+), 41 deletions(-) create mode 100644 db/migrate/20131206200009_rename_auto_close_days_to_hours.rb diff --git a/app/assets/javascripts/discourse/models/category.js b/app/assets/javascripts/discourse/models/category.js index 1ceac44edc0..81f2c5ac632 100644 --- a/app/assets/javascripts/discourse/models/category.js +++ b/app/assets/javascripts/discourse/models/category.js @@ -65,7 +65,7 @@ Discourse.Category = Discourse.Model.extend({ hotness: this.get('hotness'), secure: this.get('secure'), permissions: this.get('permissionsForUpdate'), - auto_close_days: this.get('auto_close_days'), + auto_close_hours: this.get('auto_close_hours'), position: this.get('position'), parent_category_id: this.get('parent_category_id') }, diff --git a/app/assets/javascripts/discourse/templates/modal/edit_category.js.handlebars b/app/assets/javascripts/discourse/templates/modal/edit_category.js.handlebars index 039f3cd32cb..32ba0ad98f3 100644 --- a/app/assets/javascripts/discourse/templates/modal/edit_category.js.handlebars +++ b/app/assets/javascripts/discourse/templates/modal/edit_category.js.handlebars @@ -92,7 +92,7 @@
{{i18n category.auto_close_label}} - {{textField value=auto_close_days}} + {{textField value=auto_close_hours}} {{i18n category.auto_close_units}}
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 6b0853a09b1..b62e7744cf9 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -90,7 +90,7 @@ class CategoriesController < ApplicationController 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 diff --git a/app/models/category.rb b/app/models/category.rb index 36b2e4f0d07..512070ab299 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -151,7 +151,7 @@ SQL 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.skip_callbacks = true - t.auto_close_days = nil + t.auto_close_hours = nil t.save! update_column(:topic_id, t.id) t.posts.create(raw: post_template, user: user) @@ -309,7 +309,7 @@ end # text_color :string(6) default("FFFFFF"), not null # hotness :float default(5.0), not null # read_restricted :boolean default(FALSE), not null -# auto_close_days :float +# auto_close_hours :float # post_count :integer default(0), not null # latest_post_id :integer # latest_topic_id :integer diff --git a/app/models/topic.rb b/app/models/topic.rb index 3112e197a91..f539e2eef0f 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -145,8 +145,8 @@ class Topic < ActiveRecord::Base before_create do self.bumped_at ||= Time.now 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? - set_auto_close(self.category.auto_close_days * 24) + 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_hours) end end @@ -268,8 +268,8 @@ class Topic < ActiveRecord::Base @post_numbers ||= posts.order(:post_number).pluck(:post_number) end - def age_in_days - ((Time.zone.now - created_at) / 1.day).round + def age_in_minutes + ((Time.zone.now - created_at) / 1.minute).round end def has_meta_data_boolean?(key) @@ -602,10 +602,9 @@ class Topic < ActiveRecord::Base end end - # TODO: change this method, along with category's auto_close_days. Use hours. - def auto_close_days=(num_days) + def auto_close_hours=(num_hours) @ignore_category_auto_close = true - set_auto_close( num_days ? num_days * 24 : nil) + set_auto_close( num_hours ) end def self.auto_close diff --git a/app/models/topic_status_update.rb b/app/models/topic_status_update.rb index 8f07cf53b79..f5113b2a93a 100644 --- a/app/models/topic_status_update.rb +++ b/app/models/topic_status_update.rb @@ -46,8 +46,17 @@ TopicStatusUpdate = Struct.new(:topic, :user) do def message_for(status) 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 - I18n.t status.locale_key, count: num_days + num_minutes = topic.auto_close_started_at ? ((Time.zone.now - topic.auto_close_started_at) / 1.minute).round : topic.age_in_minutes + 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 I18n.t status.locale_key end diff --git a/app/serializers/category_serializer.rb b/app/serializers/category_serializer.rb index 85f872404ad..1e0cbf70bae 100644 --- a/app/serializers/category_serializer.rb +++ b/app/serializers/category_serializer.rb @@ -1,6 +1,6 @@ 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 @group_permissions ||= begin diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 73ef1ec7a9b..3fea4b4ecfa 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -977,7 +977,7 @@ en: already_used: 'This color has been used by another category' security: "Security" auto_close_label: "Auto-close topics after:" - auto_close_units: "days" + auto_close_units: "hours" edit_permissions: "Edit Permissions" add_permission: "Add Permission" this_year: "this year" diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 29cc0e8d7bd..7b909a9e42b 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -772,10 +772,18 @@ en: 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_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." 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." + 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." 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." diff --git a/db/migrate/20131206200009_rename_auto_close_days_to_hours.rb b/db/migrate/20131206200009_rename_auto_close_days_to_hours.rb new file mode 100644 index 00000000000..6a1f550e84c --- /dev/null +++ b/db/migrate/20131206200009_rename_auto_close_days_to_hours.rb @@ -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 diff --git a/spec/controllers/categories_controller_spec.rb b/spec/controllers/categories_controller_spec.rb index fead81681ee..8af52341c92 100644 --- a/spec/controllers/categories_controller_spec.rb +++ b/spec/controllers/categories_controller_spec.rb @@ -51,7 +51,7 @@ describe CategoriesController do xhr :post, :create, name: "hello", color: "ff0", text_color: "fff", hotness: 2, - auto_close_days: 3, + auto_close_hours: 72, permissions: { "everyone" => readonly, "staff" => create_post @@ -65,7 +65,7 @@ describe CategoriesController do category.name.should == "hello" category.color.should == "ff0" category.hotness.should == 2 - category.auto_close_days.should == 3 + category.auto_close_hours.should == 72 end end end @@ -152,7 +152,7 @@ describe CategoriesController do xhr :put, :update, id: @category.id, name: "hello", color: "ff0", text_color: "fff", hotness: 2, - auto_close_days: 3, + auto_close_hours: 72, permissions: { "everyone" => readonly, "staff" => create_post @@ -166,7 +166,7 @@ describe CategoriesController do @category.name.should == "hello" @category.color.should == "ff0" @category.hotness.should == 2 - @category.auto_close_days.should == 3 + @category.auto_close_hours.should == 72 end end diff --git a/spec/integration/topic_auto_close_spec.rb b/spec/integration/topic_auto_close_spec.rb index 7ad05d921c2..9743363924a 100644 --- a/spec/integration/topic_auto_close_spec.rb +++ b/spec/integration/topic_auto_close_spec.rb @@ -34,7 +34,7 @@ describe Topic do end 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 } And { scheduled_jobs_for(:close_topic).should be_empty } end @@ -50,8 +50,8 @@ describe Topic do end context 'category has a default auto-close' do - Given(:category) { Fabricate(:category, auto_close_days: 2.0) } - Then { topic.auto_close_at.should == 2.days.from_now } + Given(:category) { Fabricate(:category, auto_close_hours: 2.0) } + 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 { 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 } @@ -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 } end - context 'auto_close_days of topic was set to 0' do - Given(:dont_close_topic) { Fabricate(:topic, auto_close_days: 0, category: category) } + context 'auto_close_hours of topic was set to 0' do + Given(:dont_close_topic) { Fabricate(:topic, auto_close_hours: 0, category: category) } Then { scheduled_jobs_for(:close_topic).should be_empty } end diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb index 0ad7272279e..24d93225953 100644 --- a/spec/models/category_spec.rb +++ b/spec/models/category_spec.rb @@ -211,7 +211,7 @@ describe Category do end 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 end diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index ba0944fc3f1..ab4e97f1d4c 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -554,7 +554,7 @@ describe Topic do it 'puts the autoclose duration in the moderator post' do @topic.created_at = 7.days.ago Timecop.freeze(2.days.ago) do - @topic.set_auto_close(2) + @topic.set_auto_close(48) end @topic.update_status(status, true, @user) 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 it 'queues a job to close the topic' 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) )) - Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin)) + 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_hours: 7, user: Fabricate(:admin)) end end @@ -942,7 +942,7 @@ describe Topic do Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args| job_args[:user_id] == topic_creator.id end - Fabricate(:topic, auto_close_days: 7, user: topic_creator) + Fabricate(:topic, auto_close_hours: 7, user: topic_creator) end 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| job_args[:user_id] == topic_closer.id 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 it "ignores the category's default auto-close" 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) )) - Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin), category_id: Fabricate(:category, auto_close_days: 2).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_hours: 7, user: Fabricate(:admin), category_id: Fabricate(:category, auto_close_hours: 2).id) end end it 'sets the time when auto_close timer starts' 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) end end @@ -1048,7 +1048,7 @@ describe Topic do Timecop.freeze(Time.zone.now) do mod = Fabricate(:moderator) # 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)) topic.auto_close_at = 12.hours.from_now topic.save @@ -1067,25 +1067,25 @@ describe Topic do end end - describe "auto_close_days=" do + describe "auto_close_hours=" do subject(:topic) { Fabricate.build(:topic) } it 'can take a number' do Timecop.freeze(Time.zone.now) do - topic.auto_close_days = 2 - topic.auto_close_at.should be_within_one_second_of(2.days.from_now) + topic.auto_close_hours = 2 + topic.auto_close_at.should be_within_one_second_of(2.hours.from_now) end end it 'can take nil' do - topic.auto_close_days = nil + topic.auto_close_hours = nil topic.auto_close_at.should be_nil end end describe 'set_auto_close' do 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) } before { Discourse.stubs(:system_user).returns(admin) }