Skip to content

Commit bff9fa7

Browse files
Merge pull request #91 from epochtalk/polls
Polls
2 parents 9b054ad + ab1258d commit bff9fa7

File tree

19 files changed

+636
-106
lines changed

19 files changed

+636
-106
lines changed

PortRoadmap.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
| bct-trust | posts.byThread.post | userTrust | :white_check_mark: |
8181
| bct-trust | posts.byThread.post | showTrust | :white_check_mark: |
8282
| ept-auto-moderation | posts.create.pre | moderate | :white_check_mark: |
83-
| ept-auto-moderation | posts.update.pre | moderate | :x: |
83+
| ept-auto-moderation | posts.update.pre | moderate | :white_check_mark: |
8484
| ept-auto-moderation | threads.create.pre | moderate | :white_check_mark: |
8585
| ept-ignore-users | users.find.post | userIgnored | :x: |
8686
| ept-ignore-users | posts.patroller.post | isIgnored | :x: |
@@ -93,14 +93,14 @@
9393
| ept-mentions | posts.search.post | userIdToUsername | :x: |
9494
| ept-mentions | mentions.page.post | userIdToUsername | :x: |
9595
| ept-mentions | portal.view.post | userIdToUsername | :x: |
96-
| ept-mentions | posts.update.post | userIdToUsername | :x: |
97-
| ept-mentions | posts.update.post | correctTextSearchVector | :x: |
96+
| ept-mentions | posts.update.post | userIdToUsername | :white_check_mark: |
97+
| ept-mentions | posts.update.post | correctTextSearchVector | :white_check_mark: |
9898
| ept-mentions | posts.create.pre | usernameToUserId | :white_check_mark: |
99-
| ept-mentions | posts.update.pre | usernameToUserId | :x: |
99+
| ept-mentions | posts.update.pre | usernameToUserId | :white_check_mark: |
100100
| ept-mentions | threads.create.pre | usernameToUserId | :white_check_mark: |
101101
| ept-mentions | posts.create.post | createMention | :white_check_mark: |
102102
| ept-mentions | posts.create.post | correctTextSearchVector | :white_check_mark: |
103-
| ept-mentions | posts.update.post | removeMentionIds | :x: |
103+
| ept-mentions | posts.update.post | removeMentionIds | **N/A** |
104104
| ept-mentions | threads.create.post | createMention | :white_check_mark: |
105105
| ept-mentions | threads.create.post | correctTextSearchVector | :white_check_mark: |
106106
| ept-mentions | users.find.post | userIgnoredMentions | :x: |

lib/epochtalk_server/models/board.ex

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,46 @@ defmodule EpochtalkServer.Models.Board do
334334
else: {:error, :board_does_not_exist}
335335
end
336336

337+
@doc """
338+
Returns boolean indicating if `Board` has `Post` edit disabled, which is determined by
339+
the `post_edit_diabled` setting within the `meta` field of the `Board`
340+
"""
341+
@spec is_post_edit_disabled_by_thread_id(
342+
thread_id :: non_neg_integer,
343+
post_created_at :: NaiveDateTime.t()
344+
) :: boolean
345+
def is_post_edit_disabled_by_thread_id(thread_id, post_created_at) when is_integer(thread_id) do
346+
query =
347+
from b in Board,
348+
left_join: t in Thread,
349+
on: t.board_id == b.id,
350+
where: t.id == ^thread_id,
351+
select: b.meta["disable_post_edit"]
352+
353+
disable_post_edit = Repo.one(query)
354+
355+
# check time elapsed if post edit is disabled
356+
editing_disabled =
357+
if is_integer(disable_post_edit) and disable_post_edit > -1 do
358+
current_time =
359+
NaiveDateTime.utc_now()
360+
|> DateTime.from_naive!("Etc/UTC")
361+
|> DateTime.to_unix(:millisecond)
362+
363+
post_created_at =
364+
post_created_at |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_unix(:millisecond)
365+
366+
editable_for_mins = disable_post_edit * 60 * 1000
367+
368+
current_time - post_created_at >= editable_for_mins
369+
else
370+
# diable_post_edit not set
371+
false
372+
end
373+
374+
editing_disabled
375+
end
376+
337377
@doc """
338378
Used to obtain breadcrumb data for a specific `Board` given it's `slug`
339379
"""

