feat: Sort subreddit posts by most comments

This commit is contained in:
Daniel Kempkens 2023-10-18 17:52:24 +02:00
parent ddb9288415
commit caea9d54ce
Signed by: daniel
SSH key fingerprint: SHA256:Ks/MyhQYcPRQiwMKLAKquWCdCPe3JXlb1WttgnAoSeM
5 changed files with 55 additions and 13 deletions

View file

@ -123,6 +123,29 @@ defmodule BdfrBrowser.HTTP.Plug do
|> send_resp(200, content) |> send_resp(200, content)
end end
get "/s/:subreddits/most_comments" do
subreddit_names = String.split(subreddits, "+")
subreddit_records = Subreddit.multiple_names(subreddit_names) |> Repo.all()
{:ok, range_start} = Date.from_iso8601("1970-01-01")
range_end = Date.utc_today()
tpl_args = [
subreddit: subreddit_names,
date: "Most Comments",
posts:
subreddit_records
|> Post.during_range(range_start, range_end, :most_comments)
|> Post.with_comments(1)
|> Repo.all()
]
content = render_template("subreddit_posts", tpl_args)
conn
|> put_resp_header("content-type", "text/html; charset=utf-8")
|> send_resp(200, content)
end
get "/chats" do get "/chats" do
tpl_args = [chats: Chat.listing() |> Repo.all()] tpl_args = [chats: Chat.listing() |> Repo.all()]
content = render_template("chats", tpl_args) content = render_template("chats", tpl_args)

View file

@ -1,7 +1,7 @@
defmodule BdfrBrowser.Post do defmodule BdfrBrowser.Post do
use Ecto.Schema use Ecto.Schema
import Ecto.Query, only: [from: 2] import Ecto.Query, only: [dynamic: 1, dynamic: 2, from: 2, having: 3]
alias BdfrBrowser.{Comment, Subreddit} alias BdfrBrowser.{Comment, Subreddit}
@ -46,7 +46,9 @@ defmodule BdfrBrowser.Post do
during_range(subreddit, Date.beginning_of_month(d), Date.end_of_month(d)) during_range(subreddit, Date.beginning_of_month(d), Date.end_of_month(d))
end end
def during_range(subreddits, start_date, end_date) when is_list(subreddits) do def during_range(subreddits, start_date, end_date, sort_field \\ :posted_at)
def during_range(subreddits, start_date, end_date, sort_field) when is_list(subreddits) do
subreddit_ids = for s <- subreddits, do: s.id subreddit_ids = for s <- subreddits, do: s.id
from(p in __MODULE__, from(p in __MODULE__,
@ -58,18 +60,19 @@ defmodule BdfrBrowser.Post do
url: p.url, url: p.url,
author: p.author, author: p.author,
posted_at: p.posted_at, posted_at: p.posted_at,
num_comments: count(c.id), num_comments: selected_as(count(c.id), :num_comments),
subreddit: s.name subreddit: s.name,
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
}, },
where: where:
p.subreddit_id in ^subreddit_ids and type(p.posted_at, :date) >= ^start_date and p.subreddit_id in ^subreddit_ids and type(p.posted_at, :date) >= ^start_date and
type(p.posted_at, :date) <= ^end_date, type(p.posted_at, :date) <= ^end_date,
order_by: [desc: p.posted_at], order_by: ^dynamic_sort(sort_field),
group_by: [p.id, s.name] group_by: [p.id, s.name]
) )
end end
def during_range(subreddit, start_date, end_date) do def during_range(subreddit, start_date, end_date, sort_field) do
from(p in __MODULE__, from(p in __MODULE__,
left_join: c in assoc(p, :comments), left_join: c in assoc(p, :comments),
join: s in assoc(p, :subreddit), join: s in assoc(p, :subreddit),
@ -79,17 +82,22 @@ defmodule BdfrBrowser.Post do
url: p.url, url: p.url,
author: p.author, author: p.author,
posted_at: p.posted_at, posted_at: p.posted_at,
num_comments: count(c.id), num_comments: selected_as(count(c.id), :num_comments),
subreddit: s.name subreddit: s.name,
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
}, },
where: where:
p.subreddit_id == ^subreddit.id and type(p.posted_at, :date) >= ^start_date and p.subreddit_id == ^subreddit.id and type(p.posted_at, :date) >= ^start_date and
type(p.posted_at, :date) <= ^end_date, type(p.posted_at, :date) <= ^end_date,
order_by: [desc: p.posted_at], order_by: ^dynamic_sort(sort_field),
group_by: [p.id, s.name] group_by: [p.id, s.name]
) )
end end
def with_comments(query, more_than \\ 0) do
having(query, [p, c, s], count(c.id) > ^more_than)
end
def get_full(id) do def get_full(id) do
from(p in __MODULE__, from(p in __MODULE__,
where: p.id == ^id, where: p.id == ^id,
@ -169,4 +177,7 @@ defmodule BdfrBrowser.Post do
group_by: [p.id, s.name] group_by: [p.id, s.name]
) )
end end
defp dynamic_sort(:posted_at), do: [{:desc, dynamic([p], p.posted_at)}]
defp dynamic_sort(:most_comments), do: dynamic(fragment("num_comments DESC"))
end end

