From 06f6d00ba12704d23ab70ab3631a254cdfad4eba Mon Sep 17 00:00:00 2001 From: Jordan Vidrine <30537603+jordanvidrine@users.noreply.github.com> Date: Thu, 15 Jun 2023 12:44:44 -0500 Subject: [PATCH] FEATURE: Use the same structure as core topic-list-item and add topic excerpts to docs index (#140) * FEATURE: Optionally show topic excerpts in docs index This commit adds a new docs_show_topic_excerpts site setting which, when enabled and used in conjunction either with the always_include_topic_excerpts site setting or the serialize_topic_excerpts theme modifier. For the theme modifier, this commit also fixes an issue with the Docs::Query class. Since we were re-initializing Guardian within the class (rather than using the guardian passed down from the controller), we did not have the request information needed to determine theme_id, which meant that the theme modifier had no effect. We now pass down guardian from the controller instead. In general guardian is almost always better than a user object, since we can always just call guardian.user. Adds a simple system spec as well. --- We now check both the serialize_topic_excerpts theme modifier and the always_include_topic_excerpts site setting server-side within Docs::Query, and use that on the client to determine whether or not to show the excerpts for docs. This is because if someone sets one of those values it's logical to think it will apply everywhere there is a topic list. Also include a system spec to test whether the theme modifier works to show the excerpts. --------- Co-authored-by: Martin Brennan --- app/controllers/docs/docs_controller.rb | 2 +- .../components/docs-topic-list-item.js | 24 ++++++++ .../discourse/controllers/docs-index.js | 2 + .../components/docs-topic-list-item.hbs | 1 + .../templates/components/docs-topic-list.hbs | 6 +- .../discourse/templates/docs-index.hbs | 13 ++++- .../templates/docs-topic-list-item.hbr | 34 ++++++----- lib/docs/query.rb | 18 ++++-- spec/system/docs_index_spec.rb | 57 +++++++++++++++++++ 9 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 assets/javascripts/discourse/components/docs-topic-list-item.js create mode 100644 assets/javascripts/discourse/templates/components/docs-topic-list-item.hbs create mode 100644 spec/system/docs_index_spec.rb diff --git a/app/controllers/docs/docs_controller.rb b/app/controllers/docs/docs_controller.rb index 50aa76e..4f261fa 100644 --- a/app/controllers/docs/docs_controller.rb +++ b/app/controllers/docs/docs_controller.rb @@ -18,7 +18,7 @@ module Docs page: params[:page], } - query = Docs::Query.new(current_user, filters).list + query = Docs::Query.new(guardian, filters).list if filters[:topic].present? begin diff --git a/assets/javascripts/discourse/components/docs-topic-list-item.js b/assets/javascripts/discourse/components/docs-topic-list-item.js new file mode 100644 index 0000000..327ec72 --- /dev/null +++ b/assets/javascripts/discourse/components/docs-topic-list-item.js @@ -0,0 +1,24 @@ +import Component from "@ember/component"; +import { RUNTIME_OPTIONS } from "discourse-common/lib/raw-handlebars-helpers"; +import { findRawTemplate } from "discourse-common/lib/raw-templates"; +import { htmlSafe } from "@ember/template"; + +export default Component.extend({ + tagName: "tr", + classNameBindings: [":topic-list-item"], + + didInsertElement() { + this._super(...arguments); + this.renderTopicListItem(); + }, + + renderTopicListItem() { + const template = findRawTemplate("docs-topic-list-item"); + if (template) { + this.set( + "topicListItemContents", + htmlSafe(template(this, RUNTIME_OPTIONS)) + ); + } + }, +}); diff --git a/assets/javascripts/discourse/controllers/docs-index.js b/assets/javascripts/discourse/controllers/docs-index.js index 39fe0cd..69985ba 100644 --- a/assets/javascripts/discourse/controllers/docs-index.js +++ b/assets/javascripts/discourse/controllers/docs-index.js @@ -48,6 +48,7 @@ export default Controller.extend({ categories: readOnly("model.categories"), topics: alias("model.topics.topic_list.topics"), tags: readOnly("model.tags"), + showExcerpts: readOnly("model.meta.show_topic_excerpts"), tagGroups: readOnly("model.tag_groups"), topicCount: alias("model.topic_count"), emptyResults: equal("topicCount", 0), @@ -68,6 +69,7 @@ export default Controller.extend({ }, }); }, + @discourseComputed("categories", "categorySort", "categoryFilter") sortedCategories(categories, categorySort, filter) { let { type, direction } = categorySort; diff --git a/assets/javascripts/discourse/templates/components/docs-topic-list-item.hbs b/assets/javascripts/discourse/templates/components/docs-topic-list-item.hbs new file mode 100644 index 0000000..87721b9 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/docs-topic-list-item.hbs @@ -0,0 +1 @@ +{{this.topicListItemContents}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/docs-topic-list.hbs b/assets/javascripts/discourse/templates/components/docs-topic-list.hbs index 4b50238..0945f3f 100644 --- a/assets/javascripts/discourse/templates/components/docs-topic-list.hbs +++ b/assets/javascripts/discourse/templates/components/docs-topic-list.hbs @@ -28,7 +28,11 @@ {{#each topics as |topic|}} - {{raw "docs-topic-list-item" topic=topic urlPath=urlPath}} + {{docs-topic-list-item + topic=topic + urlPath=urlPath + showExcerpt=showExcerpts + }} {{/each}} diff --git a/assets/javascripts/discourse/templates/docs-index.hbs b/assets/javascripts/discourse/templates/docs-index.hbs index 46e4003..cd82aa7 100644 --- a/assets/javascripts/discourse/templates/docs-index.hbs +++ b/assets/javascripts/discourse/templates/docs-index.hbs @@ -36,7 +36,9 @@ {{#if categories}}
-

{{i18n "docs.categories"}}

+

+ {{i18n "docs.categories"}} +

-

{{i18n "docs.tags"}}

+

+ {{i18n "docs.tags"}} +

-

{{i18n "docs.tags"}}

+

+ {{i18n "docs.tags"}} +

- - - {{~raw "topic-status" topic=topic}} - {{~raw "docs-topic-link" topic=topic urlPath=urlPath}} - - - {{category-link topic.category}} - {{discourse-tags topic mode="list"}} - - - - {{format-date topic.bumped_at format="tiny" noTitle="true"}} - - +{{~raw-plugin-outlet name="topic-list-before-columns"}} + + + {{~raw-plugin-outlet name="topic-list-before-link"}} + + {{~raw "topic-status" topic=topic}} + {{~raw "docs-topic-link" topic=topic urlPath=urlPath}} + + + {{category-link topic.category}} + {{discourse-tags topic mode="list"}} + + {{!-- {{#if showExcerpt}} --}} + {{~raw "list/topic-excerpt" topic=topic}} + {{!-- {{/if}} --}} + + + {{format-date topic.bumped_at format="tiny" noTitle="true"}} + \ No newline at end of file diff --git a/lib/docs/query.rb b/lib/docs/query.rb index e86b982..32b644c 100644 --- a/lib/docs/query.rb +++ b/lib/docs/query.rb @@ -2,8 +2,8 @@ module Docs class Query - def initialize(user = nil, filters = {}) - @user = user + def initialize(guardian, filters = {}) + @guardian = guardian @filters = filters @limit = 30 end @@ -19,7 +19,7 @@ module Docs def list # query for topics matching selected categories & tags opts = { no_definitions: true, limit: false } - tq = TopicQuery.new(@user, opts) + tq = TopicQuery.new(@guardian.user, opts) results = tq.list_docs_topics results = results.left_outer_joins(SiteSetting.show_tags_by_group ? { tags: :tag_groups } : :tags) @@ -155,7 +155,7 @@ module Docs # assemble the object topic_query = tq.create_list(:docs, { unordered: true }, results) - topic_list = TopicListSerializer.new(topic_query, scope: Guardian.new(@user)).as_json + topic_list = TopicListSerializer.new(topic_query, scope: @guardian).as_json if end_of_list.nil? topic_list["load_more_url"] = load_more_url @@ -169,6 +169,9 @@ module Docs :categories => categories, :topics => topic_list, :topic_count => results_length, + :meta => { + show_topic_excerpts: show_topic_excerpts, + }, } end @@ -200,7 +203,7 @@ module Docs tags_object << { id: tag[0], count: tag[1], active: active || false } end - allowed_tags = DiscourseTagging.filter_allowed_tags(Guardian.new(@user)).map(&:name) + allowed_tags = DiscourseTagging.filter_allowed_tags(@guardian).map(&:name) tags_object = tags_object.select { |tag| allowed_tags.include?(tag[:id]) } @@ -235,5 +238,10 @@ module Docs "/#{GlobalSetting.docs_path}.json?#{filters.join("&")}" end + + def show_topic_excerpts + SiteSetting.always_include_topic_excerpts || + ThemeModifierHelper.new(request: @guardian.request).serialize_topic_excerpts + end end end diff --git a/spec/system/docs_index_spec.rb b/spec/system/docs_index_spec.rb new file mode 100644 index 0000000..ccab8c8 --- /dev/null +++ b/spec/system/docs_index_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +describe "Discourse Docs | Index", type: :system do + fab!(:current_user) { Fabricate(:user) } + fab!(:category) { Fabricate(:category) } + fab!(:topic_1) { Fabricate(:topic, category: category) } + fab!(:topic_2) { Fabricate(:topic, category: category) } + fab!(:post_1) { Fabricate(:post, topic: topic_1) } + fab!(:post_2) { Fabricate(:post, topic: topic_2) } + + before do + SiteSetting.docs_enabled = true + SiteSetting.docs_categories = category.id.to_s + sign_in(current_user) + end + + it "does not error when showing the index" do + visit("/docs") + expect(page).to have_css(".docs-topic-link", text: topic_1.title) + expect(page).to have_css(".docs-topic-link", text: topic_2.title) + end + + describe "topic excerpts" do + before do + topic_1.update_excerpt(post_1.excerpt_for_topic) + topic_2.update_excerpt(post_2.excerpt_for_topic) + end + + it "does not show the topic excerpts by default" do + visit("/docs") + expect(page).to have_no_css(".topic-excerpt") + end + + context "when docs_show_topic_excerpts is true" do + before { SiteSetting.always_include_topic_excerpts = true } + + it "shows the excerpts" do + visit("/docs") + expect(page).to have_css(".topic-excerpt", text: topic_1.excerpt) + expect(page).to have_css(".topic-excerpt", text: topic_2.excerpt) + end + end + + context "when the theme modifier serialize_topic_excerpts is true" do + before do + ThemeModifierSet.find_by(theme_id: Theme.first.id).update!(serialize_topic_excerpts: true) + Theme.clear_cache! + end + + it "shows the excerpts" do + visit("/docs") + expect(page).to have_css(".topic-excerpt", text: topic_1.excerpt) + expect(page).to have_css(".topic-excerpt", text: topic_2.excerpt) + end + end + end +end