diff --git a/lib/aggiedit/rooms.ex b/lib/aggiedit/rooms.ex index 1eb09f9..898dfe1 100644 --- a/lib/aggiedit/rooms.ex +++ b/lib/aggiedit/rooms.ex @@ -9,96 +9,30 @@ defmodule Aggiedit.Rooms do alias Aggiedit.Accounts alias Aggiedit.Rooms.Room - @doc """ - Returns the list of rooms. + alias Phoenix.PubSub - ## Examples - - iex> list_rooms() - [%Room{}, ...] - - """ def list_rooms do Repo.all(Room) 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) - @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 %Room{} |> Room.changeset(attrs) |> Repo.insert() 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 room |> Room.changeset(attrs) |> Repo.update() 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 Repo.delete(room) 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 Room.changeset(room, attrs) end @@ -117,23 +51,9 @@ defmodule Aggiedit.Rooms do end 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 - @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 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(:room, user.room) |> Repo.insert() + |> broadcast_post_over_room(:post_created) |> post_saved(after_save) end @@ -152,6 +73,7 @@ defmodule Aggiedit.Rooms do post |> Post.changeset(attrs) |> Repo.update() + |> broadcast_post_over_room(:post_updated) |> post_saved(after_save) end @@ -160,32 +82,22 @@ defmodule Aggiedit.Rooms do end 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 Repo.delete(post) + |> broadcast_post_over_room(:post_deleted) 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 Post.changeset(post, attrs) 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 diff --git a/lib/aggiedit_web/live/post_live/index.ex b/lib/aggiedit_web/live/post_live/index.ex index 57ae727..6b2be56 100644 --- a/lib/aggiedit_web/live/post_live/index.ex +++ b/lib/aggiedit_web/live/post_live/index.ex @@ -10,7 +10,9 @@ defmodule AggieditWeb.PostLive.Index do def mount(%{"room_id" => _room_id} = params, session, socket) do {:ok, socket} = assign_socket_room_and_user_or_error(params, session, socket) 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} 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))} 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 diff --git a/lib/aggiedit_web/live/post_live/index.html.heex b/lib/aggiedit_web/live/post_live/index.html.heex index 7532685..efb42cb 100644 --- a/lib/aggiedit_web/live/post_live/index.html.heex +++ b/lib/aggiedit_web/live/post_live/index.html.heex @@ -15,39 +15,28 @@ <% end %> <%= live_patch "New Post", to: Routes.post_index_path(@socket, :new, @room) %> -<%= for post <- @posts do %> -
- <%= if !is_nil(post.upload) do %> - <%= live_redirect to: Routes.post_show_path(@socket, :show, @room, post) do %> -
- -
+
+ <%= for post <- @posts do %> +
+ <%= if !is_nil(post.upload) do %> + <%= live_redirect to: Routes.post_show_path(@socket, :show, @room, post) do %> +
+ +
+ <% end %> <% end %> - <% end %> -
- <%= live_redirect to: Routes.post_show_path(@socket, :show, @room, post) do %> -

<%= post.title %>

- <% end %> -
aggie/<%= post.user.username %>
-

<%= post.body %>

+
+ <%= live_redirect to: Routes.post_show_path(@socket, :show, @room, post) do %> +

<%= post.title %>

+ <% end %> +
aggie/<%= post.user.username %>
+

<%= post.body %>

- <%= if Aggiedit.Roles.guard?(@current_user, :edit, post) && Aggiedit.Roles.guard?(@current_user, :edit, post) do %> - <%= live_patch "Edit", to: Routes.post_index_path(@socket, :edit, @room, post) %> - <%= link "Delete", to: "#", phx_click: "delete", phx_value_id: post.id %> - <% end %> + <%= if Aggiedit.Roles.guard?(@current_user, :edit, post) && Aggiedit.Roles.guard?(@current_user, :edit, post) do %> + <%= live_patch "Edit", to: Routes.post_index_path(@socket, :edit, @room, post) %> + <%= link "Delete", to: "#", phx_click: "delete", phx_value_id: post.id %> + <% end %> +
-
- -<% end %> - + <% end %> +
diff --git a/lib/aggiedit_web/templates/layout/_user_menu.html.heex b/lib/aggiedit_web/templates/layout/_user_menu.html.heex index 4ab3b78..bbd9f97 100644 --- a/lib/aggiedit_web/templates/layout/_user_menu.html.heex +++ b/lib/aggiedit_web/templates/layout/_user_menu.html.heex @@ -1,6 +1,6 @@ <%= if @current_user do %>