Skip to content

Commit

Permalink
Add support for tag filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
ellmetha committed Dec 29, 2023
1 parent cdb8719 commit 4578f4c
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 11 deletions.
124 changes: 124 additions & 0 deletions spec/apps/blogging/handlers/home_handler_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,130 @@ describe Blogging::HomeHandler do
article.author.should eq other_user.profile!
end
end

it "inserts the first page of tag-specific articles when a tag is targeted" do
user = create_user(username: "test1", email: "[email protected]", password: "insecure")
other_user = create_user(username: "test2", email: "[email protected]", password: "insecure")

tag = Blogging::Tag.create!(label: "test")
other_tag = Blogging::Tag.create!(label: "other")

15.times do |i|
article = Blogging::Article.create!(
title: "Article #{i}",
slug: "article-#{i}",
description: "My article description",
body: "# Hello World",
author: other_user.profile!,
)

article.tags.add(tag)
end

15.times do |i|
article = Blogging::Article.create!(
title: "Other article #{i}",
slug: "article-#{i}",
description: "My article description",
body: "# Hello World",
author: other_user.profile!,
)

article.tags.add(other_tag)
end

request = Marten::HTTP::Request.new(method: "GET", resource: "/test/xyz?tag=test")
request.session = Marten::HTTP::Session::Store::Cookie.new("sessionkey")
MartenAuth.sign_in(request, user)

handler = Blogging::HomeHandler.new(request, Marten::Routing::MatchParameters.new)

handler.render_to_response

handler.context["current_tab"].should eq "tag"

page = handler.context["articles"].raw.as(Marten::DB::Query::Page(Blogging::Article))
page.size.should eq 10
page.each do |article|
article.title!.starts_with?("Article").should be_true
end
end

it "inserts the right page of tag-specific articles when a tag is targeted and a page is set" do
user = create_user(username: "test1", email: "[email protected]", password: "insecure")
other_user = create_user(username: "test2", email: "[email protected]", password: "insecure")

tag = Blogging::Tag.create!(label: "test")
other_tag = Blogging::Tag.create!(label: "other")

15.times do |i|
article = Blogging::Article.create!(
title: "Article #{i}",
slug: "article-#{i}",
description: "My article description",
body: "# Hello World",
author: other_user.profile!,
)

article.tags.add(tag)
end

15.times do |i|
article = Blogging::Article.create!(
title: "Other article #{i}",
slug: "article-#{i}",
description: "My article description",
body: "# Hello World",
author: other_user.profile!,
)

article.tags.add(other_tag)
end

request = Marten::HTTP::Request.new(method: "GET", resource: "/test/xyz?tag=test&page=2")
request.session = Marten::HTTP::Session::Store::Cookie.new("sessionkey")
MartenAuth.sign_in(request, user)

handler = Blogging::HomeHandler.new(request, Marten::Routing::MatchParameters.new)

handler.render_to_response

handler.context["current_tab"].should eq "tag"

page = handler.context["articles"].raw.as(Marten::DB::Query::Page(Blogging::Article))
page.size.should eq 5
page.each do |article|
article.title!.starts_with?("Article").should be_true
end
end

it "inserts the expected popular tags" do
user = create_user(username: "test1", email: "[email protected]", password: "insecure")
other_user = create_user(username: "test2", email: "[email protected]", password: "insecure")

25.times do |i|
article = Blogging::Article.create!(
title: "Article #{i}",
slug: "article-#{i}",
description: "My article description",
body: "# Hello World",
author: other_user.profile!,
)

tag = Blogging::Tag.create!(label: "tag-#{i}")
article.tags.add(tag)
end

request = Marten::HTTP::Request.new(method: "GET", resource: "/test/xyz?articles=global")
request.session = Marten::HTTP::Session::Store::Cookie.new("sessionkey")
MartenAuth.sign_in(request, user)