lib/epochtalk_server/models/board_ban.ex

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ defmodule EpochtalkServer.Models.BoardBan do
4747
Returns `true` if the user is banned from the specified `Board` or `false`
4848
otherwise.
4949
"""
50-
@spec is_banned_from_board(user :: User.t(), opts :: list) :: {:ok, banned :: boolean}
51-
def is_banned_from_board(%{id: user_id} = _user, opts) when is_integer(user_id) do
50+
@spec banned_from_board?(user :: User.t(), opts :: list) :: {:ok, banned :: boolean}
51+
def banned_from_board?(%{id: user_id} = _user, opts) when is_integer(user_id) do
5252
board_id = Keyword.get(opts, :board_id)
5353
post_id = Keyword.get(opts, :post_id)
5454
thread_id = Keyword.get(opts, :thread_id)
@@ -91,7 +91,7 @@ defmodule EpochtalkServer.Models.BoardBan do
9191
{:ok, result}
9292
end
9393

94-
def is_banned_from_board(nil, _opts), do: {:ok, false}
94+
def banned_from_board?(nil, _opts), do: {:ok, false}
9595

9696
@doc """
9797
Used to check if `User` with specified `user_id` is not banned from board.
@@ -100,13 +100,13 @@ defmodule EpochtalkServer.Models.BoardBan do
100100
Returns `true` if the user is **not** banned from the specified `Board` or `false`
101101
otherwise.
102102
"""
103-
@spec is_not_banned_from_board(user :: User.t(), opts :: list) :: {:ok, not_banned :: boolean}
104-
def is_not_banned_from_board(user, opts \\ [])
103+
@spec not_banned_from_board?(user :: User.t(), opts :: list) :: {:ok, not_banned :: boolean}
104+
def not_banned_from_board?(user, opts \\ [])
105105

106-
def is_not_banned_from_board(%{id: user_id} = user, opts) when is_integer(user_id) do
107-
{:ok, banned} = is_banned_from_board(user, opts)
106+
def not_banned_from_board?(%{id: user_id} = user, opts) when is_integer(user_id) do
107+
{:ok, banned} = banned_from_board?(user, opts)
108108
{:ok, !banned}
109109
end
110110

111-
def is_not_banned_from_board(nil, _opts), do: {:ok, true}
111+
def not_banned_from_board?(nil, _opts), do: {:ok, true}
112112
end

lib/epochtalk_server/models/poll.ex

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ defmodule EpochtalkServer.Models.Poll do
66
alias EpochtalkServer.Repo
77
alias EpochtalkServer.Models.Poll
88
alias EpochtalkServer.Models.PollAnswer
9+
alias EpochtalkServer.Models.PollResponse
910
alias EpochtalkServer.Models.Thread
1011

1112
@moduledoc """
@@ -24,11 +25,14 @@ defmodule EpochtalkServer.Models.Poll do
2425
@derive {Jason.Encoder,
2526
only: [
2627
:thread_id,
28+
:id,
2729
:question,
2830
:locked,
2931
:max_answers,
3032
:expiration,
3133
:change_vote,
34+
:has_voted,
35+
:answers,
3236
:display_mode
3337
]}
3438
schema "polls" do
@@ -39,6 +43,8 @@ defmodule EpochtalkServer.Models.Poll do
3943
field :expiration, :naive_datetime
4044
field :change_vote, :boolean
4145
field :display_mode, Ecto.Enum, values: [:always, :voted, :expired]
46+
field :has_voted, :boolean, virtual: true
47+
field :answers, {:array, :map}, virtual: true
4248
has_many :poll_answers, PollAnswer
4349
end
4450

@@ -142,6 +148,25 @@ defmodule EpochtalkServer.Models.Poll do
142148
end)
143149
end
144150

151+
@doc """
152+
Returns boolean indicating if the specified `User` has voted on the specified `Thread`
153+
"""
154+
@spec has_voted(thread_id :: integer, user_id :: integer) :: boolean
155+
def has_voted(thread_id, user_id) do
156+
query =
157+
from p in Poll,
158+
left_join: pr in PollResponse,
159+
on: true,
160+
left_join: pa in PollAnswer,
161+
on: true,
162+
where:
163+
p.id == pa.poll_id and pr.answer_id == pa.id and p.thread_id == ^thread_id and
164+
pr.user_id == ^user_id,
165+
select: pr.user_id
166+
167+
Repo.exists?(query)
168+
end
169+
145170
@doc """
146171
Queries `Poll` Data by thread
147172
"""

lib/epochtalk_server/models/poll_answer.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ defmodule EpochtalkServer.Models.PollAnswer do
1515
poll_id: non_neg_integer | nil,
1616
answer: String.t() | nil
1717
}
18-
@derive {Jason.Encoder, only: [:poll_id, :answer]}
18+
@derive {Jason.Encoder, only: [:id, :answer, :votes]}
1919
schema "poll_answers" do
2020
belongs_to :poll, Poll
2121
field :answer, :string
22+
field :votes, :integer, virtual: true, default: 0
2223
has_many :poll_responses, PollResponse, foreign_key: :answer_id
2324
end
2425

lib/epochtalk_server/models/poll_response.ex

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ defmodule EpochtalkServer.Models.PollResponse do
22
use Ecto.Schema
33
import Ecto.Changeset
44
# import Ecto.Query
5-
# alias EpochtalkServer.Repo
6-
# alias EpochtalkServer.Models.PollResponse
5+
alias EpochtalkServer.Repo
6+
alias EpochtalkServer.Models.PollResponse
77
alias EpochtalkServer.Models.PollAnswer
88
alias EpochtalkServer.Models.User
99

@@ -50,4 +50,21 @@ defmodule EpochtalkServer.Models.PollResponse do
5050
|> foreign_key_constraint(:answer_id, name: :poll_responses_answer_id_fkey)
5151
|> foreign_key_constraint(:user_id, name: :poll_responses_user_id_fkey)
5252
end
53+
54+
## === Database Functions ===
55+
56+
@doc """
57+
Create on `PollResponse` for specific poll. Used to vote for a `Poll`
58+
"""
59+
@spec create(attrs :: map, user_id :: integer) :: :ok
60+
def create(%{"answer_ids" => answer_ids} = attrs, user_id)
61+
when is_map(attrs) and is_integer(user_id),
62+
do: Enum.each(answer_ids, &PollResponse.create(&1, user_id))
63+
64+
def create(answer_id, user_id) do
65+
poll_response_cs =
66+
create_changeset(%PollResponse{}, %{answer_id: answer_id, user_id: user_id})
67+
68+
Repo.insert(poll_response_cs)
69+
end
5370
end

0 commit comments

Comments
 (0)