diff --git a/lib/curious_messenger/chat.ex b/lib/curious_messenger/chat.ex
index b2bfef1..05568ba 100644
--- a/lib/curious_messenger/chat.ex
+++ b/lib/curious_messenger/chat.ex
@@ -9,8 +9,6 @@ defmodule CuriousMessenger.Chat do
alias CuriousMessenger.Chat.Message
- alias CuriousMessenger.Chat.Conversation.Batches
-
@doc """
Returns the list of chat_messages.
@@ -532,11 +530,10 @@ defmodule CuriousMessenger.Chat do
{:error, %Ecto.Changeset{}}
"""
- def create_conversation(attrs \\ %{}, member_attrs \\ []) do
- case Batches.create_conversation_with_members(attrs, member_attrs) |> Repo.transaction() do
- {:ok, %{create_conversation_members: conversation}} -> {:ok, conversation}
- anything -> anything
- end
+ def create_conversation(attrs \\ %{}) do
+ %Conversation{}
+ |> Conversation.changeset(attrs)
+ |> Repo.insert()
end
@doc """
diff --git a/lib/curious_messenger/chat/conversation.ex b/lib/curious_messenger/chat/conversation.ex
index 18ad0c9..56c04b4 100644
--- a/lib/curious_messenger/chat/conversation.ex
+++ b/lib/curious_messenger/chat/conversation.ex
@@ -8,6 +8,7 @@ defmodule CuriousMessenger.Chat.Conversation do
field :title, :string
has_many :conversation_members, ConversationMember, on_replace: :delete
+ has_many :users, through: [:conversation_members, :user]
has_many :messages, Message
timestamps()
@@ -17,6 +18,7 @@ defmodule CuriousMessenger.Chat.Conversation do
def changeset(conversation, attrs) do
conversation
|> cast(attrs, [:title])
+ |> cast_assoc(:conversation_members)
|> validate_required([:title])
end
end
diff --git a/lib/curious_messenger/chat/conversation/batches.ex b/lib/curious_messenger/chat/conversation/batches.ex
deleted file mode 100644
index 8437bef..0000000
--- a/lib/curious_messenger/chat/conversation/batches.ex
+++ /dev/null
@@ -1,30 +0,0 @@
-defmodule CuriousMessenger.Chat.Conversation.Batches do
- alias Ecto.{Multi, Changeset}
- alias CuriousMessenger.Chat.{Conversation}
-
- def create_conversation_with_members(attrs \\ %{}, member_attrs \\ []) do
- Multi.new()
- |> Multi.run(:create_conversation, create_conversation(attrs))
- |> Multi.run(:create_conversation_members, create_conversation_members(member_attrs))
- end
-
- defp create_conversation(attrs) do
- fn repo, _ ->
- %Conversation{}
- |> Conversation.changeset(attrs)
- |> repo.insert()
- end
- end
-
- defp create_conversation_members(member_attrs) do
- fn repo, %{create_conversation: conversation} ->
- member_attrs =
- Enum.map(member_attrs, fn member -> %{member | conversation_id: conversation.id} end)
-
- %{conversation | conversation_members: []}
- |> Conversation.changeset(%{})
- |> Changeset.put_assoc(:conversation_members, member_attrs)
- |> repo.update
- end
- end
-end
diff --git a/lib/curious_messenger/chat/conversation_member.ex b/lib/curious_messenger/chat/conversation_member.ex
index 7a47dd5..8177a94 100644
--- a/lib/curious_messenger/chat/conversation_member.ex
+++ b/lib/curious_messenger/chat/conversation_member.ex
@@ -17,9 +17,10 @@ defmodule CuriousMessenger.Chat.ConversationMember do
@doc false
def changeset(conversation_member, attrs) do
conversation_member
- |> cast(attrs, [:owner, :conversation_id, :user_id])
- |> validate_required([:owner, :conversation_id, :user_id])
- |> unique_constraint(:user, name: :chat_conversation_members_conversation_id_user_id_index)
+ |> cast(attrs, [:owner, :user_id])
+ |> unique_constraint(:user,
+ name: :chat_conversation_members_conversation_id_user_id_index
+ )
|> unique_constraint(:conversation_id,
name: :chat_conversation_members_owner
)
diff --git a/lib/curious_messenger_web/controllers/page_controller.ex b/lib/curious_messenger_web/controllers/page_controller.ex
index b331c07..0bb529c 100644
--- a/lib/curious_messenger_web/controllers/page_controller.ex
+++ b/lib/curious_messenger_web/controllers/page_controller.ex
@@ -1,28 +1,9 @@
defmodule CuriousMessengerWeb.PageController do
use CuriousMessengerWeb, :controller
- alias CuriousMessenger.Auth
- alias CuriousMessenger.Chat.Conversation
-
plug CuriousMessengerWeb.AssignUser, preload: :conversations
- plug :assign_contacts
- plug :assign_new_conversation_changeset
def index(conn, opts \\ []) do
render(conn, "index.html")
end
-
- defp assign_contacts(conn, _params) do
- users = Auth.list_auth_users()
-
- conn
- |> assign(:contacts, users)
- end
-
- defp assign_new_conversation_changeset(conn, _params) do
- changeset = %Conversation{} |> Conversation.changeset(%{})
-
- conn
- |> assign(:conversation_changeset, changeset)
- end
end
diff --git a/lib/curious_messenger_web/live/dashboard_live.ex b/lib/curious_messenger_web/live/dashboard_live.ex
new file mode 100644
index 0000000..a7e0524
--- /dev/null
+++ b/lib/curious_messenger_web/live/dashboard_live.ex
@@ -0,0 +1,116 @@
+defmodule CuriousMessengerWeb.DashboardLive do
+ use Phoenix.LiveView, container: {:div, [class: "row"]}
+ use Phoenix.HTML
+
+ alias CuriousMessenger.Auth
+ alias CuriousMessenger.Chat.Conversation
+ alias CuriousMessengerWeb.DashboardView
+ alias CuriousMessenger.Repo
+ alias Ecto.Changeset
+
+ def render(assigns) do
+ DashboardView.render("show.html", assigns)
+ end
+
+ def mount(%{current_user: current_user}, socket) do
+ {:ok,
+ socket
+ |> assign(current_user: current_user)
+ |> assign_new_conversation_changeset()
+ |> assign_contacts(current_user)}
+ end
+
+ def handle_event(
+ "create_conversation",
+ %{"conversation" => conversation_form},
+ %{
+ assigns: %{
+ conversation_changeset: changeset,
+ current_user: current_user,
+ contacts: contacts
+ }
+ } = socket
+ ) do
+ conversation_form =
+ Map.put(
+ conversation_form,
+ "title",
+ if(conversation_form["title"] == "",
+ do: build_title(changeset, contacts),
+ else: conversation_form["title"]
+ )
+ )
+
+ {:ok, _} =
+ %Conversation{}
+ |> Conversation.changeset(conversation_form)
+ |> Repo.insert()
+
+ {:noreply,
+ assign(
+ socket,
+ :current_user,
+ Repo.preload(current_user, :conversations, force: true)
+ )}
+ end
+
+ def handle_event(
+ "add_member",
+ %{"user-id" => new_member_id},
+ %{assigns: %{conversation_changeset: changeset}} = socket
+ ) do
+ {:ok, new_member_id} = Ecto.Type.cast(:integer, new_member_id)
+
+ old_members = socket.assigns[:conversation_changeset].changes.conversation_members
+ existing_ids = old_members |> Enum.map(& &1.changes.user_id)
+
+ cond do
+ new_member_id not in existing_ids ->
+ new_members = [%{user_id: new_member_id} | old_members]
+
+ new_changeset = Changeset.put_change(changeset, :conversation_members, new_members)
+
+ {:noreply, assign(socket, :conversation_changeset, new_changeset)}
+
+ true ->
+ {:noreply, socket}
+ end
+ end
+
+ def handle_event(
+ "remove_member",
+ %{"user-id" => removed_member_id},
+ %{assigns: %{conversation_changeset: changeset}} = socket
+ ) do
+ {:ok, removed_member_id} = Ecto.Type.cast(:integer, removed_member_id)
+
+ old_members = socket.assigns[:conversation_changeset].changes.conversation_members
+ new_members = old_members |> Enum.reject(&(&1.changes[:user_id] == removed_member_id))
+
+ new_changeset = Changeset.put_change(changeset, :conversation_members, new_members)
+
+ {:noreply, assign(socket, :conversation_changeset, new_changeset)}
+ end
+
+ defp assign_new_conversation_changeset(socket) do
+ changeset =
+ %Conversation{}
+ |> Conversation.changeset(%{
+ "conversation_members" => [%{owner: true, user_id: socket.assigns[:current_user].id}]
+ })
+
+ assign(socket, :conversation_changeset, changeset)
+ end
+
+ defp assign_contacts(socket, current_user) do
+ users = Auth.list_auth_users()
+
+ assign(socket, :contacts, users)
+ end
+
+ defp build_title(changeset, contacts) do
+ user_ids = Enum.map(changeset.changes.conversation_members, & &1.changes.user_id)
+ nicknames = contacts |> Enum.filter(&(&1.id in user_ids)) |> Enum.map(& &1.nickname)
+ Enum.join(nicknames, ", ")
+ end
+end
diff --git a/lib/curious_messenger_web/templates/dashboard/show.html.leex b/lib/curious_messenger_web/templates/dashboard/show.html.leex
new file mode 100644
index 0000000..9a88b23
--- /dev/null
+++ b/lib/curious_messenger_web/templates/dashboard/show.html.leex
@@ -0,0 +1,47 @@
+
+ <%= inputs_for f, :conversation_members, fn cmf -> %>
+ <% user_id = cmf.source.changes[:user_id] %>
+ <% nickname = @contacts |> Enum.find(&(&1.id == user_id)) |> Map.get(:nickname) %>
+
+ <%= link "#{nickname} #{if user_id == @current_user.id, do: "(me)", else: "✖"} ",
+ to: "#!",
+ phx_click: (unless user_id == @current_user.id, do: "remove_member"),
+ phx_value_user_id: user_id %>
+
+ <%= hidden_input cmf, :user_id, value: user_id %>
+ <% end %>
+
+ <%= text_input f, :title, placeholder: "Title (optional)" %>
+ <%= submit "Create", disabled: Enum.count(@conversation_changeset.changes[:conversation_members]) < 2 %>
+ Ongoing Conversations
+ <%= for conversation <- @current_user.conversations do %>
+ Create Conversation
+
+ <%= form_for @conversation_changeset,
+ "",
+ [phx_submit: :create_conversation], fn f -> %>
+
+ <%= for user <- Enum.reject(@contacts, &(&1.id == @current_user.id)) do %>
+
+ <% end %>
+
+
An awesome instant messaging app
made with ❤️ by Curiosum.