207 lines
6.3 KiB
Elixir
207 lines
6.3 KiB
Elixir
defmodule DiffuserWeb.PromptRequestLive.Index do
|
|
use DiffuserWeb, :live_view
|
|
|
|
alias Diffuser.Generator
|
|
alias Diffuser.Generator.PromptRequest
|
|
alias Diffuser.Accounts
|
|
alias Diffuser.Accounts.User
|
|
alias DiffuserWeb.Endpoint
|
|
alias Phoenix.Socket.Broadcast
|
|
alias Diffuser.Repo
|
|
alias Ecto.Association.NotLoaded
|
|
|
|
@impl true
|
|
def mount(params, %{"user" => user, "is_admin" => is_admin}, socket) do
|
|
changeset = Accounts.change_user(user)
|
|
|
|
{:ok,
|
|
socket
|
|
|> assign(:user, user)
|
|
|> assign(:params, params)
|
|
|> assign(:is_admin, is_admin)
|
|
|> assign(:user_changeset, changeset)}
|
|
end
|
|
|
|
@impl true
|
|
def handle_params(params, _url, socket) do
|
|
page = list_prompt_requests(params) |> subscribe_to_queued_prompts()
|
|
|
|
socket =
|
|
socket
|
|
|> apply_action(socket.assigns.live_action, params)
|
|
|> assign(:page, page)
|
|
|> assign(:params, params)
|
|
|
|
{:noreply, socket}
|
|
end
|
|
|
|
defp apply_action(socket, :edit, %{"id" => id}) do
|
|
socket
|
|
|> assign(:page_title, "Edit Prompt")
|
|
|> assign(:prompt_request, Generator.get_prompt_request!(id))
|
|
end
|
|
|
|
defp apply_action(socket, :new, _params) do
|
|
socket
|
|
|> assign(:page_title, "New Prompt")
|
|
|> assign(:prompt_request, %PromptRequest{})
|
|
end
|
|
|
|
defp apply_action(socket, :index, _params) do
|
|
socket
|
|
|> assign(:page_title, "Listing Prompts")
|
|
|> assign(:prompt_request, nil)
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("delete", %{"id" => id}, %{assigns: %{params: params}} = socket) do
|
|
prompt_request = Generator.get_prompt_request!(id)
|
|
{:ok, _} = Generator.delete_prompt_request(prompt_request)
|
|
|
|
{:noreply, assign(socket, :page, list_prompt_requests(params))}
|
|
end
|
|
|
|
def handle_event("upvote", %{"id" => id}, %{assigns: %{user: user, params: params}} = socket) do
|
|
prompt_request = Generator.get_prompt_request!(id)
|
|
Diffuser.Accounts.upvote(user, prompt_request)
|
|
|
|
{:noreply, assign(socket, :page, list_prompt_requests(params))}
|
|
end
|
|
|
|
def handle_event(
|
|
"update_user",
|
|
%{"user" => params},
|
|
%{assigns: %{user: user}} = socket
|
|
) do
|
|
case Accounts.update_user(user, params) do
|
|
{:ok, user} ->
|
|
{:noreply, assign(socket, :user, user)}
|
|
|
|
{:error, %Ecto.Changeset{} = changeset} ->
|
|
{:noreply, assign(socket, :user_changeset, changeset)}
|
|
end
|
|
end
|
|
|
|
def handle_event(
|
|
"search",
|
|
%{"search" => %{"query" => query}},
|
|
%{assigns: %{params: params}} = socket
|
|
) do
|
|
params = Map.put(params, :query, query)
|
|
page = Generator.paginate_prompt_requests(PromptRequest, params)
|
|
{:noreply, socket |> assign(:params, params) |> assign(:page, page)}
|
|
end
|
|
|
|
def handle_event("clear", _, socket) do
|
|
page = Generator.paginate_prompt_requests(PromptRequest, %{page: 1})
|
|
{:noreply, socket |> assign(:params, %{page: 1}) |> assign(:page, page)}
|
|
end
|
|
|
|
def handle_event("order_by", %{"votes" => direction}, %{assigns: %{params: params}} = socket) do
|
|
direction = if direction in ["asc", "desc"], do: direction, else: nil
|
|
params = Map.put(params, :order_by, direction)
|
|
page = Generator.paginate_prompt_requests(PromptRequest, params)
|
|
{:noreply, socket |> assign(:params, params) |> assign(:page, page)}
|
|
end
|
|
|
|
def handle_event("go_to" = event, %{"jump" => %{"page" => _page} = result}, socket),
|
|
do: handle_event(event, result, socket)
|
|
|
|
def handle_event("go_to", %{"page" => page}, %{assigns: %{params: params}} = socket) do
|
|
params = Map.put(params, :page, page)
|
|
page = Generator.paginate_prompt_requests(PromptRequest, params)
|
|
{:noreply, socket |> assign(:params, params) |> assign(:page, page)}
|
|
end
|
|
|
|
defp has_voted(nil, _), do: false
|
|
|
|
defp has_voted(%{id: user_id}, %{votes: prompt_request_votes}) do
|
|
prompt_request_votes
|
|
|> Enum.any?(fn %{user_id: id} ->
|
|
user_id == id
|
|
end)
|
|
end
|
|
|
|
defp display_current_filters(params) do
|
|
query = Map.get(params, :query, nil)
|
|
order_by = Map.get(params, :order_by, nil)
|
|
page = Map.get(params, :page, 1)
|
|
|
|
query_str = if query, do: "Searching for \"#{query}\"", else: "Everything"
|
|
order_by_str = if order_by == "desc", do: " with most votes", else: ""
|
|
|
|
query_str <> order_by_str <> " on page #{page}"
|
|
end
|
|
|
|
defp display_name(%User{username: username}) when not is_nil(username), do: username
|
|
|
|
defp display_name(%User{id: id}), do: id |> String.slice(0, 8)
|
|
|
|
defp fake_name(), do: for(_ <- 1..8, into: "", do: <<Enum.random('0123456789abcdef')>>)
|
|
|
|
defp list_prompt_requests(params) do
|
|
Generator.paginate_prompt_requests(PromptRequest, params)
|
|
end
|
|
|
|
defp total_time(%PromptRequest{began_at: began_at, ended_at: ended_at})
|
|
when not is_nil(began_at) and not is_nil(ended_at) do
|
|
"Processing Time: #{NaiveDateTime.diff(ended_at, began_at, :second)} seconds"
|
|
end
|
|
|
|
defp total_time(_), do: ""
|
|
|
|
defp owns_prompt_request(user, %{user: %NotLoaded{} = prompt_request}),
|
|
do: user |> owns_prompt_request(prompt_request |> Repo.preload(:user))
|
|
|
|
defp owns_prompt_request(nil, _), do: false
|
|
|
|
defp owns_prompt_request(_, %{user: nil}), do: false
|
|
|
|
defp owns_prompt_request(%{ip_address: their_ip_address, id: their_id}, %{
|
|
user: %{ip_address: ip_address, id: id}
|
|
})
|
|
when their_ip_address == ip_address or their_id == id,
|
|
do: true
|
|
|
|
defp owns_prompt_request(_, _), do: false
|
|
|
|
defp subscribe_to_queued_prompts(%Scrivener.Page{entries: entries} = page) do
|
|
entries
|
|
|> Enum.each(fn %PromptRequest{id: id, status: status} ->
|
|
if status in ["queued", "in_progress"] do
|
|
Endpoint.subscribe("request:#{id}")
|
|
end
|
|
end)
|
|
|
|
page
|
|
end
|
|
|
|
@impl true
|
|
def handle_info(
|
|
%Broadcast{
|
|
topic: _,
|
|
event: event,
|
|
payload: %{prompt_request: %PromptRequest{} = prompt_request}
|
|
},
|
|
socket
|
|
)
|
|
when event in ["request", "progress"],
|
|
do: {:noreply, socket |> update_subscribed_prompt(prompt_request)}
|
|
|
|
defp update_subscribed_prompt(
|
|
%{assigns: %{page: %Scrivener.Page{entries: entries} = page}} = socket,
|
|
%PromptRequest{id: id} = prompt_request
|
|
) do
|
|
entries =
|
|
entries
|
|
|> Enum.map(
|
|
&if &1.id === id, do: prompt_request |> Repo.preload([:votes, :user, :images]), else: &1
|
|
)
|
|
|
|
page = Map.put(page, :entries, entries)
|
|
|
|
socket
|
|
|> assign(:page, page)
|
|
end
|
|
end
|