Skip to content

Commit

Permalink
Add dashboard view and complete conversation creation code
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentvanbush committed Nov 1, 2020
1 parent 548f4fc commit 9f41825
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 90 deletions.
11 changes: 4 additions & 7 deletions lib/curious_messenger/chat.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ defmodule CuriousMessenger.Chat do

alias CuriousMessenger.Chat.Message

alias CuriousMessenger.Chat.Conversation.Batches

@doc """
Returns the list of chat_messages.
Expand Down Expand Up @@ -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 """
Expand Down
2 changes: 2 additions & 0 deletions lib/curious_messenger/chat/conversation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
30 changes: 0 additions & 30 deletions lib/curious_messenger/chat/conversation/batches.ex

This file was deleted.

7 changes: 4 additions & 3 deletions lib/curious_messenger/chat/conversation_member.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
19 changes: 0 additions & 19 deletions lib/curious_messenger_web/controllers/page_controller.ex
Original file line number Diff line number Diff line change
@@ -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
116 changes: 116 additions & 0 deletions lib/curious_messenger_web/live/dashboard_live.ex
Original file line number Diff line number Diff line change
@@ -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
47 changes: 47 additions & 0 deletions lib/curious_messenger_web/templates/dashboard/show.html.leex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<article class="column">
<h2>Ongoing Conversations</h2>
<%= for conversation <- @current_user.conversations do %>
<div>
<%= link conversation.title, to: Routes.conversation_path(@socket, CuriousMessengerWeb.ConversationLive, conversation.id, @current_user.id) %>
</div>
<% end %>
</article>

<article class="column">
<h2>Create Conversation</h2>

<%= form_for @conversation_changeset,
"",
[phx_submit: :create_conversation], fn f -> %>
<p>
<%= 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 %>
</p>

<p>
<%= text_input f, :title, placeholder: "Title (optional)" %>
<%= submit "Create", disabled: Enum.count(@conversation_changeset.changes[:conversation_members]) < 2 %>
</p>

<ul>
<%= for user <- Enum.reject(@contacts, &(&1.id == @current_user.id)) do %>
<li>
<%= link user.nickname,
to: "#!",
phx_click: "add_member",
phx_value_user_id: user.id %>
</li>
<% end %>
</ul>
<% end %>

</article>
28 changes: 5 additions & 23 deletions lib/curious_messenger_web/templates/page/index.html.eex
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,8 @@
<p>An awesome instant messaging app<br/>made with ❤️ by <a href="https://curiosum.dev">Curiosum</a>.</p>
</section>

<section class="row">
<%= if @current_user do %>
<article class="column">
<h2>Ongoing Conversations</h2>
<ul>
<%= for conversation <- @current_user.conversations do %>
<%= link conversation.title, to: Routes.conversation_path(@conn, CuriousMessengerWeb.ConversationLive, conversation.id, @current_user.id) %>
<% end %>
</ul>
</article>
<article class="column">
<h2>Contact List</h2>
<%= form_for @conversation_changeset, Routes.conversation_path(@conn, :create) do %>
<ul>
<%= for user <- @contacts do %>

<% end %>
</ul>
<% end %>

</article>
<% end%>
</section>
<%= if @current_user do %>
<%= live_render(@conn,
CuriousMessengerWeb.DashboardLive,
session: %{current_user: @current_user}) %>
<% end%>
5 changes: 5 additions & 0 deletions lib/curious_messenger_web/views/dashboard_view.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule CuriousMessengerWeb.DashboardView do
use CuriousMessengerWeb, :view

require IEx
end
13 changes: 5 additions & 8 deletions priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# and so on) as they will fail if something goes wrong.

alias CuriousMessenger.Auth.User
alias CuriousMessenger.Chat.{Conversation, ConversationMember}
alias CuriousMessenger.Chat.Conversation

alias CuriousMessenger.{Auth, Chat}

Expand All @@ -35,13 +35,10 @@ rand2 = Enum.random(0..1000)
})

{:ok, %Conversation{id: conv_id} = conversation} =
Chat.create_conversation(%{title: "Modern Talking"})

{:ok, %ConversationMember{}} =
Chat.create_conversation_member(%{conversation_id: conv_id, user_id: u1_id, owner: true})

{:ok, %ConversationMember{}} =
Chat.create_conversation_member(%{conversation_id: conv_id, user_id: u2_id, owner: false})
Chat.create_conversation(%{
title: "Modern Talking",
conversation_members: [%{user_id: u1_id, owner: true}, %{user_id: u2_id, owner: false}]
})

IO.puts("Created records:")
IO.inspect(user1)
Expand Down

0 comments on commit 9f41825

Please sign in to comment.