Add pubsub

This commit is contained in:
Logan Hunt 2022-04-14 11:43:34 -06:00
parent ddfab312f7
commit cc58a376a9
Signed by untrusted user who does not match committer: simponic
GPG Key ID: 52B3774857EB24B1
4 changed files with 48 additions and 138 deletions

View File

@ -9,96 +9,30 @@ defmodule Aggiedit.Rooms do
alias Aggiedit.Accounts alias Aggiedit.Accounts
alias Aggiedit.Rooms.Room alias Aggiedit.Rooms.Room
@doc """ alias Phoenix.PubSub
Returns the list of rooms.
## Examples
iex> list_rooms()
[%Room{}, ...]
"""
def list_rooms do def list_rooms do
Repo.all(Room) Repo.all(Room)
end end
@doc """
Gets a single room.
Raises `Ecto.NoResultsError` if the Room does not exist.
## Examples
iex> get_room!(123)
%Room{}
iex> get_room!(456)
** (Ecto.NoResultsError)
"""
def get_room!(id), do: Repo.get!(Room, id) def get_room!(id), do: Repo.get!(Room, id)
@doc """
Creates a room.
## Examples
iex> create_room(%{field: value})
{:ok, %Room{}}
iex> create_room(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_room(attrs \\ %{}) do def create_room(attrs \\ %{}) do
%Room{} %Room{}
|> Room.changeset(attrs) |> Room.changeset(attrs)
|> Repo.insert() |> Repo.insert()
end end
@doc """
Updates a room.
## Examples
iex> update_room(room, %{field: new_value})
{:ok, %Room{}}
iex> update_room(room, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_room(%Room{} = room, attrs) do def update_room(%Room{} = room, attrs) do
room room
|> Room.changeset(attrs) |> Room.changeset(attrs)
|> Repo.update() |> Repo.update()
end end
@doc """
Deletes a room.
## Examples
iex> delete_room(room)
{:ok, %Room{}}
iex> delete_room(room)
{:error, %Ecto.Changeset{}}
"""
def delete_room(%Room{} = room) do def delete_room(%Room{} = room) do
Repo.delete(room) Repo.delete(room)
end end
@doc """
Returns an `%Ecto.Changeset{}` for tracking room changes.
## Examples
iex> change_room(room)
%Ecto.Changeset{data: %Room{}}
"""
def change_room(%Room{} = room, attrs \\ %{}) do def change_room(%Room{} = room, attrs \\ %{}) do
Room.changeset(room, attrs) Room.changeset(room, attrs)
end end
@ -117,23 +51,9 @@ defmodule Aggiedit.Rooms do
end end
def posts_in_room(room_id) do def posts_in_room(room_id) do
Repo.all((from p in Post, where: p.room_id == ^room_id, select: p)) Repo.all((from p in Post, where: p.room_id == ^room_id, order_by: [asc: :id], select: p))
end end
@doc """
Gets a single post.
Raises `Ecto.NoResultsError` if the Post does not exist.
## Examples
iex> get_post!(123)
%Post{}
iex> get_post!(456)
** (Ecto.NoResultsError)
"""
def get_post!(id), do: Repo.get!(Post, id) def get_post!(id), do: Repo.get!(Post, id)
def create_post(attrs, user, after_save \\ &{:ok, &1}) do def create_post(attrs, user, after_save \\ &{:ok, &1}) do
@ -145,6 +65,7 @@ defmodule Aggiedit.Rooms do
|> Ecto.Changeset.put_assoc(:user, user) |> Ecto.Changeset.put_assoc(:user, user)
|> Ecto.Changeset.put_assoc(:room, user.room) |> Ecto.Changeset.put_assoc(:room, user.room)
|> Repo.insert() |> Repo.insert()
|> broadcast_post_over_room(:post_created)
|> post_saved(after_save) |> post_saved(after_save)
end end
@ -152,6 +73,7 @@ defmodule Aggiedit.Rooms do
post post
|> Post.changeset(attrs) |> Post.changeset(attrs)
|> Repo.update() |> Repo.update()
|> broadcast_post_over_room(:post_updated)
|> post_saved(after_save) |> post_saved(after_save)
end end
@ -160,32 +82,22 @@ defmodule Aggiedit.Rooms do
end end
defp post_saved(error, _fun), do: error defp post_saved(error, _fun), do: error
@doc """
Deletes a post.
## Examples
iex> delete_post(post)
{:ok, %Post{}}
iex> delete_post(post)
{:error, %Ecto.Changeset{}}
"""
def delete_post(%Post{} = post) do def delete_post(%Post{} = post) do
Repo.delete(post) Repo.delete(post)
|> broadcast_post_over_room(:post_deleted)
end end
@doc """
Returns an `%Ecto.Changeset{}` for tracking post changes.
## Examples
iex> change_post(post)
%Ecto.Changeset{data: %Post{}}
"""
def change_post(%Post{} = post, attrs \\ %{}) do def change_post(%Post{} = post, attrs \\ %{}) do
Post.changeset(post, attrs) Post.changeset(post, attrs)
end end
defp broadcast_post_over_room({:error, _reason}=error, _event), do: error
defp broadcast_post_over_room({:ok, post}, event) do
PubSub.broadcast(Aggiedit.PubSub, "room:#{post.room_id}:posts", {event, post})
{:ok, post}
end
def subscribe(room) do
PubSub.subscribe(Aggiedit.PubSub, "room:#{room.id}:posts")
end
end end

View File

@ -10,7 +10,9 @@ defmodule AggieditWeb.PostLive.Index do
def mount(%{"room_id" => _room_id} = params, session, socket) do def mount(%{"room_id" => _room_id} = params, session, socket) do
{:ok, socket} = assign_socket_room_and_user_or_error(params, session, socket) {:ok, socket} = assign_socket_room_and_user_or_error(params, session, socket)
case socket.assigns do case socket.assigns do
%{:room => room} -> {:ok, assign(socket, %{:posts => room |> Repo.preload(posts: [:user, :upload]) |> Map.get(:posts)})} %{:room => room} ->
if connected?(socket), do: Rooms.subscribe(socket.assigns.room)
{:ok, assign(socket, %{:posts => room |> Repo.preload(posts: [:user, :upload]) |> Map.get(:posts)}), temporary_assigns: [posts: []]}
_ -> {:ok, socket} _ -> {:ok, socket}
end end
end end
@ -59,4 +61,11 @@ defmodule AggieditWeb.PostLive.Index do
{:noreply, socket |> put_flash(:error, "You do not have permission to delete this post.") |> redirect(to: Routes.post_index_path(socket, :index, socket.assigns.room))} {:noreply, socket |> put_flash(:error, "You do not have permission to delete this post.") |> redirect(to: Routes.post_index_path(socket, :index, socket.assigns.room))}
end end
end end
@impl true
def handle_info({action, post}, socket) when action in [:post_created, :post_updated, :post_deleted] do
{:noreply, update(socket, :posts, fn posts ->
[posts | post]
end)}
end
end end

View File

@ -15,8 +15,9 @@
<% end %> <% end %>
<span><%= live_patch "New Post", to: Routes.post_index_path(@socket, :new, @room) %></span> <span><%= live_patch "New Post", to: Routes.post_index_path(@socket, :new, @room) %></span>
<%= for post <- @posts do %> <div id="posts" phx-update="prepend">
<div class="card d-flex flex-row align-items-center p-2 m-2 shadow"> <%= for post <- @posts do %>
<div id={"post-#{post.id}"} class="card d-flex flex-row align-items-center p-2 m-2 shadow">
<%= if !is_nil(post.upload) do %> <%= if !is_nil(post.upload) do %>
<%= live_redirect to: Routes.post_show_path(@socket, :show, @room, post) do %> <%= live_redirect to: Routes.post_show_path(@socket, :show, @room, post) do %>
<div class="card-image d-flex justify-content-center" style="width: 100px"> <div class="card-image d-flex justify-content-center" style="width: 100px">
@ -37,17 +38,5 @@
<% end %> <% end %>
</div> </div>
</div> </div>
<!-- <% end %>
<div class=> </div>
</div>
<tr id={"post-#{post.id}"}>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td>
<span></span>
</td>
</tr>
-->
<% end %>

View File

@ -1,6 +1,6 @@
<%= if @current_user do %> <%= if @current_user do %>
<li class="nav-item active"> <li class="nav-item active">
<%= link "Settings", to: Routes.user_settings_path(@conn, :edit), class: "nav-link" %> <%= link "#{@current_user.username}/settings", to: Routes.user_settings_path(@conn, :edit), class: "nav-link" %>
</li> </li>
<li class="nav-item active"> <li class="nav-item active">
<%= link "Log out", to: Routes.user_session_path(@conn, :delete), method: :delete, class: "nav-link" %> <%= link "Log out", to: Routes.user_session_path(@conn, :delete), method: :delete, class: "nav-link" %>