Skip to content

Commit 59f5f2c

Browse files
Merge pull request #111 from epochtalk/recent-threads
Recent threads
2 parents b3b0bcc + f6ca0b4 commit 59f5f2c

File tree

3 files changed

+164
-16
lines changed

3 files changed

+164
-16
lines changed

lib/epochtalk_server/models/thread.ex

Lines changed: 121 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -405,17 +405,129 @@ defmodule EpochtalkServer.Models.Thread do
405405
@doc """
406406
Returns recent threads accounting for user priority and user's ignored boards
407407
"""
408-
# TODO(akinsey): complete implementation for main view
409-
@spec recent(user :: User.t(), user_priority :: non_neg_integer, opts :: list() | nil) :: [t()]
410-
def recent(_user, _user_priority, opts \\ []) do
411-
limit = Keyword.get(opts, :limit, 5)
408+
@spec recent(user :: User.t() | nil, user_priority :: non_neg_integer) :: [t()]
409+
def recent(user \\ nil, user_priority) do
410+
user_id = if user, do: user.id
411+
limit = 5
412+
offset = 0
413+
414+
ignore_boards =
415+
if user,
416+
do: """
417+
AND NOT (b.id::text = ANY(SELECT jsonb_array_elements_text(up.ignored_boards->'boards') FROM users.preferences up WHERE up.user_id = #{user_id}))
418+
""",
419+
else: ""
412420

413-
query =
414-
from Thread,
415-
order_by: [desc: :updated_at],
416-
limit: ^limit
421+
thread_view_time =
422+
if user,
423+
do:
424+
"( SELECT time FROM users.thread_views WHERE thread_id = tlist.id AND user_id = #{user_id} ) AS time,",
425+
else: ""
417426

418-
Repo.all(query)
427+
latest_user_time =
428+
if user,
429+
do: "AND created_at >= t.time",
430+
else: "AND FALSE"
431+
432+
query = """
433+
SELECT
434+
tlist.id,
435+
tlist.slug,
436+
t.locked,
437+
t.sticky,
438+
t.moderated,
439+
t.poll,
440+
t.updated_at,
441+
t.views AS view_count,
442+
t.board_name,
443+
t.board_slug,
444+
t.board_id,
445+
pf.title,
446+
tv.id AS new_post_id,
447+
tv.position AS new_post_position,
448+
pl.last_post_id,
449+
pl.position AS last_post_position,
450+
pl.created_at AS last_post_created_at,
451+
pl.deleted AS last_post_deleted,
452+
pl.id AS last_post_user_id,
453+
pl.username AS last_post_username,
454+
pl.user_deleted AS last_post_user_deleted
455+
FROM (
456+
SELECT t.id, t.slug
457+
FROM threads t
458+
WHERE EXISTS (
459+
SELECT 1
460+
FROM boards b
461+
WHERE b.id = t.board_id
462+
#{ignore_boards}
463+
AND ( b.viewable_by IS NULL OR b.viewable_by >= #{user_priority} )
464+
AND ( SELECT EXISTS ( SELECT 1 FROM board_mapping WHERE board_id = t.board_id ))
465+
)
466+
AND t.updated_at IS NOT NULL
467+
ORDER BY t.updated_at DESC
468+
LIMIT #{limit} OFFSET #{offset}
469+
) tlist
470+
LEFT JOIN LATERAL (
471+
SELECT
472+
t1.locked,
473+
t1.sticky,
474+
t1.moderated,
475+
t1.updated_at,
476+
mt.views,
477+
( SELECT EXISTS ( SELECT 1 FROM polls WHERE thread_id = tlist.id )) AS poll,
478+
#{thread_view_time}
479+
( SELECT b.name FROM boards b WHERE b.id = t1.board_id ) AS board_name,
480+
( SELECT b.slug FROM boards b WHERE b.id = t1.board_id ) AS board_slug,
481+
( SELECT b.id FROM boards b WHERE b.id = t1.board_id ) AS board_id
482+
FROM threads t1
483+
LEFT JOIN metadata.threads mt ON tlist.id = mt.thread_id
484+
WHERE t1.id = tlist.id
485+
) t ON true
486+
LEFT JOIN LATERAL (
487+
SELECT content ->> 'title' as title
488+
FROM posts
489+
WHERE thread_id = tlist.id
490+
ORDER BY created_at
491+
LIMIT 1
492+
) pf ON true
493+
LEFT JOIN LATERAL (
494+
SELECT id, position
495+
FROM posts
496+
WHERE thread_id = tlist.id
497+
#{latest_user_time}
498+
ORDER BY created_at
499+
LIMIT 1
500+
) tv ON true
501+
LEFT JOIN LATERAL (
502+
SELECT
503+
p.id AS last_post_id,
504+
p.position,
505+
p.created_at,
506+
p.deleted,
507+
u.id,
508+
u.username,
509+
u.deleted as user_deleted
510+
FROM posts p
511+
LEFT JOIN users u ON p.user_id = u.id
512+
WHERE p.thread_id = tlist.id
513+
ORDER BY p.created_at DESC
514+
LIMIT 1
515+
) pl ON true
516+
"""
517+
518+
raw_data = Ecto.Adapters.SQL.query!(Repo, query)
519+
520+
# convert raw sql query results into list of recent thread maps
521+
Enum.reduce(raw_data.rows, [], fn row, recent_threads ->
522+
recent_thread =
523+
raw_data.columns
524+
|> Enum.with_index()
525+
|> Enum.reduce(%{}, fn {key, row_index}, recent_thread_map ->
526+
Map.put(recent_thread_map, String.to_atom(key), Enum.at(row, row_index))
527+
end)
528+
529+
recent_threads ++ [recent_thread]
530+
end)
419531
end
420532

