notification clearing, forum subscriptions

This commit is contained in:
byte[] 2019-11-29 14:29:01 -05:00
parent 0efa3b40c3
commit ca1036088f
21 changed files with 274 additions and 45 deletions

View file

@ -7,6 +7,8 @@ defmodule Philomena.Forums do
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Forums.Forum alias Philomena.Forums.Forum
alias Philomena.Forums.Subscription
alias Philomena.Notifications
@doc """ @doc """
Returns the list of forums. Returns the list of forums.
@ -101,4 +103,41 @@ defmodule Philomena.Forums do
def change_forum(%Forum{} = forum) do def change_forum(%Forum{} = forum) do
Forum.changeset(forum, %{}) Forum.changeset(forum, %{})
end end
def subscribed?(_forum, nil), do: false
def subscribed?(forum, user) do
Subscription
|> where(forum_id: ^forum.id, user_id: ^user.id)
|> Repo.exists?()
end
def create_subscription(_forum, nil), do: {:ok, nil}
def create_subscription(forum, user) do
%Subscription{forum_id: forum.id, user_id: user.id}
|> Subscription.changeset(%{})
|> Repo.insert(on_conflict: :nothing)
end
@doc """
Deletes a Subscription.
## Examples
iex> delete_subscription(subscription)
{:ok, %Subscription{}}
iex> delete_subscription(subscription)
{:error, %Ecto.Changeset{}}
"""
def delete_subscription(forum, user) do
clear_notification(forum, user)
%Subscription{forum_id: forum.id, user_id: user.id}
|> Repo.delete()
end
def clear_notification(forum, user) do
Notifications.delete_unread_notification("Forum", forum.id, user)
end
end end

View file

@ -14,6 +14,7 @@ defmodule Philomena.Images do
alias Philomena.Tags alias Philomena.Tags
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.Processors alias Philomena.Processors
alias Philomena.Notifications
@doc """ @doc """
Gets a single image. Gets a single image.
@ -283,7 +284,13 @@ defmodule Philomena.Images do
""" """
def delete_subscription(image, user) do def delete_subscription(image, user) do
clear_notification(image, user)
%Subscription{image_id: image.id, user_id: user.id} %Subscription{image_id: image.id, user_id: user.id}
|> Repo.delete() |> Repo.delete()
end end
def clear_notification(image, user) do
Notifications.delete_unread_notification("Image", image.id, user)
end
end end

View file

@ -158,8 +158,17 @@ defmodule Philomena.Notifications do
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
def delete_unread_notification(%UnreadNotification{} = unread_notification) do def delete_unread_notification(actor_type, actor_id, user) do
Repo.delete(unread_notification) notification =
Notification
|> where(actor_type: ^actor_type, actor_id: ^actor_id)
|> Repo.one()
if notification do
UnreadNotification
|> where(notification_id: ^notification.id, user_id: ^user.id)
|> Repo.delete_all()
end
end end
@doc """ @doc """

View file

@ -184,7 +184,13 @@ defmodule Philomena.Topics do
""" """
def delete_subscription(topic, user) do def delete_subscription(topic, user) do
clear_notification(topic, user)
%Subscription{topic_id: topic.id, user_id: user.id} %Subscription{topic_id: topic.id, user_id: user.id}
|> Repo.delete() |> Repo.delete()
end end
def clear_notification(topic, user) do
Notifications.delete_unread_notification("Topic", topic.id, user)
end
end end

View file

@ -0,0 +1,18 @@
defmodule PhilomenaWeb.Forum.ReadController do
import Plug.Conn
use PhilomenaWeb, :controller
alias Philomena.Forums.Forum
alias Philomena.Forums
plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
def create(conn, _params) do
forum = conn.assigns.forum
user = conn.assigns.current_user
Forums.clear_notification(forum, user)
send_resp(conn, :ok, "")
end
end

View file

@ -0,0 +1,35 @@
defmodule PhilomenaWeb.Forum.SubscriptionController do
use PhilomenaWeb, :controller
alias Philomena.Forums.Forum
alias Philomena.Forums
plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show
plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
def create(conn, _params) do
forum = conn.assigns.forum
user = conn.assigns.current_user
case Forums.create_subscription(forum, user) do
{:ok, _subscription} ->
render(conn, "_subscription.html", forum: forum, watching: true, layout: false)
{:error, _changeset} ->
render(conn, "_error.html", layout: false)
end
end
def delete(conn, _params) do
forum = conn.assigns.forum
user = conn.assigns.current_user
case Forums.delete_subscription(forum, user) do
{:ok, _subscription} ->
render(conn, "_subscription.html", forum: forum, watching: false, layout: false)
{:error, _changeset} ->
render(conn, "_error.html", layout: false)
end
end
end

