add topic subscriptions

This commit is contained in:
byte[] 2019-11-17 13:05:50 -05:00
parent 8131782a20
commit f9bdda08a7
7 changed files with 95 additions and 70 deletions

View file

@ -104,35 +104,13 @@ defmodule Philomena.Topics do
alias Philomena.Topics.Subscription
@doc """
Returns the list of topic_subscriptions.
## Examples
iex> list_topic_subscriptions()
[%Subscription{}, ...]
"""
def list_topic_subscriptions do
Repo.all(Subscription)
def subscribed?(topic, nil), do: false
def subscribed?(topic, user) do
Subscription
|> where(topic_id: ^topic.id, user_id: ^user.id)
|> Repo.exists?()
end
@doc """
Gets a single subscription.
Raises `Ecto.NoResultsError` if the Subscription does not exist.
## Examples
iex> get_subscription!(123)
%Subscription{}
iex> get_subscription!(456)
** (Ecto.NoResultsError)
"""
def get_subscription!(id), do: Repo.get!(Subscription, id)
@doc """
Creates a subscription.
@ -145,28 +123,10 @@ defmodule Philomena.Topics do
{:error, %Ecto.Changeset{}}
"""
def create_subscription(attrs \\ %{}) do
%Subscription{}
|> Subscription.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a subscription.
## Examples
iex> update_subscription(subscription, %{field: new_value})
{:ok, %Subscription{}}
iex> update_subscription(subscription, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_subscription(%Subscription{} = subscription, attrs) do
subscription
|> Subscription.changeset(attrs)
|> Repo.update()
def create_subscription(topic, user) do
%Subscription{topic_id: topic.id, user_id: user.id}
|> Subscription.changeset(%{})
|> Repo.insert(on_conflict: :nothing)
end
@doc """
@ -181,20 +141,8 @@ defmodule Philomena.Topics do
{:error, %Ecto.Changeset{}}
"""
def delete_subscription(%Subscription{} = subscription) do
Repo.delete(subscription)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking subscription changes.
## Examples
iex> change_subscription(subscription)
%Ecto.Changeset{source: %Subscription{}}
"""
def change_subscription(%Subscription{} = subscription) do
Subscription.changeset(subscription, %{})
def delete_subscription(topic, user) do
%Subscription{topic_id: topic.id, user_id: user.id}
|> Repo.delete()
end
end

View file

@ -0,0 +1,45 @@
defmodule PhilomenaWeb.Topic.SubscriptionController do
use PhilomenaWeb, :controller
alias Philomena.{Topics, Topics.Topic, Forums.Forum}
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.Plugs.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, %{"topic_id" => slug}) do
topic = load_topic(conn, slug)
user = conn.assigns.current_user
case Topics.create_subscription(topic, user) do
{:ok, _subscription} ->
render(conn, "_subscription.html", forum: conn.assigns.forum, topic: topic, watching: true, layout: false)
{:error, _changeset} ->
render(conn, "_error.html", layout: false)
end
end
def delete(conn, %{"topic_id" => slug}) do
topic = load_topic(conn, slug)
user = conn.assigns.current_user
case Topics.delete_subscription(topic, user) do
{:ok, _subscription} ->
render(conn, "_subscription.html", forum: conn.assigns.forum, topic: topic, watching: false, layout: false)
{:error, _changeset} ->
render(conn, "_error.html", layout: false)
end
end
defp load_topic(conn, slug) do
forum = conn.assigns.forum
topic =
Topic
|> where(forum_id: ^forum.id, slug: ^slug, hidden_from_users: false)
|> preload(:user)
|> Repo.one()
end
end

View file

@ -1,7 +1,7 @@
defmodule PhilomenaWeb.TopicController do
use PhilomenaWeb, :controller
alias Philomena.{Forums.Forum, Topics.Topic, Posts.Post, Textile.Renderer}
alias Philomena.{Forums.Forum, Topics, Topics.Topic, Posts.Post, Textile.Renderer}
alias Philomena.Repo
import Ecto.Query
@ -51,6 +51,9 @@ defmodule PhilomenaWeb.TopicController do
total_pages: div(topic.post_count + 25 - 1, 25)
}
render(conn, "show.html", posts: posts)
watching =
Topics.subscribed?(topic, conn.assigns.current_user)
render(conn, "show.html", posts: posts, watching: watching)
end
end

View file

@ -60,6 +60,12 @@ defmodule PhilomenaWeb.Router do
resources "/hide", Image.HideController, only: [:create, :delete], singleton: true
resources "/subscription", Image.SubscriptionController, only: [:create, :delete], singleton: true
end
resources "/forums", ForumController, only: [] do
resources "/topics", TopicController, only: [] do
resources "/subscription", Topic.SubscriptionController, only: [:create, :delete], singleton: true
end
end
end
scope "/", PhilomenaWeb do

View file

@ -24,10 +24,7 @@ h1 = @topic.title
.flex--fixed.block__header__item
=> @topic.post_count - 1
' replies
/= if current_user
/ = subscription_link(@topic, current_user)
/- else
' Login to subscribe to responses
= render PhilomenaWeb.Topic.SubscriptionView, "_subscription.html", forum: @forum, topic: @topic, watching: @watching, conn: @conn
/ Display the poll, if any
/= render partial: 'polls/display', locals: { poll: @topic.poll }

View file

@ -0,0 +1,23 @@
elixir:
watch_path = Routes.forum_topic_subscription_path(@conn, :create, @forum, @topic)
watch_class = if @watching, do: "hidden", else: ""
unwatch_path = Routes.forum_topic_subscription_path(@conn, :delete, @forum, @topic)
unwatch_class = if @watching, do: "", else: "hidden"
= if @conn.assigns.current_user do
#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

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