add conversations controller/templates

This commit is contained in:
byte[] 2019-11-15 23:38:42 -05:00
parent 02fc81f23b
commit f28fcc59d0
15 changed files with 147 additions and 6 deletions

View file

@ -2,6 +2,8 @@ defmodule Philomena.Conversations.Conversation do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
@derive {Phoenix.Param, key: :slug}
schema "conversations" do schema "conversations" do
belongs_to :from, Philomena.Users.User belongs_to :from, Philomena.Users.User
belongs_to :to, Philomena.Users.User belongs_to :to, Philomena.Users.User

View file

@ -1,6 +1,7 @@
defimpl Canada.Can, for: [Atom, Philomena.Users.User] do defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
alias Philomena.Users.User alias Philomena.Users.User
alias Philomena.Comments.Comment alias Philomena.Comments.Comment
alias Philomena.Conversations.Conversation
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Forums.Forum alias Philomena.Forums.Forum
alias Philomena.Topics.Topic alias Philomena.Topics.Topic
@ -27,6 +28,9 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
when level in ["normal", "assistant", "staff"], do: true when level in ["normal", "assistant", "staff"], do: true
def can?(%User{role: "moderator"}, :show, %Topic{hidden_from_users: true}), do: true def can?(%User{role: "moderator"}, :show, %Topic{hidden_from_users: true}), do: true
# View conversations
def can?(%User{role: "moderator"}, :show, %Conversation{}), do: true
# #
# Assistants can... # Assistants can...
# #
@ -43,6 +47,10 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
# Users and anonymous users can... # Users and anonymous users can...
# #
# View conversations they are involved in
def can?(%User{id: id}, :show, %Conversation{to_id: id}), do: true
def can?(%User{id: id}, :show, %Conversation{from_id: id}), do: true
# View filters they own and system filters # View filters they own and system filters
def can?(_user, :show, %Filter{system: true}), do: true def can?(_user, :show, %Filter{system: true}), do: true
def can?(%User{id: id}, :show, %Filter{user_id: id}), do: true def can?(%User{id: id}, :show, %Filter{user_id: id}), do: true

View file

@ -0,0 +1,44 @@
defmodule PhilomenaWeb.ConversationController do
use PhilomenaWeb, :controller
alias Philomena.Conversations.{Conversation, Message}
alias Philomena.Textile.Renderer
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.Plugs.FilterBannedUsers when action in [:new, :create]
plug :load_and_authorize_resource, model: Conversation, id_field: "slug", only: :show
def index(conn, _params) do
user = conn.assigns.current_user
conversations =
Conversation
|> where([c], (c.from_id == ^user.id and not c.from_hidden) or (c.to_id == ^user.id and not c.to_hidden))
|> order_by(desc: :last_message_at)
|> preload([:to, :from])
|> Repo.paginate(conn.assigns.scrivener)
render(conn, "index.html", conversations: conversations)
end
def show(conn, _params) do
conversation = conn.assigns.conversation
messages =
Message
|> where(conversation_id: ^conversation.id)
|> order_by(asc: :created_at)
|> preload([:from])
|> Repo.paginate(conn.assigns.scrivener)
rendered =
messages.entries
|> Renderer.render_collection()
messages =
%{messages | entries: Enum.zip(messages.entries, rendered)}
render(conn, "index.html", conversation: conversation, messages: messages)
end
end

View file

@ -53,6 +53,7 @@ defmodule PhilomenaWeb.Router do
pipe_through [:browser, :ensure_totp, :protected] pipe_through [:browser, :ensure_totp, :protected]
resources "/notifications", NotificationController, only: [:index, :delete] resources "/notifications", NotificationController, only: [:index, :delete]
resources "/conversations", ConversationController, only: [:index, :show]
end end
scope "/", PhilomenaWeb do scope "/", PhilomenaWeb do

View file

@ -0,0 +1,34 @@
elixir:
route = fn p -> Routes.conversation_path(@conn, :index, p) end
pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @conversations, route: route, conn: @conn
h1 My Conversations
.block
.block__header
= pagination
.block__content
table.table.table--communication-list
thead
tr
th.table--communication-list__name Conversation
th.table--communication-list__stats With
th.table--communication-list__options Options
tbody
= for c <- @conversations do
td.table--communication-list__name
=> link c.title, to: Routes.conversation_path(@conn, :show, c)
.small-text.hide-mobile
' Started
= pretty_time(c.created_at)
' , last message
= pretty_time(c.last_message_at)
td.table--communication-list__stats
= render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: other_party(@current_user.id, c)}, conn: @conn
td.table--communication-list__options
| Last message
.block__header.block__header--light
= pagination

