diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 697ee04..2eb4fe6 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1,4 +1,6 @@ en: + accepted_answer: "Accepted Answer" + site_settings: solved_enabled: "Enable solved plugin, allow users to select solutions for topics" allow_solved_on_all_topics: "Allow users to select solutions on all topics (by default you control this by editing categories)" diff --git a/plugin.rb b/plugin.rb index 11e99b2..491ed9f 100644 --- a/plugin.rb +++ b/plugin.rb @@ -686,4 +686,49 @@ SQL body: PrettyText.cook(I18n.t('education.topic_is_solved', base_url: Discourse.base_url)) } end + + class ::Topic + attr_accessor :accepted_answer_user_id + end + + register_topic_list_preload_user_ids do |topics, user_ids, topic_list| + Topic.preload_custom_fields(topics, ['accepted_answer_post_id']) + answer_post_ids = topics.map { |t| t.custom_fields['accepted_answer_post_id'] }.uniq.compact + answer_user_ids = Post.where(id: answer_post_ids).pluck(:topic_id, :user_id).to_h + topics.each { |topic| topic.accepted_answer_user_id = answer_user_ids[topic.id] } + user_ids.concat(answer_user_ids.values) + end + + module AddSolvedToTopicPostersSummary + def descriptions_by_id + if !defined? @descriptions_by_id + super(ids: old_user_ids) + + if id = topic.accepted_answer_user_id + @descriptions_by_id[id] ||= [] + @descriptions_by_id[id] << I18n.t(:accepted_answer) + end + end + + super + end + + def last_poster_is_topic_creator? + super || topic.accepted_answer_user_id == topic.last_post_user_id + end + + def user_ids + if id = topic.accepted_answer_user_id + super.insert(1, id) + else + super + end + end + end + + TopicPostersSummary.class_eval do + alias :old_user_ids :user_ids + + prepend AddSolvedToTopicPostersSummary + end end diff --git a/spec/requests/list_controller_spec.rb b/spec/requests/list_controller_spec.rb new file mode 100644 index 0000000..c3803c6 --- /dev/null +++ b/spec/requests/list_controller_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ListController do + fab!(:p1) { Fabricate(:post) } + fab!(:p2) { Fabricate(:post, topic: p1.topic) } + fab!(:p3) { Fabricate(:post, topic: p1.topic) } + + before do + SiteSetting.allow_solved_on_all_topics = true + end + + it 'shows the user who posted the accepted answer second' do + TopicFeaturedUsers.ensure_consistency! + DiscourseSolved.accept_answer!(p3, p1.user, topic: p1.topic) + + get '/latest.json' + posters = response.parsed_body["topic_list"]["topics"].first["posters"] + expect(posters[0]["user_id"]).to eq(p1.user_id) + expect(posters[1]["user_id"]).to eq(p3.user_id) + expect(posters[1]["description"]).to include("Accepted Answer") + expect(posters[2]["user_id"]).to eq(p2.user_id) + end +end