View file

@ -1,7 +1,7 @@
defmodule PhilomenaWeb.ForumController do defmodule PhilomenaWeb.ForumController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.{Forums.Forum, Topics.Topic} alias Philomena.{Forums, Forums.Forum, Topics.Topic}
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query import Ecto.Query
@ -22,14 +22,19 @@ defmodule PhilomenaWeb.ForumController do
end end
def show(conn, %{"id" => _id}) do def show(conn, %{"id" => _id}) do
forum = conn.assigns.forum
user = conn.assigns.current_user
topics = topics =
Topic Topic
|> where(forum_id: ^conn.assigns.forum.id) |> where(forum_id: ^forum.id)
|> where(hidden_from_users: false) |> where(hidden_from_users: false)
|> order_by(desc: :sticky, desc: :last_replied_to_at) |> order_by(desc: :sticky, desc: :last_replied_to_at)
|> preload([:poll, :forum, :user, last_post: :user]) |> preload([:poll, :forum, :user, last_post: :user])
|> Repo.paginate(conn.assigns.scrivener) |> Repo.paginate(conn.assigns.scrivener)
render(conn, "show.html", forum: conn.assigns.forum, topics: topics) watching = Forums.subscribed?(forum, user)
render(conn, "show.html", forum: conn.assigns.forum, watching: watching, topics: topics)
end end
end end

View file

@ -0,0 +1,18 @@
defmodule PhilomenaWeb.Image.ReadController do
import Plug.Conn
use PhilomenaWeb, :controller
alias Philomena.Images.Image
alias Philomena.Images
plug :load_resource, model: Image, id_name: "image_id", persisted: true
def create(conn, _params) do
image = conn.assigns.image
user = conn.assigns.current_user
Images.clear_notification(image, user)
send_resp(conn, :ok, "")
end
end

View file

@ -0,0 +1,30 @@
defmodule PhilomenaWeb.Topic.ReadController do
import Plug.Conn
use PhilomenaWeb, :controller
alias Philomena.Forums.Forum
alias Philomena.Topics.Topic
alias Philomena.Topics
alias Philomena.Repo
import Ecto.Query
plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
def create(conn, %{"topic_id" => slug}) do
topic = load_topic(conn, slug)
user = conn.assigns.current_user
Topics.clear_notification(topic, user)
send_resp(conn, :ok, "")
end
defp load_topic(conn, slug) do
forum = conn.assigns.forum
Topic
|> where(forum_id: ^forum.id, slug: ^slug, hidden_from_users: false)
|> preload(:user)
|> Repo.one()
end
end

View file

@ -65,12 +65,17 @@ defmodule PhilomenaWeb.Router do
resources "/fave", Image.FaveController, only: [:create, :delete], singleton: true resources "/fave", Image.FaveController, only: [:create, :delete], singleton: true
resources "/hide", Image.HideController, only: [:create, :delete], singleton: true resources "/hide", Image.HideController, only: [:create, :delete], singleton: true
resources "/subscription", Image.SubscriptionController, only: [:create, :delete], singleton: true resources "/subscription", Image.SubscriptionController, only: [:create, :delete], singleton: true
resources "/read", Image.ReadController, only: [:create], singleton: true
end end
resources "/forums", ForumController, only: [] do resources "/forums", ForumController, only: [] do
resources "/topics", TopicController, only: [:new, :create] do resources "/topics", TopicController, only: [:new, :create] do
resources "/subscription", Topic.SubscriptionController, only: [:create, :delete], singleton: true resources "/subscription", Topic.SubscriptionController, only: [:create, :delete], singleton: true
resources "/read", Topic.ReadController, only: [:create], singleton: true
end end
resources "/subscription", Forum.SubscriptionController, only: [:create, :delete], singleton: true
resources "/read", Forum.ReadController, only: [:create], singleton: true
end end
scope "/filters", Filter, as: :filter do scope "/filters", Filter, as: :filter do

