Added "Tags" category to search results (#16265)

* Added tag search to nav menu

* Added tag search

* Improved tags search results view

* Removed commented lines from the controller

* Fix specs for Search::Tag

* Prepare for tags search pagination

* Fixed Search::Tag specs

* styling

Co-authored-by: Paweł Ludwiczak <ludwiczakpawel@gmail.com>
This commit is contained in:
Anna Buianova 2022-01-26 20:51:15 +03:00 committed by GitHub
parent 46fb59c944
commit 3fdb87ee66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 12 deletions

View file

@ -3,6 +3,31 @@
/* eslint-disable no-multi-str */
function buildArticleHTML(article) {
var tagIcon = `<svg width="24" height="24" viewBox="0 0 24 24" class="crayons-icon" xmlns="http://www.w3.org/2000/svg"><path d="M7.784 14l.42-4H4V8h4.415l.525-5h2.011l-.525 5h3.989l.525-5h2.011l-.525 5H20v2h-3.784l-.42 4H20v2h-4.415l-.525 5h-2.011l.525-5H9.585l-.525 5H7.049l.525-5H4v-2h3.784zm2.011 0h3.99l.42-4h-3.99l-.42 4z"/></svg>`;
if (article && article.class_name === 'Tag') {
return `<article class="crayons-story">
<div class="crayons-story__body flex items-start gap-2">
<span class="radius-default p-2 shrink-0" style="background: ${
article.bg_color_hex || '#000000'
}1a; color: ${article.bg_color_hex || '#000'}">
${tagIcon}
</span>
<div>
<h3 class="crayons-subtitle-2 lh-tight py-2">
<a href="/t/${article.name}" class="c-link">
${article.name}
</a>
</h3>
${
article.short_summary
? `<div class="truncate-at-3">${article.short_summary}</div>`
: ''
}
</div>
</div>
</article>`;
}
if (article && article.class_name === 'PodcastEpisode') {
return `<article class="crayons-story crayons-podcast-episode mb-2">
<div class="crayons-story__body flex flex-start">

View file

@ -51,8 +51,7 @@ class SearchController < ApplicationController
].freeze
def tags
result = Search::Tag.search_documents(params[:name])
result = Search::Tag.search_documents(term: params[:name])
render json: { result: result }
end
@ -134,8 +133,13 @@ class SearchController < ApplicationController
)
elsif class_name.Article?
search_postgres_article
elsif class_name.Tag?
Search::Tag.search_documents(
term: feed_params[:search_fields],
page: feed_params[:page],
per_page: feed_params[:per_page],
)
end
render json: { result: result }
end

View file

@ -1,5 +1,6 @@
module Search
class TagSerializer < ApplicationSerializer
attribute :class_name, -> { "Tag" }
attributes :id, :name, :hotness_score, :supported, :short_summary, :rules_html, :bg_color_hex
attribute :badge do |tag|
if tag.badge

View file

@ -2,8 +2,16 @@ module Search
class Tag
ATTRIBUTES = %i[id name hotness_score rules_html supported short_summary bg_color_hex badge_id].freeze
def self.search_documents(term)
results = ::Tag.search_by_name(term).supported.includes(:badge).reorder(hotness_score: :desc).select(*ATTRIBUTES)
DEFAULT_PER_PAGE = 60
MAX_PER_PAGE = 100
def self.search_documents(
page: 0,
per_page: DEFAULT_PER_PAGE,
term: nil
)
results = ::Tag.search_by_name(term).supported.includes(:badge)
.reorder(hotness_score: :desc).page(page).per(per_page).select(*ATTRIBUTES)
serialize(results)
end

View file

@ -8,6 +8,9 @@
<li><a class="query-filter-button crayons-navigation__item" data-filter="class_name:User" href="javascript:;">
<%= t("views.search.nav.people") %>
</a></li>
<li><a class="query-filter-button crayons-navigation__item" data-filter="class_name:Tag" href="javascript:;">
<%= t("views.search.nav.tags") %>
</a></li>
<li><a class="query-filter-button crayons-navigation__item" data-filter="class_name:Comment" href="javascript:;">
<%= t("views.search.nav.comments") %>
</a></li>

View file

@ -85,6 +85,7 @@ en:
people: People
comments: Comments
my_posts: My posts only
tags: Tags
sort:
aria_label: Search result sort options
relevance: Most Relevant

View file

@ -219,6 +219,26 @@ RSpec.describe "Search", type: :request, proper_status: true do
expect(response.parsed_body["result"].first).to include("body_text" => podcast_episode.body_text)
end
end
context "when using searching for tags" do
let!(:tag) { create(:tag, name: "webdev") }
it "returns the correct keys for tags" do
get search_feed_content_path(search_fields: "web", class_name: "Tag")
expect(response.parsed_body["result"]).to be_present
end
it "supports the search params for tags" do
get search_feed_content_path(
search_fields: "web",
class_name: "Tag",
page: 0,
per_page: 1,
)
expect(response.parsed_body["result"].first).to include("name" => tag.name)
end
end
end
describe "GET /search/reactions" do

View file

@ -5,29 +5,29 @@ RSpec.describe Search::Tag, type: :service do
it "does not find non supported tags" do
tag = create(:tag, supported: false)
expect(described_class.search_documents(tag.name)).to be_empty
expect(described_class.search_documents(term: tag.name)).to be_empty
end
it "returns data in the expected format" do
tag = create(:tag, supported: true)
result = described_class.search_documents(tag.name)
result = described_class.search_documents(term: tag.name)
expect(result.first.keys).to match_array(
%i[id name hotness_score rules_html supported short_summary badge bg_color_hex],
%i[id name class_name hotness_score rules_html supported short_summary badge bg_color_hex],
)
end
it "finds a tag by its name" do
tag = create(:tag, supported: true)
expect(described_class.search_documents(tag.name)).to be_present
expect(described_class.search_documents(term: tag.name)).to be_present
end
it "finds a tag by a partial name" do
tag = create(:tag, supported: true)
expect(described_class.search_documents(tag.name.first(1))).to be_present
expect(described_class.search_documents(term: tag.name.first(1))).to be_present
end
it "finds multiple tags whose names have common parts", :aggregate_failures do
@ -35,7 +35,7 @@ RSpec.describe Search::Tag, type: :service do
javascript = create(:tag, name: "javascript")
ruby = create(:tag, name: "ruby")
result = described_class.search_documents("jav")
result = described_class.search_documents(term: "jav")
tags = result.pluck(:name)
expect(tags).to include(java.name)
@ -55,7 +55,7 @@ RSpec.describe Search::Tag, type: :service do
tag1.save!
tag2.save!
result = described_class.search_documents("jav")
result = described_class.search_documents(term: "jav")
tags = result.pluck(:name)
expect(tags).to eq([tag2.name, tag1.name])