View file

@ -0,0 +1,22 @@
elixir:
route = fn p -> Routes.conversation_path(@conn, :show, @conversation, p) end
pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @messages, route: route, conn: @conn
other = other_party(@current_user.id, @conversation)
h1 = @conversation.title
.block
.block__header
=> link "Message Center", to: Routes.conversation_path(@conn, :index)
' &raquo;
=> link @conversation.title, to: Routes.conversation_path(@conn, :show, @conversation)
' Conversation with
=> render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: other}, conn: @conn
.block__header--sub.block__header--light
= pagination
= for {message, body} <- @messages do
= render PhilomenaWeb.MessageView, "_message.html", message: message, body: body, conn: @conn
.block
.block__header.block__header--light
= pagination

View file

@ -0,0 +1,18 @@
article.block.communication
.block__content.flex.flex--no-wrap
.flex__fixed.spacing-right
= render PhilomenaWeb.UserAttributionView, "_user_avatar.html", object: %{user: @message.from}, conn: @conn, class: "avatar--100px"
.flex__grow.communication__body
span.communication__body__sender-name
= render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: @message.from}, badges: true, conn: @conn
br
.communication__body__text
== @body
.block__content.communication__options
.flex.flex--wrap.flex--spaced-out
div
' Posted
= pretty_time(@message.created_at)

View file

@ -1,7 +1,7 @@
- forum = @notification.actor - forum = @notification.actor
- topic = @notification.actor_child - topic = @notification.actor_child
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: topic => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: topic, conn: @conn
=> @notification.action => @notification.action
' titled ' titled

View file

@ -1,4 +1,4 @@
=> render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: @notification.actor.creator} => render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: @notification.actor.creator}, conn: @conn
=> @notification.action => @notification.action
strong> strong>

View file

@ -1,4 +1,4 @@
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @notification.actor_child => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @notification.actor_child, conn: @conn
=> @notification.action => @notification.action
strong strong

View file

@ -5,7 +5,7 @@
= render PhilomenaWeb.ImageView, "_image_container.html", image: @notification.actor, size: :thumb_tiny, conn: @conn = render PhilomenaWeb.ImageView, "_image_container.html", image: @notification.actor, size: :thumb_tiny, conn: @conn
.flex.flex--centered.flex__grow .flex.flex--centered.flex__grow
div div
=> render PhilomenaWeb.NotificationView, notification_template_path(@notification.actor_type), notification: @notification => render PhilomenaWeb.NotificationView, notification_template_path(@notification.actor_type), notification: @notification, conn: @conn
=> pretty_time @notification.updated_at => pretty_time @notification.updated_at
.flex.flex--centered.flex--no-wrap .flex.flex--centered.flex--no-wrap
a.button.button--separate-right title="Delete" data-click-markread=@notification.id a.button.button--separate-right title="Delete" data-click-markread=@notification.id

View file

@ -1,7 +1,7 @@
- topic = @notification.actor - topic = @notification.actor
- post = @notification.actor_child - post = @notification.actor_child
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: post => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: post, conn: @conn
=> @notification.action => @notification.action
strong strong

View file

@ -3,7 +3,7 @@
h1 Notification Area h1 Notification Area
.walloftext .walloftext
.block__header .block__header
= render PhilomenaWeb.PaginationView, "_pagination.html", page: @notifications, route: route = render PhilomenaWeb.PaginationView, "_pagination.html", page: @notifications, route: route, conn: @conn
= for notification <- @notifications do = for notification <- @notifications do
= render PhilomenaWeb.NotificationView, "_notification.html", notification: notification = render PhilomenaWeb.NotificationView, "_notification.html", notification: notification

View file

@ -0,0 +1,9 @@
defmodule PhilomenaWeb.ConversationView do
use PhilomenaWeb, :view
def other_party(user_id, %{to_id: user_id} = conversation),
do: conversation.from
def other_party(_user_id, conversation),
do: conversation.to
end

View file

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