View file

@ -17,10 +17,7 @@ h1 = @forum.name
.block__header--sub.block__header--light .block__header--sub.block__header--light
= pagination = pagination
span.block__header__title = @forum.description span.block__header__title = @forum.description
/- if current_user = render PhilomenaWeb.Forum.SubscriptionView, "_subscription.html", forum: @forum, watching: @watching, conn: @conn
/ = subscription_link(@forum, current_user)
/- else
/ | Login to subscribe to new threads
.block__content .block__content
table.table.table--communication-list table.table.table--communication-list
thead thead

View file

@ -0,0 +1,23 @@
elixir:
watch_path = Routes.forum_subscription_path(@conn, :create, @forum)
watch_class = if @watching, do: "hidden", else: ""
unwatch_path = Routes.forum_subscription_path(@conn, :delete, @forum)
unwatch_class = if @watching, do: "", else: "hidden"
= if @conn.assigns.current_user do
span#js-subscription-target
a.js-subscription-link href=watch_path class=watch_class data-remote="true" data-method="post"
i.fa.fa-bell>
span.hide-mobile
' Subscribe
a.js-subscription-link href=unwatch_path class=unwatch_class data-remote="true" data-method="delete"
i.fa.fa-bell-slash>
span.hide-mobile
' Unsubscribe
- else
a href=Routes.pow_session_path(@conn, :new)
i.fa.fa-bell>
span.hide-mobile
' Subscribe

View file

@ -6,7 +6,7 @@ elixir:
unwatch_class = if @watching, do: "", else: "hidden" unwatch_class = if @watching, do: "", else: "hidden"
= if @conn.assigns.current_user do = if @conn.assigns.current_user do
#js-subscription-target span#js-subscription-target
a.js-subscription-link href=watch_path class=watch_class data-remote="true" data-method="post" a.js-subscription-link href=watch_path class=watch_class data-remote="true" data-method="post"
i.fa.fa-bell> i.fa.fa-bell>
span.hide-mobile span.hide-mobile

View file

@ -1,4 +1,8 @@
.flex.flex--centered.flex__grow
div
strong> strong>
= link @notification.actor.title, to: "#" = link @notification.actor.title, to: "#"
/= link @notification.actor.title, to: Routes.channel_path(@conn, :show, notification.actor) /= link @notification.actor.title, to: Routes.channel_path(@conn, :show, notification.actor)
=<> @notification.action =<> @notification.action
=> pretty_time @notification.updated_at

View file

@ -1,6 +1,8 @@
- forum = @notification.actor - forum = @notification.actor
- topic = @notification.actor_child - topic = @notification.actor_child
.flex.flex--centered.flex__grow
div
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: topic, conn: @conn => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: topic, conn: @conn
=> @notification.action => @notification.action
@ -12,3 +14,12 @@ strong>
' in ' in
=> link forum.name, to: Routes.forum_path(@conn, :show, forum) => link forum.name, to: Routes.forum_path(@conn, :show, forum)
=> pretty_time @notification.updated_at
.flex.flex--centered.flex--no-wrap
a.button.button--separate-right title="Delete" href=Routes.forum_read_path(@conn, :create, forum) data-method="post" data-remote="true" data-fetchcomplete-hide="#notification-#{@notification.id}"
i.fa.fa-trash
a.button title="Unsubscribe" href=Routes.forum_subscription_path(@conn, :delete, forum) data-method="delete" data-remote="true" data-fetchcomplete-hide="#notification-#{@notification.id}"
i.fa.fa-bell-slash

View file

@ -1,6 +1,10 @@
.flex.flex--centered.flex__grow
div
=> render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: @notification.actor.creator}, conn: @conn => render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: @notification.actor.creator}, conn: @conn
=> @notification.action => @notification.action
strong> strong>
= link @notification.actor.title, to: "#" = link @notification.actor.title, to: "#"
/= link @notification.actor.title, to: Routes.gallery_path(@conn, :show, @notification.actor) /= link @notification.actor.title, to: Routes.gallery_path(@conn, :show, @notification.actor)
=> pretty_time @notification.updated_at

View file

