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:
parent
46fb59c944
commit
3fdb87ee66
8 changed files with 74 additions and 12 deletions
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue