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 <martin@discourse.org>
This commit is contained in:
Jordan Vidrine 2023-06-15 12:44:44 -05:00 committed by GitHub
parent ed77e768e6
commit 06f6d00ba1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 132 additions and 25 deletions

View File

@ -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

View File

@ -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))
);
}
},
});

View File

@ -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;

View File

@ -0,0 +1 @@
{{this.topicListItemContents}}

View File

@ -28,7 +28,11 @@
<tbody class="topic-list-body">
{{#each topics as |topic|}}
{{raw "docs-topic-list-item" topic=topic urlPath=urlPath}}
{{docs-topic-list-item
topic=topic
urlPath=urlPath
showExcerpt=showExcerpts
}}
{{/each}}
</tbody>
</table>

View File

@ -36,7 +36,9 @@
{{#if categories}}
<div class="docs-items docs-categories">
<section class="item-controls">
<h3>{{i18n "docs.categories"}}</h3>
<h3>
{{i18n "docs.categories"}}
</h3>
<div class="item-controls-buttons">
<DButton
class={{if
@ -87,7 +89,9 @@
{{#if (and tags shouldShowTags)}}
<div class="docs-items docs-tags">
<section class="item-controls">
<h3>{{i18n "docs.tags"}}</h3>
<h3>
{{i18n "docs.tags"}}
</h3>
<div class="item-controls-buttons">
<DButton
class={{if
@ -142,7 +146,9 @@
{{#if (and tagGroups shouldShowTagsByGroup)}}
<div class="docs-items docs-tags">
<section class="item-controls">
<h3>{{i18n "docs.tags"}}</h3>
<h3>
{{i18n "docs.tags"}}
</h3>
<div class="item-controls-buttons">
<DButton
class={{if
@ -232,6 +238,7 @@
{{#unless emptyResults}}
<DocsTopicList
@topics={{topics}}
@showExcerpts={{showExcerpts}}
@ascending={{ascending}}
@order={{orderColumn}}
@sortBy={{action "sortBy"}}

View File

@ -1,15 +1,19 @@
<tr class="topic-list-item">
<td class="main-link topic-list-data">
<span class="link-top-line">
{{~raw "topic-status" topic=topic}}
{{~raw "docs-topic-link" topic=topic urlPath=urlPath}}
</span>
<span class="link-bottom-line">
{{category-link topic.category}}
{{discourse-tags topic mode="list"}}
</span>
</td>
<td class="topic-list-data">
{{format-date topic.bumped_at format="tiny" noTitle="true"}}
</td>
</tr>
{{~raw-plugin-outlet name="topic-list-before-columns"}}
<td class="main-link topic-list-data">
{{~raw-plugin-outlet name="topic-list-before-link"}}
<span class="link-top-line">
{{~raw "topic-status" topic=topic}}
{{~raw "docs-topic-link" topic=topic urlPath=urlPath}}
</span>
<span class="link-bottom-line">
{{category-link topic.category}}
{{discourse-tags topic mode="list"}}
</span>
{{!-- {{#if showExcerpt}} --}}
{{~raw "list/topic-excerpt" topic=topic}}
{{!-- {{/if}} --}}
</td>
<td class="topic-list-data">
{{format-date topic.bumped_at format="tiny" noTitle="true"}}
</td>

View File

@ -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

View File

@ -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