@ -1,5 +1,16 @@
.flex.flex--centered.flex__grow
div
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @notification.actor_child, conn: @conn => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @notification.actor_child, conn: @conn
=> @notification.action => @notification.action
strong strong>
= link "##{@notification.actor_id}", to: Routes.image_path(@conn, :show, @notification.actor) <> "#comments" = link "##{@notification.actor_id}", to: Routes.image_path(@conn, :show, @notification.actor) <> "#comments"
=> pretty_time @notification.updated_at
.flex.flex--centered.flex--no-wrap
a.button.button--separate-right title="Delete" href=Routes.image_read_path(@conn, :create, @notification.actor) data-method="post" data-remote="true" data-fetchcomplete-hide="#notification-#{@notification.id}"
i.fa.fa-trash
a.button title="Unsubscribe" href=Routes.image_subscription_path(@conn, :delete, @notification.actor) data-method="delete" data-remote="true" data-fetchcomplete-hide="#notification-#{@notification.id}"
i.fa.fa-bell-slash

View file

@ -1,14 +1,7 @@
= if @notification.actor do = if @notification.actor do
.block.block--fixed.flex class="js-notification-id-#{@notification.id}" .block.block--fixed.flex id="notification-#{@notification.id}"
= if @notification.actor_type == "Image" and @notification.actor do = if @notification.actor_type == "Image" and @notification.actor do
.flex.flex--centered.flex__fixed.thumb-tiny-container.spacing-right .flex.flex--centered.flex__fixed.thumb-tiny-container.spacing-right
= render PhilomenaWeb.ImageView, "_image_container.html", image: @notification.actor, size: :thumb_tiny, conn: @conn = render PhilomenaWeb.ImageView, "_image_container.html", image: @notification.actor, size: :thumb_tiny, conn: @conn
.flex.flex--centered.flex__grow
div
=> render PhilomenaWeb.NotificationView, notification_template_path(@notification.actor_type), notification: @notification, conn: @conn => render PhilomenaWeb.NotificationView, notification_template_path(@notification.actor_type), notification: @notification, conn: @conn
=> pretty_time @notification.updated_at
.flex.flex--centered.flex--no-wrap
a.button.button--separate-right title="Delete" data-click-markread=@notification.id
i.fa.fa-trash
a.button title="Unsubscribe" data-subscription-id=@notification.actor_id data-subscription-type=@notification.actor_type data-click-togglesubscription="unwatch" data-click-hide=".js-notification-id-#{@notification.id}"
.fa.fa-bell-slash

View file

@ -1,8 +1,19 @@
- topic = @notification.actor - topic = @notification.actor
- post = @notification.actor_child - post = @notification.actor_child
.flex.flex--centered.flex__grow
div
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: post, conn: @conn => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: post, conn: @conn
=> @notification.action => @notification.action
strong strong>
= link topic.title, to: Routes.forum_topic_path(@conn, :show, topic.forum, topic, post_id: post.id) <> "#post_#{post.id}" = link topic.title, to: Routes.forum_topic_path(@conn, :show, topic.forum, topic, post_id: post.id) <> "#post_#{post.id}"
=> pretty_time @notification.updated_at
.flex.flex--centered.flex--no-wrap
a.button.button--separate-right title="Delete" href=Routes.forum_topic_read_path(@conn, :create, topic.forum, topic) data-method="post" data-remote="true" data-fetchcomplete-hide="#notification-#{@notification.id}"
i.fa.fa-trash
a.button title="Unsubscribe" href=Routes.forum_topic_subscription_path(@conn, :delete, topic.forum, topic) data-method="delete" data-remote="true" data-fetchcomplete-hide="#notification-#{@notification.id}"
i.fa.fa-bell-slash

View file

@ -6,7 +6,7 @@ elixir:
unwatch_class = if @watching, do: "", else: "hidden" unwatch_class = if @watching, do: "", else: "hidden"
= if @conn.assigns.current_user do = if @conn.assigns.current_user do
#js-subscription-target span#js-subscription-target
a.js-subscription-link href=watch_path class=watch_class data-remote="true" data-method="post" a.js-subscription-link href=watch_path class=watch_class data-remote="true" data-method="post"
i.fa.fa-bell> i.fa.fa-bell>
span.hide-mobile span.hide-mobile

View file

@ -0,0 +1,3 @@
defmodule PhilomenaWeb.Forum.SubscriptionView do
use PhilomenaWeb, :view
end