store comment attribution correctly; count unread conversations

This commit is contained in:
byte[] 2019-11-17 13:52:59 -05:00
parent 41bf4790af
commit 790ee13a36
9 changed files with 83 additions and 39 deletions

View file

@ -39,11 +39,10 @@ defmodule Philomena.Comments do
{:error, %Ecto.Changeset{}}
"""
def create_comment(image, user, attrs \\ %{}) do
user_id = if user, do: user.id, else: nil
def create_comment(image, attributes, params \\ %{}) do
comment =
%Comment{image_id: image.id, user_id: user_id}
|> Comment.creation_changeset(attrs)
struct(Comment, [image_id: image.id] ++ attributes)
|> Comment.creation_changeset(params)
image_query =
Image

View file

@ -102,6 +102,21 @@ defmodule Philomena.Conversations do
Conversation.changeset(conversation, %{})
end
def count_unread_conversations(user) do
Conversation
|> where([c],
(
(c.to_id == ^user.id and c.to_read == false) or
(c.from_id == ^user.id and c.from_read == false)
)
and not (
(c.to_id == ^user.id and c.to_hidden == true) or
(c.from_id == ^user.id and c.from_hidden == true)
)
)
|> Repo.aggregate(:count, :id)
end
alias Philomena.Conversations.Message
@doc """

View file

@ -104,35 +104,12 @@ defmodule Philomena.Notifications do
alias Philomena.Notifications.UnreadNotification
@doc """
Returns the list of unread_notifications.
## Examples
iex> list_unread_notifications()
[%UnreadNotification{}, ...]
"""
def list_unread_notifications do
Repo.all(UnreadNotification)
def count_unread_notifications(user) do
UnreadNotification
|> where(user_id: ^user.id)
|> Repo.aggregate(:count, :notification_id)
end
@doc """
Gets a single unread_notification.
Raises `Ecto.NoResultsError` if the Unread notification does not exist.
## Examples
iex> get_unread_notification!(123)
%UnreadNotification{}
iex> get_unread_notification!(456)
** (Ecto.NoResultsError)
"""
def get_unread_notification!(id), do: Repo.get!(UnreadNotification, id)
@doc """
Creates a unread_notification.

View file

@ -20,7 +20,7 @@ defmodule Philomena.Polymorphic do
@preloads %{
"Comment" => [:user],
"Gallery" => [:creator],
"Image" => [:user],
"Image" => [:user, :tags],
"Post" => [:user],
"Topic" => [:forum, :user]
}

View file

@ -15,6 +15,7 @@ defmodule PhilomenaWeb.Image.CommentController do
plug :load_and_authorize_resource, model: Comment, only: [:show], preload: [:image, user: [awards: :badge]]
plug PhilomenaWeb.FilterBannedUsersPlug when action in [:create, :edit, :update]
plug PhilomenaWeb.UserAttributionPlug when action in [:create]
def index(conn, %{"comment_id" => comment_id}) do
comment =
@ -60,10 +61,10 @@ defmodule PhilomenaWeb.Image.CommentController do
end
def create(conn, %{"comment" => comment_params}) do
user = conn.assigns.current_user
attributes = conn.assigns.attributes
image = conn.assigns.image
case Comments.create_comment(image, user, comment_params) do
case Comments.create_comment(image, attributes, comment_params) do
{:ok, %{comment: comment}} ->
Comments.notify_comment(comment)
Comments.reindex_comment(comment)

View file

@ -0,0 +1,43 @@
defmodule PhilomenaWeb.NotificationCountPlug do
@moduledoc """
This plug stores the current notification count.
## Example
plug PhilomenaWeb.NotificationCountPlug
"""
alias Plug.Conn
alias Philomena.Conversations
alias Philomena.Notifications
@doc false
@spec init(any()) :: any()
def init(opts), do: opts
@doc false
@spec call(Plug.Conn.t(), any()) :: Plug.Conn.t()
def call(conn, _opts) do
user = Pow.Plug.current_user(conn)
conn
|> maybe_assign_notifications(user)
|> maybe_assign_conversations(user)
end
defp maybe_assign_notifications(conn, nil), do: conn
defp maybe_assign_notifications(conn, user) do
notifications = Notifications.count_unread_notifications(user)
conn
|> Conn.assign(:notification_count, notifications)
end
defp maybe_assign_conversations(conn, nil), do: conn
defp maybe_assign_conversations(conn, user) do
conversations = Conversations.count_unread_conversations(user)
conn
|> Conn.assign(:conversation_count, conversations)
end
end

View file

@ -17,15 +17,16 @@ defmodule PhilomenaWeb.UserAttributionPlug do
@doc false
@spec call(Plug.Conn.t(), any()) :: Plug.Conn.t()
def call(conn, _opts) do
{:ok, remote_ip} = EctoNetwork.INET.cast(conn.remote_ip)
conn = Conn.fetch_cookies(conn)
attributes =
%{
ip: conn.remote_ip,
[
ip: remote_ip,
fingerprint: conn.cookies["_ses"],
referrer: conn.assigns.referrer,
user_agent: user_agent(conn),
user_id: user_id(conn)
}
]
conn
|> Conn.assign(:attributes, attributes)

View file

@ -14,6 +14,7 @@ defmodule PhilomenaWeb.Router do
plug PhilomenaWeb.PaginationPlug
plug PhilomenaWeb.EnsureUserEnabledPlug
plug PhilomenaWeb.CurrentBanPlug
plug PhilomenaWeb.NotificationCountPlug
end
pipeline :api do

View file

@ -23,14 +23,21 @@ header.header
.flex.flex--centered.flex--no-wrap.header__force-right
= if @current_user do
- notification_count = 0
- notification_count = @conn.assigns.notification_count
- conversation_count = @conn.assigns.conversation_count
a.header__link href="/notifications" title="Notifications"
i.fa-embedded--notification>
span.js-notification-ticker.fa__text.header__counter data-notification-count=notification_count = notification_count
a.header__link href="/conversations" title="Conversations"
i.fa-embedded--message>
span.fa-embedded__text.header__counter.hidden = "0"
= if @conversation_count > 0 do
span.fa-embedded__text.header__counter
= @conversation_count
- else
span.fa-embedded__text.header__counter.hidden
| 0
a.header__link.hide-mobile href="/filters" title="Filters"
i.fa.fa-filter