handler = Blogging::HomeHandler.new(request, Marten::Routing::MatchParameters.new)

handler.render_to_response

handler.context["tags"].to_a.should eq Blogging::Tag.all[..20].to_a
end
end
end
end
25 changes: 24 additions & 1 deletion src/apps/blogging/handlers/home_handler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ module Blogging

before_render :add_user_data_to_context
before_render :add_articles_to_context
before_render :add_popular_tags_to_context
before_render :add_targeted_tag_to_context

private PAGE_PARAM = "page"
private PAGE_SIZE = 10
private TAGS_COUNT = 20

private def add_articles_to_context
if request.query_params.fetch(:articles, "user") == "user" && following_users?
if !targeted_tag.nil?
context[:current_tab] = "tag"
context[:articles] = paginated_tag_feed_articles
elsif request.query_params.fetch(:articles, "user") == "user" && following_users?
context[:current_tab] = "user"
context[:articles] = paginated_user_feed_articles
else
Expand All @@ -23,6 +29,14 @@ module Blogging
end
end

private def add_popular_tags_to_context
context[:tags] = Tag.all[..TAGS_COUNT]
end

private def add_targeted_tag_to_context
context[:targeted_tag] = targeted_tag
end

private def add_user_data_to_context
context[:following_users] = following_users?
end
Expand All @@ -42,10 +56,19 @@ module Blogging
paginator.page(page_number)
end

private def paginated_tag_feed_articles
paginator = Article.filter(tags__label: targeted_tag).order("-created_at").paginator(PAGE_SIZE)
paginator.page(page_number)
end

private def paginated_user_feed_articles
followed_user_pks = request.user!.profile!.followed_users.pluck(:pk).flatten
paginator = Article.filter(author_id__in: followed_user_pks).order("-created_at").paginator(PAGE_SIZE)
paginator.page(page_number)
end

private def targeted_tag
request.query_params[:tag]?
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
name="{{ schema.tags.id }}"
value="{{ schema.tags.value }}"
/>
<input id="tags_fake_input" type="text" class="form-control" placeholder="Enter tags" />
<input id="tags_fake_input" type="text" class="form-control" placeholder="Enter tags" autocomplete="off" />
<div id="tags_list" class="tag-list">
</div>
{% for error in schema.tags.errors %}<div class="invalid-feedback">{{ error.message }}</div>{% endfor %}
Expand Down
19 changes: 10 additions & 9 deletions src/apps/blogging/templates/blogging/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ <h1 class="logo-font">conduit</h1>
<li class="nav-item">
<a class="nav-link{% if current_tab == 'global' %} active{% endif %}" href="?articles=global">Global Feed</a>
</li>
{% if targeted_tag %}
<li class="nav-item">
<a class="nav-link active" href="?tag={{ targeted_tag }}"><i class="ion-pound"></i> {{ targeted_tag }}</a>
</li>
{% endif %}
</ul>
</div>

Expand All @@ -36,22 +41,18 @@ <h1 class="logo-font">conduit</h1>
{% include "partials/article_feed.html" with additional_page_params = articles_query_param %}
</div>

{% if not tags.empty? %}
<div class="col-md-3">
<div class="sidebar">
<p>Popular Tags</p>

<div class="tag-list">
<a href="" class="tag-pill tag-default">programming</a>
<a href="" class="tag-pill tag-default">javascript</a>
<a href="" class="tag-pill tag-default">emberjs</a>
<a href="" class="tag-pill tag-default">angularjs</a>
<a href="" class="tag-pill tag-default">react</a>
<a href="" class="tag-pill tag-default">mean</a>
<a href="" class="tag-pill tag-default">node</a>
<a href="" class="tag-pill tag-default">rails</a>
{% for tag in tags %}
<a href="?tag={{ tag.label }}" class="tag-pill tag-default">{{ tag.label }}</a>
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
Expand Down

0 comments on commit 4578f4c

Please sign in to comment.