421533
@doc """

lib/epochtalk_server_web/controllers/thread.ex

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,10 @@ defmodule EpochtalkServerWeb.Controllers.Thread do
3030
@doc """
3131
Used to retrieve recent threads
3232
"""
33-
# TODO(akinsey): come back to this after implementing thread and post create
34-
def recent(conn, attrs) do
35-
with limit <- Validate.cast(attrs, "limit", :integer, default: 5),
36-
user <- Guardian.Plug.current_resource(conn),
33+
def recent(conn, _attrs) do
34+
with user <- Guardian.Plug.current_resource(conn),
3735
user_priority <- ACL.get_user_priority(conn),
38-
threads <- Thread.recent(user, user_priority, limit: limit) do
36+
threads <- Thread.recent(user, user_priority) do
3937
render(conn, :recent, %{threads: threads})
4038
else
4139
_ -> ErrorHelpers.render_json_error(conn, 400, "Error, cannot fetch recent threads")

lib/epochtalk_server_web/json/thread_json.ex

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,46 @@ defmodule EpochtalkServerWeb.Controllers.ThreadJSON do
1212
threads: threads
1313
}) do
1414
threads
15-
|> Enum.map(fn thread ->
16-
%{id: thread.id, slug: thread.slug, updated_at: thread.updated_at}
15+
|> Enum.map(fn t ->
16+
%{
17+
id: t.id,
18+
slug: t.slug,
19+
locked: t.locked,
20+
sticky: t.sticky,
21+
moderated: t.moderated,
22+
poll: t.poll,
23+
title: t.title,
24+
updated_at: t.updated_at,
25+
view_count: t.view_count,
26+
board: %{
27+
id: t.board_id,
28+
name: t.board_name,
29+
slug: t.board_slug
30+
},
31+
post: %{
32+
id: t.last_post_id,
33+
position: t.last_post_position,
34+
created_at: t.last_post_created_at,
35+
deleted: t.last_post_deleted
36+
},
37+
user:
38+
if(t.last_post_user_deleted || t.last_post_deleted,
39+
do: %{
40+
id: "",
41+
username: "",
42+
deleted: true
43+
},
44+
else: %{
45+
id: t.last_post_user_id,
46+
username: t.last_post_username,
47+
deleted: t.last_post_user_deleted
48+
}
49+
),
50+
lastest:
51+
if(t.new_post_id || t.new_post_position,
52+
do: %{id: t.new_post_id, position: t.new_post_position || 1}
53+
)
54+
}
1755
end)
1856
end
1957

0 commit comments

Comments
 (0)