View file

@ -12,7 +12,9 @@
<p> <p>
<small><%= BdfrBrowser.RenderUtils.link_to_user(post.author) %></small> <small><%= BdfrBrowser.RenderUtils.link_to_user(post.author) %></small>
- -
<small><%= DateTime.to_iso8601(post.posted_at) %></small> <small><%= BdfrBrowser.RenderUtils.format_date(post.posted_at, :long) %></small>
-
<small><i class="bi bi-arrow-up-square"></i> <%= Float.round(post.upvote_ratio * 100, 1) %>%</small>
- -
<a href="https://www.reddit.com<%= post.permalink %>" rel="noreferrer">Open reddit</a> <a href="https://www.reddit.com<%= post.permalink %>" rel="noreferrer">Open reddit</a>
</p> </p>

View file

@ -12,7 +12,7 @@
</nav> </nav>
<h2> <h2>
<%= if is_list(subreddit) do %> <%= if is_list(subreddit) and length(subreddit) > 1 do %>
Multi-Reddit Multi-Reddit
<% else %> <% else %>
<%= subreddit %> <%= subreddit %>
@ -41,6 +41,12 @@
<div class="row text-center"> <div class="row text-center">
<div class="d-grid gap-2 col-12 mx-auto"> <div class="d-grid gap-2 col-12 mx-auto">
<%= if is_list(subreddit) do %>
<a class="btn btn-outline-info btn-lg" href="/s/<%= Enum.join(subreddit, "+") %>/most_comments" role="button">Most Comments</a>
<% else %>
<a class="btn btn-outline-info btn-lg" href="/s/<%= subreddit %>/most_comments" role="button">Most Comments</a>
<% end %>
<%= for date <- dates do %> <%= for date <- dates do %>
<%= if is_list(subreddit) do %> <%= if is_list(subreddit) do %>
<a class="btn btn-outline-secondary btn-lg" href="/m/<%= Enum.join(subreddit, "+") %>/<%= date %>" role="button"><%= date %></a> <a class="btn btn-outline-secondary btn-lg" href="/m/<%= Enum.join(subreddit, "+") %>/<%= date %>" role="button"><%= date %></a>

View file

@ -13,7 +13,7 @@
</nav> </nav>
<h2> <h2>
<%= if is_list(subreddit) do %> <%= if is_list(subreddit) and length(subreddit) > 1 do %>
Multi-Reddit Multi-Reddit
<% else %> <% else %>
<%= subreddit %> <%= subreddit %>
@ -25,7 +25,7 @@
<%= for post <- posts do %> <%= for post <- posts do %>
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title"><a href="/r/<%= post.subreddit %>/<%= date %>/<%= post.id %>"><%= post.title %></a></h5> <h5 class="card-title"><a href="/r/<%= post.subreddit %>/<%= post.date %>/<%= post.id %>"><%= post.title %></a></h5>
<h6 class="card-subtitle mb-2 text-body-secondary"> <h6 class="card-subtitle mb-2 text-body-secondary">
<small> <small>
<%= BdfrBrowser.RenderUtils.post_type_icon(post.url) %> <%= BdfrBrowser.RenderUtils.post_type_icon(post.url) %>