From ed8b0103f63f1fdc788f8d404de24c6c1b8350db Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Mon, 22 May 2017 17:09:40 +0800 Subject: [PATCH] FEATURE: Add `solved_topics_auto_close_hours` site setting. https://meta.discourse.org/t/automatically-close-solved-topics-after-n-hours/58383 --- config/locales/server.en.yml | 1 + config/settings.yml | 3 ++- plugin.rb | 24 +++++++++++++++++------- spec/integration/solved_spec.rb | 31 +++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 spec/integration/solved_spec.rb diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index d8b809b..25ccf27 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -5,6 +5,7 @@ en: accept_all_solutions_trust_level: "Minimum trust level required to accept solutions on any topic (even when not OP)" empty_box_on_unsolved: "Display an empty box next to unsolved topics" solved_quote_length: "Number of characters to quote when displaying the solution under the first post" + solved_topics_auto_close_hours: "Auto close topic (n) hours after the last reply once the topic has been marked as solved" reports: accepted_solutions: title: "Accepted solutions" diff --git a/config/settings.yml b/config/settings.yml index 7730ad3..da6d43e 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -14,4 +14,5 @@ plugins: solved_quote_length: default: 300 client: false - + solved_topics_auto_close_hours: + default: 0 diff --git a/plugin.rb b/plugin.rb index ccc7e15..6db948e 100644 --- a/plugin.rb +++ b/plugin.rb @@ -65,10 +65,11 @@ SQL limit_accepts post = Post.find(params[:id].to_i) + topic = post.topic - guardian.ensure_can_accept_answer!(post.topic) + guardian.ensure_can_accept_answer!(topic) - accepted_id = post.topic.custom_fields["accepted_answer_post_id"].to_i + accepted_id = topic.custom_fields["accepted_answer_post_id"].to_i if accepted_id > 0 if p2 = Post.find_by(id: accepted_id) p2.custom_fields["is_accepted_answer"] = nil @@ -81,8 +82,8 @@ SQL end post.custom_fields["is_accepted_answer"] = "true" - post.topic.custom_fields["accepted_answer_post_id"] = post.id - post.topic.save! + topic.custom_fields["accepted_answer_post_id"] = post.id + topic.save! post.save! if defined?(UserAction::SOLVED) @@ -102,13 +103,22 @@ SQL data: { message: 'solved.accepted_notification', display_username: current_user.username, - topic_title: post.topic.title + topic_title: topic.title }.to_json ) end - DiscourseEvent.trigger(:accepted_solution, post) + if (auto_close_hours = SiteSetting.solved_topics_auto_close_hours) > 0 + topic.set_or_create_timer( + TopicTimer.types[:close], + auto_close_hours, + based_on_last_post: true + ) + MessageBus.publish("/topic/#{topic.id}", reload_topic: true) + end + + DiscourseEvent.trigger(:accepted_solution, post) render json: success_json end @@ -236,7 +246,7 @@ SQL .joins(:user) .pluck('post_number', 'username', 'cooked') .first - + if postInfo postInfo[2] = PrettyText.excerpt(postInfo[2], SiteSetting.solved_quote_length) return postInfo diff --git a/spec/integration/solved_spec.rb b/spec/integration/solved_spec.rb new file mode 100644 index 0000000..73891e8 --- /dev/null +++ b/spec/integration/solved_spec.rb @@ -0,0 +1,31 @@ +require 'rails_helper' + +RSpec.describe "Managing Posts solved status" do + let(:topic) { Fabricate(:topic) } + let(:user) { Fabricate(:trust_level_4) } + let(:p1) { Fabricate(:post, topic: topic) } + + before do + SiteSetting.allow_solved_on_all_topics = true + end + + describe 'accepting a post as the answer' do + before do + sign_in(user) + SiteSetting.solved_topics_auto_close_hours = 2 + end + + it 'can mark a post as the accepted answer correctly' do + xhr :post, "/solution/accept", id: p1.id + + expect(p1.reload.custom_fields["is_accepted_answer"]).to eq("true") + + expect(topic.public_topic_timer.status_type).to eq(TopicTimer.types[:close]) + + expect(topic.public_topic_timer.execute_at) + .to be_within(1.second).of(Time.zone.now + 2.hours) + + expect(topic.public_topic_timer.based_on_last_post).to eq(true) + end + end +end